| 1 | /* THIS IS A SINGLE-FILE DISTRIBUTION CONCATENATED FROM THE OPEN62541 SOURCES |
|---|---|
| 2 | * visit http://open62541.org/ for information about this software |
| 3 | * Git-Revision: v1.4.13 |
| 4 | */ |
| 5 | |
| 6 | /* |
| 7 | * Copyright (C) 2014-2021 the contributors as stated in the AUTHORS file |
| 8 | * |
| 9 | * This file is part of open62541. open62541 is free software: you can |
| 10 | * redistribute it and/or modify it under the terms of the Mozilla Public |
| 11 | * License v2.0 as stated in the LICENSE file provided with open62541. |
| 12 | * |
| 13 | * open62541 is distributed in the hope that it will be useful, but WITHOUT ANY |
| 14 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
| 15 | * A PARTICULAR PURPOSE. |
| 16 | */ |
| 17 | |
| 18 | #ifndef UA_DYNAMIC_LINKING_EXPORT |
| 19 | # define UA_DYNAMIC_LINKING_EXPORT |
| 20 | # define MDNSD_DYNAMIC_LINKING |
| 21 | #endif |
| 22 | |
| 23 | #define UA_INLINABLE_IMPL 1 |
| 24 | |
| 25 | /* Disable security warnings for BSD sockets on MSVC */ |
| 26 | #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) |
| 27 | # define _CRT_SECURE_NO_WARNINGS |
| 28 | #endif |
| 29 | |
| 30 | #include "open62541.h" |
| 31 | |
| 32 | /**** amalgamated original file "/arch/win32/ua_architecture.h" ****/ |
| 33 | |
| 34 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 35 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 36 | * |
| 37 | * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB |
| 38 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 39 | * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 40 | */ |
| 41 | |
| 42 | #ifdef UA_ARCHITECTURE_WIN32 |
| 43 | |
| 44 | #ifndef PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_ |
| 45 | #define PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_ |
| 46 | |
| 47 | /* Disable some security warnings on MSVC */ |
| 48 | #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) |
| 49 | # define _CRT_SECURE_NO_WARNINGS |
| 50 | #endif |
| 51 | |
| 52 | |
| 53 | #include <stdlib.h> |
| 54 | #include <stdio.h> |
| 55 | #include <errno.h> |
| 56 | #include <winsock2.h> |
| 57 | #include <windows.h> |
| 58 | #include <ws2tcpip.h> |
| 59 | #include <basetsd.h> |
| 60 | |
| 61 | #ifndef _SSIZE_T_DEFINED |
| 62 | typedef SSIZE_T ssize_t; |
| 63 | #endif |
| 64 | |
| 65 | #define UA_IPV6 1 |
| 66 | #define UA_SOCKET SOCKET |
| 67 | #define UA_INVALID_SOCKET INVALID_SOCKET |
| 68 | #define UA_ERRNO WSAGetLastError() |
| 69 | #define UA_INTERRUPTED WSAEINTR |
| 70 | #define UA_AGAIN EAGAIN /* the same as wouldblock on nearly every system */ |
| 71 | #define UA_INPROGRESS WSAEINPROGRESS |
| 72 | #define UA_WOULDBLOCK WSAEWOULDBLOCK |
| 73 | #define UA_POLLIN POLLRDNORM |
| 74 | #define UA_POLLOUT POLLWRNORM |
| 75 | #define UA_SHUT_RDWR SD_BOTH |
| 76 | |
| 77 | #define UA_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \ |
| 78 | getnameinfo(sa, (socklen_t)salen, host, (DWORD)hostlen, serv, (DWORD)servlen, flags) |
| 79 | #define UA_poll(fds,nfds,timeout) WSAPoll((LPWSAPOLLFD)fds, nfds, timeout) |
| 80 | #define UA_send(sockfd, buf, len, flags) send(sockfd, buf, (int)(len), flags) |
| 81 | #define UA_recv(sockfd, buf, len, flags) recv(sockfd, buf, (int)(len), flags) |
| 82 | #define UA_sendto(sockfd, buf, len, flags, dest_addr, addrlen) \ |
| 83 | sendto(sockfd, (const char*)(buf), (int)(len), flags, dest_addr, (int) (addrlen)) |
| 84 | #define UA_close closesocket |
| 85 | #define UA_select(nfds, readfds, writefds, exceptfds, timeout) \ |
| 86 | select((int)(nfds), readfds, writefds, exceptfds, timeout) |
| 87 | #define UA_connect(sockfd, addr, addrlen) connect(sockfd, addr, (int)(addrlen)) |
| 88 | #define UA_getsockopt(sockfd, level, optname, optval, optlen) \ |
| 89 | getsockopt(sockfd, level, optname, (char*) (optval), optlen) |
| 90 | #define UA_setsockopt(sockfd, level, optname, optval, optlen) \ |
| 91 | setsockopt(sockfd, level, optname, (const char*) (optval), optlen) |
| 92 | #define UA_inet_pton InetPton |
| 93 | |
| 94 | #if UA_IPV6 |
| 95 | # define UA_if_nametoindex if_nametoindex |
| 96 | |
| 97 | # include <iphlpapi.h> |
| 98 | |
| 99 | #endif |
| 100 | |
| 101 | #ifdef maxStringLength //defined in mingw64 |
| 102 | # undef maxStringLength |
| 103 | #endif |
| 104 | |
| 105 | #define UA_LOG_SOCKET_ERRNO_WRAP(LOG) { \ |
| 106 | char *errno_str = NULL; \ |
| 107 | FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \ |
| 108 | NULL, WSAGetLastError(), \ |
| 109 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), \ |
| 110 | (LPSTR)&errno_str, 0, NULL); \ |
| 111 | LOG; \ |
| 112 | LocalFree(errno_str); \ |
| 113 | } |
| 114 | #define UA_LOG_SOCKET_ERRNO_GAI_WRAP UA_LOG_SOCKET_ERRNO_WRAP |
| 115 | |
| 116 | /* Fix redefinition of SLIST_ENTRY on mingw winnt.h */ |
| 117 | #if !defined(_SYS_QUEUE_H_) && defined(SLIST_ENTRY) |
| 118 | # undef SLIST_ENTRY |
| 119 | #endif |
| 120 | |
| 121 | #endif /* PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_ */ |
| 122 | |
| 123 | #endif /* UA_ARCHITECTURE_WIN32 */ |
| 124 | |
| 125 | /**** amalgamated original file "/arch/posix/ua_architecture.h" ****/ |
| 126 | |
| 127 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 128 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 129 | * |
| 130 | * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB |
| 131 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 132 | */ |
| 133 | |
| 134 | #ifdef UA_ARCHITECTURE_POSIX |
| 135 | |
| 136 | |
| 137 | |
| 138 | #include <errno.h> |
| 139 | #include <arpa/inet.h> |
| 140 | #include <netinet/in.h> |
| 141 | #include <netinet/tcp.h> |
| 142 | #include <netdb.h> |
| 143 | #include <sys/ioctl.h> |
| 144 | #include <sys/select.h> |
| 145 | #include <net/if.h> |
| 146 | #include <poll.h> |
| 147 | #include <fcntl.h> |
| 148 | #include <unistd.h> |
| 149 | #include <ifaddrs.h> |
| 150 | |
| 151 | #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) |
| 152 | # include <sys/param.h> |
| 153 | # if defined(BSD) |
| 154 | # include <sys/socket.h> |
| 155 | # endif |
| 156 | #endif |
| 157 | |
| 158 | #define UA_IPV6 1 |
| 159 | #define UA_SOCKET int |
| 160 | #define UA_INVALID_SOCKET -1 |
| 161 | #define UA_ERRNO errno |
| 162 | #define UA_INTERRUPTED EINTR |
| 163 | #define UA_AGAIN EAGAIN /* the same as wouldblock on nearly every system */ |
| 164 | #define UA_INPROGRESS EINPROGRESS |
| 165 | #define UA_WOULDBLOCK EWOULDBLOCK |
| 166 | #define UA_POLLIN POLLIN |
| 167 | #define UA_POLLOUT POLLOUT |
| 168 | #define UA_SHUT_RDWR SHUT_RDWR |
| 169 | |
| 170 | #define UA_getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) \ |
| 171 | getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) |
| 172 | #define UA_poll poll |
| 173 | #define UA_send send |
| 174 | #define UA_recv recv |
| 175 | #define UA_sendto sendto |
| 176 | #define UA_close close |
| 177 | #define UA_select select |
| 178 | #define UA_connect connect |
| 179 | #define UA_getsockopt getsockopt |
| 180 | #define UA_setsockopt setsockopt |
| 181 | #define UA_inet_pton inet_pton |
| 182 | #define UA_if_nametoindex if_nametoindex |
| 183 | |
| 184 | #define UA_clean_errno(STR_FUN) (errno == 0 ? (char*) "None" : (STR_FUN)(errno)) |
| 185 | |
| 186 | #define UA_LOG_SOCKET_ERRNO_WRAP(LOG) { \ |
| 187 | char *errno_str = UA_clean_errno(strerror); \ |
| 188 | LOG; \ |
| 189 | errno = 0; \ |
| 190 | } |
| 191 | #define UA_LOG_SOCKET_ERRNO_GAI_WRAP(LOG) { \ |
| 192 | const char *errno_str = UA_clean_errno(gai_strerror); \ |
| 193 | LOG; \ |
| 194 | errno = 0; \ |
| 195 | } |
| 196 | |
| 197 | #if defined(__APPLE__) && defined(_SYS_QUEUE_H_) |
| 198 | // in some compilers there's already a _SYS_QUEUE_H_ which is included first and doesn't |
| 199 | // have all functions |
| 200 | |
| 201 | #undef SLIST_HEAD |
| 202 | #undef SLIST_HEAD_INITIALIZER |
| 203 | #undef SLIST_ENTRY |
| 204 | #undef SLIST_FIRST |
| 205 | #undef SLIST_END |
| 206 | #undef SLIST_EMPTY |
| 207 | #undef SLIST_NEXT |
| 208 | #undef SLIST_FOREACH |
| 209 | #undef SLIST_FOREACH_SAFE |
| 210 | #undef SLIST_INIT |
| 211 | #undef SLIST_INSERT_AFTER |
| 212 | #undef SLIST_INSERT_HEAD |
| 213 | #undef SLIST_REMOVE_AFTER |
| 214 | #undef SLIST_REMOVE_HEAD |
| 215 | #undef SLIST_REMOVE |
| 216 | #undef LIST_HEAD |
| 217 | #undef LIST_HEAD_INITIALIZER |
| 218 | #undef LIST_ENTRY |
| 219 | #undef LIST_FIRST |
| 220 | #undef LIST_END |
| 221 | #undef LIST_EMPTY |
| 222 | #undef LIST_NEXT |
| 223 | #undef LIST_FOREACH |
| 224 | #undef LIST_FOREACH_SAFE |
| 225 | #undef LIST_INIT |
| 226 | #undef LIST_INSERT_AFTER |
| 227 | #undef LIST_INSERT_BEFORE |
| 228 | #undef LIST_INSERT_HEAD |
| 229 | #undef LIST_REMOVE |
| 230 | #undef LIST_REPLACE |
| 231 | #undef SIMPLEQ_HEAD |
| 232 | #undef SIMPLEQ_HEAD_INITIALIZER |
| 233 | #undef SIMPLEQ_ENTRY |
| 234 | #undef SIMPLEQ_FIRST |
| 235 | #undef SIMPLEQ_END |
| 236 | #undef SIMPLEQ_EMPTY |
| 237 | #undef SIMPLEQ_NEXT |
| 238 | #undef SIMPLEQ_FOREACH |
| 239 | #undef SIMPLEQ_FOREACH_SAFE |
| 240 | #undef SIMPLEQ_INIT |
| 241 | #undef SIMPLEQ_INSERT_HEAD |
| 242 | #undef SIMPLEQ_INSERT_TAIL |
| 243 | #undef SIMPLEQ_INSERT_AFTER |
| 244 | #undef SIMPLEQ_REMOVE_HEAD |
| 245 | #undef SIMPLEQ_REMOVE_AFTER |
| 246 | #undef XSIMPLEQ_HEAD |
| 247 | #undef XSIMPLEQ_ENTRY |
| 248 | #undef XSIMPLEQ_XOR |
| 249 | #undef XSIMPLEQ_FIRST |
| 250 | #undef XSIMPLEQ_END |
| 251 | #undef XSIMPLEQ_EMPTY |
| 252 | #undef XSIMPLEQ_NEXT |
| 253 | #undef XSIMPLEQ_FOREACH |
| 254 | #undef XSIMPLEQ_FOREACH_SAFE |
| 255 | #undef XSIMPLEQ_INIT |
| 256 | #undef XSIMPLEQ_INSERT_HEAD |
| 257 | #undef XSIMPLEQ_INSERT_TAIL |
| 258 | #undef XSIMPLEQ_INSERT_AFTER |
| 259 | #undef XSIMPLEQ_REMOVE_HEAD |
| 260 | #undef XSIMPLEQ_REMOVE_AFTER |
| 261 | #undef TAILQ_HEAD |
| 262 | #undef TAILQ_HEAD_INITIALIZER |
| 263 | #undef TAILQ_ENTRY |
| 264 | #undef TAILQ_FIRST |
| 265 | #undef TAILQ_END |
| 266 | #undef TAILQ_NEXT |
| 267 | #undef TAILQ_LAST |
| 268 | #undef TAILQ_PREV |
| 269 | #undef TAILQ_EMPTY |
| 270 | #undef TAILQ_FOREACH |
| 271 | #undef TAILQ_FOREACH_SAFE |
| 272 | #undef TAILQ_FOREACH_REVERSE |
| 273 | #undef TAILQ_FOREACH_REVERSE_SAFE |
| 274 | #undef TAILQ_INIT |
| 275 | #undef TAILQ_INSERT_HEAD |
| 276 | #undef TAILQ_INSERT_TAIL |
| 277 | #undef TAILQ_INSERT_AFTER |
| 278 | #undef TAILQ_INSERT_BEFORE |
| 279 | #undef TAILQ_REMOVE |
| 280 | #undef TAILQ_REPLACE |
| 281 | #undef CIRCLEQ_HEAD |
| 282 | #undef CIRCLEQ_HEAD_INITIALIZER |
| 283 | #undef CIRCLEQ_ENTRY |
| 284 | #undef CIRCLEQ_FIRST |
| 285 | #undef CIRCLEQ_LAST |
| 286 | #undef CIRCLEQ_END |
| 287 | #undef CIRCLEQ_NEXT |
| 288 | #undef CIRCLEQ_PREV |
| 289 | #undef CIRCLEQ_EMPTY |
| 290 | #undef CIRCLEQ_FOREACH |
| 291 | #undef CIRCLEQ_FOREACH_SAFE |
| 292 | #undef CIRCLEQ_FOREACH_REVERSE |
| 293 | #undef CIRCLEQ_FOREACH_REVERSE_SAFE |
| 294 | #undef CIRCLEQ_INIT |
| 295 | #undef CIRCLEQ_INSERT_AFTER |
| 296 | #undef CIRCLEQ_INSERT_BEFORE |
| 297 | #undef CIRCLEQ_INSERT_HEAD |
| 298 | #undef CIRCLEQ_INSERT_TAIL |
| 299 | #undef CIRCLEQ_REMOVE |
| 300 | #undef CIRCLEQ_REPLACE |
| 301 | |
| 302 | #undef _SYS_QUEUE_H_ |
| 303 | |
| 304 | #endif /* defined(__APPLE__) && defined(_SYS_QUEUE_H_) */ |
| 305 | |
| 306 | |
| 307 | #endif /* UA_ARCHITECTURE_POSIX */ |
| 308 | |
| 309 | /**** amalgamated original file "/deps/open62541_queue.h" ****/ |
| 310 | |
| 311 | /* $OpenBSD: queue.h,v 1.38 2013/07/03 15:05:21 fgsch Exp $ */ |
| 312 | /* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */ |
| 313 | |
| 314 | /* |
| 315 | * Copyright (c) 1991, 1993 |
| 316 | * The Regents of the University of California. All rights reserved. |
| 317 | * |
| 318 | * Redistribution and use in source and binary forms, with or without |
| 319 | * modification, are permitted provided that the following conditions |
| 320 | * are met: |
| 321 | * 1. Redistributions of source code must retain the above copyright |
| 322 | * notice, this list of conditions and the following disclaimer. |
| 323 | * 2. Redistributions in binary form must reproduce the above copyright |
| 324 | * notice, this list of conditions and the following disclaimer in the |
| 325 | * documentation and/or other materials provided with the distribution. |
| 326 | * 3. Neither the name of the University nor the names of its contributors |
| 327 | * may be used to endorse or promote products derived from this software |
| 328 | * without specific prior written permission. |
| 329 | * |
| 330 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
| 331 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 332 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 333 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
| 334 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 335 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 336 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 337 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 338 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 339 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 340 | * SUCH DAMAGE. |
| 341 | * |
| 342 | * @(#)queue.h 8.5 (Berkeley) 8/20/94 |
| 343 | */ |
| 344 | |
| 345 | |
| 346 | /* |
| 347 | * This file defines five types of data structures: singly-linked lists, |
| 348 | * lists, simple queues, tail queues, and circular queues. |
| 349 | * |
| 350 | * |
| 351 | * A singly-linked list is headed by a single forward pointer. The elements |
| 352 | * are singly linked for minimum space and pointer manipulation overhead at |
| 353 | * the expense of O(n) removal for arbitrary elements. New elements can be |
| 354 | * added to the list after an existing element or at the head of the list. |
| 355 | * Elements being removed from the head of the list should use the explicit |
| 356 | * macro for this purpose for optimum efficiency. A singly-linked list may |
| 357 | * only be traversed in the forward direction. Singly-linked lists are ideal |
| 358 | * for applications with large datasets and few or no removals or for |
| 359 | * implementing a LIFO queue. |
| 360 | * |
| 361 | * A list is headed by a single forward pointer (or an array of forward |
| 362 | * pointers for a hash table header). The elements are doubly linked |
| 363 | * so that an arbitrary element can be removed without a need to |
| 364 | * traverse the list. New elements can be added to the list before |
| 365 | * or after an existing element or at the head of the list. A list |
| 366 | * may only be traversed in the forward direction. |
| 367 | * |
| 368 | * A simple queue is headed by a pair of pointers, one the head of the |
| 369 | * list and the other to the tail of the list. The elements are singly |
| 370 | * linked to save space, so elements can only be removed from the |
| 371 | * head of the list. New elements can be added to the list before or after |
| 372 | * an existing element, at the head of the list, or at the end of the |
| 373 | * list. A simple queue may only be traversed in the forward direction. |
| 374 | * |
| 375 | * A tail queue is headed by a pair of pointers, one to the head of the |
| 376 | * list and the other to the tail of the list. The elements are doubly |
| 377 | * linked so that an arbitrary element can be removed without a need to |
| 378 | * traverse the list. New elements can be added to the list before or |
| 379 | * after an existing element, at the head of the list, or at the end of |
| 380 | * the list. A tail queue may be traversed in either direction. |
| 381 | * |
| 382 | * A circle queue is headed by a pair of pointers, one to the head of the |
| 383 | * list and the other to the tail of the list. The elements are doubly |
| 384 | * linked so that an arbitrary element can be removed without a need to |
| 385 | * traverse the list. New elements can be added to the list before or after |
| 386 | * an existing element, at the head of the list, or at the end of the list. |
| 387 | * A circle queue may be traversed in either direction, but has a more |
| 388 | * complex end of list detection. |
| 389 | * |
| 390 | * For details on the use of these macros, see the queue(3) manual page. |
| 391 | */ |
| 392 | |
| 393 | #if defined(QUEUE_MACRO_DEBUG) || (defined(_KERNEL) && defined(DIAGNOSTIC)) |
| 394 | #define _Q_INVALIDATE(a) (a) = ((void *)-1) |
| 395 | #else |
| 396 | #define _Q_INVALIDATE(a) |
| 397 | #endif |
| 398 | |
| 399 | /* |
| 400 | * Singly-linked List definitions. |
| 401 | */ |
| 402 | #define SLIST_HEAD(name, type) \ |
| 403 | struct name { \ |
| 404 | struct type *slh_first; /* first element */ \ |
| 405 | } |
| 406 | |
| 407 | #define SLIST_HEAD_INITIALIZER(head) \ |
| 408 | { NULL } |
| 409 | |
| 410 | #define SLIST_ENTRY(type) \ |
| 411 | struct { \ |
| 412 | struct type *sle_next; /* next element */ \ |
| 413 | } |
| 414 | |
| 415 | /* |
| 416 | * Singly-linked List access methods. |
| 417 | */ |
| 418 | #define SLIST_FIRST(head) ((head)->slh_first) |
| 419 | #define SLIST_END(head) NULL |
| 420 | #define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head)) |
| 421 | #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) |
| 422 | |
| 423 | #define SLIST_FOREACH(var, head, field) \ |
| 424 | for((var) = SLIST_FIRST(head); \ |
| 425 | (var) != SLIST_END(head); \ |
| 426 | (var) = SLIST_NEXT(var, field)) |
| 427 | |
| 428 | #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ |
| 429 | for ((var) = SLIST_FIRST(head); \ |
| 430 | (var) && ((tvar) = SLIST_NEXT(var, field), 1); \ |
| 431 | (var) = (tvar)) |
| 432 | |
| 433 | /* |
| 434 | * Singly-linked List functions. |
| 435 | */ |
| 436 | #define SLIST_INIT(head) do { \ |
| 437 | SLIST_FIRST(head) = SLIST_END(head); \ |
| 438 | } while(0) |
| 439 | |
| 440 | #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ |
| 441 | (elm)->field.sle_next = (slistelm)->field.sle_next; \ |
| 442 | (slistelm)->field.sle_next = (elm); \ |
| 443 | } while (0) |
| 444 | |
| 445 | #define SLIST_INSERT_HEAD(head, elm, field) do { \ |
| 446 | (elm)->field.sle_next = (head)->slh_first; \ |
| 447 | (head)->slh_first = (elm); \ |
| 448 | } while (0) |
| 449 | |
| 450 | #define SLIST_REMOVE_AFTER(elm, field) do { \ |
| 451 | (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \ |
| 452 | } while (0) |
| 453 | |
| 454 | #define SLIST_REMOVE_HEAD(head, field) do { \ |
| 455 | (head)->slh_first = (head)->slh_first->field.sle_next; \ |
| 456 | } while (0) |
| 457 | |
| 458 | #define SLIST_REMOVE(head, elm, type, field) do { \ |
| 459 | if ((head)->slh_first == (elm)) { \ |
| 460 | SLIST_REMOVE_HEAD((head), field); \ |
| 461 | } else { \ |
| 462 | struct type *curelm = (head)->slh_first; \ |
| 463 | \ |
| 464 | while (curelm->field.sle_next != (elm)) \ |
| 465 | curelm = curelm->field.sle_next; \ |
| 466 | curelm->field.sle_next = \ |
| 467 | curelm->field.sle_next->field.sle_next; \ |
| 468 | _Q_INVALIDATE((elm)->field.sle_next); \ |
| 469 | } \ |
| 470 | } while (0) |
| 471 | |
| 472 | /* |
| 473 | * List definitions. |
| 474 | */ |
| 475 | #define LIST_HEAD(name, type) \ |
| 476 | struct name { \ |
| 477 | struct type *lh_first; /* first element */ \ |
| 478 | } |
| 479 | |
| 480 | #define LIST_HEAD_INITIALIZER(head) \ |
| 481 | { NULL } |
| 482 | |
| 483 | #define LIST_ENTRY(type) \ |
| 484 | struct { \ |
| 485 | struct type *le_next; /* next element */ \ |
| 486 | struct type **le_prev; /* address of previous next element */ \ |
| 487 | } |
| 488 | |
| 489 | /* |
| 490 | * List access methods |
| 491 | */ |
| 492 | #define LIST_FIRST(head) ((head)->lh_first) |
| 493 | #define LIST_END(head) NULL |
| 494 | #define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head)) |
| 495 | #define LIST_NEXT(elm, field) ((elm)->field.le_next) |
| 496 | |
| 497 | #define LIST_FOREACH(var, head, field) \ |
| 498 | for((var) = LIST_FIRST(head); \ |
| 499 | (var)!= LIST_END(head); \ |
| 500 | (var) = LIST_NEXT(var, field)) |
| 501 | |
| 502 | #define LIST_FOREACH_SAFE(var, head, field, tvar) \ |
| 503 | for ((var) = LIST_FIRST(head); \ |
| 504 | (var) && ((tvar) = LIST_NEXT(var, field), 1); \ |
| 505 | (var) = (tvar)) |
| 506 | |
| 507 | /* |
| 508 | * List functions. |
| 509 | */ |
| 510 | #define LIST_INIT(head) do { \ |
| 511 | LIST_FIRST(head) = LIST_END(head); \ |
| 512 | } while (0) |
| 513 | |
| 514 | #define LIST_INSERT_AFTER(listelm, elm, field) do { \ |
| 515 | if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ |
| 516 | (listelm)->field.le_next->field.le_prev = \ |
| 517 | &(elm)->field.le_next; \ |
| 518 | (listelm)->field.le_next = (elm); \ |
| 519 | (elm)->field.le_prev = &(listelm)->field.le_next; \ |
| 520 | } while (0) |
| 521 | |
| 522 | #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ |
| 523 | (elm)->field.le_prev = (listelm)->field.le_prev; \ |
| 524 | (elm)->field.le_next = (listelm); \ |
| 525 | *(listelm)->field.le_prev = (elm); \ |
| 526 | (listelm)->field.le_prev = &(elm)->field.le_next; \ |
| 527 | } while (0) |
| 528 | |
| 529 | #define LIST_INSERT_HEAD(head, elm, field) do { \ |
| 530 | if (((elm)->field.le_next = (head)->lh_first) != NULL) \ |
| 531 | (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ |
| 532 | (head)->lh_first = (elm); \ |
| 533 | (elm)->field.le_prev = &(head)->lh_first; \ |
| 534 | } while (0) |
| 535 | |
| 536 | #define LIST_REMOVE(elm, field) do { \ |
| 537 | if ((elm)->field.le_next != NULL) \ |
| 538 | (elm)->field.le_next->field.le_prev = \ |
| 539 | (elm)->field.le_prev; \ |
| 540 | *(elm)->field.le_prev = (elm)->field.le_next; \ |
| 541 | _Q_INVALIDATE((elm)->field.le_prev); \ |
| 542 | _Q_INVALIDATE((elm)->field.le_next); \ |
| 543 | } while (0) |
| 544 | |
| 545 | #define LIST_REPLACE(elm, elm2, field) do { \ |
| 546 | if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ |
| 547 | (elm2)->field.le_next->field.le_prev = \ |
| 548 | &(elm2)->field.le_next; \ |
| 549 | (elm2)->field.le_prev = (elm)->field.le_prev; \ |
| 550 | *(elm2)->field.le_prev = (elm2); \ |
| 551 | _Q_INVALIDATE((elm)->field.le_prev); \ |
| 552 | _Q_INVALIDATE((elm)->field.le_next); \ |
| 553 | } while (0) |
| 554 | |
| 555 | /* |
| 556 | * Simple queue definitions. |
| 557 | */ |
| 558 | #define SIMPLEQ_HEAD(name, type) \ |
| 559 | struct name { \ |
| 560 | struct type *sqh_first; /* first element */ \ |
| 561 | struct type **sqh_last; /* addr of last next element */ \ |
| 562 | } |
| 563 | |
| 564 | #define SIMPLEQ_HEAD_INITIALIZER(head) \ |
| 565 | { NULL, &(head).sqh_first } |
| 566 | |
| 567 | #define SIMPLEQ_ENTRY(type) \ |
| 568 | struct { \ |
| 569 | struct type *sqe_next; /* next element */ \ |
| 570 | } |
| 571 | |
| 572 | /* |
| 573 | * Simple queue access methods. |
| 574 | */ |
| 575 | #define SIMPLEQ_FIRST(head) ((head)->sqh_first) |
| 576 | #define SIMPLEQ_END(head) NULL |
| 577 | #define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head)) |
| 578 | #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) |
| 579 | |
| 580 | #define SIMPLEQ_FOREACH(var, head, field) \ |
| 581 | for((var) = SIMPLEQ_FIRST(head); \ |
| 582 | (var) != SIMPLEQ_END(head); \ |
| 583 | (var) = SIMPLEQ_NEXT(var, field)) |
| 584 | |
| 585 | #define SIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ |
| 586 | for ((var) = SIMPLEQ_FIRST(head); \ |
| 587 | (var) && ((tvar) = SIMPLEQ_NEXT(var, field), 1); \ |
| 588 | (var) = (tvar)) |
| 589 | |
| 590 | /* |
| 591 | * Simple queue functions. |
| 592 | */ |
| 593 | #define SIMPLEQ_INIT(head) do { \ |
| 594 | (head)->sqh_first = NULL; \ |
| 595 | (head)->sqh_last = &(head)->sqh_first; \ |
| 596 | } while (0) |
| 597 | |
| 598 | #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ |
| 599 | if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ |
| 600 | (head)->sqh_last = &(elm)->field.sqe_next; \ |
| 601 | (head)->sqh_first = (elm); \ |
| 602 | } while (0) |
| 603 | |
| 604 | #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ |
| 605 | (elm)->field.sqe_next = NULL; \ |
| 606 | *(head)->sqh_last = (elm); \ |
| 607 | (head)->sqh_last = &(elm)->field.sqe_next; \ |
| 608 | } while (0) |
| 609 | |
| 610 | #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ |
| 611 | if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ |
| 612 | (head)->sqh_last = &(elm)->field.sqe_next; \ |
| 613 | (listelm)->field.sqe_next = (elm); \ |
| 614 | } while (0) |
| 615 | |
| 616 | #define SIMPLEQ_REMOVE_HEAD(head, field) do { \ |
| 617 | if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ |
| 618 | (head)->sqh_last = &(head)->sqh_first; \ |
| 619 | } while (0) |
| 620 | |
| 621 | #define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ |
| 622 | if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ |
| 623 | == NULL) \ |
| 624 | (head)->sqh_last = &(elm)->field.sqe_next; \ |
| 625 | } while (0) |
| 626 | |
| 627 | /* |
| 628 | * XOR Simple queue definitions. |
| 629 | */ |
| 630 | #define XSIMPLEQ_HEAD(name, type) \ |
| 631 | struct name { \ |
| 632 | struct type *sqx_first; /* first element */ \ |
| 633 | struct type **sqx_last; /* addr of last next element */ \ |
| 634 | unsigned long sqx_cookie; \ |
| 635 | } |
| 636 | |
| 637 | #define XSIMPLEQ_ENTRY(type) \ |
| 638 | struct { \ |
| 639 | struct type *sqx_next; /* next element */ \ |
| 640 | } |
| 641 | |
| 642 | /* |
| 643 | * XOR Simple queue access methods. |
| 644 | */ |
| 645 | #define XSIMPLEQ_XOR(head, ptr) ((__typeof(ptr))((head)->sqx_cookie ^ \ |
| 646 | (unsigned long)(ptr))) |
| 647 | #define XSIMPLEQ_FIRST(head) XSIMPLEQ_XOR(head, ((head)->sqx_first)) |
| 648 | #define XSIMPLEQ_END(head) NULL |
| 649 | #define XSIMPLEQ_EMPTY(head) (XSIMPLEQ_FIRST(head) == XSIMPLEQ_END(head)) |
| 650 | #define XSIMPLEQ_NEXT(head, elm, field) XSIMPLEQ_XOR(head, ((elm)->field.sqx_next)) |
| 651 | |
| 652 | |
| 653 | #define XSIMPLEQ_FOREACH(var, head, field) \ |
| 654 | for ((var) = XSIMPLEQ_FIRST(head); \ |
| 655 | (var) != XSIMPLEQ_END(head); \ |
| 656 | (var) = XSIMPLEQ_NEXT(head, var, field)) |
| 657 | |
| 658 | #define XSIMPLEQ_FOREACH_SAFE(var, head, field, tvar) \ |
| 659 | for ((var) = XSIMPLEQ_FIRST(head); \ |
| 660 | (var) && ((tvar) = XSIMPLEQ_NEXT(head, var, field), 1); \ |
| 661 | (var) = (tvar)) |
| 662 | |
| 663 | /* |
| 664 | * XOR Simple queue functions. |
| 665 | */ |
| 666 | #define XSIMPLEQ_INIT(head) do { \ |
| 667 | arc4random_buf(&(head)->sqx_cookie, sizeof((head)->sqx_cookie)); \ |
| 668 | (head)->sqx_first = XSIMPLEQ_XOR(head, NULL); \ |
| 669 | (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ |
| 670 | } while (0) |
| 671 | |
| 672 | #define XSIMPLEQ_INSERT_HEAD(head, elm, field) do { \ |
| 673 | if (((elm)->field.sqx_next = (head)->sqx_first) == \ |
| 674 | XSIMPLEQ_XOR(head, NULL)) \ |
| 675 | (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ |
| 676 | (head)->sqx_first = XSIMPLEQ_XOR(head, (elm)); \ |
| 677 | } while (0) |
| 678 | |
| 679 | #define XSIMPLEQ_INSERT_TAIL(head, elm, field) do { \ |
| 680 | (elm)->field.sqx_next = XSIMPLEQ_XOR(head, NULL); \ |
| 681 | *(XSIMPLEQ_XOR(head, (head)->sqx_last)) = XSIMPLEQ_XOR(head, (elm)); \ |
| 682 | (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ |
| 683 | } while (0) |
| 684 | |
| 685 | #define XSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ |
| 686 | if (((elm)->field.sqx_next = (listelm)->field.sqx_next) == \ |
| 687 | XSIMPLEQ_XOR(head, NULL)) \ |
| 688 | (head)->sqx_last = XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ |
| 689 | (listelm)->field.sqx_next = XSIMPLEQ_XOR(head, (elm)); \ |
| 690 | } while (0) |
| 691 | |
| 692 | #define XSIMPLEQ_REMOVE_HEAD(head, field) do { \ |
| 693 | if (((head)->sqx_first = XSIMPLEQ_XOR(head, \ |
| 694 | (head)->sqx_first)->field.sqx_next) == XSIMPLEQ_XOR(head, NULL)) \ |
| 695 | (head)->sqx_last = XSIMPLEQ_XOR(head, &(head)->sqx_first); \ |
| 696 | } while (0) |
| 697 | |
| 698 | #define XSIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ |
| 699 | if (((elm)->field.sqx_next = XSIMPLEQ_XOR(head, \ |
| 700 | (elm)->field.sqx_next)->field.sqx_next) \ |
| 701 | == XSIMPLEQ_XOR(head, NULL)) \ |
| 702 | (head)->sqx_last = \ |
| 703 | XSIMPLEQ_XOR(head, &(elm)->field.sqx_next); \ |
| 704 | } while (0) |
| 705 | |
| 706 | |
| 707 | /* |
| 708 | * Tail queue definitions. |
| 709 | */ |
| 710 | #define TAILQ_HEAD(name, type) \ |
| 711 | struct name { \ |
| 712 | struct type *tqh_first; /* first element */ \ |
| 713 | struct type **tqh_last; /* addr of last next element */ \ |
| 714 | } |
| 715 | |
| 716 | #define TAILQ_HEAD_INITIALIZER(head) \ |
| 717 | { NULL, &(head).tqh_first } |
| 718 | |
| 719 | #define TAILQ_ENTRY(type) \ |
| 720 | struct { \ |
| 721 | struct type *tqe_next; /* next element */ \ |
| 722 | struct type **tqe_prev; /* address of previous next element */ \ |
| 723 | } |
| 724 | |
| 725 | /* |
| 726 | * tail queue access methods |
| 727 | */ |
| 728 | #define TAILQ_FIRST(head) ((head)->tqh_first) |
| 729 | #define TAILQ_END(head) NULL |
| 730 | #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) |
| 731 | #define TAILQ_LAST(head, headname) \ |
| 732 | (*(((struct headname *)((head)->tqh_last))->tqh_last)) |
| 733 | /* XXX */ |
| 734 | #define TAILQ_PREV(elm, headname, field) \ |
| 735 | (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) |
| 736 | #define TAILQ_EMPTY(head) \ |
| 737 | (TAILQ_FIRST(head) == TAILQ_END(head)) |
| 738 | |
| 739 | #define TAILQ_FOREACH(var, head, field) \ |
| 740 | for((var) = TAILQ_FIRST(head); \ |
| 741 | (var) != TAILQ_END(head); \ |
| 742 | (var) = TAILQ_NEXT(var, field)) |
| 743 | |
| 744 | #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ |
| 745 | for ((var) = TAILQ_FIRST(head); \ |
| 746 | (var) != TAILQ_END(head) && \ |
| 747 | ((tvar) = TAILQ_NEXT(var, field), 1); \ |
| 748 | (var) = (tvar)) |
| 749 | |
| 750 | |
| 751 | #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ |
| 752 | for((var) = TAILQ_LAST(head, headname); \ |
| 753 | (var) != TAILQ_END(head); \ |
| 754 | (var) = TAILQ_PREV(var, headname, field)) |
| 755 | |
| 756 | #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ |
| 757 | for ((var) = TAILQ_LAST(head, headname); \ |
| 758 | (var) != TAILQ_END(head) && \ |
| 759 | ((tvar) = TAILQ_PREV(var, headname, field), 1); \ |
| 760 | (var) = (tvar)) |
| 761 | |
| 762 | /* |
| 763 | * Tail queue functions. |
| 764 | */ |
| 765 | #define TAILQ_INIT(head) do { \ |
| 766 | (head)->tqh_first = NULL; \ |
| 767 | (head)->tqh_last = &(head)->tqh_first; \ |
| 768 | } while (0) |
| 769 | |
| 770 | #define TAILQ_INSERT_HEAD(head, elm, field) do { \ |
| 771 | if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ |
| 772 | (head)->tqh_first->field.tqe_prev = \ |
| 773 | &(elm)->field.tqe_next; \ |
| 774 | else \ |
| 775 | (head)->tqh_last = &(elm)->field.tqe_next; \ |
| 776 | (head)->tqh_first = (elm); \ |
| 777 | (elm)->field.tqe_prev = &(head)->tqh_first; \ |
| 778 | } while (0) |
| 779 | |
| 780 | #define TAILQ_INSERT_TAIL(head, elm, field) do { \ |
| 781 | (elm)->field.tqe_next = NULL; \ |
| 782 | (elm)->field.tqe_prev = (head)->tqh_last; \ |
| 783 | *(head)->tqh_last = (elm); \ |
| 784 | (head)->tqh_last = &(elm)->field.tqe_next; \ |
| 785 | } while (0) |
| 786 | |
| 787 | #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ |
| 788 | if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ |
| 789 | (elm)->field.tqe_next->field.tqe_prev = \ |
| 790 | &(elm)->field.tqe_next; \ |
| 791 | else \ |
| 792 | (head)->tqh_last = &(elm)->field.tqe_next; \ |
| 793 | (listelm)->field.tqe_next = (elm); \ |
| 794 | (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ |
| 795 | } while (0) |
| 796 | |
| 797 | #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ |
| 798 | (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ |
| 799 | (elm)->field.tqe_next = (listelm); \ |
| 800 | *(listelm)->field.tqe_prev = (elm); \ |
| 801 | (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ |
| 802 | } while (0) |
| 803 | |
| 804 | #define TAILQ_REMOVE(head, elm, field) do { \ |
| 805 | if (((elm)->field.tqe_next) != NULL) \ |
| 806 | (elm)->field.tqe_next->field.tqe_prev = \ |
| 807 | (elm)->field.tqe_prev; \ |
| 808 | else \ |
| 809 | (head)->tqh_last = (elm)->field.tqe_prev; \ |
| 810 | *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ |
| 811 | _Q_INVALIDATE((elm)->field.tqe_prev); \ |
| 812 | _Q_INVALIDATE((elm)->field.tqe_next); \ |
| 813 | } while (0) |
| 814 | |
| 815 | #define TAILQ_REPLACE(head, elm, elm2, field) do { \ |
| 816 | if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \ |
| 817 | (elm2)->field.tqe_next->field.tqe_prev = \ |
| 818 | &(elm2)->field.tqe_next; \ |
| 819 | else \ |
| 820 | (head)->tqh_last = &(elm2)->field.tqe_next; \ |
| 821 | (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ |
| 822 | *(elm2)->field.tqe_prev = (elm2); \ |
| 823 | _Q_INVALIDATE((elm)->field.tqe_prev); \ |
| 824 | _Q_INVALIDATE((elm)->field.tqe_next); \ |
| 825 | } while (0) |
| 826 | |
| 827 | /* |
| 828 | * Circular queue definitions. |
| 829 | */ |
| 830 | #define CIRCLEQ_HEAD(name, type) \ |
| 831 | struct name { \ |
| 832 | struct type *cqh_first; /* first element */ \ |
| 833 | struct type *cqh_last; /* last element */ \ |
| 834 | } |
| 835 | |
| 836 | #define CIRCLEQ_HEAD_INITIALIZER(head) \ |
| 837 | { CIRCLEQ_END(&head), CIRCLEQ_END(&head) } |
| 838 | |
| 839 | #define CIRCLEQ_ENTRY(type) \ |
| 840 | struct { \ |
| 841 | struct type *cqe_next; /* next element */ \ |
| 842 | struct type *cqe_prev; /* previous element */ \ |
| 843 | } |
| 844 | |
| 845 | /* |
| 846 | * Circular queue access methods |
| 847 | */ |
| 848 | #define CIRCLEQ_FIRST(head) ((head)->cqh_first) |
| 849 | #define CIRCLEQ_LAST(head) ((head)->cqh_last) |
| 850 | #define CIRCLEQ_END(head) ((void *)(head)) |
| 851 | #define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) |
| 852 | #define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) |
| 853 | #define CIRCLEQ_EMPTY(head) \ |
| 854 | (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head)) |
| 855 | |
| 856 | #define CIRCLEQ_FOREACH(var, head, field) \ |
| 857 | for((var) = CIRCLEQ_FIRST(head); \ |
| 858 | (var) != CIRCLEQ_END(head); \ |
| 859 | (var) = CIRCLEQ_NEXT(var, field)) |
| 860 | |
| 861 | #define CIRCLEQ_FOREACH_SAFE(var, head, field, tvar) \ |
| 862 | for ((var) = CIRCLEQ_FIRST(head); \ |
| 863 | (var) != CIRCLEQ_END(head) && \ |
| 864 | ((tvar) = CIRCLEQ_NEXT(var, field), 1); \ |
| 865 | (var) = (tvar)) |
| 866 | |
| 867 | #define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ |
| 868 | for((var) = CIRCLEQ_LAST(head); \ |
| 869 | (var) != CIRCLEQ_END(head); \ |
| 870 | (var) = CIRCLEQ_PREV(var, field)) |
| 871 | |
| 872 | #define CIRCLEQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ |
| 873 | for ((var) = CIRCLEQ_LAST(head, headname); \ |
| 874 | (var) != CIRCLEQ_END(head) && \ |
| 875 | ((tvar) = CIRCLEQ_PREV(var, headname, field), 1); \ |
| 876 | (var) = (tvar)) |
| 877 | |
| 878 | /* |
| 879 | * Circular queue functions. |
| 880 | */ |
| 881 | #define CIRCLEQ_INIT(head) do { \ |
| 882 | (head)->cqh_first = CIRCLEQ_END(head); \ |
| 883 | (head)->cqh_last = CIRCLEQ_END(head); \ |
| 884 | } while (0) |
| 885 | |
| 886 | #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ |
| 887 | (elm)->field.cqe_next = (listelm)->field.cqe_next; \ |
| 888 | (elm)->field.cqe_prev = (listelm); \ |
| 889 | if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \ |
| 890 | (head)->cqh_last = (elm); \ |
| 891 | else \ |
| 892 | (listelm)->field.cqe_next->field.cqe_prev = (elm); \ |
| 893 | (listelm)->field.cqe_next = (elm); \ |
| 894 | } while (0) |
| 895 | |
| 896 | #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ |
| 897 | (elm)->field.cqe_next = (listelm); \ |
| 898 | (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ |
| 899 | if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \ |
| 900 | (head)->cqh_first = (elm); \ |
| 901 | else \ |
| 902 | (listelm)->field.cqe_prev->field.cqe_next = (elm); \ |
| 903 | (listelm)->field.cqe_prev = (elm); \ |
| 904 | } while (0) |
| 905 | |
| 906 | #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ |
| 907 | (elm)->field.cqe_next = (head)->cqh_first; \ |
| 908 | (elm)->field.cqe_prev = CIRCLEQ_END(head); \ |
| 909 | if ((head)->cqh_last == CIRCLEQ_END(head)) \ |
| 910 | (head)->cqh_last = (elm); \ |
| 911 | else \ |
| 912 | (head)->cqh_first->field.cqe_prev = (elm); \ |
| 913 | (head)->cqh_first = (elm); \ |
| 914 | } while (0) |
| 915 | |
| 916 | #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ |
| 917 | (elm)->field.cqe_next = CIRCLEQ_END(head); \ |
| 918 | (elm)->field.cqe_prev = (head)->cqh_last; \ |
| 919 | if ((head)->cqh_first == CIRCLEQ_END(head)) \ |
| 920 | (head)->cqh_first = (elm); \ |
| 921 | else \ |
| 922 | (head)->cqh_last->field.cqe_next = (elm); \ |
| 923 | (head)->cqh_last = (elm); \ |
| 924 | } while (0) |
| 925 | |
| 926 | #define CIRCLEQ_REMOVE(head, elm, field) do { \ |
| 927 | if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \ |
| 928 | (head)->cqh_last = (elm)->field.cqe_prev; \ |
| 929 | else \ |
| 930 | (elm)->field.cqe_next->field.cqe_prev = \ |
| 931 | (elm)->field.cqe_prev; \ |
| 932 | if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \ |
| 933 | (head)->cqh_first = (elm)->field.cqe_next; \ |
| 934 | else \ |
| 935 | (elm)->field.cqe_prev->field.cqe_next = \ |
| 936 | (elm)->field.cqe_next; \ |
| 937 | _Q_INVALIDATE((elm)->field.cqe_prev); \ |
| 938 | _Q_INVALIDATE((elm)->field.cqe_next); \ |
| 939 | } while (0) |
| 940 | |
| 941 | #define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \ |
| 942 | if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \ |
| 943 | CIRCLEQ_END(head)) \ |
| 944 | (head)->cqh_last = (elm2); \ |
| 945 | else \ |
| 946 | (elm2)->field.cqe_next->field.cqe_prev = (elm2); \ |
| 947 | if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \ |
| 948 | CIRCLEQ_END(head)) \ |
| 949 | (head)->cqh_first = (elm2); \ |
| 950 | else \ |
| 951 | (elm2)->field.cqe_prev->field.cqe_next = (elm2); \ |
| 952 | _Q_INVALIDATE((elm)->field.cqe_prev); \ |
| 953 | _Q_INVALIDATE((elm)->field.cqe_next); \ |
| 954 | } while (0) |
| 955 | |
| 956 | |
| 957 | /**** amalgamated original file "/deps/pcg_basic.h" ****/ |
| 958 | |
| 959 | /* |
| 960 | * PCG Random Number Generation for C. |
| 961 | * |
| 962 | * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org> |
| 963 | * |
| 964 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 965 | * you may not use this file except in compliance with the License. |
| 966 | * You may obtain a copy of the License at |
| 967 | * |
| 968 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 969 | * |
| 970 | * Unless required by applicable law or agreed to in writing, software |
| 971 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 972 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 973 | * See the License for the specific language governing permissions and |
| 974 | * limitations under the License. |
| 975 | * |
| 976 | * For additional information about the PCG random number generation scheme, |
| 977 | * including its license and other licensing options, visit |
| 978 | * |
| 979 | * http://www.pcg-random.org |
| 980 | */ |
| 981 | |
| 982 | |
| 983 | #if defined(UNDER_CE) || !defined(_MSC_VER) || _MSC_VER >= 1800 |
| 984 | # include <stdint.h> |
| 985 | #else |
| 986 | #endif |
| 987 | |
| 988 | #ifdef __cplusplus |
| 989 | extern "C"{ |
| 990 | #endif |
| 991 | |
| 992 | typedef struct pcg_state_setseq_64 { |
| 993 | uint64_t state; /* RNG state. All values are possible. */ |
| 994 | uint64_t inc; /* Controls which RNG sequence (stream) is selected. Must |
| 995 | * *always* be odd. */ |
| 996 | } pcg32_random_t; |
| 997 | |
| 998 | #define PCG32_INITIALIZER { 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL } |
| 999 | |
| 1000 | void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initial_state, uint64_t initseq); |
| 1001 | uint32_t pcg32_random_r(pcg32_random_t* rng); |
| 1002 | |
| 1003 | #ifdef __cplusplus |
| 1004 | } |
| 1005 | #endif |
| 1006 | |
| 1007 | |
| 1008 | /**** amalgamated original file "/deps/libc_time.h" ****/ |
| 1009 | |
| 1010 | |
| 1011 | struct musl_tm { |
| 1012 | int tm_sec; |
| 1013 | int tm_min; |
| 1014 | int tm_hour; |
| 1015 | int tm_mday; |
| 1016 | int tm_mon; |
| 1017 | int tm_year; |
| 1018 | int tm_wday; |
| 1019 | int tm_yday; |
| 1020 | /* int tm_isdst; */ |
| 1021 | /* long __tm_gmtoff; */ |
| 1022 | /* const char *__tm_zone; */ |
| 1023 | }; |
| 1024 | |
| 1025 | int musl_secs_to_tm(long long t, struct musl_tm *tm); |
| 1026 | long long musl_tm_to_secs(const struct musl_tm *tm); |
| 1027 | |
| 1028 | |
| 1029 | /**** amalgamated original file "/deps/base64.h" ****/ |
| 1030 | |
| 1031 | #ifndef UA_BASE64_H_ |
| 1032 | #define UA_BASE64_H_ |
| 1033 | |
| 1034 | |
| 1035 | _UA_BEGIN_DECLS |
| 1036 | |
| 1037 | #include <stddef.h> |
| 1038 | |
| 1039 | /** |
| 1040 | * base64_encode - Base64 encode |
| 1041 | * @src: Data to be encoded |
| 1042 | * @len: Length of the data to be encoded |
| 1043 | * @out_len: Pointer to output length variable |
| 1044 | * Returns: Allocated buffer of out_len bytes of encoded data, |
| 1045 | * or %NULL on failure. The output is NOT Null-terminated. */ |
| 1046 | unsigned char * |
| 1047 | UA_base64(const unsigned char *src, size_t len, size_t *out_len); |
| 1048 | |
| 1049 | /* Requires as input a buffer of length at least 4*((len + 2) / 3). |
| 1050 | * Returns the actual size */ |
| 1051 | size_t |
| 1052 | UA_base64_buf(const unsigned char *src, size_t len, unsigned char *out); |
| 1053 | |
| 1054 | /** |
| 1055 | * base64_decode - Base64 decode |
| 1056 | * @src: Data to be decoded |
| 1057 | * @len: Length of the data to be decoded |
| 1058 | * @out_len: Pointer to output length variable |
| 1059 | * Returns: Allocated buffer of out_len bytes of decoded data, |
| 1060 | * or %NULL on failure. */ |
| 1061 | unsigned char * |
| 1062 | UA_unbase64(const unsigned char *src, size_t len, size_t *out_len); |
| 1063 | |
| 1064 | _UA_END_DECLS |
| 1065 | |
| 1066 | #endif /* UA_BASE64_H_ */ |
| 1067 | |
| 1068 | /**** amalgamated original file "/deps/dtoa.h" ****/ |
| 1069 | |
| 1070 | // Copyright 2013, Andreas Samoljuk |
| 1071 | // Copyright 2023, Julius Pfrommer |
| 1072 | // |
| 1073 | // Boost Software License - Version 1.0 - August 17th, 2003 |
| 1074 | // |
| 1075 | // Permission is hereby granted, free of charge, to any person or organization |
| 1076 | // obtaining a copy of the software and accompanying documentation covered by |
| 1077 | // this license (the "Software") to use, reproduce, display, distribute, |
| 1078 | // execute, and transmit the Software, and to prepare derivative works of the |
| 1079 | // Software, and to permit third-parties to whom the Software is furnished to |
| 1080 | // do so, all subject to the following: |
| 1081 | // |
| 1082 | // The copyright notices in the Software and this entire statement, including |
| 1083 | // the above license grant, this restriction and the following disclaimer, |
| 1084 | // must be included in all copies of the Software, in whole or in part, and |
| 1085 | // all derivative works of the Software, unless such copies or derivative |
| 1086 | // works are solely in the form of machine-executable object code generated by |
| 1087 | // a source language processor. |
| 1088 | // |
| 1089 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 1090 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 1091 | // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT |
| 1092 | // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE |
| 1093 | // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, |
| 1094 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 1095 | // DEALINGS IN THE SOFTWARE. |
| 1096 | |
| 1097 | #ifndef DTOA_H |
| 1098 | #define DTOA_H |
| 1099 | |
| 1100 | #ifdef __cplusplus |
| 1101 | extern "C"{ |
| 1102 | #endif |
| 1103 | |
| 1104 | // Prints a double-value as a readable string. The buffer must be at least 24 |
| 1105 | // chars wide. Returns the number of printed characters. Does not |
| 1106 | // null-terminate. |
| 1107 | unsigned dtoa(double d, char* buffer); |
| 1108 | |
| 1109 | #ifdef __cplusplus |
| 1110 | } |
| 1111 | #endif |
| 1112 | |
| 1113 | #endif // DTOA_H |
| 1114 | |
| 1115 | /**** amalgamated original file "/deps/mp_printf.h" ****/ |
| 1116 | |
| 1117 | /** |
| 1118 | * @author (c) Eyal Rozenberg <eyalroz1@gmx.com> |
| 1119 | * 2021-2023, Haifa, Palestine/Israel |
| 1120 | * @author (c) Marco Paland (info@paland.com) |
| 1121 | * 2014-2019, PALANDesign Hannover, Germany |
| 1122 | * |
| 1123 | * @note Others have made smaller contributions to this file: see the |
| 1124 | * contributors page at https://github.com/eyalroz/printf/graphs/contributors |
| 1125 | * or ask one of the authors. |
| 1126 | * |
| 1127 | * @brief Small stand-alone implementation of the printf family of functions |
| 1128 | * (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems with |
| 1129 | * a very limited resources. |
| 1130 | * |
| 1131 | * @note the implementations are thread-safe; re-entrant; use no functions from |
| 1132 | * the standard library; and do not dynamically allocate any memory. |
| 1133 | * |
| 1134 | * @license The MIT License (MIT) |
| 1135 | * |
| 1136 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 1137 | * of this software and associated documentation files (the "Software"), to deal |
| 1138 | * in the Software without restriction, including without limitation the rights |
| 1139 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 1140 | * copies of the Software, and to permit persons to whom the Software is |
| 1141 | * furnished to do so, subject to the following conditions: |
| 1142 | * |
| 1143 | * The above copyright notice and this permission notice shall be included in |
| 1144 | * all copies or substantial portions of the Software. |
| 1145 | * |
| 1146 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 1147 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 1148 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 1149 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 1150 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 1151 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 1152 | * THE SOFTWARE. |
| 1153 | */ |
| 1154 | |
| 1155 | #ifndef MP_PRINTF_H |
| 1156 | #define MP_PRINTF_H |
| 1157 | |
| 1158 | #include <stdarg.h> |
| 1159 | #include <stddef.h> |
| 1160 | |
| 1161 | #ifdef __cplusplus |
| 1162 | extern "C"{ |
| 1163 | #endif |
| 1164 | |
| 1165 | #ifdef __GNUC__ |
| 1166 | # if ((__GNUC__ == 4 && __GNUC_MINOR__>= 4) || __GNUC__ > 4) |
| 1167 | # define ATTR_PRINTF(one_based_format_index, first_arg) \ |
| 1168 | __attribute__((format(gnu_printf, (one_based_format_index), (first_arg)))) |
| 1169 | # else |
| 1170 | # define ATTR_PRINTF(one_based_format_index, first_arg) \ |
| 1171 | __attribute__((format(printf, (one_based_format_index), (first_arg)))) |
| 1172 | # endif |
| 1173 | # define ATTR_VPRINTF(one_based_format_index) ATTR_PRINTF((one_based_format_index), 0) |
| 1174 | #else |
| 1175 | # define ATTR_PRINTF(one_based_format_index, first_arg) |
| 1176 | # define ATTR_VPRINTF(one_based_format_index) |
| 1177 | #endif |
| 1178 | |
| 1179 | /** |
| 1180 | * An implementation of the C standard's snprintf/vsnprintf |
| 1181 | * |
| 1182 | * @param s An array in which to store the formatted string. It must be large |
| 1183 | * enough to fit either the entire formatted output, or at least @p n |
| 1184 | * characters. Alternatively, it can be NULL, in which case nothing will be |
| 1185 | * printed, and only the number of characters which _could_ have been printed is |
| 1186 | * tallied and returned. |
| 1187 | * @param n The maximum number of characters to write to the array, including a |
| 1188 | * terminating null character |
| 1189 | * @param format A string specifying the format of the output, with %-marked |
| 1190 | * specifiers of how to interpret additional arguments. |
| 1191 | * @param arg Additional arguments to the function, one for each specifier in @p |
| 1192 | * format |
| 1193 | * @return The number of characters that COULD have been written into @p s, not |
| 1194 | * counting the terminating null character. A value equal or larger than @p n |
| 1195 | * indicates truncation. Only when the returned value is non-negative and less |
| 1196 | * than @p n, the null-terminated string has been fully and successfully |
| 1197 | * printed. |
| 1198 | */ |
| 1199 | int mp_snprintf(char* s, size_t count, const char* format, ...) ATTR_PRINTF(3, 4); |
| 1200 | int mp_vsnprintf(char* s, size_t count, const char* format, va_list arg) ATTR_VPRINTF(3); |
| 1201 | |
| 1202 | #ifdef __cplusplus |
| 1203 | } // extern "C" |
| 1204 | #endif |
| 1205 | |
| 1206 | #endif // MP_PRINTF_H |
| 1207 | |
| 1208 | /**** amalgamated original file "/deps/itoa.h" ****/ |
| 1209 | |
| 1210 | /* |
| 1211 | * Copyright 2017 Techie Delight |
| 1212 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 1213 | * of this software and associated documentation files (the "Software"), to deal |
| 1214 | * in the Software without restriction, including without limitation the rights |
| 1215 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 1216 | * copies of the Software, and to permit persons to whom the Software is |
| 1217 | * furnished to do so, subject to the following conditions: |
| 1218 | * |
| 1219 | * The above copyright notice and this permission notice shall be included |
| 1220 | * in all copies or substantial portions of the Software. |
| 1221 | * |
| 1222 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 1223 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 1224 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 1225 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 1226 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF |
| 1227 | * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 1228 | */ |
| 1229 | |
| 1230 | #ifndef ITOA_H |
| 1231 | #define ITOA_H |
| 1232 | |
| 1233 | #ifdef __cplusplus |
| 1234 | extern "C"{ |
| 1235 | #endif |
| 1236 | |
| 1237 | |
| 1238 | UA_UInt16 itoaUnsigned(UA_UInt64 value, char* buffer, UA_Byte base); |
| 1239 | UA_UInt16 itoaSigned(UA_Int64 value, char* buffer); |
| 1240 | |
| 1241 | #ifdef __cplusplus |
| 1242 | } |
| 1243 | #endif |
| 1244 | |
| 1245 | #endif /* ITOA_H */ |
| 1246 | |
| 1247 | |
| 1248 | /**** amalgamated original file "/deps/ziptree.h" ****/ |
| 1249 | |
| 1250 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 1251 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 1252 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 1253 | * |
| 1254 | * Copyright 2018, 2021-2022 (c) Julius Pfrommer |
| 1255 | */ |
| 1256 | |
| 1257 | |
| 1258 | #include <stddef.h> |
| 1259 | |
| 1260 | #ifdef _MSC_VER |
| 1261 | # define ZIP_INLINE __inline |
| 1262 | #else |
| 1263 | # define ZIP_INLINE inline |
| 1264 | #endif |
| 1265 | |
| 1266 | #if defined(__GNUC__) || defined(__clang__) |
| 1267 | # define ZIP_UNUSED __attribute__((unused)) |
| 1268 | #else |
| 1269 | # define ZIP_UNUSED |
| 1270 | #endif |
| 1271 | |
| 1272 | #ifdef __cplusplus |
| 1273 | extern "C"{ |
| 1274 | #endif |
| 1275 | |
| 1276 | /* Reusable zip tree implementation. The style is inspired by the BSD |
| 1277 | * sys/queue.h linked list definition. |
| 1278 | * |
| 1279 | * Zip trees were developed in: Tarjan, R. E., Levy, C. C., and Timmel, S. "Zip |
| 1280 | * Trees." arXiv preprint arXiv:1806.06726 (2018). The original definition was |
| 1281 | * modified in two ways: |
| 1282 | * |
| 1283 | * - Multiple elements with the same key can be inserted. These appear adjacent |
| 1284 | * in the tree. ZIP_FIND will return the topmost of these elements. |
| 1285 | * - The pointer-value of the elements are used as the rank. This simplifies the |
| 1286 | * code and is (empirically) faster. |
| 1287 | * |
| 1288 | * The ZIP_ENTRY definitions are to be contained in the tree entries themselves. |
| 1289 | * Use ZIP_FUNCTIONS to define the signature of the zip tree functions. */ |
| 1290 | |
| 1291 | #define ZIP_HEAD(name, type) \ |
| 1292 | struct name { \ |
| 1293 | struct type *root; \ |
| 1294 | } |
| 1295 | |
| 1296 | #define ZIP_ENTRY(type) \ |
| 1297 | struct { \ |
| 1298 | struct type *left; \ |
| 1299 | struct type *right; \ |
| 1300 | } |
| 1301 | |
| 1302 | enum ZIP_CMP { |
| 1303 | ZIP_CMP_LESS = -1, |
| 1304 | ZIP_CMP_EQ = 0, |
| 1305 | ZIP_CMP_MORE = 1 |
| 1306 | }; |
| 1307 | |
| 1308 | /* The comparison method "cmp" for a zip tree has the signature. |
| 1309 | * Provide this to the ZIP_FUNCTIONS macro. |
| 1310 | * |
| 1311 | * enum ZIP_CMP cmpMethod(const keytype *a, const keytype *b); |
| 1312 | */ |
| 1313 | typedef enum ZIP_CMP (*zip_cmp_cb)(const void *key1, const void *key2); |
| 1314 | |
| 1315 | #define ZIP_INIT(head) do { (head)->root = NULL; } while (0) |
| 1316 | #define ZIP_ROOT(head) (head)->root |
| 1317 | #define ZIP_LEFT(elm, field) (elm)->field.left |
| 1318 | #define ZIP_RIGHT(elm, field) (elm)->field.right |
| 1319 | #define ZIP_INSERT(name, head, elm) name##_ZIP_INSERT(head, elm) |
| 1320 | #define ZIP_FIND(name, head, key) name##_ZIP_FIND(head, key) |
| 1321 | #define ZIP_MIN(name, head) name##_ZIP_MIN(head) |
| 1322 | #define ZIP_MAX(name, head) name##_ZIP_MAX(head) |
| 1323 | |
| 1324 | /* Returns the element if it was found in the tree. Returns NULL otherwise. */ |
| 1325 | #define ZIP_REMOVE(name, head, elm) name##_ZIP_REMOVE(head, elm) |
| 1326 | |
| 1327 | /* Split (_UNZIP) and merge (_ZIP) trees. _UNZIP splits at the key and moves |
| 1328 | * elements <= into the left output (right otherwise). */ |
| 1329 | #define ZIP_ZIP(name, left, right) name##_ZIP_ZIP(left, right) |
| 1330 | #define ZIP_UNZIP(name, head, key, left, right) \ |
| 1331 | name##_ZIP_UNZIP(head, key, left, right) |
| 1332 | |
| 1333 | /* ZIP_ITER uses in-order traversal of the tree (in the order of the keys). The |
| 1334 | * memory if a node is not accessed by ZIP_ITER after the callback has been |
| 1335 | * executed for it. So a tree can be cleaned by calling free on each node from |
| 1336 | * within the iteration callback. |
| 1337 | * |
| 1338 | * ZIP_ITER returns a void pointer. The first callback to return non-NULL aborts |
| 1339 | * the iteration. This pointer is then returned. */ |
| 1340 | typedef void * (*zip_iter_cb)(void *context, void *elm); |
| 1341 | #define ZIP_ITER(name, head, cb, ctx) name##_ZIP_ITER(head, cb, ctx) |
| 1342 | |
| 1343 | /* Same as _ITER, but only visits elements with the given key */ |
| 1344 | #define ZIP_ITER_KEY(name, head, key, cb, ctx) name##_ZIP_ITER_KEY(head, key, cb, ctx) |
| 1345 | |
| 1346 | /* Macro to generate typed ziptree methods */ |
| 1347 | #define ZIP_FUNCTIONS(name, type, field, keytype, keyfield, cmp) \ |
| 1348 | \ |
| 1349 | ZIP_UNUSED static ZIP_INLINE void \ |
| 1350 | name##_ZIP_INSERT(struct name *head, struct type *el) { \ |
| 1351 | __ZIP_INSERT(head, (zip_cmp_cb)cmp, offsetof(struct type, field), \ |
| 1352 | offsetof(struct type, keyfield), el); \ |
| 1353 | } \ |
| 1354 | \ |
| 1355 | ZIP_UNUSED static ZIP_INLINE struct type * \ |
| 1356 | name##_ZIP_REMOVE(struct name *head, struct type *elm) { \ |
| 1357 | return (struct type*) \ |
| 1358 | __ZIP_REMOVE(head, (zip_cmp_cb)cmp, \ |
| 1359 | offsetof(struct type, field), \ |
| 1360 | offsetof(struct type, keyfield), elm); \ |
| 1361 | } \ |
| 1362 | \ |
| 1363 | ZIP_UNUSED static ZIP_INLINE struct type * \ |
| 1364 | name##_ZIP_FIND(struct name *head, const keytype *key) { \ |
| 1365 | struct type *cur = ZIP_ROOT(head); \ |
| 1366 | while(cur) { \ |
| 1367 | enum ZIP_CMP eq = cmp(key, &cur->keyfield); \ |
| 1368 | if(eq == ZIP_CMP_EQ) \ |
| 1369 | break; \ |
| 1370 | if(eq == ZIP_CMP_LESS) \ |
| 1371 | cur = ZIP_LEFT(cur, field); \ |
| 1372 | else \ |
| 1373 | cur = ZIP_RIGHT(cur, field); \ |
| 1374 | } \ |
| 1375 | return cur; \ |
| 1376 | } \ |
| 1377 | \ |
| 1378 | ZIP_UNUSED static ZIP_INLINE struct type * \ |
| 1379 | name##_ZIP_MIN(struct name *head) { \ |
| 1380 | struct type *cur = ZIP_ROOT(head); \ |
| 1381 | if(!cur) \ |
| 1382 | return NULL; \ |
| 1383 | while(ZIP_LEFT(cur, field)) { \ |
| 1384 | cur = ZIP_LEFT(cur, field); \ |
| 1385 | } \ |
| 1386 | return cur; \ |
| 1387 | } \ |
| 1388 | \ |
| 1389 | ZIP_UNUSED static ZIP_INLINE struct type * \ |
| 1390 | name##_ZIP_MAX(struct name *head) { \ |
| 1391 | struct type *cur = ZIP_ROOT(head); \ |
| 1392 | if(!cur) \ |
| 1393 | return NULL; \ |
| 1394 | while(ZIP_RIGHT(cur, field)) { \ |
| 1395 | cur = ZIP_RIGHT(cur, field); \ |
| 1396 | } \ |
| 1397 | return cur; \ |
| 1398 | } \ |
| 1399 | \ |
| 1400 | typedef void * (*name##_cb)(void *context, struct type *elm); \ |
| 1401 | \ |
| 1402 | ZIP_UNUSED static ZIP_INLINE void * \ |
| 1403 | name##_ZIP_ITER(struct name *head, name##_cb cb, void *context) { \ |
| 1404 | return __ZIP_ITER(offsetof(struct type, field), (zip_iter_cb)cb, \ |
| 1405 | context, ZIP_ROOT(head)); \ |
| 1406 | } \ |
| 1407 | \ |
| 1408 | ZIP_UNUSED static ZIP_INLINE void * \ |
| 1409 | name##_ZIP_ITER_KEY(struct name *head, const keytype *key, \ |
| 1410 | name##_cb cb, void *context) { \ |
| 1411 | return __ZIP_ITER_KEY((zip_cmp_cb)cmp, offsetof(struct type, field), \ |
| 1412 | offsetof(struct type, keyfield), key, \ |
| 1413 | (zip_iter_cb)cb, context, ZIP_ROOT(head)); \ |
| 1414 | } \ |
| 1415 | \ |
| 1416 | ZIP_UNUSED static ZIP_INLINE struct type * \ |
| 1417 | name##_ZIP_ZIP(struct type *left, struct type *right) { \ |
| 1418 | return (struct type*) \ |
| 1419 | __ZIP_ZIP(offsetof(struct type, field), left, right); \ |
| 1420 | } \ |
| 1421 | \ |
| 1422 | ZIP_UNUSED static ZIP_INLINE void \ |
| 1423 | name##_ZIP_UNZIP(struct name *head, const keytype *key, \ |
| 1424 | struct name *left, struct name *right) { \ |
| 1425 | __ZIP_UNZIP((zip_cmp_cb)cmp, offsetof(struct type, field), \ |
| 1426 | offsetof(struct type, keyfield), key, \ |
| 1427 | head, left, right); \ |
| 1428 | } |
| 1429 | |
| 1430 | /* Internal definitions. Don't use directly. */ |
| 1431 | |
| 1432 | void |
| 1433 | __ZIP_INSERT(void *h, zip_cmp_cb cmp, unsigned short fieldoffset, |
| 1434 | unsigned short keyoffset, void *elm); |
| 1435 | |
| 1436 | void * |
| 1437 | __ZIP_REMOVE(void *h, zip_cmp_cb cmp, unsigned short fieldoffset, |
| 1438 | unsigned short keyoffset, void *elm); |
| 1439 | |
| 1440 | void * |
| 1441 | __ZIP_ITER(unsigned short fieldoffset, zip_iter_cb cb, |
| 1442 | void *context, void *elm); |
| 1443 | |
| 1444 | void * |
| 1445 | __ZIP_ITER_KEY(zip_cmp_cb cmp, unsigned short fieldoffset, |
| 1446 | unsigned short keyoffset, const void *key, |
| 1447 | zip_iter_cb cb, void *context, void *elm); |
| 1448 | |
| 1449 | void * |
| 1450 | __ZIP_ZIP(unsigned short fieldoffset, void *left, void *right); |
| 1451 | |
| 1452 | void |
| 1453 | __ZIP_UNZIP(zip_cmp_cb cmp, unsigned short fieldoffset, |
| 1454 | unsigned short keyoffset, const void *key, |
| 1455 | void *h, void *l, void *r); |
| 1456 | |
| 1457 | #ifdef __cplusplus |
| 1458 | } /* extern "C" */ |
| 1459 | #endif |
| 1460 | |
| 1461 | |
| 1462 | /**** amalgamated original file "/src/ua_types_encoding_binary.h" ****/ |
| 1463 | |
| 1464 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 1465 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 1466 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 1467 | * |
| 1468 | * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 1469 | * Copyright 2015 (c) Sten Grüner |
| 1470 | * Copyright 2014, 2017 (c) Florian Palm |
| 1471 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 1472 | * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB |
| 1473 | */ |
| 1474 | |
| 1475 | |
| 1476 | |
| 1477 | _UA_BEGIN_DECLS |
| 1478 | |
| 1479 | typedef UA_StatusCode (*UA_exchangeEncodeBuffer)(void *handle, UA_Byte **bufPos, |
| 1480 | const UA_Byte **bufEnd); |
| 1481 | |
| 1482 | /* Encodes the scalar value described by type in the binary encoding. Encoding |
| 1483 | * is thread-safe if thread-local variables are enabled. Encoding is also |
| 1484 | * reentrant and can be safely called from signal handlers or interrupts. |
| 1485 | * |
| 1486 | * @param src The value. Must not be NULL. |
| 1487 | * @param type The value type. Must not be NULL. |
| 1488 | * @param bufPos Points to a pointer to the current position in the encoding |
| 1489 | * buffer. Must not be NULL. The pointer is advanced by the number of |
| 1490 | * encoded bytes, or, if the buffer is exchanged, to the position in the |
| 1491 | * new buffer. |
| 1492 | * @param bufEnd Points to a pointer to the end of the encoding buffer (encoding |
| 1493 | * always stops before *buf_end). Must not be NULL. The pointer is |
| 1494 | * changed when the buffer is exchanged. |
| 1495 | * @param exchangeCallback Called when the end of the buffer is reached. This is |
| 1496 | used to send out a message chunk before continuing with the encoding. |
| 1497 | Is ignored if NULL. |
| 1498 | * @param exchangeHandle Custom data passed into the exchangeCallback. |
| 1499 | * @return Returns a statuscode whether encoding succeeded. */ |
| 1500 | UA_StatusCode |
| 1501 | UA_encodeBinaryInternal(const void *src, const UA_DataType *type, |
| 1502 | UA_Byte **bufPos, const UA_Byte **bufEnd, |
| 1503 | UA_exchangeEncodeBuffer exchangeCallback, |
| 1504 | void *exchangeHandle) |
| 1505 | UA_FUNC_ATTR_WARN_UNUSED_RESULT; |
| 1506 | |
| 1507 | /* Decodes a scalar value described by type from binary encoding. Decoding |
| 1508 | * is thread-safe if thread-local variables are enabled. Decoding is also |
| 1509 | * reentrant and can be safely called from signal handlers or interrupts. |
| 1510 | * |
| 1511 | * @param src The buffer with the binary encoded value. Must not be NULL. |
| 1512 | * @param offset The current position in the buffer. Must not be NULL. The value |
| 1513 | * is advanced as decoding progresses. |
| 1514 | * @param dst The target value. Must not be NULL. The target is assumed to have |
| 1515 | * size type->memSize. The value is reset to zero before decoding. If |
| 1516 | * decoding fails, members are deleted and the value is reset (zeroed) |
| 1517 | * again. |
| 1518 | * @param type The value type. Must not be NULL. |
| 1519 | * @param customTypesSize The number of non-standard datatypes contained in the |
| 1520 | * customTypes array. |
| 1521 | * @param customTypes An array of non-standard datatypes (not included in |
| 1522 | * UA_TYPES). Can be NULL if customTypesSize is zero. |
| 1523 | * @return Returns a statuscode whether decoding succeeded. */ |
| 1524 | UA_StatusCode |
| 1525 | UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset, |
| 1526 | void *dst, const UA_DataType *type, |
| 1527 | const UA_DataTypeArray *customTypes) |
| 1528 | UA_FUNC_ATTR_WARN_UNUSED_RESULT; |
| 1529 | |
| 1530 | const UA_DataType * |
| 1531 | UA_findDataTypeByBinary(const UA_NodeId *typeId); |
| 1532 | |
| 1533 | _UA_END_DECLS |
| 1534 | |
| 1535 | |
| 1536 | /**** amalgamated original file "/src/ua_util_internal.h" ****/ |
| 1537 | |
| 1538 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 1539 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 1540 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 1541 | * |
| 1542 | * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 1543 | * Copyright 2014, 2017 (c) Florian Palm |
| 1544 | * Copyright 2015 (c) LEvertz |
| 1545 | * Copyright 2015-2016 (c) Sten Grüner |
| 1546 | * Copyright 2015 (c) Chris Iatrou |
| 1547 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 1548 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 1549 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes) |
| 1550 | */ |
| 1551 | |
| 1552 | |
| 1553 | #define UA_INTERNAL |
| 1554 | |
| 1555 | |
| 1556 | _UA_BEGIN_DECLS |
| 1557 | |
| 1558 | /* Macro-Expand for MSVC workarounds */ |
| 1559 | #define UA_MACRO_EXPAND(x) x |
| 1560 | |
| 1561 | /* Try if the type of the value can be adjusted "in situ" to the target type. |
| 1562 | * That can be done, for example, to map between int32 and an enum. |
| 1563 | * |
| 1564 | * This can also "unwrap" a type. For example: string -> array of bytes |
| 1565 | * |
| 1566 | * If value->data is changed during adjustType, free the pointer afterwards (if |
| 1567 | * you did not keep the original variant for _clear). */ |
| 1568 | void |
| 1569 | adjustType(UA_Variant *value, const UA_DataType *targetType); |
| 1570 | |
| 1571 | /* Print a NodeId in logs */ |
| 1572 | #define UA_LOG_NODEID_INTERNAL(NODEID, LEVEL, LOG) \ |
| 1573 | if(UA_LOGLEVEL <= UA_LOGLEVEL_##LEVEL) { \ |
| 1574 | UA_String nodeIdStr = UA_STRING_NULL; \ |
| 1575 | UA_NodeId_print(NODEID, &nodeIdStr); \ |
| 1576 | LOG; \ |
| 1577 | UA_String_clear(&nodeIdStr); \ |
| 1578 | } |
| 1579 | |
| 1580 | #define UA_LOG_NODEID_TRACE(NODEID, LOG) UA_LOG_NODEID_INTERNAL(NODEID, TRACE, LOG) |
| 1581 | #define UA_LOG_NODEID_DEBUG(NODEID, LOG) UA_LOG_NODEID_INTERNAL(NODEID, DEBUG, LOG) |
| 1582 | #define UA_LOG_NODEID_INFO(NODEID, LOG) UA_LOG_NODEID_INTERNAL(NODEID, INFO, LOG) |
| 1583 | #define UA_LOG_NODEID_WARNING(NODEID, LOG) UA_LOG_NODEID_INTERNAL(NODEID, WARNING, LOG) |
| 1584 | #define UA_LOG_NODEID_ERROR(NODEID, LOG) UA_LOG_NODEID_INTERNAL(NODEID, ERROR, LOG) |
| 1585 | #define UA_LOG_NODEID_FATAL(NODEID, LOG) UA_LOG_NODEID_INTERNAL(NODEID, FATAL, LOG) |
| 1586 | |
| 1587 | /* Short names for integer. These are not exposed on the public API, since many |
| 1588 | * user-applications make the same definitions in their headers. */ |
| 1589 | typedef UA_Byte u8; |
| 1590 | typedef UA_SByte i8; |
| 1591 | typedef UA_UInt16 u16; |
| 1592 | typedef UA_Int16 i16; |
| 1593 | typedef UA_UInt32 u32; |
| 1594 | typedef UA_Int32 i32; |
| 1595 | typedef UA_UInt64 u64; |
| 1596 | typedef UA_Int64 i64; |
| 1597 | typedef UA_StatusCode status; |
| 1598 | |
| 1599 | /** |
| 1600 | * Error checking macros |
| 1601 | */ |
| 1602 | |
| 1603 | static UA_INLINE UA_Boolean |
| 1604 | isGood(UA_StatusCode code) { |
| 1605 | return code == UA_STATUSCODE_GOOD; |
| 1606 | } |
| 1607 | |
| 1608 | static UA_INLINE UA_Boolean |
| 1609 | isNonNull(const void *ptr) { |
| 1610 | return ptr != NULL; |
| 1611 | } |
| 1612 | |
| 1613 | static UA_INLINE UA_Boolean |
| 1614 | isTrue(uint8_t expr) { |
| 1615 | return expr; |
| 1616 | } |
| 1617 | |
| 1618 | #define UA_CHECK(A, EVAL_ON_ERROR) \ |
| 1619 | do { \ |
| 1620 | if(UA_UNLIKELY(!isTrue(A))) { \ |
| 1621 | EVAL_ON_ERROR; \ |
| 1622 | } \ |
| 1623 | } while(0) |
| 1624 | |
| 1625 | #define UA_CHECK_STATUS(STATUSCODE, EVAL_ON_ERROR) \ |
| 1626 | UA_CHECK(isGood(STATUSCODE), EVAL_ON_ERROR) |
| 1627 | |
| 1628 | #define UA_CHECK_MEM(STATUSCODE, EVAL_ON_ERROR) \ |
| 1629 | UA_CHECK(isNonNull(STATUSCODE), EVAL_ON_ERROR) |
| 1630 | |
| 1631 | #ifdef UA_DEBUG_FILE_LINE_INFO |
| 1632 | #define UA_CHECK_LOG_INTERNAL(A, STATUSCODE, EVAL, LOG, LOGGER, CAT, MSG, ...) \ |
| 1633 | UA_MACRO_EXPAND( \ |
| 1634 | UA_CHECK(A, LOG(LOGGER, CAT, "" MSG "%s (%s:%d: StatusCode: %s)", __VA_ARGS__, \ |
| 1635 | __FILE__, __LINE__, UA_StatusCode_name(STATUSCODE)); \ |
| 1636 | EVAL)) |
| 1637 | #else |
| 1638 | #define UA_CHECK_LOG_INTERNAL(A, STATUSCODE, EVAL, LOG, LOGGER, CAT, MSG, ...) \ |
| 1639 | UA_MACRO_EXPAND( \ |
| 1640 | UA_CHECK(A, LOG(LOGGER, CAT, "" MSG "%s (StatusCode: %s)", __VA_ARGS__, \ |
| 1641 | UA_StatusCode_name(STATUSCODE)); \ |
| 1642 | EVAL)) |
| 1643 | #endif |
| 1644 | |
| 1645 | #define UA_CHECK_LOG(A, EVAL, LEVEL, LOGGER, CAT, ...) \ |
| 1646 | UA_MACRO_EXPAND(UA_CHECK_LOG_INTERNAL(A, UA_STATUSCODE_BAD, EVAL, UA_LOG_##LEVEL, \ |
| 1647 | LOGGER, CAT, __VA_ARGS__, "")) |
| 1648 | |
| 1649 | #define UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, LEVEL, LOGGER, CAT, ...) \ |
| 1650 | UA_MACRO_EXPAND(UA_CHECK_LOG_INTERNAL(isGood(STATUSCODE), STATUSCODE, \ |
| 1651 | EVAL, UA_LOG_##LEVEL, LOGGER, CAT, \ |
| 1652 | __VA_ARGS__, "")) |
| 1653 | |
| 1654 | #define UA_CHECK_MEM_LOG(PTR, EVAL, LEVEL, LOGGER, CAT, ...) \ |
| 1655 | UA_MACRO_EXPAND(UA_CHECK_LOG_INTERNAL(isNonNull(PTR), UA_STATUSCODE_BADOUTOFMEMORY, \ |
| 1656 | EVAL, UA_LOG_##LEVEL, LOGGER, CAT, \ |
| 1657 | __VA_ARGS__, "")) |
| 1658 | |
| 1659 | /** |
| 1660 | * Check Macros |
| 1661 | * Usage examples: |
| 1662 | * |
| 1663 | * void *data = malloc(...); |
| 1664 | * UA_CHECK(data, return error); |
| 1665 | * |
| 1666 | * UA_StatusCode rv = some_func(...); |
| 1667 | * UA_CHECK_STATUS(rv, return rv); |
| 1668 | * |
| 1669 | * UA_Logger *logger = &server->config.logger; |
| 1670 | * rv = bar_func(...); |
| 1671 | * UA_CHECK_STATUS_WARN(rv, return rv, logger, UA_LOGCATEGORY_SERVER, "msg & args %s", "arg"); |
| 1672 | */ |
| 1673 | #define UA_CHECK_FATAL(A, EVAL, LOGGER, CAT, ...) \ |
| 1674 | UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, FATAL, LOGGER, CAT, __VA_ARGS__)) |
| 1675 | #define UA_CHECK_ERROR(A, EVAL, LOGGER, CAT, ...) \ |
| 1676 | UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, ERROR, LOGGER, CAT, __VA_ARGS__)) |
| 1677 | #define UA_CHECK_WARN(A, EVAL, LOGGER, CAT, ...) \ |
| 1678 | UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, WARNING, LOGGER, CAT, __VA_ARGS__)) |
| 1679 | #define UA_CHECK_INFO(A, EVAL, LOGGER, CAT, ...) \ |
| 1680 | UA_MACRO_EXPAND(UA_CHECK_LOG(A, EVAL, INFO, LOGGER, CAT, __VA_ARGS__)) |
| 1681 | |
| 1682 | #define UA_CHECK_STATUS_FATAL(STATUSCODE, EVAL, LOGGER, CAT, ...) \ |
| 1683 | UA_MACRO_EXPAND( \ |
| 1684 | UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, FATAL, LOGGER, CAT, __VA_ARGS__)) |
| 1685 | #define UA_CHECK_STATUS_ERROR(STATUSCODE, EVAL, LOGGER, CAT, ...) \ |
| 1686 | UA_MACRO_EXPAND( \ |
| 1687 | UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, ERROR, LOGGER, CAT, __VA_ARGS__)) |
| 1688 | #define UA_CHECK_STATUS_WARN(STATUSCODE, EVAL, LOGGER, CAT, ...) \ |
| 1689 | UA_MACRO_EXPAND( \ |
| 1690 | UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, WARNING, LOGGER, CAT, __VA_ARGS__)) |
| 1691 | #define UA_CHECK_STATUS_INFO(STATUSCODE, EVAL, LOGGER, CAT, ...) \ |
| 1692 | UA_MACRO_EXPAND( \ |
| 1693 | UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, INFO, LOGGER, CAT, __VA_ARGS__)) |
| 1694 | #define UA_CHECK_STATUS_DEBUG(STATUSCODE, EVAL, LOGGER, CAT, ...) \ |
| 1695 | UA_MACRO_EXPAND( \ |
| 1696 | UA_CHECK_STATUS_LOG(STATUSCODE, EVAL, DEBUG, LOGGER, CAT, __VA_ARGS__)) |
| 1697 | |
| 1698 | #define UA_CHECK_MEM_FATAL(PTR, EVAL, LOGGER, CAT, ...) \ |
| 1699 | UA_MACRO_EXPAND( \ |
| 1700 | UA_CHECK_MEM_LOG(PTR, EVAL, FATAL, LOGGER, CAT, __VA_ARGS__)) |
| 1701 | #define UA_CHECK_MEM_ERROR(PTR, EVAL, LOGGER, CAT, ...) \ |
| 1702 | UA_MACRO_EXPAND( \ |
| 1703 | UA_CHECK_MEM_LOG(PTR, EVAL, ERROR, LOGGER, CAT, __VA_ARGS__)) |
| 1704 | #define UA_CHECK_MEM_WARN(PTR, EVAL, LOGGER, CAT, ...) \ |
| 1705 | UA_MACRO_EXPAND( \ |
| 1706 | UA_CHECK_MEM_LOG(PTR, EVAL, WARNING, LOGGER, CAT, __VA_ARGS__)) |
| 1707 | #define UA_CHECK_MEM_INFO(PTR, EVAL, LOGGER, CAT, ...) \ |
| 1708 | UA_MACRO_EXPAND( \ |
| 1709 | UA_CHECK_MEM_LOG(PTR, EVAL, INFO, LOGGER, CAT, __VA_ARGS__)) |
| 1710 | |
| 1711 | /** |
| 1712 | * Utility Functions |
| 1713 | * ----------------- */ |
| 1714 | |
| 1715 | #ifdef UA_ENABLE_DISCOVERY_SEMAPHORE |
| 1716 | # ifdef UA_ARCHITECTURE_WIN32 |
| 1717 | # include <io.h> |
| 1718 | # define UA_fileExists(X) ( _access(X, 0) == 0) |
| 1719 | # else |
| 1720 | # include <unistd.h> |
| 1721 | # define UA_fileExists(X) ( access(X, 0) == 0) |
| 1722 | # endif |
| 1723 | #endif |
| 1724 | |
| 1725 | void |
| 1726 | UA_cleanupDataTypeWithCustom(const UA_DataTypeArray *customTypes); |
| 1727 | |
| 1728 | /* Get the number of optional fields contained in an structure type */ |
| 1729 | size_t UA_EXPORT |
| 1730 | getCountOfOptionalFields(const UA_DataType *type); |
| 1731 | |
| 1732 | /* Dump packet for debugging / fuzzing */ |
| 1733 | #ifdef UA_DEBUG_DUMP_PKGS |
| 1734 | void UA_EXPORT |
| 1735 | UA_dump_hex_pkg(UA_Byte* buffer, size_t bufferLen); |
| 1736 | #endif |
| 1737 | |
| 1738 | /* Get pointer to leaf certificate of a specified valid chain of DER encoded |
| 1739 | * certificates */ |
| 1740 | UA_ByteString getLeafCertificate(UA_ByteString chain); |
| 1741 | |
| 1742 | /* Unions that represent any of the supported request or response message */ |
| 1743 | typedef union { |
| 1744 | UA_RequestHeader requestHeader; |
| 1745 | UA_FindServersRequest findServersRequest; |
| 1746 | UA_GetEndpointsRequest getEndpointsRequest; |
| 1747 | #ifdef UA_ENABLE_DISCOVERY |
| 1748 | # ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 1749 | UA_FindServersOnNetworkRequest findServersOnNetworkRequest; |
| 1750 | # endif |
| 1751 | UA_RegisterServerRequest registerServerRequest; |
| 1752 | UA_RegisterServer2Request registerServer2Request; |
| 1753 | #endif |
| 1754 | UA_OpenSecureChannelRequest openSecureChannelRequest; |
| 1755 | UA_CreateSessionRequest createSessionRequest; |
| 1756 | UA_ActivateSessionRequest activateSessionRequest; |
| 1757 | UA_CloseSessionRequest closeSessionRequest; |
| 1758 | UA_AddNodesRequest addNodesRequest; |
| 1759 | UA_AddReferencesRequest addReferencesRequest; |
| 1760 | UA_DeleteNodesRequest deleteNodesRequest; |
| 1761 | UA_DeleteReferencesRequest deleteReferencesRequest; |
| 1762 | UA_BrowseRequest browseRequest; |
| 1763 | UA_BrowseNextRequest browseNextRequest; |
| 1764 | UA_TranslateBrowsePathsToNodeIdsRequest translateBrowsePathsToNodeIdsRequest; |
| 1765 | UA_RegisterNodesRequest registerNodesRequest; |
| 1766 | UA_UnregisterNodesRequest unregisterNodesRequest; |
| 1767 | UA_ReadRequest readRequest; |
| 1768 | UA_WriteRequest writeRequest; |
| 1769 | #ifdef UA_ENABLE_HISTORIZING |
| 1770 | UA_HistoryReadRequest historyReadRequest; |
| 1771 | UA_HistoryUpdateRequest historyUpdateRequest; |
| 1772 | #endif |
| 1773 | #ifdef UA_ENABLE_METHODCALLS |
| 1774 | UA_CallRequest callRequest; |
| 1775 | #endif |
| 1776 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 1777 | UA_CreateMonitoredItemsRequest createMonitoredItemsRequest; |
| 1778 | UA_DeleteMonitoredItemsRequest deleteMonitoredItemsRequest; |
| 1779 | UA_ModifyMonitoredItemsRequest modifyMonitoredItemsRequest; |
| 1780 | UA_SetMonitoringModeRequest setMonitoringModeRequest; |
| 1781 | UA_CreateSubscriptionRequest createSubscriptionRequest; |
| 1782 | UA_ModifySubscriptionRequest modifySubscriptionRequest; |
| 1783 | UA_SetPublishingModeRequest setPublishingModeRequest; |
| 1784 | UA_PublishRequest publishRequest; |
| 1785 | UA_RepublishRequest republishRequest; |
| 1786 | UA_DeleteSubscriptionsRequest deleteSubscriptionsRequest; |
| 1787 | #endif |
| 1788 | } UA_Request; |
| 1789 | |
| 1790 | typedef union { |
| 1791 | UA_ResponseHeader responseHeader; |
| 1792 | UA_FindServersResponse findServersResponse; |
| 1793 | UA_GetEndpointsResponse getEndpointsResponse; |
| 1794 | #ifdef UA_ENABLE_DISCOVERY |
| 1795 | # ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 1796 | UA_FindServersOnNetworkResponse findServersOnNetworkResponse; |
| 1797 | # endif |
| 1798 | UA_RegisterServerResponse registerServerResponse; |
| 1799 | UA_RegisterServer2Response registerServer2Response; |
| 1800 | #endif |
| 1801 | UA_OpenSecureChannelResponse openSecureChannelResponse; |
| 1802 | UA_CreateSessionResponse createSessionResponse; |
| 1803 | UA_ActivateSessionResponse activateSessionResponse; |
| 1804 | UA_CloseSessionResponse closeSessionResponse; |
| 1805 | UA_AddNodesResponse addNodesResponse; |
| 1806 | UA_AddReferencesResponse addReferencesResponse; |
| 1807 | UA_DeleteNodesResponse deleteNodesResponse; |
| 1808 | UA_DeleteReferencesResponse deleteReferencesResponse; |
| 1809 | UA_BrowseResponse browseResponse; |
| 1810 | UA_BrowseNextResponse browseNextResponse; |
| 1811 | UA_TranslateBrowsePathsToNodeIdsResponse translateBrowsePathsToNodeIdsResponse; |
| 1812 | UA_RegisterNodesResponse registerNodesResponse; |
| 1813 | UA_UnregisterNodesResponse unregisterNodesResponse; |
| 1814 | UA_ReadResponse readResponse; |
| 1815 | UA_WriteResponse writeResponse; |
| 1816 | #ifdef UA_ENABLE_HISTORIZING |
| 1817 | UA_HistoryReadResponse historyReadResponse; |
| 1818 | UA_HistoryUpdateResponse historyUpdateResponse; |
| 1819 | #endif |
| 1820 | #ifdef UA_ENABLE_METHODCALLS |
| 1821 | UA_CallResponse callResponse; |
| 1822 | #endif |
| 1823 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 1824 | UA_CreateMonitoredItemsResponse createMonitoredItemsResponse; |
| 1825 | UA_DeleteMonitoredItemsResponse deleteMonitoredItemsResponse; |
| 1826 | UA_ModifyMonitoredItemsResponse modifyMonitoredItemsResponse; |
| 1827 | UA_SetMonitoringModeResponse setMonitoringModeResponse; |
| 1828 | UA_CreateSubscriptionResponse createSubscriptionResponse; |
| 1829 | UA_ModifySubscriptionResponse modifySubscriptionResponse; |
| 1830 | UA_SetPublishingModeResponse setPublishingModeResponse; |
| 1831 | UA_PublishResponse publishResponse; |
| 1832 | UA_RepublishResponse republishResponse; |
| 1833 | UA_DeleteSubscriptionsResponse deleteSubscriptionsResponse; |
| 1834 | #endif |
| 1835 | } UA_Response; |
| 1836 | |
| 1837 | /* Do not expose UA_String_equal_ignorecase to public API as it currently only handles |
| 1838 | * ASCII strings, and not UTF8! */ |
| 1839 | UA_Boolean UA_EXPORT |
| 1840 | UA_String_equal_ignorecase(const UA_String *s1, const UA_String *s2); |
| 1841 | |
| 1842 | /********************/ |
| 1843 | /* Encoding Helpers */ |
| 1844 | /********************/ |
| 1845 | |
| 1846 | /* out must be a buffer with at least 36 elements, the length of every guid */ |
| 1847 | void UA_Guid_to_hex(const UA_Guid *guid, u8* out, UA_Boolean lower); |
| 1848 | |
| 1849 | #define UA_ENCODING_HELPERS(TYPE, UPCASE_TYPE) \ |
| 1850 | static UA_INLINE size_t \ |
| 1851 | UA_##TYPE##_calcSizeBinary(const UA_##TYPE *src) { \ |
| 1852 | return UA_calcSizeBinary(src, &UA_TYPES[UA_TYPES_##UPCASE_TYPE]); \ |
| 1853 | } \ |
| 1854 | static UA_INLINE UA_StatusCode \ |
| 1855 | UA_##TYPE##_encodeBinary(const UA_##TYPE *src, UA_Byte **bufPos, const UA_Byte *bufEnd) { \ |
| 1856 | return UA_encodeBinaryInternal(src, &UA_TYPES[UA_TYPES_##UPCASE_TYPE], \ |
| 1857 | bufPos, &bufEnd, NULL, NULL); \ |
| 1858 | } \ |
| 1859 | static UA_INLINE UA_StatusCode \ |
| 1860 | UA_##TYPE##_decodeBinary(const UA_ByteString *src, size_t *offset, UA_##TYPE *dst) { \ |
| 1861 | return UA_decodeBinaryInternal(src, offset, dst, \ |
| 1862 | &UA_TYPES[UA_TYPES_##UPCASE_TYPE], NULL); \ |
| 1863 | } |
| 1864 | |
| 1865 | UA_ENCODING_HELPERS(Boolean, BOOLEAN) |
| 1866 | UA_ENCODING_HELPERS(SByte, SBYTE) |
| 1867 | UA_ENCODING_HELPERS(Byte, BYTE) |
| 1868 | UA_ENCODING_HELPERS(Int16, INT16) |
| 1869 | UA_ENCODING_HELPERS(UInt16, UINT16) |
| 1870 | UA_ENCODING_HELPERS(Int32, INT32) |
| 1871 | UA_ENCODING_HELPERS(UInt32, UINT32) |
| 1872 | UA_ENCODING_HELPERS(Int64, INT64) |
| 1873 | UA_ENCODING_HELPERS(UInt64, UINT64) |
| 1874 | UA_ENCODING_HELPERS(Float, FLOAT) |
| 1875 | UA_ENCODING_HELPERS(Double, DOUBLE) |
| 1876 | UA_ENCODING_HELPERS(String, STRING) |
| 1877 | UA_ENCODING_HELPERS(DateTime, DATETIME) |
| 1878 | UA_ENCODING_HELPERS(Guid, GUID) |
| 1879 | UA_ENCODING_HELPERS(ByteString, BYTESTRING) |
| 1880 | UA_ENCODING_HELPERS(XmlElement, XMLELEMENT) |
| 1881 | UA_ENCODING_HELPERS(NodeId, NODEID) |
| 1882 | UA_ENCODING_HELPERS(ExpandedNodeId, EXPANDEDNODEID) |
| 1883 | UA_ENCODING_HELPERS(StatusCode, STATUSCODE) |
| 1884 | UA_ENCODING_HELPERS(QualifiedName, QUALIFIEDNAME) |
| 1885 | UA_ENCODING_HELPERS(LocalizedText, LOCALIZEDTEXT) |
| 1886 | UA_ENCODING_HELPERS(ExtensionObject, EXTENSIONOBJECT) |
| 1887 | UA_ENCODING_HELPERS(DataValue, DATAVALUE) |
| 1888 | UA_ENCODING_HELPERS(Variant, VARIANT) |
| 1889 | UA_ENCODING_HELPERS(DiagnosticInfo, DIAGNOSTICINFO) |
| 1890 | |
| 1891 | _UA_END_DECLS |
| 1892 | |
| 1893 | |
| 1894 | /**** amalgamated original file "/build/src_generated/open62541/transport_generated.h" ****/ |
| 1895 | |
| 1896 | /********************************** |
| 1897 | * Autogenerated -- do not modify * |
| 1898 | **********************************/ |
| 1899 | |
| 1900 | /* Must be before the include guards */ |
| 1901 | #ifdef UA_ENABLE_AMALGAMATION |
| 1902 | #else |
| 1903 | #endif |
| 1904 | |
| 1905 | |
| 1906 | |
| 1907 | _UA_BEGIN_DECLS |
| 1908 | |
| 1909 | /** |
| 1910 | * Every type is assigned an index in an array containing the type descriptions. |
| 1911 | * These descriptions are used during type handling (copying, deletion, |
| 1912 | * binary encoding, ...). */ |
| 1913 | #define UA_TRANSPORT_COUNT 9 |
| 1914 | extern UA_EXPORT UA_DataType UA_TRANSPORT[UA_TRANSPORT_COUNT]; |
| 1915 | |
| 1916 | /* MessageType: Message Type and whether the message contains an intermediate chunk */ |
| 1917 | typedef enum { |
| 1918 | UA_MESSAGETYPE_ACK = 0x4B4341, |
| 1919 | UA_MESSAGETYPE_HEL = 0x4C4548, |
| 1920 | UA_MESSAGETYPE_MSG = 0x47534D, |
| 1921 | UA_MESSAGETYPE_OPN = 0x4E504F, |
| 1922 | UA_MESSAGETYPE_CLO = 0x4F4C43, |
| 1923 | UA_MESSAGETYPE_ERR = 0x525245, |
| 1924 | UA_MESSAGETYPE_RHE = 0x454852, |
| 1925 | UA_MESSAGETYPE_INVALID = 0x0, |
| 1926 | __UA_MESSAGETYPE_FORCE32BIT = 0x7fffffff |
| 1927 | } UA_MessageType; |
| 1928 | |
| 1929 | UA_STATIC_ASSERT(sizeof(UA_MessageType) == sizeof(UA_Int32), enum_must_be_32bit); |
| 1930 | |
| 1931 | #define UA_TRANSPORT_MESSAGETYPE 0 |
| 1932 | |
| 1933 | /* ChunkType: Type of the chunk */ |
| 1934 | typedef enum { |
| 1935 | UA_CHUNKTYPE_FINAL = 0x46000000, |
| 1936 | UA_CHUNKTYPE_INTERMEDIATE = 0x43000000, |
| 1937 | UA_CHUNKTYPE_ABORT = 0x41000000, |
| 1938 | __UA_CHUNKTYPE_FORCE32BIT = 0x7fffffff |
| 1939 | } UA_ChunkType; |
| 1940 | |
| 1941 | UA_STATIC_ASSERT(sizeof(UA_ChunkType) == sizeof(UA_Int32), enum_must_be_32bit); |
| 1942 | |
| 1943 | #define UA_TRANSPORT_CHUNKTYPE 1 |
| 1944 | |
| 1945 | /* TcpMessageHeader: TCP Header */ |
| 1946 | typedef struct { |
| 1947 | UA_UInt32 messageTypeAndChunkType; |
| 1948 | UA_UInt32 messageSize; |
| 1949 | } UA_TcpMessageHeader; |
| 1950 | |
| 1951 | #define UA_TRANSPORT_TCPMESSAGEHEADER 2 |
| 1952 | |
| 1953 | /* TcpHelloMessage: Hello Message */ |
| 1954 | typedef struct { |
| 1955 | UA_UInt32 protocolVersion; |
| 1956 | UA_UInt32 receiveBufferSize; |
| 1957 | UA_UInt32 sendBufferSize; |
| 1958 | UA_UInt32 maxMessageSize; |
| 1959 | UA_UInt32 maxChunkCount; |
| 1960 | UA_String endpointUrl; |
| 1961 | } UA_TcpHelloMessage; |
| 1962 | |
| 1963 | #define UA_TRANSPORT_TCPHELLOMESSAGE 3 |
| 1964 | |
| 1965 | /* TcpReverseHelloMessage */ |
| 1966 | typedef struct { |
| 1967 | UA_String serverUri; |
| 1968 | UA_String endpointUrl; |
| 1969 | } UA_TcpReverseHelloMessage; |
| 1970 | |
| 1971 | #define UA_TRANSPORT_TCPREVERSEHELLOMESSAGE 4 |
| 1972 | |
| 1973 | /* TcpAcknowledgeMessage: Acknowledge Message */ |
| 1974 | typedef struct { |
| 1975 | UA_UInt32 protocolVersion; |
| 1976 | UA_UInt32 receiveBufferSize; |
| 1977 | UA_UInt32 sendBufferSize; |
| 1978 | UA_UInt32 maxMessageSize; |
| 1979 | UA_UInt32 maxChunkCount; |
| 1980 | } UA_TcpAcknowledgeMessage; |
| 1981 | |
| 1982 | #define UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE 5 |
| 1983 | |
| 1984 | /* TcpErrorMessage: Error Message */ |
| 1985 | typedef struct { |
| 1986 | UA_UInt32 error; |
| 1987 | UA_String reason; |
| 1988 | } UA_TcpErrorMessage; |
| 1989 | |
| 1990 | #define UA_TRANSPORT_TCPERRORMESSAGE 6 |
| 1991 | |
| 1992 | /* AsymmetricAlgorithmSecurityHeader: Asymmetric Security Header */ |
| 1993 | typedef struct { |
| 1994 | UA_ByteString securityPolicyUri; |
| 1995 | UA_ByteString senderCertificate; |
| 1996 | UA_ByteString receiverCertificateThumbprint; |
| 1997 | } UA_AsymmetricAlgorithmSecurityHeader; |
| 1998 | |
| 1999 | #define UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER 7 |
| 2000 | |
| 2001 | /* SequenceHeader: Secure Layer Sequence Header */ |
| 2002 | typedef struct { |
| 2003 | UA_UInt32 sequenceNumber; |
| 2004 | UA_UInt32 requestId; |
| 2005 | } UA_SequenceHeader; |
| 2006 | |
| 2007 | #define UA_TRANSPORT_SEQUENCEHEADER 8 |
| 2008 | |
| 2009 | |
| 2010 | _UA_END_DECLS |
| 2011 | |
| 2012 | |
| 2013 | /**** amalgamated original file "/build/src_generated/open62541/transport_generated_handling.h" ****/ |
| 2014 | |
| 2015 | /********************************** |
| 2016 | * Autogenerated -- do not modify * |
| 2017 | **********************************/ |
| 2018 | |
| 2019 | |
| 2020 | |
| 2021 | _UA_BEGIN_DECLS |
| 2022 | |
| 2023 | #if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 6 |
| 2024 | # pragma GCC diagnostic push |
| 2025 | # pragma GCC diagnostic ignored "-Wmissing-field-initializers" |
| 2026 | # pragma GCC diagnostic ignored "-Wmissing-braces" |
| 2027 | #endif |
| 2028 | |
| 2029 | |
| 2030 | /* MessageType */ |
| 2031 | static UA_INLINE void |
| 2032 | UA_MessageType_init(UA_MessageType *p) { |
| 2033 | memset(s: p, c: 0, n: sizeof(UA_MessageType)); |
| 2034 | } |
| 2035 | |
| 2036 | static UA_INLINE UA_MessageType * |
| 2037 | UA_MessageType_new(void) { |
| 2038 | return (UA_MessageType*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]); |
| 2039 | } |
| 2040 | |
| 2041 | static UA_INLINE UA_StatusCode |
| 2042 | UA_MessageType_copy(const UA_MessageType *src, UA_MessageType *dst) { |
| 2043 | return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]); |
| 2044 | } |
| 2045 | |
| 2046 | UA_DEPRECATED static UA_INLINE void |
| 2047 | UA_MessageType_deleteMembers(UA_MessageType *p) { |
| 2048 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]); |
| 2049 | } |
| 2050 | |
| 2051 | static UA_INLINE void |
| 2052 | UA_MessageType_clear(UA_MessageType *p) { |
| 2053 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]); |
| 2054 | } |
| 2055 | |
| 2056 | static UA_INLINE void |
| 2057 | UA_MessageType_delete(UA_MessageType *p) { |
| 2058 | UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]); |
| 2059 | }static UA_INLINE UA_Boolean |
| 2060 | UA_MessageType_equal(const UA_MessageType *p1, const UA_MessageType *p2) { |
| 2061 | return (UA_order(p1, p2, type: &UA_TRANSPORT[UA_TRANSPORT_MESSAGETYPE]) == UA_ORDER_EQ); |
| 2062 | } |
| 2063 | |
| 2064 | |
| 2065 | |
| 2066 | /* ChunkType */ |
| 2067 | static UA_INLINE void |
| 2068 | UA_ChunkType_init(UA_ChunkType *p) { |
| 2069 | memset(s: p, c: 0, n: sizeof(UA_ChunkType)); |
| 2070 | } |
| 2071 | |
| 2072 | static UA_INLINE UA_ChunkType * |
| 2073 | UA_ChunkType_new(void) { |
| 2074 | return (UA_ChunkType*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]); |
| 2075 | } |
| 2076 | |
| 2077 | static UA_INLINE UA_StatusCode |
| 2078 | UA_ChunkType_copy(const UA_ChunkType *src, UA_ChunkType *dst) { |
| 2079 | return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]); |
| 2080 | } |
| 2081 | |
| 2082 | UA_DEPRECATED static UA_INLINE void |
| 2083 | UA_ChunkType_deleteMembers(UA_ChunkType *p) { |
| 2084 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]); |
| 2085 | } |
| 2086 | |
| 2087 | static UA_INLINE void |
| 2088 | UA_ChunkType_clear(UA_ChunkType *p) { |
| 2089 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]); |
| 2090 | } |
| 2091 | |
| 2092 | static UA_INLINE void |
| 2093 | UA_ChunkType_delete(UA_ChunkType *p) { |
| 2094 | UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]); |
| 2095 | }static UA_INLINE UA_Boolean |
| 2096 | UA_ChunkType_equal(const UA_ChunkType *p1, const UA_ChunkType *p2) { |
| 2097 | return (UA_order(p1, p2, type: &UA_TRANSPORT[UA_TRANSPORT_CHUNKTYPE]) == UA_ORDER_EQ); |
| 2098 | } |
| 2099 | |
| 2100 | |
| 2101 | |
| 2102 | /* TcpMessageHeader */ |
| 2103 | static UA_INLINE void |
| 2104 | UA_TcpMessageHeader_init(UA_TcpMessageHeader *p) { |
| 2105 | memset(s: p, c: 0, n: sizeof(UA_TcpMessageHeader)); |
| 2106 | } |
| 2107 | |
| 2108 | static UA_INLINE UA_TcpMessageHeader * |
| 2109 | UA_TcpMessageHeader_new(void) { |
| 2110 | return (UA_TcpMessageHeader*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]); |
| 2111 | } |
| 2112 | |
| 2113 | static UA_INLINE UA_StatusCode |
| 2114 | UA_TcpMessageHeader_copy(const UA_TcpMessageHeader *src, UA_TcpMessageHeader *dst) { |
| 2115 | return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]); |
| 2116 | } |
| 2117 | |
| 2118 | UA_DEPRECATED static UA_INLINE void |
| 2119 | UA_TcpMessageHeader_deleteMembers(UA_TcpMessageHeader *p) { |
| 2120 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]); |
| 2121 | } |
| 2122 | |
| 2123 | static UA_INLINE void |
| 2124 | UA_TcpMessageHeader_clear(UA_TcpMessageHeader *p) { |
| 2125 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]); |
| 2126 | } |
| 2127 | |
| 2128 | static UA_INLINE void |
| 2129 | UA_TcpMessageHeader_delete(UA_TcpMessageHeader *p) { |
| 2130 | UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]); |
| 2131 | }static UA_INLINE UA_Boolean |
| 2132 | UA_TcpMessageHeader_equal(const UA_TcpMessageHeader *p1, const UA_TcpMessageHeader *p2) { |
| 2133 | return (UA_order(p1, p2, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER]) == UA_ORDER_EQ); |
| 2134 | } |
| 2135 | |
| 2136 | |
| 2137 | |
| 2138 | /* TcpHelloMessage */ |
| 2139 | static UA_INLINE void |
| 2140 | UA_TcpHelloMessage_init(UA_TcpHelloMessage *p) { |
| 2141 | memset(s: p, c: 0, n: sizeof(UA_TcpHelloMessage)); |
| 2142 | } |
| 2143 | |
| 2144 | static UA_INLINE UA_TcpHelloMessage * |
| 2145 | UA_TcpHelloMessage_new(void) { |
| 2146 | return (UA_TcpHelloMessage*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]); |
| 2147 | } |
| 2148 | |
| 2149 | static UA_INLINE UA_StatusCode |
| 2150 | UA_TcpHelloMessage_copy(const UA_TcpHelloMessage *src, UA_TcpHelloMessage *dst) { |
| 2151 | return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]); |
| 2152 | } |
| 2153 | |
| 2154 | UA_DEPRECATED static UA_INLINE void |
| 2155 | UA_TcpHelloMessage_deleteMembers(UA_TcpHelloMessage *p) { |
| 2156 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]); |
| 2157 | } |
| 2158 | |
| 2159 | static UA_INLINE void |
| 2160 | UA_TcpHelloMessage_clear(UA_TcpHelloMessage *p) { |
| 2161 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]); |
| 2162 | } |
| 2163 | |
| 2164 | static UA_INLINE void |
| 2165 | UA_TcpHelloMessage_delete(UA_TcpHelloMessage *p) { |
| 2166 | UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]); |
| 2167 | }static UA_INLINE UA_Boolean |
| 2168 | UA_TcpHelloMessage_equal(const UA_TcpHelloMessage *p1, const UA_TcpHelloMessage *p2) { |
| 2169 | return (UA_order(p1, p2, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE]) == UA_ORDER_EQ); |
| 2170 | } |
| 2171 | |
| 2172 | |
| 2173 | |
| 2174 | /* TcpReverseHelloMessage */ |
| 2175 | static UA_INLINE void |
| 2176 | UA_TcpReverseHelloMessage_init(UA_TcpReverseHelloMessage *p) { |
| 2177 | memset(s: p, c: 0, n: sizeof(UA_TcpReverseHelloMessage)); |
| 2178 | } |
| 2179 | |
| 2180 | static UA_INLINE UA_TcpReverseHelloMessage * |
| 2181 | UA_TcpReverseHelloMessage_new(void) { |
| 2182 | return (UA_TcpReverseHelloMessage*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_TCPREVERSEHELLOMESSAGE]); |
| 2183 | } |
| 2184 | |
| 2185 | static UA_INLINE UA_StatusCode |
| 2186 | UA_TcpReverseHelloMessage_copy(const UA_TcpReverseHelloMessage *src, UA_TcpReverseHelloMessage *dst) { |
| 2187 | return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_TCPREVERSEHELLOMESSAGE]); |
| 2188 | } |
| 2189 | |
| 2190 | UA_DEPRECATED static UA_INLINE void |
| 2191 | UA_TcpReverseHelloMessage_deleteMembers(UA_TcpReverseHelloMessage *p) { |
| 2192 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPREVERSEHELLOMESSAGE]); |
| 2193 | } |
| 2194 | |
| 2195 | static UA_INLINE void |
| 2196 | UA_TcpReverseHelloMessage_clear(UA_TcpReverseHelloMessage *p) { |
| 2197 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPREVERSEHELLOMESSAGE]); |
| 2198 | } |
| 2199 | |
| 2200 | static UA_INLINE void |
| 2201 | UA_TcpReverseHelloMessage_delete(UA_TcpReverseHelloMessage *p) { |
| 2202 | UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPREVERSEHELLOMESSAGE]); |
| 2203 | }static UA_INLINE UA_Boolean |
| 2204 | UA_TcpReverseHelloMessage_equal(const UA_TcpReverseHelloMessage *p1, const UA_TcpReverseHelloMessage *p2) { |
| 2205 | return (UA_order(p1, p2, type: &UA_TRANSPORT[UA_TRANSPORT_TCPREVERSEHELLOMESSAGE]) == UA_ORDER_EQ); |
| 2206 | } |
| 2207 | |
| 2208 | |
| 2209 | |
| 2210 | /* TcpAcknowledgeMessage */ |
| 2211 | static UA_INLINE void |
| 2212 | UA_TcpAcknowledgeMessage_init(UA_TcpAcknowledgeMessage *p) { |
| 2213 | memset(s: p, c: 0, n: sizeof(UA_TcpAcknowledgeMessage)); |
| 2214 | } |
| 2215 | |
| 2216 | static UA_INLINE UA_TcpAcknowledgeMessage * |
| 2217 | UA_TcpAcknowledgeMessage_new(void) { |
| 2218 | return (UA_TcpAcknowledgeMessage*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]); |
| 2219 | } |
| 2220 | |
| 2221 | static UA_INLINE UA_StatusCode |
| 2222 | UA_TcpAcknowledgeMessage_copy(const UA_TcpAcknowledgeMessage *src, UA_TcpAcknowledgeMessage *dst) { |
| 2223 | return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]); |
| 2224 | } |
| 2225 | |
| 2226 | UA_DEPRECATED static UA_INLINE void |
| 2227 | UA_TcpAcknowledgeMessage_deleteMembers(UA_TcpAcknowledgeMessage *p) { |
| 2228 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]); |
| 2229 | } |
| 2230 | |
| 2231 | static UA_INLINE void |
| 2232 | UA_TcpAcknowledgeMessage_clear(UA_TcpAcknowledgeMessage *p) { |
| 2233 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]); |
| 2234 | } |
| 2235 | |
| 2236 | static UA_INLINE void |
| 2237 | UA_TcpAcknowledgeMessage_delete(UA_TcpAcknowledgeMessage *p) { |
| 2238 | UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]); |
| 2239 | }static UA_INLINE UA_Boolean |
| 2240 | UA_TcpAcknowledgeMessage_equal(const UA_TcpAcknowledgeMessage *p1, const UA_TcpAcknowledgeMessage *p2) { |
| 2241 | return (UA_order(p1, p2, type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE]) == UA_ORDER_EQ); |
| 2242 | } |
| 2243 | |
| 2244 | |
| 2245 | |
| 2246 | /* TcpErrorMessage */ |
| 2247 | static UA_INLINE void |
| 2248 | UA_TcpErrorMessage_init(UA_TcpErrorMessage *p) { |
| 2249 | memset(s: p, c: 0, n: sizeof(UA_TcpErrorMessage)); |
| 2250 | } |
| 2251 | |
| 2252 | static UA_INLINE UA_TcpErrorMessage * |
| 2253 | UA_TcpErrorMessage_new(void) { |
| 2254 | return (UA_TcpErrorMessage*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]); |
| 2255 | } |
| 2256 | |
| 2257 | static UA_INLINE UA_StatusCode |
| 2258 | UA_TcpErrorMessage_copy(const UA_TcpErrorMessage *src, UA_TcpErrorMessage *dst) { |
| 2259 | return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]); |
| 2260 | } |
| 2261 | |
| 2262 | UA_DEPRECATED static UA_INLINE void |
| 2263 | UA_TcpErrorMessage_deleteMembers(UA_TcpErrorMessage *p) { |
| 2264 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]); |
| 2265 | } |
| 2266 | |
| 2267 | static UA_INLINE void |
| 2268 | UA_TcpErrorMessage_clear(UA_TcpErrorMessage *p) { |
| 2269 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]); |
| 2270 | } |
| 2271 | |
| 2272 | static UA_INLINE void |
| 2273 | UA_TcpErrorMessage_delete(UA_TcpErrorMessage *p) { |
| 2274 | UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]); |
| 2275 | }static UA_INLINE UA_Boolean |
| 2276 | UA_TcpErrorMessage_equal(const UA_TcpErrorMessage *p1, const UA_TcpErrorMessage *p2) { |
| 2277 | return (UA_order(p1, p2, type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE]) == UA_ORDER_EQ); |
| 2278 | } |
| 2279 | |
| 2280 | |
| 2281 | |
| 2282 | /* AsymmetricAlgorithmSecurityHeader */ |
| 2283 | static UA_INLINE void |
| 2284 | UA_AsymmetricAlgorithmSecurityHeader_init(UA_AsymmetricAlgorithmSecurityHeader *p) { |
| 2285 | memset(s: p, c: 0, n: sizeof(UA_AsymmetricAlgorithmSecurityHeader)); |
| 2286 | } |
| 2287 | |
| 2288 | static UA_INLINE UA_AsymmetricAlgorithmSecurityHeader * |
| 2289 | UA_AsymmetricAlgorithmSecurityHeader_new(void) { |
| 2290 | return (UA_AsymmetricAlgorithmSecurityHeader*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]); |
| 2291 | } |
| 2292 | |
| 2293 | static UA_INLINE UA_StatusCode |
| 2294 | UA_AsymmetricAlgorithmSecurityHeader_copy(const UA_AsymmetricAlgorithmSecurityHeader *src, UA_AsymmetricAlgorithmSecurityHeader *dst) { |
| 2295 | return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]); |
| 2296 | } |
| 2297 | |
| 2298 | UA_DEPRECATED static UA_INLINE void |
| 2299 | UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(UA_AsymmetricAlgorithmSecurityHeader *p) { |
| 2300 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]); |
| 2301 | } |
| 2302 | |
| 2303 | static UA_INLINE void |
| 2304 | UA_AsymmetricAlgorithmSecurityHeader_clear(UA_AsymmetricAlgorithmSecurityHeader *p) { |
| 2305 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]); |
| 2306 | } |
| 2307 | |
| 2308 | static UA_INLINE void |
| 2309 | UA_AsymmetricAlgorithmSecurityHeader_delete(UA_AsymmetricAlgorithmSecurityHeader *p) { |
| 2310 | UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]); |
| 2311 | }static UA_INLINE UA_Boolean |
| 2312 | UA_AsymmetricAlgorithmSecurityHeader_equal(const UA_AsymmetricAlgorithmSecurityHeader *p1, const UA_AsymmetricAlgorithmSecurityHeader *p2) { |
| 2313 | return (UA_order(p1, p2, type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER]) == UA_ORDER_EQ); |
| 2314 | } |
| 2315 | |
| 2316 | |
| 2317 | |
| 2318 | /* SequenceHeader */ |
| 2319 | static UA_INLINE void |
| 2320 | UA_SequenceHeader_init(UA_SequenceHeader *p) { |
| 2321 | memset(s: p, c: 0, n: sizeof(UA_SequenceHeader)); |
| 2322 | } |
| 2323 | |
| 2324 | static UA_INLINE UA_SequenceHeader * |
| 2325 | UA_SequenceHeader_new(void) { |
| 2326 | return (UA_SequenceHeader*)UA_new(type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]); |
| 2327 | } |
| 2328 | |
| 2329 | static UA_INLINE UA_StatusCode |
| 2330 | UA_SequenceHeader_copy(const UA_SequenceHeader *src, UA_SequenceHeader *dst) { |
| 2331 | return UA_copy(src, dst, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]); |
| 2332 | } |
| 2333 | |
| 2334 | UA_DEPRECATED static UA_INLINE void |
| 2335 | UA_SequenceHeader_deleteMembers(UA_SequenceHeader *p) { |
| 2336 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]); |
| 2337 | } |
| 2338 | |
| 2339 | static UA_INLINE void |
| 2340 | UA_SequenceHeader_clear(UA_SequenceHeader *p) { |
| 2341 | UA_clear(p, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]); |
| 2342 | } |
| 2343 | |
| 2344 | static UA_INLINE void |
| 2345 | UA_SequenceHeader_delete(UA_SequenceHeader *p) { |
| 2346 | UA_delete(p, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]); |
| 2347 | }static UA_INLINE UA_Boolean |
| 2348 | UA_SequenceHeader_equal(const UA_SequenceHeader *p1, const UA_SequenceHeader *p2) { |
| 2349 | return (UA_order(p1, p2, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER]) == UA_ORDER_EQ); |
| 2350 | } |
| 2351 | |
| 2352 | |
| 2353 | |
| 2354 | #if defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 6 |
| 2355 | # pragma GCC diagnostic pop |
| 2356 | #endif |
| 2357 | |
| 2358 | _UA_END_DECLS |
| 2359 | |
| 2360 | |
| 2361 | /**** amalgamated original file "/src/ua_securechannel.h" ****/ |
| 2362 | |
| 2363 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 2364 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 2365 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 2366 | * |
| 2367 | * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 2368 | * Copyright 2017 (c) Florian Palm |
| 2369 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 2370 | * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB |
| 2371 | */ |
| 2372 | |
| 2373 | |
| 2374 | |
| 2375 | |
| 2376 | _UA_BEGIN_DECLS |
| 2377 | |
| 2378 | struct UA_SecureChannel; |
| 2379 | typedef struct UA_SecureChannel UA_SecureChannel; |
| 2380 | |
| 2381 | /* The message header of the OPC UA binary protocol is structured as follows: |
| 2382 | * |
| 2383 | * - MessageType (3 Byte) |
| 2384 | * - IsFinal (1 Byte) |
| 2385 | * - MessageSize (4 Byte) |
| 2386 | * *** UA_SECURECHANNEL_MESSAGEHEADER_LENGTH *** |
| 2387 | * - SecureChannelId (4 Byte) |
| 2388 | * *** UA_SECURECHANNEL_CHANNELHEADER_LENGTH *** |
| 2389 | * - SecurityHeader (4 Byte TokenId for symmetric, otherwise dynamic length) |
| 2390 | * - SequenceHeader (8 Byte) |
| 2391 | * - SequenceNumber |
| 2392 | * - RequestId |
| 2393 | */ |
| 2394 | |
| 2395 | #define UA_SECURECHANNEL_MESSAGEHEADER_LENGTH 8 |
| 2396 | #define UA_SECURECHANNEL_CHANNELHEADER_LENGTH 12 |
| 2397 | #define UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH 4 |
| 2398 | #define UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH 8 |
| 2399 | #define UA_SECURECHANNEL_SYMMETRIC_HEADER_UNENCRYPTEDLENGTH \ |
| 2400 | (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + \ |
| 2401 | UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH) |
| 2402 | #define UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH \ |
| 2403 | (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + \ |
| 2404 | UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH + \ |
| 2405 | UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH) |
| 2406 | |
| 2407 | /* Minimum length of a valid message (ERR message with an empty reason) */ |
| 2408 | #define UA_SECURECHANNEL_MESSAGE_MIN_LENGTH 16 |
| 2409 | |
| 2410 | /* The Session implementation differs between client and server. Still, it is |
| 2411 | * expected that the Session structure begins with the SessionHeader. This is |
| 2412 | * the interface that will be used by the SecureChannel. The lifecycle of |
| 2413 | * Sessions is independent of the underlying SecureChannel. But every Session |
| 2414 | * can be attached to only one SecureChannel. */ |
| 2415 | typedef struct UA_SessionHeader { |
| 2416 | SLIST_ENTRY(UA_SessionHeader) next; |
| 2417 | UA_NodeId authenticationToken; |
| 2418 | UA_Boolean serverSession; /* Disambiguate client and server session */ |
| 2419 | UA_SecureChannel *channel; /* The pointer back to the SecureChannel in the session. */ |
| 2420 | } UA_SessionHeader; |
| 2421 | |
| 2422 | /* For chunked requests */ |
| 2423 | typedef struct UA_Chunk { |
| 2424 | TAILQ_ENTRY(UA_Chunk) pointers; |
| 2425 | UA_ByteString bytes; |
| 2426 | UA_MessageType messageType; |
| 2427 | UA_ChunkType chunkType; |
| 2428 | UA_UInt32 requestId; |
| 2429 | UA_Boolean copied; /* Do the bytes point to a buffer from the network or was |
| 2430 | * memory allocated for the chunk separately */ |
| 2431 | } UA_Chunk; |
| 2432 | |
| 2433 | typedef TAILQ_HEAD(UA_ChunkQueue, UA_Chunk) UA_ChunkQueue; |
| 2434 | |
| 2435 | typedef enum { |
| 2436 | UA_SECURECHANNELRENEWSTATE_NORMAL, |
| 2437 | |
| 2438 | /* Client has sent an OPN, but not received a response so far. */ |
| 2439 | UA_SECURECHANNELRENEWSTATE_SENT, |
| 2440 | |
| 2441 | /* The server waits for the first request with the new token for the rollover. |
| 2442 | * The new token is stored in the altSecurityToken. The configured local and |
| 2443 | * remote symmetric encryption keys are the old ones. */ |
| 2444 | UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER, |
| 2445 | |
| 2446 | /* The client already uses the new token. But he waits for the server to respond |
| 2447 | * with the new token to complete the rollover. The old token is stored in |
| 2448 | * altSecurityToken. The local symmetric encryption key is new. The remote |
| 2449 | * encryption key is the old one. */ |
| 2450 | UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT |
| 2451 | } UA_SecureChannelRenewState; |
| 2452 | |
| 2453 | struct UA_SecureChannel { |
| 2454 | UA_SecureChannelState state; |
| 2455 | UA_SecureChannelRenewState renewState; |
| 2456 | UA_MessageSecurityMode securityMode; |
| 2457 | UA_ShutdownReason shutdownReason; |
| 2458 | UA_ConnectionConfig config; |
| 2459 | |
| 2460 | UA_String endpointUrl; |
| 2461 | |
| 2462 | /* Connection handling in the EventLoop */ |
| 2463 | UA_ConnectionManager *connectionManager; |
| 2464 | uintptr_t connectionId; |
| 2465 | |
| 2466 | /* Rules for revolving the token with a renew OPN request: The client is |
| 2467 | * allowed to accept messages with the old token until the OPN response has |
| 2468 | * arrived. The server accepts the old token until one message secured with |
| 2469 | * the new token has arrived. |
| 2470 | * |
| 2471 | * We recognize whether nextSecurityToken contains a valid next token if the |
| 2472 | * ChannelId is not 0. */ |
| 2473 | UA_ChannelSecurityToken securityToken; /* Also contains the channelId */ |
| 2474 | UA_ChannelSecurityToken altSecurityToken; /* Alternative token for the rollover. |
| 2475 | * See the renewState. */ |
| 2476 | |
| 2477 | /* The endpoint and context of the channel */ |
| 2478 | UA_SecurityPolicy *securityPolicy; |
| 2479 | void *channelContext; /* For interaction with the security policy */ |
| 2480 | |
| 2481 | /* Asymmetric encryption info */ |
| 2482 | UA_ByteString remoteCertificate; |
| 2483 | UA_Byte remoteCertificateThumbprint[20]; /* The thumbprint of the remote certificate */ |
| 2484 | |
| 2485 | /* Symmetric encryption nonces. These are used to generate the key material |
| 2486 | * and must not be reused once the keys are in place. |
| 2487 | * |
| 2488 | * Nonces are also used during the CreateSession / ActivateSession |
| 2489 | * handshake. These are not handled here, as the Session handling can |
| 2490 | * overlap with a RenewSecureChannel. */ |
| 2491 | UA_ByteString remoteNonce; |
| 2492 | UA_ByteString localNonce; |
| 2493 | |
| 2494 | UA_UInt32 receiveSequenceNumber; |
| 2495 | UA_UInt32 sendSequenceNumber; |
| 2496 | |
| 2497 | /* Sessions that are bound to the SecureChannel */ |
| 2498 | SLIST_HEAD(, UA_SessionHeader) sessions; |
| 2499 | |
| 2500 | /* (Decrypted) chunks waiting to be processed */ |
| 2501 | UA_ChunkQueue chunks; |
| 2502 | size_t chunksCount; |
| 2503 | size_t chunksLength; |
| 2504 | |
| 2505 | /* Received buffer from which no chunks have been extracted so far */ |
| 2506 | UA_ByteString unprocessed; |
| 2507 | size_t unprocessedOffset; |
| 2508 | UA_Boolean unprocessedCopied; |
| 2509 | UA_DelayedCallback unprocessedDelayed; |
| 2510 | |
| 2511 | UA_CertificateVerification *certificateVerification; |
| 2512 | void *processOPNHeaderApplication; |
| 2513 | UA_StatusCode (*processOPNHeader)(void *application, UA_SecureChannel *channel, |
| 2514 | const UA_AsymmetricAlgorithmSecurityHeader *asymHeader); |
| 2515 | }; |
| 2516 | |
| 2517 | void UA_SecureChannel_init(UA_SecureChannel *channel); |
| 2518 | |
| 2519 | /* Trigger the shutdown */ |
| 2520 | void UA_SecureChannel_shutdown(UA_SecureChannel *channel, |
| 2521 | UA_ShutdownReason shutdownReason); |
| 2522 | |
| 2523 | /* Eventual cleanup after the channel has closed. It is possible to call _init |
| 2524 | * on the channel afterwards to reset it to the fresh status. */ |
| 2525 | void UA_SecureChannel_clear(UA_SecureChannel *channel); |
| 2526 | |
| 2527 | /* Process the remote configuration in the HEL/ACK handshake. The connection |
| 2528 | * config is initialized with the local settings. */ |
| 2529 | UA_StatusCode |
| 2530 | UA_SecureChannel_processHELACK(UA_SecureChannel *channel, |
| 2531 | const UA_TcpAcknowledgeMessage *remoteConfig); |
| 2532 | |
| 2533 | UA_StatusCode |
| 2534 | UA_SecureChannel_setSecurityPolicy(UA_SecureChannel *channel, |
| 2535 | UA_SecurityPolicy *securityPolicy, |
| 2536 | const UA_ByteString *remoteCertificate); |
| 2537 | |
| 2538 | UA_Boolean |
| 2539 | UA_SecureChannel_isConnected(UA_SecureChannel *channel); |
| 2540 | |
| 2541 | /* When a fatal error occurs the Server shall send an Error Message to the |
| 2542 | * Client and close the socket. When a Client encounters one of these errors, it |
| 2543 | * shall also close the socket but does not send an Error Message. After the |
| 2544 | * socket is closed a Client shall try to reconnect automatically using the |
| 2545 | * mechanisms described in [...]. */ |
| 2546 | void |
| 2547 | UA_SecureChannel_sendError(UA_SecureChannel *channel, UA_TcpErrorMessage *error); |
| 2548 | |
| 2549 | /* Remove (partially) received unprocessed chunks */ |
| 2550 | void |
| 2551 | UA_SecureChannel_deleteBuffered(UA_SecureChannel *channel); |
| 2552 | |
| 2553 | /* Wrapper function for generating a local nonce for the supplied channel. Uses |
| 2554 | * the random generator of the channels security policy to allocate and generate |
| 2555 | * a nonce with the specified length. */ |
| 2556 | UA_StatusCode |
| 2557 | UA_SecureChannel_generateLocalNonce(UA_SecureChannel *channel); |
| 2558 | |
| 2559 | UA_StatusCode |
| 2560 | UA_SecureChannel_generateLocalKeys(const UA_SecureChannel *channel); |
| 2561 | |
| 2562 | UA_StatusCode |
| 2563 | generateRemoteKeys(const UA_SecureChannel *channel); |
| 2564 | |
| 2565 | /** |
| 2566 | * Sending Messages |
| 2567 | * ---------------- */ |
| 2568 | |
| 2569 | UA_StatusCode |
| 2570 | UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel, UA_UInt32 requestId, |
| 2571 | const void *content, const UA_DataType *contentType); |
| 2572 | |
| 2573 | UA_StatusCode |
| 2574 | UA_SecureChannel_sendSymmetricMessage(UA_SecureChannel *channel, UA_UInt32 requestId, |
| 2575 | UA_MessageType messageType, void *payload, |
| 2576 | const UA_DataType *payloadType); |
| 2577 | |
| 2578 | /* The MessageContext is forwarded into the encoding layer so that we can send |
| 2579 | * chunks before continuing to encode. This lets us reuse a fixed chunk-sized |
| 2580 | * messages buffer. */ |
| 2581 | typedef struct { |
| 2582 | UA_SecureChannel *channel; |
| 2583 | UA_UInt32 requestId; |
| 2584 | UA_UInt32 messageType; |
| 2585 | |
| 2586 | UA_UInt16 chunksSoFar; |
| 2587 | size_t messageSizeSoFar; |
| 2588 | |
| 2589 | UA_ByteString messageBuffer; |
| 2590 | UA_Byte *buf_pos; |
| 2591 | const UA_Byte *buf_end; |
| 2592 | |
| 2593 | UA_Boolean final; |
| 2594 | } UA_MessageContext; |
| 2595 | |
| 2596 | /* Start the context of a new symmetric message. */ |
| 2597 | UA_StatusCode |
| 2598 | UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel, |
| 2599 | UA_UInt32 requestId, UA_MessageType messageType); |
| 2600 | |
| 2601 | /* Encode the content and send out full chunks. If the return code is good, then |
| 2602 | * the ChunkInfo contains encoded content that has not been sent. If the return |
| 2603 | * code is bad, then the ChunkInfo has been cleaned up internally. */ |
| 2604 | UA_StatusCode |
| 2605 | UA_MessageContext_encode(UA_MessageContext *mc, const void *content, |
| 2606 | const UA_DataType *contentType); |
| 2607 | |
| 2608 | /* Sends a symmetric message already encoded in the context. The context is |
| 2609 | * cleaned up, also in case of errors. */ |
| 2610 | UA_StatusCode |
| 2611 | UA_MessageContext_finish(UA_MessageContext *mc); |
| 2612 | |
| 2613 | /* To be used when a failure occures when a MessageContext is open. Note that |
| 2614 | * the _encode and _finish methods will clean up internally. _abort can be run |
| 2615 | * on a MessageContext that has already been cleaned up before. */ |
| 2616 | void |
| 2617 | UA_MessageContext_abort(UA_MessageContext *mc); |
| 2618 | |
| 2619 | /** |
| 2620 | * Receive Message |
| 2621 | * --------------- */ |
| 2622 | |
| 2623 | /* Process a received buffer. This always has these three steps: |
| 2624 | * |
| 2625 | * 1. loadBuffer: The chunks in the SecureChannel are cut into chunks. |
| 2626 | * The chunks can still point to the buffer. |
| 2627 | * 2. getCompleteMessage: Assemble chunks into a complete message. This is |
| 2628 | * repeated until an error occours or an empty message is returned. |
| 2629 | * 3. persistBuffer: Make a copy of the remaining unpprocessed bytestring. So |
| 2630 | * that the NetworkManager can reuse or free the packet memory. |
| 2631 | * |
| 2632 | * Note that only MSG and CLO messages are decrypted. HEL/ACK/OPN/... are |
| 2633 | * forwarded verbatim to the application. */ |
| 2634 | UA_StatusCode |
| 2635 | UA_SecureChannel_loadBuffer(UA_SecureChannel *channel, const UA_ByteString buffer); |
| 2636 | |
| 2637 | UA_StatusCode |
| 2638 | UA_SecureChannel_getCompleteMessage(UA_SecureChannel *channel, |
| 2639 | UA_MessageType *messageType, UA_UInt32 *requestId, |
| 2640 | UA_ByteString *payload, UA_Boolean *copied); |
| 2641 | |
| 2642 | UA_StatusCode |
| 2643 | UA_SecureChannel_persistBuffer(UA_SecureChannel *channel); |
| 2644 | |
| 2645 | /* Internal methods in ua_securechannel_crypto.h */ |
| 2646 | |
| 2647 | void |
| 2648 | hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start, |
| 2649 | const UA_Byte **buf_end); |
| 2650 | |
| 2651 | /* Decrypt and verify via the signature. The chunk buffer is reused to hold the |
| 2652 | * decrypted data after the MessageHeader and SecurityHeader. The chunk length |
| 2653 | * is reduced by the signature, padding and encryption overhead. |
| 2654 | * |
| 2655 | * The offset argument points to the start of the encrypted content (beginning |
| 2656 | * with the SequenceHeader).*/ |
| 2657 | UA_StatusCode |
| 2658 | decryptAndVerifyChunk(const UA_SecureChannel *channel, |
| 2659 | const UA_SecurityPolicyCryptoModule *cryptoModule, |
| 2660 | UA_MessageType messageType, UA_ByteString *chunk, |
| 2661 | size_t offset); |
| 2662 | |
| 2663 | size_t |
| 2664 | calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel); |
| 2665 | |
| 2666 | UA_StatusCode |
| 2667 | prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos, |
| 2668 | const UA_Byte *buf_end, size_t totalLength, |
| 2669 | size_t securityHeaderLength, UA_UInt32 requestId, |
| 2670 | size_t *const finalLength); |
| 2671 | |
| 2672 | void |
| 2673 | setBufPos(UA_MessageContext *mc); |
| 2674 | |
| 2675 | UA_StatusCode |
| 2676 | checkSymHeader(UA_SecureChannel *channel, const UA_UInt32 tokenId); |
| 2677 | |
| 2678 | UA_StatusCode |
| 2679 | checkAsymHeader(UA_SecureChannel *channel, |
| 2680 | const UA_AsymmetricAlgorithmSecurityHeader *asymHeader); |
| 2681 | |
| 2682 | void |
| 2683 | padChunk(UA_SecureChannel *channel, const UA_SecurityPolicyCryptoModule *cm, |
| 2684 | const UA_Byte *start, UA_Byte **pos); |
| 2685 | |
| 2686 | UA_StatusCode |
| 2687 | signAndEncryptAsym(UA_SecureChannel *channel, size_t preSignLength, |
| 2688 | UA_ByteString *buf, size_t securityHeaderLength, |
| 2689 | size_t totalLength); |
| 2690 | |
| 2691 | UA_StatusCode |
| 2692 | signAndEncryptSym(UA_MessageContext *messageContext, |
| 2693 | size_t preSigLength, size_t totalLength); |
| 2694 | |
| 2695 | /** |
| 2696 | * Log Helper |
| 2697 | * ---------- |
| 2698 | * C99 requires at least one element for the variadic argument. If the log |
| 2699 | * statement has no variable arguments, supply an additional NULL. It will be |
| 2700 | * ignored by printf. |
| 2701 | * |
| 2702 | * We have to jump through some hoops to enable the use of format strings |
| 2703 | * without arguments since (pedantic) C99 does not allow variadic macros with |
| 2704 | * zero arguments. So we add a dummy argument that is not printed (%.0s is |
| 2705 | * string of length zero). */ |
| 2706 | |
| 2707 | #define UA_LOG_CHANNEL_INTERNAL(LOGGER, LEVEL, CHANNEL, MSG, ...) \ |
| 2708 | if(UA_LOGLEVEL <= UA_LOGLEVEL_##LEVEL) { \ |
| 2709 | UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_SECURECHANNEL, \ |
| 2710 | "TCP %lu\t| SC %" PRIu32 "\t| " MSG "%.0s", \ |
| 2711 | (long unsigned)(CHANNEL)->connectionId, \ |
| 2712 | (CHANNEL)->securityToken.channelId, __VA_ARGS__); \ |
| 2713 | } |
| 2714 | |
| 2715 | #define UA_LOG_TRACE_CHANNEL(LOGGER, CHANNEL, ...) \ |
| 2716 | UA_MACRO_EXPAND(UA_LOG_CHANNEL_INTERNAL(LOGGER, TRACE, CHANNEL, __VA_ARGS__, "")) |
| 2717 | #define UA_LOG_DEBUG_CHANNEL(LOGGER, CHANNEL, ...) \ |
| 2718 | UA_MACRO_EXPAND(UA_LOG_CHANNEL_INTERNAL(LOGGER, DEBUG, CHANNEL, __VA_ARGS__, "")) |
| 2719 | #define UA_LOG_INFO_CHANNEL(LOGGER, CHANNEL, ...) \ |
| 2720 | UA_MACRO_EXPAND(UA_LOG_CHANNEL_INTERNAL(LOGGER, INFO, CHANNEL, __VA_ARGS__, "")) |
| 2721 | #define UA_LOG_WARNING_CHANNEL(LOGGER, CHANNEL, ...) \ |
| 2722 | UA_MACRO_EXPAND(UA_LOG_CHANNEL_INTERNAL(LOGGER, WARNING, CHANNEL, __VA_ARGS__, "")) |
| 2723 | #define UA_LOG_ERROR_CHANNEL(LOGGER, CHANNEL, ...) \ |
| 2724 | UA_MACRO_EXPAND(UA_LOG_CHANNEL_INTERNAL(LOGGER, ERROR, CHANNEL, __VA_ARGS__, "")) |
| 2725 | #define UA_LOG_FATAL_CHANNEL(LOGGER, CHANNEL, ...) \ |
| 2726 | UA_MACRO_EXPAND(UA_LOG_CHANNEL_INTERNAL(LOGGER, FATAL, CHANNEL, __VA_ARGS__, "")) |
| 2727 | |
| 2728 | _UA_END_DECLS |
| 2729 | |
| 2730 | |
| 2731 | /**** amalgamated original file "/src/server/ua_session.h" ****/ |
| 2732 | |
| 2733 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 2734 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 2735 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 2736 | * |
| 2737 | * Copyright 2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 2738 | * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 2739 | */ |
| 2740 | |
| 2741 | |
| 2742 | |
| 2743 | |
| 2744 | _UA_BEGIN_DECLS |
| 2745 | |
| 2746 | #define UA_MAXCONTINUATIONPOINTS 5 |
| 2747 | |
| 2748 | struct ContinuationPoint; |
| 2749 | typedef struct ContinuationPoint ContinuationPoint; |
| 2750 | |
| 2751 | /* Returns the next entry in the linked list */ |
| 2752 | ContinuationPoint * |
| 2753 | ContinuationPoint_clear(ContinuationPoint *cp); |
| 2754 | |
| 2755 | struct UA_Subscription; |
| 2756 | typedef struct UA_Subscription UA_Subscription; |
| 2757 | |
| 2758 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 2759 | typedef struct UA_PublishResponseEntry { |
| 2760 | SIMPLEQ_ENTRY(UA_PublishResponseEntry) listEntry; |
| 2761 | UA_UInt32 requestId; |
| 2762 | UA_DateTime maxTime; /* Based on the TimeoutHint of the request */ |
| 2763 | UA_PublishResponse response; |
| 2764 | } UA_PublishResponseEntry; |
| 2765 | #endif |
| 2766 | |
| 2767 | typedef struct { |
| 2768 | UA_SessionHeader header; |
| 2769 | UA_ApplicationDescription clientDescription; |
| 2770 | UA_String sessionName; |
| 2771 | UA_Boolean activated; |
| 2772 | void *sessionHandle; /* pointer assigned in userland-callback */ |
| 2773 | UA_NodeId sessionId; |
| 2774 | UA_String clientUserIdOfSession; |
| 2775 | UA_UInt32 maxRequestMessageSize; |
| 2776 | UA_UInt32 maxResponseMessageSize; |
| 2777 | UA_Double timeout; /* in ms */ |
| 2778 | UA_DateTime validTill; |
| 2779 | UA_ByteString serverNonce; |
| 2780 | |
| 2781 | UA_UInt16 availableContinuationPoints; |
| 2782 | ContinuationPoint *continuationPoints; |
| 2783 | |
| 2784 | UA_KeyValueMap *attributes; |
| 2785 | |
| 2786 | /* Localization information */ |
| 2787 | size_t localeIdsSize; |
| 2788 | UA_String *localeIds; |
| 2789 | |
| 2790 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 2791 | /* The queue is ordered according to the priority byte (higher bytes come |
| 2792 | * first). When a late subscription finally publishes, then it is pushed to |
| 2793 | * the back within the sub-set of subscriptions that has the same priority |
| 2794 | * (round-robin scheduling). */ |
| 2795 | size_t subscriptionsSize; |
| 2796 | TAILQ_HEAD(, UA_Subscription) subscriptions; |
| 2797 | |
| 2798 | size_t responseQueueSize; |
| 2799 | SIMPLEQ_HEAD(, UA_PublishResponseEntry) responseQueue; |
| 2800 | |
| 2801 | size_t totalRetransmissionQueueSize; /* Retransmissions of all subscriptions */ |
| 2802 | #endif |
| 2803 | |
| 2804 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 2805 | UA_SessionSecurityDiagnosticsDataType securityDiagnostics; |
| 2806 | UA_SessionDiagnosticsDataType diagnostics; |
| 2807 | #endif |
| 2808 | } UA_Session; |
| 2809 | |
| 2810 | /** |
| 2811 | * Session Lifecycle |
| 2812 | * ----------------- */ |
| 2813 | |
| 2814 | void UA_Session_init(UA_Session *session); |
| 2815 | void UA_Session_clear(UA_Session *session, UA_Server *server); |
| 2816 | void UA_Session_attachToSecureChannel(UA_Session *session, UA_SecureChannel *channel); |
| 2817 | void UA_Session_detachFromSecureChannel(UA_Session *session); |
| 2818 | UA_StatusCode UA_Session_generateNonce(UA_Session *session); |
| 2819 | |
| 2820 | /* If any activity on a session happens, the timeout is extended */ |
| 2821 | void UA_Session_updateLifetime(UA_Session *session); |
| 2822 | |
| 2823 | /** |
| 2824 | * Subscription handling |
| 2825 | * --------------------- */ |
| 2826 | |
| 2827 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 2828 | |
| 2829 | void |
| 2830 | UA_Session_attachSubscription(UA_Session *session, UA_Subscription *sub); |
| 2831 | |
| 2832 | /* If releasePublishResponses is true and the last subscription is removed, all |
| 2833 | * outstanding PublishResponse are sent with a StatusCode. But we don't do that |
| 2834 | * if a Subscription is only detached for modification. */ |
| 2835 | void |
| 2836 | UA_Session_detachSubscription(UA_Server *server, UA_Session *session, |
| 2837 | UA_Subscription *sub, UA_Boolean releasePublishResponses); |
| 2838 | |
| 2839 | UA_Subscription * |
| 2840 | UA_Session_getSubscriptionById(UA_Session *session, |
| 2841 | UA_UInt32 subscriptionId); |
| 2842 | |
| 2843 | |
| 2844 | void |
| 2845 | UA_Session_queuePublishReq(UA_Session *session, |
| 2846 | UA_PublishResponseEntry* entry, |
| 2847 | UA_Boolean head); |
| 2848 | |
| 2849 | UA_PublishResponseEntry * |
| 2850 | UA_Session_dequeuePublishReq(UA_Session *session); |
| 2851 | |
| 2852 | #endif |
| 2853 | |
| 2854 | /** |
| 2855 | * Log Helper |
| 2856 | * ---------- |
| 2857 | * We have to jump through some hoops to enable the use of format strings |
| 2858 | * without arguments since (pedantic) C99 does not allow variadic macros with |
| 2859 | * zero arguments. So we add a dummy argument that is not printed (%.0s is |
| 2860 | * string of length zero). */ |
| 2861 | |
| 2862 | #define UA_LOG_SESSION_INTERNAL(LOGGER, LEVEL, SESSION, MSG, ...) \ |
| 2863 | if(UA_LOGLEVEL <= UA_LOGLEVEL_##LEVEL) { \ |
| 2864 | int nameLen = (SESSION) ? (int)(SESSION)->sessionName.length : 0; \ |
| 2865 | const char *nameStr = (SESSION) ? \ |
| 2866 | (const char*)(SESSION)->sessionName.data : ""; \ |
| 2867 | unsigned long sockId = ((SESSION) && (SESSION)->header.channel) ? \ |
| 2868 | (unsigned long)(SESSION)->header.channel->connectionId : 0; \ |
| 2869 | UA_UInt32 chanId = ((SESSION) && (SESSION)->header.channel) ? \ |
| 2870 | (SESSION)->header.channel->securityToken.channelId : 0; \ |
| 2871 | UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_SESSION, \ |
| 2872 | "TCP %lu\t| SC %" PRIu32 "\t| Session \"%.*s\"\t| " MSG "%.0s", \ |
| 2873 | sockId, chanId, nameLen, nameStr, __VA_ARGS__); \ |
| 2874 | } |
| 2875 | |
| 2876 | #define UA_LOG_TRACE_SESSION(LOGGER, SESSION, ...) \ |
| 2877 | UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, TRACE, SESSION, __VA_ARGS__, "")) |
| 2878 | #define UA_LOG_DEBUG_SESSION(LOGGER, SESSION, ...) \ |
| 2879 | UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, DEBUG, SESSION, __VA_ARGS__, "")) |
| 2880 | #define UA_LOG_INFO_SESSION(LOGGER, SESSION, ...) \ |
| 2881 | UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, INFO, SESSION, __VA_ARGS__, "")) |
| 2882 | #define UA_LOG_WARNING_SESSION(LOGGER, SESSION, ...) \ |
| 2883 | UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, WARNING, SESSION, __VA_ARGS__, "")) |
| 2884 | #define UA_LOG_ERROR_SESSION(LOGGER, SESSION, ...) \ |
| 2885 | UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, ERROR, SESSION, __VA_ARGS__, "")) |
| 2886 | #define UA_LOG_FATAL_SESSION(LOGGER, SESSION, ...) \ |
| 2887 | UA_MACRO_EXPAND(UA_LOG_SESSION_INTERNAL(LOGGER, FATAL, SESSION, __VA_ARGS__, "")) |
| 2888 | |
| 2889 | _UA_END_DECLS |
| 2890 | |
| 2891 | |
| 2892 | /**** amalgamated original file "/src/server/ua_subscription.h" ****/ |
| 2893 | |
| 2894 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 2895 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 2896 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 2897 | * |
| 2898 | * Copyright 2015-2018, 2021-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 2899 | * Copyright 2015 (c) Chris Iatrou |
| 2900 | * Copyright 2015-2016 (c) Sten Grüner |
| 2901 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 2902 | * Copyright 2017 (c) Florian Palm |
| 2903 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 2904 | * Copyright 2017 (c) Mattias Bornhager |
| 2905 | * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 2906 | * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 2907 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
| 2908 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes) |
| 2909 | */ |
| 2910 | |
| 2911 | |
| 2912 | |
| 2913 | |
| 2914 | _UA_BEGIN_DECLS |
| 2915 | |
| 2916 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 2917 | |
| 2918 | /* MonitoredItems create Notifications. Subscriptions collect Notifications from |
| 2919 | * (several) MonitoredItems and publish them to the client. |
| 2920 | * |
| 2921 | * Notifications are put into two queues at the same time. One for the |
| 2922 | * MonitoredItem that generated the notification. Here we can remove it if the |
| 2923 | * space reserved for the MonitoredItem runs full. The second queue is the |
| 2924 | * "global" queue for all Notifications generated in a Subscription. For |
| 2925 | * publication, the notifications are taken out of the "global" queue in the |
| 2926 | * order of their creation. */ |
| 2927 | |
| 2928 | /*****************/ |
| 2929 | /* Notifications */ |
| 2930 | /*****************/ |
| 2931 | |
| 2932 | /* Set to the TAILQ_NEXT pointer of a notification, the sentinel that the |
| 2933 | * notification was not added to the global queue */ |
| 2934 | #define UA_SUBSCRIPTION_QUEUE_SENTINEL ((UA_Notification*)0x01) |
| 2935 | |
| 2936 | typedef struct UA_Notification { |
| 2937 | TAILQ_ENTRY(UA_Notification) localEntry; /* Notification list for the MonitoredItem */ |
| 2938 | TAILQ_ENTRY(UA_Notification) globalEntry; /* Notification list for the Subscription */ |
| 2939 | UA_MonitoredItem *mon; /* Always set */ |
| 2940 | |
| 2941 | /* The event field is used if mon->attributeId is the EventNotifier */ |
| 2942 | union { |
| 2943 | UA_MonitoredItemNotification dataChange; |
| 2944 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 2945 | UA_EventFieldList event; |
| 2946 | #endif |
| 2947 | } data; |
| 2948 | |
| 2949 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 2950 | UA_Boolean isOverflowEvent; /* Counted manually */ |
| 2951 | #endif |
| 2952 | } UA_Notification; |
| 2953 | |
| 2954 | /* Initializes and sets the sentinel pointers */ |
| 2955 | UA_Notification * UA_Notification_new(void); |
| 2956 | |
| 2957 | /* Notifications are always added to the queue of the MonitoredItem. That queue |
| 2958 | * can overflow. If Notifications are reported, they are also added to the |
| 2959 | * global queue of the Subscription. There they are picked up by the publishing |
| 2960 | * callback. |
| 2961 | * |
| 2962 | * There are two ways Notifications can be put into the global queue of the |
| 2963 | * Subscription: They are added because the MonitoringMode of the MonitoredItem |
| 2964 | * is "reporting". Or the MonitoringMode is "sampling" and a link is trigered |
| 2965 | * that puts the last Notification into the global queue. */ |
| 2966 | void UA_Notification_enqueueAndTrigger(UA_Server *server, |
| 2967 | UA_Notification *n); |
| 2968 | |
| 2969 | /* Dequeue and delete the notification */ |
| 2970 | void UA_Notification_delete(UA_Notification *n); |
| 2971 | |
| 2972 | /* A NotificationMessage contains an array of notifications. |
| 2973 | * Sent NotificationMessages are stored for the republish service. */ |
| 2974 | typedef struct UA_NotificationMessageEntry { |
| 2975 | TAILQ_ENTRY(UA_NotificationMessageEntry) listEntry; |
| 2976 | UA_NotificationMessage message; |
| 2977 | } UA_NotificationMessageEntry; |
| 2978 | |
| 2979 | /* Queue Definitions */ |
| 2980 | typedef TAILQ_HEAD(NotificationQueue, UA_Notification) NotificationQueue; |
| 2981 | typedef TAILQ_HEAD(NotificationMessageQueue, UA_NotificationMessageEntry) |
| 2982 | NotificationMessageQueue; |
| 2983 | |
| 2984 | /*****************/ |
| 2985 | /* MonitoredItem */ |
| 2986 | /*****************/ |
| 2987 | |
| 2988 | /* The type of sampling for MonitoredItems depends on the sampling interval. |
| 2989 | * |
| 2990 | * >0: Cyclic callback |
| 2991 | * =0: Attached to the node. Sampling is triggered after every "write". |
| 2992 | * <0: Attached to the subscription. Triggered just before every "publish". */ |
| 2993 | typedef enum { |
| 2994 | UA_MONITOREDITEMSAMPLINGTYPE_NONE = 0, |
| 2995 | UA_MONITOREDITEMSAMPLINGTYPE_CYCLIC, /* Cyclic callback */ |
| 2996 | UA_MONITOREDITEMSAMPLINGTYPE_EVENT, /* Attached to the node. Can be a "write |
| 2997 | * event" for DataChange MonitoredItems |
| 2998 | * with a zero sampling interval .*/ |
| 2999 | UA_MONITOREDITEMSAMPLINGTYPE_PUBLISH /* Attached to the subscription */ |
| 3000 | } UA_MonitoredItemSamplingType; |
| 3001 | |
| 3002 | struct UA_MonitoredItem { |
| 3003 | UA_DelayedCallback delayedFreePointers; |
| 3004 | LIST_ENTRY(UA_MonitoredItem) listEntry; /* Linked list in the Subscription */ |
| 3005 | UA_Subscription *subscription; /* If NULL, then this is a Local MonitoredItem */ |
| 3006 | UA_UInt32 monitoredItemId; |
| 3007 | |
| 3008 | /* Status and Settings */ |
| 3009 | UA_ReadValueId itemToMonitor; |
| 3010 | UA_MonitoringMode monitoringMode; |
| 3011 | UA_TimestampsToReturn timestampsToReturn; |
| 3012 | UA_Boolean registered; /* Registered in the server / Subscription */ |
| 3013 | UA_DateTime triggeredUntil; /* If the MonitoringMode is SAMPLING, |
| 3014 | * triggering the MonitoredItem puts the latest |
| 3015 | * Notification into the publishing queue (of |
| 3016 | * the Subscription). In addition, the first |
| 3017 | * new sample is also published (and not just |
| 3018 | * sampled) if it occurs within the duration of |
| 3019 | * one publishing cycle after the triggering. */ |
| 3020 | |
| 3021 | /* If the filter is a UA_DataChangeFilter: The DataChangeFilter always |
| 3022 | * contains an absolute deadband definition. Part 8, §6.2 gives the |
| 3023 | * following formula to test for percentage deadbands: |
| 3024 | * |
| 3025 | * DataChange if (absolute value of (last cached value - current value) |
| 3026 | * > (deadbandValue/100.0) * ((high–low) of EURange))) |
| 3027 | * |
| 3028 | * So we can convert from a percentage to an absolute deadband and keep |
| 3029 | * the hot code path simple. |
| 3030 | * |
| 3031 | * TODO: Store the percentage deadband to recompute when the UARange is |
| 3032 | * changed at runtime of the MonitoredItem */ |
| 3033 | UA_MonitoringParameters parameters; |
| 3034 | |
| 3035 | /* Sampling */ |
| 3036 | UA_MonitoredItemSamplingType samplingType; |
| 3037 | union { |
| 3038 | UA_UInt64 callbackId; |
| 3039 | UA_MonitoredItem *nodeListNext; /* Event-Based: Attached to Node */ |
| 3040 | LIST_ENTRY(UA_MonitoredItem) subscriptionSampling; /* Linked to publish |
| 3041 | * interval */ |
| 3042 | } sampling; |
| 3043 | UA_DataValue lastValue; |
| 3044 | |
| 3045 | /* Triggering Links */ |
| 3046 | size_t triggeringLinksSize; |
| 3047 | UA_UInt32 *triggeringLinks; |
| 3048 | |
| 3049 | /* Notification Queue */ |
| 3050 | NotificationQueue queue; |
| 3051 | size_t queueSize; /* This is the current size. See also the configured |
| 3052 | * (maximum) queueSize in the parameters. */ |
| 3053 | size_t eventOverflows; /* Separate counter for the queue. Can at most double |
| 3054 | * the queue size */ |
| 3055 | }; |
| 3056 | |
| 3057 | void UA_MonitoredItem_init(UA_MonitoredItem *mon); |
| 3058 | void UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *mon); |
| 3059 | void UA_MonitoredItem_removeOverflowInfoBits(UA_MonitoredItem *mon); |
| 3060 | void UA_MonitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *mon); |
| 3061 | void UA_Server_registerMonitoredItem(UA_Server *server, UA_MonitoredItem *mon); |
| 3062 | |
| 3063 | /* Register sampling. Either by adding a repeated callback or by adding the |
| 3064 | * MonitoredItem to a linked list in the node. */ |
| 3065 | UA_StatusCode |
| 3066 | UA_MonitoredItem_registerSampling(UA_Server *server, UA_MonitoredItem *mon); |
| 3067 | |
| 3068 | void |
| 3069 | UA_MonitoredItem_unregisterSampling(UA_Server *server, UA_MonitoredItem *mon); |
| 3070 | |
| 3071 | UA_StatusCode |
| 3072 | UA_MonitoredItem_setMonitoringMode(UA_Server *server, UA_MonitoredItem *mon, |
| 3073 | UA_MonitoringMode monitoringMode); |
| 3074 | |
| 3075 | |
| 3076 | /* Do not use the value after calling this. It will be moved to mon or freed. */ |
| 3077 | void |
| 3078 | UA_MonitoredItem_processSampledValue(UA_Server *server, UA_MonitoredItem *mon, |
| 3079 | UA_DataValue *value); |
| 3080 | |
| 3081 | UA_StatusCode |
| 3082 | UA_MonitoredItem_removeLink(UA_Subscription *sub, UA_MonitoredItem *mon, |
| 3083 | UA_UInt32 linkId); |
| 3084 | |
| 3085 | UA_StatusCode |
| 3086 | UA_MonitoredItem_addLink(UA_Subscription *sub, UA_MonitoredItem *mon, |
| 3087 | UA_UInt32 linkId); |
| 3088 | |
| 3089 | UA_StatusCode |
| 3090 | UA_MonitoredItem_createDataChangeNotification(UA_Server *server, UA_MonitoredItem *mon, |
| 3091 | const UA_DataValue *value); |
| 3092 | |
| 3093 | /* Remove entries until mon->maxQueueSize is reached. Sets infobits for lost |
| 3094 | * data if required. */ |
| 3095 | void UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon); |
| 3096 | |
| 3097 | /****************/ |
| 3098 | /* Subscription */ |
| 3099 | /****************/ |
| 3100 | |
| 3101 | /* We use only a subset of the states defined in the standard */ |
| 3102 | typedef enum { |
| 3103 | UA_SUBSCRIPTIONSTATE_STOPPED = 0, |
| 3104 | UA_SUBSCRIPTIONSTATE_REMOVING, |
| 3105 | UA_SUBSCRIPTIONSTATE_ENABLED_NOPUBLISH, /* only keepalive */ |
| 3106 | UA_SUBSCRIPTIONSTATE_ENABLED |
| 3107 | } UA_SubscriptionState; |
| 3108 | |
| 3109 | /* Subscriptions are managed in a server-wide linked list. If they are attached |
| 3110 | * to a Session, then they are additionaly in the per-Session linked-list. A |
| 3111 | * subscription is always generated for a Session. But the CloseSession Service |
| 3112 | * may keep Subscriptions intact beyond the Session lifetime. They can then be |
| 3113 | * re-bound to a new Session with the TransferSubscription Service. */ |
| 3114 | struct UA_Subscription { |
| 3115 | UA_DelayedCallback delayedFreePointers; |
| 3116 | LIST_ENTRY(UA_Subscription) serverListEntry; |
| 3117 | /* Ordered according to the priority byte and round-robin scheduling for |
| 3118 | * late subscriptions. See ua_session.h. Only set if session != NULL. */ |
| 3119 | TAILQ_ENTRY(UA_Subscription) sessionListEntry; |
| 3120 | UA_Session *session; /* May be NULL if no session is attached. */ |
| 3121 | UA_UInt32 subscriptionId; |
| 3122 | |
| 3123 | /* Settings */ |
| 3124 | UA_UInt32 lifeTimeCount; |
| 3125 | UA_UInt32 maxKeepAliveCount; |
| 3126 | UA_Double publishingInterval; /* in ms */ |
| 3127 | UA_UInt32 notificationsPerPublish; |
| 3128 | UA_Byte priority; |
| 3129 | |
| 3130 | /* Runtime information */ |
| 3131 | UA_SubscriptionState state; |
| 3132 | UA_Boolean late; |
| 3133 | UA_StatusCode statusChange; /* If set, a notification is generated and the |
| 3134 | * Subscription is deleted within |
| 3135 | * UA_Subscription_publish. */ |
| 3136 | UA_UInt32 nextSequenceNumber; |
| 3137 | UA_UInt32 currentKeepAliveCount; |
| 3138 | UA_UInt32 currentLifetimeCount; |
| 3139 | |
| 3140 | /* Publish Callback. Registered if id > 0. */ |
| 3141 | UA_UInt64 publishCallbackId; |
| 3142 | |
| 3143 | /* Delayed callback to schedule publication of more notifications */ |
| 3144 | UA_Boolean delayedCallbackRegistered; |
| 3145 | UA_DelayedCallback delayedMoreNotifications; |
| 3146 | |
| 3147 | /* MonitoredItems */ |
| 3148 | UA_UInt32 lastMonitoredItemId; /* increase the identifiers */ |
| 3149 | LIST_HEAD(, UA_MonitoredItem) monitoredItems; |
| 3150 | UA_UInt32 monitoredItemsSize; |
| 3151 | |
| 3152 | /* MonitoredItems that are sampled in every publish callback (with the |
| 3153 | * publish interval of the subscription) */ |
| 3154 | LIST_HEAD(, UA_MonitoredItem) samplingMonitoredItems; |
| 3155 | |
| 3156 | /* Global list of notifications from the MonitoredItems */ |
| 3157 | TAILQ_HEAD(, UA_Notification) notificationQueue; |
| 3158 | UA_UInt32 notificationQueueSize; /* Total queue size */ |
| 3159 | UA_UInt32 dataChangeNotifications; |
| 3160 | UA_UInt32 eventNotifications; |
| 3161 | |
| 3162 | /* Retransmission Queue */ |
| 3163 | NotificationMessageQueue retransmissionQueue; |
| 3164 | size_t retransmissionQueueSize; |
| 3165 | |
| 3166 | /* Statistics for the server diagnostics. The fields are defined according |
| 3167 | * to the SubscriptionDiagnosticsDataType (Part 5, §12.15). */ |
| 3168 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 3169 | UA_NodeId ns0Id; /* Representation in the Session object */ |
| 3170 | |
| 3171 | UA_UInt32 modifyCount; |
| 3172 | UA_UInt32 enableCount; |
| 3173 | UA_UInt32 disableCount; |
| 3174 | UA_UInt32 republishRequestCount; |
| 3175 | UA_UInt32 republishMessageCount; |
| 3176 | UA_UInt32 transferRequestCount; |
| 3177 | UA_UInt32 transferredToAltClientCount; |
| 3178 | UA_UInt32 transferredToSameClientCount; |
| 3179 | UA_UInt32 publishRequestCount; |
| 3180 | UA_UInt32 dataChangeNotificationsCount; |
| 3181 | UA_UInt32 eventNotificationsCount; |
| 3182 | UA_UInt32 notificationsCount; |
| 3183 | UA_UInt32 latePublishRequestCount; |
| 3184 | UA_UInt32 discardedMessageCount; |
| 3185 | UA_UInt32 monitoringQueueOverflowCount; |
| 3186 | UA_UInt32 eventQueueOverFlowCount; |
| 3187 | #endif |
| 3188 | }; |
| 3189 | |
| 3190 | UA_Subscription * UA_Subscription_new(void); |
| 3191 | |
| 3192 | void |
| 3193 | UA_Subscription_delete(UA_Server *server, UA_Subscription *sub); |
| 3194 | |
| 3195 | UA_StatusCode |
| 3196 | Subscription_setState(UA_Server *server, UA_Subscription *sub, |
| 3197 | UA_SubscriptionState state); |
| 3198 | |
| 3199 | void |
| 3200 | Subscription_resetLifetime(UA_Subscription *sub); |
| 3201 | |
| 3202 | UA_MonitoredItem * |
| 3203 | UA_Subscription_getMonitoredItem(UA_Subscription *sub, |
| 3204 | UA_UInt32 monitoredItemId); |
| 3205 | |
| 3206 | void |
| 3207 | UA_Subscription_publish(UA_Server *server, UA_Subscription *sub); |
| 3208 | |
| 3209 | void |
| 3210 | UA_Subscription_resendData(UA_Server *server, UA_Subscription *sub); |
| 3211 | |
| 3212 | UA_StatusCode |
| 3213 | UA_Subscription_removeRetransmissionMessage(UA_Subscription *sub, |
| 3214 | UA_UInt32 sequenceNumber); |
| 3215 | |
| 3216 | void |
| 3217 | UA_Session_ensurePublishQueueSpace(UA_Server *server, UA_Session *session); |
| 3218 | |
| 3219 | /* Forward declaration for A&C used in ua_server_internal.h" */ |
| 3220 | struct UA_ConditionSource; |
| 3221 | typedef struct UA_ConditionSource UA_ConditionSource; |
| 3222 | |
| 3223 | /* Event Handling */ |
| 3224 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 3225 | |
| 3226 | #define UA_EVENTFILTER_MAXELEMENTS 64 /* Max operator elements */ |
| 3227 | #define UA_EVENTFILTER_MAXOPERANDS 64 /* Max operands per operator */ |
| 3228 | #define UA_EVENTFILTER_MAXSELECT 64 /* Max select clauses */ |
| 3229 | |
| 3230 | UA_StatusCode |
| 3231 | UA_MonitoredItem_addEvent(UA_Server *server, UA_MonitoredItem *mon, |
| 3232 | const UA_NodeId *event); |
| 3233 | |
| 3234 | UA_StatusCode |
| 3235 | generateEventId(UA_ByteString *generatedId); |
| 3236 | |
| 3237 | /* Static validation when the filter is registered */ |
| 3238 | UA_StatusCode |
| 3239 | UA_SimpleAttributeOperandValidation(UA_Server *server, |
| 3240 | const UA_SimpleAttributeOperand *sao); |
| 3241 | |
| 3242 | /* Static validation when the filter is registered */ |
| 3243 | UA_ContentFilterElementResult |
| 3244 | UA_ContentFilterElementValidation(UA_Server *server, size_t operatorIndex, |
| 3245 | size_t operatorsCount, |
| 3246 | const UA_ContentFilterElement *ef); |
| 3247 | |
| 3248 | /* Evaluate content filter, exported only for unit testing */ |
| 3249 | UA_StatusCode |
| 3250 | evaluateWhereClause(UA_Server *server, UA_Session *session, const UA_NodeId *eventNode, |
| 3251 | const UA_ContentFilter *contentFilter, |
| 3252 | UA_ContentFilterResult *contentFilterResult); |
| 3253 | |
| 3254 | #endif |
| 3255 | |
| 3256 | /***********/ |
| 3257 | /* Helpers */ |
| 3258 | /***********/ |
| 3259 | |
| 3260 | /* Setting an integer value within bounds */ |
| 3261 | #define UA_BOUNDEDVALUE_SETWBOUNDS(BOUNDS, SRC, DST) { \ |
| 3262 | if(SRC > BOUNDS.max) DST = BOUNDS.max; \ |
| 3263 | else if(SRC < BOUNDS.min) DST = BOUNDS.min; \ |
| 3264 | else DST = SRC; \ |
| 3265 | } |
| 3266 | |
| 3267 | /* Logging |
| 3268 | * See a description of the tricks used in ua_session.h */ |
| 3269 | #define UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, LEVEL, SUB, MSG, ...) \ |
| 3270 | do { \ |
| 3271 | if((SUB) && (SUB)->session) { \ |
| 3272 | UA_LOG_##LEVEL##_SESSION(LOGGER, (SUB)->session, \ |
| 3273 | "Subscription %" PRIu32 " | " MSG "%.0s", \ |
| 3274 | (SUB)->subscriptionId, __VA_ARGS__); \ |
| 3275 | } else { \ |
| 3276 | UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_SERVER, \ |
| 3277 | "Subscription %" PRIu32 " | " MSG "%.0s", \ |
| 3278 | (SUB) ? (SUB)->subscriptionId : 0, __VA_ARGS__); \ |
| 3279 | } \ |
| 3280 | } while(0) |
| 3281 | |
| 3282 | #if UA_LOGLEVEL <= 100 |
| 3283 | # define UA_LOG_TRACE_SUBSCRIPTION(LOGGER, SUB, ...) \ |
| 3284 | UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, TRACE, SUB, __VA_ARGS__, "")) |
| 3285 | #else |
| 3286 | # define UA_LOG_TRACE_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0) |
| 3287 | #endif |
| 3288 | |
| 3289 | #if UA_LOGLEVEL <= 200 |
| 3290 | # define UA_LOG_DEBUG_SUBSCRIPTION(LOGGER, SUB, ...) \ |
| 3291 | UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, DEBUG, SUB, __VA_ARGS__, "")) |
| 3292 | #else |
| 3293 | # define UA_LOG_DEBUG_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0) |
| 3294 | #endif |
| 3295 | |
| 3296 | #if UA_LOGLEVEL <= 300 |
| 3297 | # define UA_LOG_INFO_SUBSCRIPTION(LOGGER, SUB, ...) \ |
| 3298 | UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, INFO, SUB, __VA_ARGS__, "")) |
| 3299 | #else |
| 3300 | # define UA_LOG_INFO_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0) |
| 3301 | #endif |
| 3302 | |
| 3303 | #if UA_LOGLEVEL <= 400 |
| 3304 | # define UA_LOG_WARNING_SUBSCRIPTION(LOGGER, SUB, ...) \ |
| 3305 | UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, WARNING, SUB, __VA_ARGS__, "")) |
| 3306 | #else |
| 3307 | # define UA_LOG_WARNING_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0) |
| 3308 | #endif |
| 3309 | |
| 3310 | #if UA_LOGLEVEL <= 500 |
| 3311 | # define UA_LOG_ERROR_SUBSCRIPTION(LOGGER, SUB, ...) \ |
| 3312 | UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, ERROR, SUB, __VA_ARGS__, "")) |
| 3313 | #else |
| 3314 | # define UA_LOG_ERROR_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0) |
| 3315 | #endif |
| 3316 | |
| 3317 | #if UA_LOGLEVEL <= 600 |
| 3318 | # define UA_LOG_FATAL_SUBSCRIPTION(LOGGER, SUB, ...) \ |
| 3319 | UA_MACRO_EXPAND(UA_LOG_SUBSCRIPTION_INTERNAL(LOGGER, FATAL, SUB, __VA_ARGS__, "")) |
| 3320 | #else |
| 3321 | # define UA_LOG_FATAL_SUBSCRIPTION(LOGGER, SUB, ...) do {} while(0) |
| 3322 | #endif |
| 3323 | |
| 3324 | #endif /* UA_ENABLE_SUBSCRIPTIONS */ |
| 3325 | |
| 3326 | _UA_END_DECLS |
| 3327 | |
| 3328 | |
| 3329 | /**** amalgamated original file "/src/pubsub/ua_pubsub_networkmessage.h" ****/ |
| 3330 | |
| 3331 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 3332 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3333 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 3334 | * |
| 3335 | * Copyright (c) 2017 - 2018 Fraunhofer IOSB (Author: Tino Bischoff) |
| 3336 | * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner) |
| 3337 | */ |
| 3338 | |
| 3339 | |
| 3340 | |
| 3341 | #ifdef UA_ENABLE_PUBSUB |
| 3342 | |
| 3343 | _UA_BEGIN_DECLS |
| 3344 | |
| 3345 | #define UA_NETWORKMESSAGE_MAX_NONCE_LENGTH 16 |
| 3346 | |
| 3347 | /* DataSet Payload Header */ |
| 3348 | typedef struct { |
| 3349 | UA_Byte count; |
| 3350 | UA_UInt16* dataSetWriterIds; |
| 3351 | } UA_DataSetPayloadHeader; |
| 3352 | |
| 3353 | /* FieldEncoding Enum */ |
| 3354 | typedef enum { |
| 3355 | UA_FIELDENCODING_VARIANT = 0, |
| 3356 | UA_FIELDENCODING_RAWDATA = 1, |
| 3357 | UA_FIELDENCODING_DATAVALUE = 2, |
| 3358 | UA_FIELDENCODING_UNKNOWN = 3 |
| 3359 | } UA_FieldEncoding; |
| 3360 | |
| 3361 | /* DataSetMessage Type */ |
| 3362 | typedef enum { |
| 3363 | UA_DATASETMESSAGE_DATAKEYFRAME = 0, |
| 3364 | UA_DATASETMESSAGE_DATADELTAFRAME = 1, |
| 3365 | UA_DATASETMESSAGE_EVENT = 2, |
| 3366 | UA_DATASETMESSAGE_KEEPALIVE = 3 |
| 3367 | } UA_DataSetMessageType; |
| 3368 | |
| 3369 | /* DataSetMessage Header */ |
| 3370 | typedef struct { |
| 3371 | UA_Boolean dataSetMessageValid; |
| 3372 | UA_FieldEncoding fieldEncoding; |
| 3373 | UA_Boolean dataSetMessageSequenceNrEnabled; |
| 3374 | UA_Boolean timestampEnabled; |
| 3375 | UA_Boolean statusEnabled; |
| 3376 | UA_Boolean configVersionMajorVersionEnabled; |
| 3377 | UA_Boolean configVersionMinorVersionEnabled; |
| 3378 | UA_DataSetMessageType dataSetMessageType; |
| 3379 | UA_Boolean picoSecondsIncluded; |
| 3380 | UA_UInt16 dataSetMessageSequenceNr; |
| 3381 | UA_UtcTime timestamp; |
| 3382 | UA_UInt16 picoSeconds; |
| 3383 | UA_UInt16 status; |
| 3384 | UA_UInt32 configVersionMajorVersion; |
| 3385 | UA_UInt32 configVersionMinorVersion; |
| 3386 | } UA_DataSetMessageHeader; |
| 3387 | |
| 3388 | /** |
| 3389 | * DataSetMessage |
| 3390 | * ^^^^^^^^^^^^^^ */ |
| 3391 | |
| 3392 | typedef struct { |
| 3393 | UA_UInt16 fieldCount; |
| 3394 | UA_DataValue* dataSetFields; |
| 3395 | UA_ByteString rawFields; |
| 3396 | /* Json keys for the dataSetFields: TODO: own dataSetMessageType for json? */ |
| 3397 | UA_String* fieldNames; |
| 3398 | /* This information is for proper en- and decoding needed */ |
| 3399 | UA_DataSetMetaDataType *dataSetMetaDataType; |
| 3400 | } UA_DataSetMessage_DataKeyFrameData; |
| 3401 | |
| 3402 | typedef struct { |
| 3403 | UA_UInt16 fieldIndex; |
| 3404 | UA_DataValue fieldValue; |
| 3405 | } UA_DataSetMessage_DeltaFrameField; |
| 3406 | |
| 3407 | typedef struct { |
| 3408 | UA_UInt16 fieldCount; |
| 3409 | UA_DataSetMessage_DeltaFrameField* deltaFrameFields; |
| 3410 | } UA_DataSetMessage_DataDeltaFrameData; |
| 3411 | |
| 3412 | typedef struct { |
| 3413 | UA_DataSetMessageHeader header; |
| 3414 | union { |
| 3415 | UA_DataSetMessage_DataKeyFrameData keyFrameData; |
| 3416 | UA_DataSetMessage_DataDeltaFrameData deltaFrameData; |
| 3417 | } data; |
| 3418 | size_t configuredSize; |
| 3419 | } UA_DataSetMessage; |
| 3420 | |
| 3421 | typedef struct { |
| 3422 | UA_UInt16* sizes; |
| 3423 | UA_DataSetMessage* dataSetMessages; |
| 3424 | } UA_DataSetPayload; |
| 3425 | |
| 3426 | typedef enum { |
| 3427 | UA_NETWORKMESSAGE_DATASET = 0, |
| 3428 | UA_NETWORKMESSAGE_DISCOVERY_REQUEST = 1, |
| 3429 | UA_NETWORKMESSAGE_DISCOVERY_RESPONSE = 2 |
| 3430 | } UA_NetworkMessageType; |
| 3431 | |
| 3432 | /** |
| 3433 | * UA_NetworkMessageGroupHeader |
| 3434 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ |
| 3435 | typedef struct { |
| 3436 | UA_Boolean writerGroupIdEnabled; |
| 3437 | UA_Boolean groupVersionEnabled; |
| 3438 | UA_Boolean networkMessageNumberEnabled; |
| 3439 | UA_Boolean sequenceNumberEnabled; |
| 3440 | UA_UInt16 writerGroupId; |
| 3441 | UA_UInt32 groupVersion; // spec: type "VersionTime" |
| 3442 | UA_UInt16 networkMessageNumber; |
| 3443 | UA_UInt16 sequenceNumber; |
| 3444 | } UA_NetworkMessageGroupHeader; |
| 3445 | |
| 3446 | /** |
| 3447 | * UA_NetworkMessageSecurityHeader |
| 3448 | * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ |
| 3449 | typedef struct { |
| 3450 | UA_Boolean networkMessageSigned; |
| 3451 | UA_Boolean networkMessageEncrypted; |
| 3452 | UA_Boolean securityFooterEnabled; |
| 3453 | UA_Boolean forceKeyReset; |
| 3454 | UA_UInt32 securityTokenId; // spec: IntegerId |
| 3455 | UA_Byte messageNonce[UA_NETWORKMESSAGE_MAX_NONCE_LENGTH]; |
| 3456 | UA_UInt16 messageNonceSize; |
| 3457 | UA_UInt16 securityFooterSize; |
| 3458 | } UA_NetworkMessageSecurityHeader; |
| 3459 | |
| 3460 | /** |
| 3461 | * UA_NetworkMessage |
| 3462 | * ^^^^^^^^^^^^^^^^^ */ |
| 3463 | typedef struct { |
| 3464 | UA_Byte version; |
| 3465 | UA_Boolean messageIdEnabled; |
| 3466 | UA_String messageId; /* For Json NetworkMessage */ |
| 3467 | UA_Boolean publisherIdEnabled; |
| 3468 | UA_Boolean groupHeaderEnabled; |
| 3469 | UA_Boolean payloadHeaderEnabled; |
| 3470 | UA_Boolean dataSetClassIdEnabled; |
| 3471 | UA_Boolean securityEnabled; |
| 3472 | UA_Boolean timestampEnabled; |
| 3473 | UA_Boolean picosecondsEnabled; |
| 3474 | UA_Boolean chunkMessage; |
| 3475 | UA_Boolean promotedFieldsEnabled; |
| 3476 | UA_NetworkMessageType networkMessageType; |
| 3477 | UA_PublisherIdType publisherIdType; |
| 3478 | UA_PublisherId publisherId; |
| 3479 | UA_Guid dataSetClassId; |
| 3480 | |
| 3481 | UA_NetworkMessageGroupHeader groupHeader; |
| 3482 | |
| 3483 | union { |
| 3484 | UA_DataSetPayloadHeader dataSetPayloadHeader; |
| 3485 | } payloadHeader; |
| 3486 | |
| 3487 | UA_DateTime timestamp; |
| 3488 | UA_UInt16 picoseconds; |
| 3489 | UA_UInt16 promotedFieldsSize; |
| 3490 | UA_Variant* promotedFields; /* BaseDataType */ |
| 3491 | |
| 3492 | UA_NetworkMessageSecurityHeader securityHeader; |
| 3493 | |
| 3494 | union { |
| 3495 | UA_DataSetPayload dataSetPayload; |
| 3496 | } payload; |
| 3497 | |
| 3498 | UA_ByteString securityFooter; |
| 3499 | } UA_NetworkMessage; |
| 3500 | |
| 3501 | /**********************************************/ |
| 3502 | /* Network Message Offsets */ |
| 3503 | /**********************************************/ |
| 3504 | |
| 3505 | /* Offsets for buffered messages in the PubSub fast path. */ |
| 3506 | typedef enum { |
| 3507 | UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER, |
| 3508 | UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER, |
| 3509 | UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING, |
| 3510 | UA_PUBSUB_OFFSETTYPE_TIMESTAMP_PICOSECONDS, |
| 3511 | UA_PUBSUB_OFFSETTYPE_TIMESTAMP, /* source pointer */ |
| 3512 | UA_PUBSUB_OFFSETTYPE_TIMESTAMP_NOW, /* no source */ |
| 3513 | UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE, |
| 3514 | UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE_EXTERNAL, |
| 3515 | UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT, |
| 3516 | UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT_EXTERNAL, |
| 3517 | UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW, |
| 3518 | UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW_EXTERNAL, |
| 3519 | /* For subscriber RT */ |
| 3520 | UA_PUBSUB_OFFSETTYPE_PUBLISHERID, |
| 3521 | UA_PUBSUB_OFFSETTYPE_WRITERGROUPID, |
| 3522 | UA_PUBSUB_OFFSETTYPE_DATASETWRITERID |
| 3523 | /* Add more offset types as needed */ |
| 3524 | } UA_NetworkMessageOffsetType; |
| 3525 | |
| 3526 | typedef struct { |
| 3527 | UA_NetworkMessageOffsetType contentType; |
| 3528 | union { |
| 3529 | UA_UInt16 sequenceNumber; |
| 3530 | UA_DataValue **externalValue; |
| 3531 | UA_DataValue value; |
| 3532 | } content; |
| 3533 | size_t offset; |
| 3534 | } UA_NetworkMessageOffset; |
| 3535 | |
| 3536 | typedef struct { |
| 3537 | UA_ByteString buffer; /* The precomputed message buffer */ |
| 3538 | UA_NetworkMessageOffset *offsets; /* Offsets for changes in the message buffer */ |
| 3539 | size_t offsetsSize; |
| 3540 | UA_NetworkMessage *nm; /* The precomputed NetworkMessage for subscriber */ |
| 3541 | size_t rawMessageLength; |
| 3542 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 3543 | UA_ByteString encryptBuffer; /* The precomputed message buffer is copied |
| 3544 | * into the encrypt buffer for encryption and |
| 3545 | * signing*/ |
| 3546 | UA_Byte *payloadPosition; /* Payload Position of the message to encrypt*/ |
| 3547 | #endif |
| 3548 | } UA_NetworkMessageOffsetBuffer; |
| 3549 | |
| 3550 | void |
| 3551 | UA_NetworkMessageOffsetBuffer_clear(UA_NetworkMessageOffsetBuffer *nmob); |
| 3552 | |
| 3553 | UA_StatusCode |
| 3554 | UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer); |
| 3555 | |
| 3556 | UA_StatusCode |
| 3557 | UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer, |
| 3558 | const UA_ByteString *src, size_t *bufferPosition); |
| 3559 | |
| 3560 | /** |
| 3561 | * DataSetMessage |
| 3562 | * ^^^^^^^^^^^^^^ */ |
| 3563 | |
| 3564 | UA_StatusCode |
| 3565 | UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader* src, |
| 3566 | UA_Byte **bufPos, const UA_Byte *bufEnd); |
| 3567 | |
| 3568 | UA_StatusCode |
| 3569 | UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, |
| 3570 | UA_DataSetMessageHeader* dst); |
| 3571 | |
| 3572 | UA_StatusCode |
| 3573 | UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos, |
| 3574 | const UA_Byte *bufEnd); |
| 3575 | |
| 3576 | UA_StatusCode |
| 3577 | UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset, |
| 3578 | UA_DataSetMessage* dst, UA_UInt16 dsmSize, |
| 3579 | const UA_DataTypeArray *customTypes, |
| 3580 | UA_DataSetMetaDataType *dsm); |
| 3581 | |
| 3582 | size_t |
| 3583 | UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage *p, |
| 3584 | UA_NetworkMessageOffsetBuffer *offsetBuffer, |
| 3585 | size_t currentOffset); |
| 3586 | |
| 3587 | void UA_DataSetMessage_clear(UA_DataSetMessage* p); |
| 3588 | |
| 3589 | /** |
| 3590 | * NetworkMessage Encoding |
| 3591 | * ^^^^^^^^^^^^^^^^^^^^^^^ */ |
| 3592 | |
| 3593 | /* If dataToEncryptStart not-NULL, then it will be set to the start-position of |
| 3594 | * the payload in the buffer. */ |
| 3595 | UA_StatusCode |
| 3596 | UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, |
| 3597 | UA_Byte **bufPos, const UA_Byte *bufEnd, |
| 3598 | UA_Byte **dataToEncryptStart); |
| 3599 | |
| 3600 | UA_StatusCode |
| 3601 | UA_NetworkMessage_encodeHeaders(const UA_NetworkMessage* src, |
| 3602 | UA_Byte **bufPos, const UA_Byte *bufEnd); |
| 3603 | |
| 3604 | UA_StatusCode |
| 3605 | UA_NetworkMessage_encodePayload(const UA_NetworkMessage* src, |
| 3606 | UA_Byte **bufPos, const UA_Byte *bufEnd); |
| 3607 | |
| 3608 | UA_StatusCode |
| 3609 | UA_NetworkMessage_encodeFooters(const UA_NetworkMessage* src, |
| 3610 | UA_Byte **bufPos, const UA_Byte *bufEnd); |
| 3611 | |
| 3612 | /** |
| 3613 | * NetworkMessage Decoding |
| 3614 | * ^^^^^^^^^^^^^^^^^^^^^^^ */ |
| 3615 | |
| 3616 | UA_StatusCode |
| 3617 | UA_NetworkMessage_decodeHeaders(const UA_ByteString *src, size_t *offset, |
| 3618 | UA_NetworkMessage *dst); |
| 3619 | |
| 3620 | UA_StatusCode |
| 3621 | UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset, |
| 3622 | UA_NetworkMessage *dst, const UA_DataTypeArray *customTypes, |
| 3623 | UA_DataSetMetaDataType *dsm); |
| 3624 | |
| 3625 | UA_StatusCode |
| 3626 | UA_NetworkMessage_decodeFooters(const UA_ByteString *src, size_t *offset, |
| 3627 | UA_NetworkMessage *dst); |
| 3628 | |
| 3629 | UA_StatusCode |
| 3630 | UA_NetworkMessage_decodeBinary(const UA_ByteString *src, size_t *offset, |
| 3631 | UA_NetworkMessage* dst, const UA_DataTypeArray *customTypes); |
| 3632 | |
| 3633 | UA_StatusCode |
| 3634 | UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, |
| 3635 | UA_NetworkMessage *dst); |
| 3636 | |
| 3637 | /* Also stores the offset if offsetBuffer != NULL */ |
| 3638 | size_t |
| 3639 | UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, |
| 3640 | UA_NetworkMessageOffsetBuffer *offsetBuffer); |
| 3641 | |
| 3642 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 3643 | |
| 3644 | UA_StatusCode |
| 3645 | UA_NetworkMessage_signEncrypt(UA_NetworkMessage *nm, UA_MessageSecurityMode securityMode, |
| 3646 | UA_PubSubSecurityPolicy *policy, void *policyContext, |
| 3647 | UA_Byte *messageStart, UA_Byte *encryptStart, |
| 3648 | UA_Byte *sigStart); |
| 3649 | #endif |
| 3650 | |
| 3651 | void |
| 3652 | UA_NetworkMessage_clear(UA_NetworkMessage* p); |
| 3653 | |
| 3654 | #ifdef UA_ENABLE_JSON_ENCODING |
| 3655 | UA_StatusCode |
| 3656 | UA_NetworkMessage_encodeJson(const UA_NetworkMessage *src, |
| 3657 | UA_Byte **bufPos, const UA_Byte **bufEnd, UA_String *namespaces, |
| 3658 | size_t namespaceSize, UA_String *serverUris, |
| 3659 | size_t serverUriSize, UA_Boolean useReversible); |
| 3660 | |
| 3661 | size_t |
| 3662 | UA_NetworkMessage_calcSizeJson(const UA_NetworkMessage *src, |
| 3663 | UA_String *namespaces, size_t namespaceSize, |
| 3664 | UA_String *serverUris, size_t serverUriSize, |
| 3665 | UA_Boolean useReversible); |
| 3666 | |
| 3667 | UA_StatusCode UA_NetworkMessage_decodeJson(UA_NetworkMessage *dst, const UA_ByteString *src); |
| 3668 | #endif |
| 3669 | |
| 3670 | _UA_END_DECLS |
| 3671 | |
| 3672 | #endif /* UA_ENABLE_PUBSUB */ |
| 3673 | |
| 3674 | |
| 3675 | /**** amalgamated original file "/src/pubsub/ua_pubsub.h" ****/ |
| 3676 | |
| 3677 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 3678 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 3679 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 3680 | * |
| 3681 | * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner) |
| 3682 | * Copyright (c) 2019 Kalycito Infotech Private Limited |
| 3683 | * Copyright (c) 2020 Yannick Wallerer, Siemens AG |
| 3684 | * Copyright (c) 2020, 2022 Thomas Fischer, Siemens AG |
| 3685 | * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes) |
| 3686 | * Copyright (c) 2022 Siemens AG (Author: Thomas Fischer) |
| 3687 | * Copyright (c) 2022 Fraunhofer IOSB (Author: Noel Graf) |
| 3688 | * Copyright (c) 2022 Linutronix GmbH (Author: Muddasir Shakil) |
| 3689 | */ |
| 3690 | |
| 3691 | |
| 3692 | #define UA_INTERNAL |
| 3693 | |
| 3694 | |
| 3695 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 3696 | #endif |
| 3697 | |
| 3698 | _UA_BEGIN_DECLS |
| 3699 | |
| 3700 | #ifdef UA_ENABLE_PUBSUB |
| 3701 | |
| 3702 | /* Max number of underlying for sending and receiving */ |
| 3703 | #define UA_PUBSUB_MAXCHANNELS 8 |
| 3704 | |
| 3705 | struct UA_WriterGroup; |
| 3706 | typedef struct UA_WriterGroup UA_WriterGroup; |
| 3707 | |
| 3708 | struct UA_ReaderGroup; |
| 3709 | typedef struct UA_ReaderGroup UA_ReaderGroup; |
| 3710 | |
| 3711 | struct UA_SecurityGroup; |
| 3712 | typedef struct UA_SecurityGroup UA_SecurityGroup; |
| 3713 | |
| 3714 | /**********************************************/ |
| 3715 | /* PublishedDataSet */ |
| 3716 | /**********************************************/ |
| 3717 | |
| 3718 | typedef struct UA_PublishedDataSet { |
| 3719 | UA_PublishedDataSetConfig config; |
| 3720 | UA_DataSetMetaDataType dataSetMetaData; |
| 3721 | TAILQ_HEAD(, UA_DataSetField) fields; |
| 3722 | UA_UInt16 fieldSize; |
| 3723 | UA_NodeId identifier; |
| 3724 | UA_UInt16 promotedFieldsCount; |
| 3725 | UA_UInt16 configurationFreezeCounter; |
| 3726 | TAILQ_ENTRY(UA_PublishedDataSet) listEntry; |
| 3727 | } UA_PublishedDataSet; |
| 3728 | |
| 3729 | UA_StatusCode |
| 3730 | UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src, |
| 3731 | UA_PublishedDataSetConfig *dst); |
| 3732 | |
| 3733 | UA_PublishedDataSet * |
| 3734 | UA_PublishedDataSet_findPDSbyId(UA_Server *server, UA_NodeId identifier); |
| 3735 | |
| 3736 | UA_PublishedDataSet * |
| 3737 | UA_PublishedDataSet_findPDSbyName(UA_Server *server, UA_String name); |
| 3738 | |
| 3739 | UA_AddPublishedDataSetResult |
| 3740 | UA_PublishedDataSet_create(UA_Server *server, |
| 3741 | const UA_PublishedDataSetConfig *publishedDataSetConfig, |
| 3742 | UA_NodeId *pdsIdentifier); |
| 3743 | |
| 3744 | void |
| 3745 | UA_PublishedDataSet_clear(UA_Server *server, |
| 3746 | UA_PublishedDataSet *publishedDataSet); |
| 3747 | |
| 3748 | UA_StatusCode |
| 3749 | UA_PublishedDataSet_remove(UA_Server *server, UA_PublishedDataSet *publishedDataSet); |
| 3750 | |
| 3751 | UA_StatusCode |
| 3752 | getPublishedDataSetConfig(UA_Server *server, const UA_NodeId pds, |
| 3753 | UA_PublishedDataSetConfig *config); |
| 3754 | |
| 3755 | typedef struct UA_StandaloneSubscribedDataSet{ |
| 3756 | UA_StandaloneSubscribedDataSetConfig config; |
| 3757 | UA_NodeId identifier; |
| 3758 | TAILQ_ENTRY(UA_StandaloneSubscribedDataSet) listEntry; |
| 3759 | UA_NodeId connectedReader; |
| 3760 | } UA_StandaloneSubscribedDataSet; |
| 3761 | |
| 3762 | UA_StatusCode |
| 3763 | UA_StandaloneSubscribedDataSetConfig_copy(const UA_StandaloneSubscribedDataSetConfig *src, |
| 3764 | UA_StandaloneSubscribedDataSetConfig *dst); |
| 3765 | UA_StandaloneSubscribedDataSet * |
| 3766 | UA_StandaloneSubscribedDataSet_findSDSbyId(UA_Server *server, UA_NodeId identifier); |
| 3767 | UA_StandaloneSubscribedDataSet * |
| 3768 | UA_StandaloneSubscribedDataSet_findSDSbyName(UA_Server *server, UA_String identifier); |
| 3769 | void |
| 3770 | UA_StandaloneSubscribedDataSet_clear(UA_Server *server, |
| 3771 | UA_StandaloneSubscribedDataSet *subscribedDataSet); |
| 3772 | |
| 3773 | #define UA_LOG_PDS_INTERNAL(LOGGER, LEVEL, PDS, MSG, ...) \ |
| 3774 | if(UA_LOGLEVEL <= UA_LOGLEVEL_##LEVEL) { \ |
| 3775 | UA_String idStr = UA_STRING_NULL; \ |
| 3776 | if(PDS) \ |
| 3777 | UA_NodeId_print(&(PDS)->identifier, &idStr); \ |
| 3778 | UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_PUBSUB, \ |
| 3779 | "DataSet %.*s\t| " MSG "%.0s", (int)idStr.length, \ |
| 3780 | (char*)idStr.data, __VA_ARGS__); \ |
| 3781 | UA_String_clear(&idStr); \ |
| 3782 | } |
| 3783 | |
| 3784 | #define UA_LOG_TRACE_DATASET(LOGGER, PDS, ...) \ |
| 3785 | UA_MACRO_EXPAND(UA_LOG_PDS_INTERNAL(LOGGER, TRACE, PDS, __VA_ARGS__, "")) |
| 3786 | #define UA_LOG_DEBUG_DATASET(LOGGER, PDS, ...) \ |
| 3787 | UA_MACRO_EXPAND(UA_LOG_PDS_INTERNAL(LOGGER, DEBUG, PDS, __VA_ARGS__, "")) |
| 3788 | #define UA_LOG_INFO_DATASET(LOGGER, PDS, ...) \ |
| 3789 | UA_MACRO_EXPAND(UA_LOG_PDS_INTERNAL(LOGGER, INFO, PDS, __VA_ARGS__, "")) |
| 3790 | #define UA_LOG_WARNING_DATASET(LOGGER, PDS, ...) \ |
| 3791 | UA_MACRO_EXPAND(UA_LOG_PDS_INTERNAL(LOGGER, WARNING, PDS, __VA_ARGS__, "")) |
| 3792 | #define UA_LOG_ERROR_DATASET(LOGGER, PDS, ...) \ |
| 3793 | UA_MACRO_EXPAND(UA_LOG_PDS_INTERNAL(LOGGER, ERROR, PDS, __VA_ARGS__, "")) |
| 3794 | #define UA_LOG_FATAL_DATASET(LOGGER, PDS, ...) \ |
| 3795 | UA_MACRO_EXPAND(UA_LOG_PDS_INTERNAL(LOGGER, FATAL, PDS, __VA_ARGS__, "")) |
| 3796 | |
| 3797 | /**********************************************/ |
| 3798 | /* Connection */ |
| 3799 | /**********************************************/ |
| 3800 | |
| 3801 | typedef struct UA_PubSubConnection { |
| 3802 | UA_PubSubComponentEnumType componentType; |
| 3803 | |
| 3804 | TAILQ_ENTRY(UA_PubSubConnection) listEntry; |
| 3805 | UA_NodeId identifier; |
| 3806 | |
| 3807 | /* The send/recv connections are only opened if the state is operational */ |
| 3808 | UA_PubSubState state; |
| 3809 | UA_PubSubConnectionConfig config; |
| 3810 | UA_Boolean json; /* Extracted from the TransportProfileUrl */ |
| 3811 | |
| 3812 | /* Channels belonging to the PubSubConnection. Send channels belong to |
| 3813 | * WriterGroups, recv channels belong to ReaderGroups. We only open channels |
| 3814 | * if there is at least one WriterGroup/ReaderGroup respectively. |
| 3815 | * |
| 3816 | * Some channels belong exclusively to just one WriterGroup/ReaderGroup that |
| 3817 | * defines additional connection properties. For example an MQTT topic name |
| 3818 | * or QoS parameters. In that case a dedicated NetworkCallback is used that |
| 3819 | * takes this ReaderGroup/WriterGroup directly as context. */ |
| 3820 | UA_ConnectionManager *cm; |
| 3821 | uintptr_t recvChannels[UA_PUBSUB_MAXCHANNELS]; |
| 3822 | size_t recvChannelsSize; |
| 3823 | uintptr_t sendChannel; |
| 3824 | |
| 3825 | size_t writerGroupsSize; |
| 3826 | LIST_HEAD(, UA_WriterGroup) writerGroups; |
| 3827 | |
| 3828 | size_t readerGroupsSize; |
| 3829 | LIST_HEAD(, UA_ReaderGroup) readerGroups; |
| 3830 | |
| 3831 | UA_UInt16 configurationFreezeCounter; |
| 3832 | |
| 3833 | UA_DateTime silenceErrorUntil; /* Avoid generating too many logs */ |
| 3834 | |
| 3835 | UA_Boolean deleteFlag; /* To be deleted - in addition to the PubSubState */ |
| 3836 | UA_DelayedCallback dc; /* For delayed freeing */ |
| 3837 | } UA_PubSubConnection; |
| 3838 | |
| 3839 | UA_StatusCode |
| 3840 | UA_PubSubConnectionConfig_copy(const UA_PubSubConnectionConfig *src, |
| 3841 | UA_PubSubConnectionConfig *dst); |
| 3842 | |
| 3843 | UA_PubSubConnection * |
| 3844 | UA_PubSubConnection_findConnectionbyId(UA_Server *server, |
| 3845 | UA_NodeId connectionIdentifier); |
| 3846 | |
| 3847 | UA_StatusCode |
| 3848 | UA_PubSubConnection_create(UA_Server *server, |
| 3849 | const UA_PubSubConnectionConfig *connectionConfig, |
| 3850 | UA_NodeId *connectionIdentifier); |
| 3851 | |
| 3852 | void |
| 3853 | UA_PubSubConnectionConfig_clear(UA_PubSubConnectionConfig *connectionConfig); |
| 3854 | |
| 3855 | void |
| 3856 | UA_PubSubConnection_delete(UA_Server *server, UA_PubSubConnection *c); |
| 3857 | |
| 3858 | UA_StatusCode |
| 3859 | UA_PubSubConnection_connect(UA_Server *server, UA_PubSubConnection *c, |
| 3860 | UA_Boolean validate); |
| 3861 | |
| 3862 | void |
| 3863 | UA_PubSubConnection_disconnect(UA_PubSubConnection *c); |
| 3864 | |
| 3865 | /* Returns either the eventloop configured in the connection or, in its absence, |
| 3866 | * for the server */ |
| 3867 | UA_EventLoop * |
| 3868 | UA_PubSubConnection_getEL(UA_Server *server, UA_PubSubConnection *c); |
| 3869 | |
| 3870 | UA_StatusCode |
| 3871 | UA_PubSubConnection_setPubSubState(UA_Server *server, |
| 3872 | UA_PubSubConnection *connection, |
| 3873 | UA_PubSubState state, |
| 3874 | UA_StatusCode cause); |
| 3875 | |
| 3876 | #define UA_LOG_CONNECTION_INTERNAL(LOGGER, LEVEL, CONNECTION, MSG, ...) \ |
| 3877 | if(UA_LOGLEVEL <= UA_LOGLEVEL_##LEVEL) { \ |
| 3878 | UA_String idStr = UA_STRING_NULL; \ |
| 3879 | if(CONNECTION) \ |
| 3880 | UA_NodeId_print(&(CONNECTION)->identifier, &idStr); \ |
| 3881 | UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_PUBSUB, \ |
| 3882 | "Connection %.*s\t| " MSG "%.0s", (int)idStr.length, \ |
| 3883 | (char*)idStr.data, __VA_ARGS__); \ |
| 3884 | UA_String_clear(&idStr); \ |
| 3885 | } |
| 3886 | |
| 3887 | #define UA_LOG_TRACE_CONNECTION(LOGGER, CONNECTION, ...) \ |
| 3888 | UA_MACRO_EXPAND(UA_LOG_CONNECTION_INTERNAL(LOGGER, TRACE, CONNECTION, __VA_ARGS__, "")) |
| 3889 | #define UA_LOG_DEBUG_CONNECTION(LOGGER, CONNECTION, ...) \ |
| 3890 | UA_MACRO_EXPAND(UA_LOG_CONNECTION_INTERNAL(LOGGER, DEBUG, CONNECTION, __VA_ARGS__, "")) |
| 3891 | #define UA_LOG_INFO_CONNECTION(LOGGER, CONNECTION, ...) \ |
| 3892 | UA_MACRO_EXPAND(UA_LOG_CONNECTION_INTERNAL(LOGGER, INFO, CONNECTION, __VA_ARGS__, "")) |
| 3893 | #define UA_LOG_WARNING_CONNECTION(LOGGER, CONNECTION, ...) \ |
| 3894 | UA_MACRO_EXPAND(UA_LOG_CONNECTION_INTERNAL(LOGGER, WARNING, CONNECTION, __VA_ARGS__, "")) |
| 3895 | #define UA_LOG_ERROR_CONNECTION(LOGGER, CONNECTION, ...) \ |
| 3896 | UA_MACRO_EXPAND(UA_LOG_CONNECTION_INTERNAL(LOGGER, ERROR, CONNECTION, __VA_ARGS__, "")) |
| 3897 | #define UA_LOG_FATAL_CONNECTION(LOGGER, CONNECTION, ...) \ |
| 3898 | UA_MACRO_EXPAND(UA_LOG_CONNECTION_INTERNAL(LOGGER, FATAL, CONNECTION, __VA_ARGS__, "")) |
| 3899 | |
| 3900 | /**********************************************/ |
| 3901 | /* DataSetWriter */ |
| 3902 | /**********************************************/ |
| 3903 | |
| 3904 | typedef struct UA_DataSetWriterSample { |
| 3905 | UA_Boolean valueChanged; |
| 3906 | UA_DataValue value; |
| 3907 | } UA_DataSetWriterSample; |
| 3908 | |
| 3909 | typedef struct UA_DataSetWriter { |
| 3910 | UA_PubSubComponentEnumType componentType; |
| 3911 | UA_DataSetWriterConfig config; |
| 3912 | LIST_ENTRY(UA_DataSetWriter) listEntry; |
| 3913 | UA_NodeId identifier; |
| 3914 | UA_NodeId linkedWriterGroup; |
| 3915 | UA_NodeId connectedDataSet; |
| 3916 | UA_ConfigurationVersionDataType connectedDataSetVersion; |
| 3917 | UA_PubSubState state; |
| 3918 | |
| 3919 | /* Deltaframes */ |
| 3920 | UA_UInt16 deltaFrameCounter; /* count of sent deltaFrames */ |
| 3921 | size_t lastSamplesCount; |
| 3922 | UA_DataSetWriterSample *lastSamples; |
| 3923 | |
| 3924 | UA_UInt16 actualDataSetMessageSequenceCount; |
| 3925 | UA_Boolean configurationFrozen; |
| 3926 | } UA_DataSetWriter; |
| 3927 | |
| 3928 | UA_StatusCode |
| 3929 | UA_DataSetWriterConfig_copy(const UA_DataSetWriterConfig *src, |
| 3930 | UA_DataSetWriterConfig *dst); |
| 3931 | |
| 3932 | UA_DataSetWriter * |
| 3933 | UA_DataSetWriter_findDSWbyId(UA_Server *server, UA_NodeId identifier); |
| 3934 | |
| 3935 | UA_StatusCode |
| 3936 | UA_DataSetWriter_setPubSubState(UA_Server *server, |
| 3937 | UA_DataSetWriter *dataSetWriter, |
| 3938 | UA_PubSubState state, |
| 3939 | UA_StatusCode cause); |
| 3940 | |
| 3941 | UA_StatusCode |
| 3942 | UA_DataSetWriter_generateDataSetMessage(UA_Server *server, |
| 3943 | UA_DataSetMessage *dataSetMessage, |
| 3944 | UA_DataSetWriter *dataSetWriter); |
| 3945 | |
| 3946 | UA_StatusCode |
| 3947 | UA_DataSetWriter_prepareDataSet(UA_Server *server, UA_DataSetWriter *dsw, |
| 3948 | UA_DataSetMessage *dsm); |
| 3949 | |
| 3950 | void |
| 3951 | UA_DataSetWriter_freezeConfiguration(UA_Server *server, UA_DataSetWriter *dsw); |
| 3952 | |
| 3953 | void |
| 3954 | UA_DataSetWriter_unfreezeConfiguration(UA_Server *server, UA_DataSetWriter *dsw); |
| 3955 | |
| 3956 | UA_StatusCode |
| 3957 | UA_DataSetWriter_create(UA_Server *server, |
| 3958 | const UA_NodeId writerGroup, const UA_NodeId dataSet, |
| 3959 | const UA_DataSetWriterConfig *dataSetWriterConfig, |
| 3960 | UA_NodeId *writerIdentifier); |
| 3961 | |
| 3962 | |
| 3963 | UA_StatusCode |
| 3964 | UA_DataSetWriter_remove(UA_Server *server, UA_DataSetWriter *dataSetWriter); |
| 3965 | |
| 3966 | #define UA_LOG_WRITER_INTERNAL(LOGGER, LEVEL, WRITER, MSG, ...) \ |
| 3967 | if(UA_LOGLEVEL <= UA_LOGLEVEL_##LEVEL) { \ |
| 3968 | UA_String idStr = UA_STRING_NULL; \ |
| 3969 | UA_String groupIdStr = UA_STRING_NULL; \ |
| 3970 | if(WRITER) { \ |
| 3971 | UA_NodeId_print(&(WRITER)->identifier, &idStr); \ |
| 3972 | UA_NodeId_print(&(WRITER)->linkedWriterGroup, &groupIdStr); \ |
| 3973 | } \ |
| 3974 | UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_PUBSUB, \ |
| 3975 | "WriterGroup %.*s\t| Writer %.*s\t| " MSG "%.0s", \ |
| 3976 | (int)groupIdStr.length, (char*)groupIdStr.data, \ |
| 3977 | (int)idStr.length, (char*)idStr.data, \ |
| 3978 | __VA_ARGS__); \ |
| 3979 | UA_String_clear(&idStr); \ |
| 3980 | UA_String_clear(&groupIdStr); \ |
| 3981 | } |
| 3982 | |
| 3983 | #define UA_LOG_TRACE_WRITER(LOGGER, WRITER, ...) \ |
| 3984 | UA_MACRO_EXPAND(UA_LOG_WRITER_INTERNAL(LOGGER, TRACE, WRITER, __VA_ARGS__, "")) |
| 3985 | #define UA_LOG_DEBUG_WRITER(LOGGER, WRITER, ...) \ |
| 3986 | UA_MACRO_EXPAND(UA_LOG_WRITER_INTERNAL(LOGGER, DEBUG, WRITER, __VA_ARGS__, "")) |
| 3987 | #define UA_LOG_INFO_WRITER(LOGGER, WRITER, ...) \ |
| 3988 | UA_MACRO_EXPAND(UA_LOG_WRITER_INTERNAL(LOGGER, INFO, WRITER, __VA_ARGS__, "")) |
| 3989 | #define UA_LOG_WARNING_WRITER(LOGGER, WRITER, ...) \ |
| 3990 | UA_MACRO_EXPAND(UA_LOG_WRITER_INTERNAL(LOGGER, WARNING, WRITER, __VA_ARGS__, "")) |
| 3991 | #define UA_LOG_ERROR_WRITER(LOGGER, WRITER, ...) \ |
| 3992 | UA_MACRO_EXPAND(UA_LOG_WRITER_INTERNAL(LOGGER, ERROR, WRITER, __VA_ARGS__, "")) |
| 3993 | #define UA_LOG_FATAL_WRITER(LOGGER, WRITER, ...) \ |
| 3994 | UA_MACRO_EXPAND(UA_LOG_WRITER_INTERNAL(LOGGER, FATAL, WRITER, __VA_ARGS__, "")) |
| 3995 | |
| 3996 | /**********************************************/ |
| 3997 | /* WriterGroup */ |
| 3998 | /**********************************************/ |
| 3999 | |
| 4000 | struct UA_WriterGroup { |
| 4001 | UA_PubSubComponentEnumType componentType; |
| 4002 | UA_WriterGroupConfig config; |
| 4003 | LIST_ENTRY(UA_WriterGroup) listEntry; |
| 4004 | UA_NodeId identifier; |
| 4005 | |
| 4006 | LIST_HEAD(, UA_DataSetWriter) writers; |
| 4007 | UA_UInt32 writersCount; |
| 4008 | |
| 4009 | UA_UInt64 publishCallbackId; /* registered if != 0 */ |
| 4010 | UA_PubSubState state; |
| 4011 | UA_NetworkMessageOffsetBuffer bufferedMessage; |
| 4012 | UA_UInt16 sequenceNumber; /* Increased after every succressuly sent message */ |
| 4013 | UA_Boolean configurationFrozen; |
| 4014 | UA_DateTime lastPublishTimeStamp; |
| 4015 | |
| 4016 | /* The ConnectionManager pointer is stored in the Connection. The channels |
| 4017 | * are either stored here or in the Connection, but never both. */ |
| 4018 | UA_PubSubConnection *linkedConnection; |
| 4019 | uintptr_t sendChannel; |
| 4020 | UA_Boolean deleteFlag; |
| 4021 | |
| 4022 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 4023 | UA_UInt32 securityTokenId; |
| 4024 | UA_UInt32 nonceSequenceNumber; /* To be part of the MessageNonce */ |
| 4025 | void *securityPolicyContext; |
| 4026 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 4027 | UA_PubSubKeyStorage *keyStorage; /* non-owning pointer to keyStorage*/ |
| 4028 | #endif |
| 4029 | #endif |
| 4030 | }; |
| 4031 | |
| 4032 | UA_StatusCode |
| 4033 | UA_WriterGroup_create(UA_Server *server, const UA_NodeId connection, |
| 4034 | const UA_WriterGroupConfig *writerGroupConfig, |
| 4035 | UA_NodeId *writerGroupIdentifier); |
| 4036 | |
| 4037 | UA_StatusCode |
| 4038 | UA_WriterGroup_remove(UA_Server *server, UA_WriterGroup *wg); |
| 4039 | |
| 4040 | void |
| 4041 | UA_WriterGroup_disconnect(UA_WriterGroup *wg); |
| 4042 | |
| 4043 | UA_StatusCode |
| 4044 | UA_WriterGroup_connect(UA_Server *server, UA_WriterGroup *wg, |
| 4045 | UA_Boolean validate); |
| 4046 | |
| 4047 | UA_StatusCode |
| 4048 | setWriterGroupEncryptionKeys(UA_Server *server, const UA_NodeId writerGroup, |
| 4049 | UA_UInt32 securityTokenId, |
| 4050 | const UA_ByteString signingKey, |
| 4051 | const UA_ByteString encryptingKey, |
| 4052 | const UA_ByteString keyNonce); |
| 4053 | |
| 4054 | UA_StatusCode |
| 4055 | UA_WriterGroupConfig_copy(const UA_WriterGroupConfig *src, |
| 4056 | UA_WriterGroupConfig *dst); |
| 4057 | |
| 4058 | UA_WriterGroup * |
| 4059 | UA_WriterGroup_findWGbyId(UA_Server *server, UA_NodeId identifier); |
| 4060 | |
| 4061 | UA_StatusCode |
| 4062 | UA_WriterGroup_freezeConfiguration(UA_Server *server, UA_WriterGroup *wg); |
| 4063 | |
| 4064 | UA_StatusCode |
| 4065 | UA_WriterGroup_unfreezeConfiguration(UA_Server *server, UA_WriterGroup *wg); |
| 4066 | |
| 4067 | UA_StatusCode |
| 4068 | UA_WriterGroup_setPubSubState(UA_Server *server, |
| 4069 | UA_WriterGroup *writerGroup, |
| 4070 | UA_PubSubState state, |
| 4071 | UA_StatusCode cause); |
| 4072 | |
| 4073 | UA_StatusCode |
| 4074 | UA_WriterGroup_addPublishCallback(UA_Server *server, UA_WriterGroup *writerGroup); |
| 4075 | |
| 4076 | void |
| 4077 | UA_WriterGroup_publishCallback(UA_Server *server, |
| 4078 | UA_WriterGroup *writerGroup); |
| 4079 | |
| 4080 | UA_StatusCode |
| 4081 | UA_WriterGroup_updateConfig(UA_Server *server, UA_WriterGroup *wg, |
| 4082 | const UA_WriterGroupConfig *config); |
| 4083 | |
| 4084 | #define UA_LOG_WRITERGROUP_INTERNAL(LOGGER, LEVEL, WRITERGROUP, MSG, ...) \ |
| 4085 | if(UA_LOGLEVEL <= UA_LOGLEVEL_##LEVEL) { \ |
| 4086 | UA_String idStr = UA_STRING_NULL; \ |
| 4087 | if(WRITERGROUP) \ |
| 4088 | UA_NodeId_print(&(WRITERGROUP)->identifier, &idStr); \ |
| 4089 | UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_PUBSUB, \ |
| 4090 | "WriterGroup %.*s\t| " MSG "%.0s", \ |
| 4091 | (int)idStr.length, (char*)idStr.data, \ |
| 4092 | __VA_ARGS__); \ |
| 4093 | UA_String_clear(&idStr); \ |
| 4094 | } |
| 4095 | |
| 4096 | #define UA_LOG_TRACE_WRITERGROUP(LOGGER, WRITERGROUP, ...) \ |
| 4097 | UA_MACRO_EXPAND(UA_LOG_WRITERGROUP_INTERNAL(LOGGER, TRACE, WRITERGROUP, __VA_ARGS__, "")) |
| 4098 | #define UA_LOG_DEBUG_WRITERGROUP(LOGGER, WRITERGROUP, ...) \ |
| 4099 | UA_MACRO_EXPAND(UA_LOG_WRITERGROUP_INTERNAL(LOGGER, DEBUG, WRITERGROUP, __VA_ARGS__, "")) |
| 4100 | #define UA_LOG_INFO_WRITERGROUP(LOGGER, WRITERGROUP, ...) \ |
| 4101 | UA_MACRO_EXPAND(UA_LOG_WRITERGROUP_INTERNAL(LOGGER, INFO, WRITERGROUP, __VA_ARGS__, "")) |
| 4102 | #define UA_LOG_WARNING_WRITERGROUP(LOGGER, WRITERGROUP, ...) \ |
| 4103 | UA_MACRO_EXPAND(UA_LOG_WRITERGROUP_INTERNAL(LOGGER, WARNING, WRITERGROUP, __VA_ARGS__, "")) |
| 4104 | #define UA_LOG_ERROR_WRITERGROUP(LOGGER, WRITERGROUP, ...) \ |
| 4105 | UA_MACRO_EXPAND(UA_LOG_WRITERGROUP_INTERNAL(LOGGER, ERROR, WRITERGROUP, __VA_ARGS__, "")) |
| 4106 | #define UA_LOG_FATAL_WRITERGROUP(LOGGER, WRITERGROUP, ...) \ |
| 4107 | UA_MACRO_EXPAND(UA_LOG_WRITERGROUP_INTERNAL(LOGGER, FATAL, WRITERGROUP, __VA_ARGS__, "")) |
| 4108 | |
| 4109 | /**********************************************/ |
| 4110 | /* DataSetField */ |
| 4111 | /**********************************************/ |
| 4112 | |
| 4113 | typedef struct UA_DataSetField { |
| 4114 | UA_DataSetFieldConfig config; |
| 4115 | TAILQ_ENTRY(UA_DataSetField) listEntry; |
| 4116 | UA_NodeId identifier; |
| 4117 | UA_NodeId publishedDataSet; /* parent pds */ |
| 4118 | UA_FieldMetaData fieldMetaData; /* contains the dataSetFieldId */ |
| 4119 | UA_UInt64 sampleCallbackId; |
| 4120 | UA_Boolean sampleCallbackIsRegistered; |
| 4121 | UA_Boolean configurationFrozen; |
| 4122 | } UA_DataSetField; |
| 4123 | |
| 4124 | UA_StatusCode |
| 4125 | UA_DataSetFieldConfig_copy(const UA_DataSetFieldConfig *src, |
| 4126 | UA_DataSetFieldConfig *dst); |
| 4127 | |
| 4128 | UA_DataSetField * |
| 4129 | UA_DataSetField_findDSFbyId(UA_Server *server, UA_NodeId identifier); |
| 4130 | |
| 4131 | UA_DataSetFieldResult |
| 4132 | UA_DataSetField_remove(UA_Server *server, UA_DataSetField *currentField); |
| 4133 | |
| 4134 | UA_DataSetFieldResult |
| 4135 | UA_DataSetField_create(UA_Server *server, const UA_NodeId publishedDataSet, |
| 4136 | const UA_DataSetFieldConfig *fieldConfig, |
| 4137 | UA_NodeId *fieldIdentifier); |
| 4138 | |
| 4139 | void |
| 4140 | UA_PubSubDataSetField_sampleValue(UA_Server *server, UA_DataSetField *field, |
| 4141 | UA_DataValue *value); |
| 4142 | |
| 4143 | /**********************************************/ |
| 4144 | /* DataSetReader */ |
| 4145 | /**********************************************/ |
| 4146 | |
| 4147 | /* DataSetReader Type definition */ |
| 4148 | typedef struct UA_DataSetReader { |
| 4149 | UA_PubSubComponentEnumType componentType; |
| 4150 | UA_DataSetReaderConfig config; |
| 4151 | UA_NodeId identifier; |
| 4152 | UA_NodeId linkedReaderGroup; |
| 4153 | LIST_ENTRY(UA_DataSetReader) listEntry; |
| 4154 | |
| 4155 | UA_PubSubState state; /* non std */ |
| 4156 | UA_Boolean configurationFrozen; |
| 4157 | UA_NetworkMessageOffsetBuffer bufferedMessage; |
| 4158 | |
| 4159 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 4160 | /* MessageReceiveTimeout handling */ |
| 4161 | UA_ServerCallback msgRcvTimeoutTimerCallback; |
| 4162 | UA_UInt64 msgRcvTimeoutTimerId; |
| 4163 | UA_Boolean msgRcvTimeoutTimerRunning; |
| 4164 | #endif |
| 4165 | UA_DateTime lastHeartbeatReceived; |
| 4166 | } UA_DataSetReader; |
| 4167 | |
| 4168 | /* Process Network Message using DataSetReader */ |
| 4169 | void |
| 4170 | UA_DataSetReader_process(UA_Server *server, |
| 4171 | UA_ReaderGroup *readerGroup, |
| 4172 | UA_DataSetReader *dataSetReader, |
| 4173 | UA_DataSetMessage *dataSetMsg); |
| 4174 | |
| 4175 | UA_StatusCode |
| 4176 | UA_DataSetReader_checkIdentifier(UA_Server *server, UA_NetworkMessage *msg, |
| 4177 | UA_DataSetReader *reader, |
| 4178 | UA_ReaderGroupConfig readerGroupConfig); |
| 4179 | |
| 4180 | UA_StatusCode |
| 4181 | UA_DataSetReader_create(UA_Server *server, UA_NodeId readerGroupIdentifier, |
| 4182 | const UA_DataSetReaderConfig *dataSetReaderConfig, |
| 4183 | UA_NodeId *readerIdentifier); |
| 4184 | |
| 4185 | UA_StatusCode |
| 4186 | UA_DataSetReader_remove(UA_Server *server, UA_DataSetReader *dsr); |
| 4187 | |
| 4188 | /* Copy the configuration of Target Variables */ |
| 4189 | UA_StatusCode UA_TargetVariables_copy(const UA_TargetVariables *src, |
| 4190 | UA_TargetVariables *dst); |
| 4191 | |
| 4192 | /* Clear the Target Variables configuration */ |
| 4193 | void UA_TargetVariables_clear(UA_TargetVariables *subscribedDataSetTarget); |
| 4194 | |
| 4195 | /* Copy the configuration of Field Target Variables */ |
| 4196 | UA_StatusCode UA_FieldTargetVariable_copy(const UA_FieldTargetVariable *src, |
| 4197 | UA_FieldTargetVariable *dst); |
| 4198 | |
| 4199 | UA_StatusCode |
| 4200 | DataSetReader_createTargetVariables(UA_Server *server, UA_DataSetReader *dsr, |
| 4201 | size_t targetVariablesSize, |
| 4202 | const UA_FieldTargetVariable *targetVariables); |
| 4203 | |
| 4204 | UA_StatusCode |
| 4205 | UA_DataSetReader_setPubSubState(UA_Server *server, |
| 4206 | UA_DataSetReader *dataSetReader, |
| 4207 | UA_PubSubState state, |
| 4208 | UA_StatusCode cause); |
| 4209 | |
| 4210 | #define UA_LOG_READER_INTERNAL(LOGGER, LEVEL, READER, MSG, ...) \ |
| 4211 | if(UA_LOGLEVEL <= UA_LOGLEVEL_##LEVEL) { \ |
| 4212 | UA_String idStr = UA_STRING_NULL; \ |
| 4213 | UA_String groupIdStr = UA_STRING_NULL; \ |
| 4214 | if(READER) { \ |
| 4215 | UA_NodeId_print(&(READER)->identifier, &idStr); \ |
| 4216 | UA_NodeId_print(&(READER)->linkedReaderGroup, &groupIdStr); \ |
| 4217 | } \ |
| 4218 | UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_PUBSUB, \ |
| 4219 | "ReaderGroup %.*s\t| Reader %.*s\t| " MSG "%.0s", \ |
| 4220 | (int)groupIdStr.length, (char*)groupIdStr.data, \ |
| 4221 | (int)idStr.length, (char*)idStr.data, \ |
| 4222 | __VA_ARGS__); \ |
| 4223 | UA_String_clear(&idStr); \ |
| 4224 | UA_String_clear(&groupIdStr); \ |
| 4225 | } |
| 4226 | |
| 4227 | #define UA_LOG_TRACE_READER(LOGGER, READER, ...) \ |
| 4228 | UA_MACRO_EXPAND(UA_LOG_READER_INTERNAL(LOGGER, TRACE, READER, __VA_ARGS__, "")) |
| 4229 | #define UA_LOG_DEBUG_READER(LOGGER, READER, ...) \ |
| 4230 | UA_MACRO_EXPAND(UA_LOG_READER_INTERNAL(LOGGER, DEBUG, READER, __VA_ARGS__, "")) |
| 4231 | #define UA_LOG_INFO_READER(LOGGER, READER, ...) \ |
| 4232 | UA_MACRO_EXPAND(UA_LOG_READER_INTERNAL(LOGGER, INFO, READER, __VA_ARGS__, "")) |
| 4233 | #define UA_LOG_WARNING_READER(LOGGER, READER, ...) \ |
| 4234 | UA_MACRO_EXPAND(UA_LOG_READER_INTERNAL(LOGGER, WARNING, READER, __VA_ARGS__, "")) |
| 4235 | #define UA_LOG_ERROR_READER(LOGGER, READER, ...) \ |
| 4236 | UA_MACRO_EXPAND(UA_LOG_READER_INTERNAL(LOGGER, ERROR, READER, __VA_ARGS__, "")) |
| 4237 | #define UA_LOG_FATAL_READER(LOGGER, READER, ...) \ |
| 4238 | UA_MACRO_EXPAND(UA_LOG_READER_INTERNAL(LOGGER, FATAL, READER, __VA_ARGS__, "")) |
| 4239 | |
| 4240 | /**********************************************/ |
| 4241 | /* ReaderGroup */ |
| 4242 | /**********************************************/ |
| 4243 | |
| 4244 | struct UA_ReaderGroup { |
| 4245 | UA_PubSubComponentEnumType componentType; |
| 4246 | UA_ReaderGroupConfig config; |
| 4247 | UA_NodeId identifier; |
| 4248 | LIST_ENTRY(UA_ReaderGroup) listEntry; |
| 4249 | |
| 4250 | LIST_HEAD(, UA_DataSetReader) readers; |
| 4251 | UA_UInt32 readersCount; |
| 4252 | |
| 4253 | UA_PubSubState state; |
| 4254 | UA_Boolean configurationFrozen; |
| 4255 | |
| 4256 | /* The ConnectionManager pointer is stored in the Connection. The channels |
| 4257 | * are either stored here or in the Connection, but never both. */ |
| 4258 | UA_PubSubConnection *linkedConnection; |
| 4259 | uintptr_t recvChannels[UA_PUBSUB_MAXCHANNELS]; |
| 4260 | size_t recvChannelsSize; |
| 4261 | UA_Boolean deleteFlag; |
| 4262 | |
| 4263 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 4264 | UA_UInt32 securityTokenId; |
| 4265 | UA_UInt32 nonceSequenceNumber; /* To be part of the MessageNonce */ |
| 4266 | void *securityPolicyContext; |
| 4267 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 4268 | UA_PubSubKeyStorage *keyStorage; |
| 4269 | #endif |
| 4270 | #endif |
| 4271 | }; |
| 4272 | |
| 4273 | UA_StatusCode |
| 4274 | UA_ReaderGroup_create(UA_Server *server, UA_NodeId connectionId, |
| 4275 | const UA_ReaderGroupConfig *rgc, |
| 4276 | UA_NodeId *readerGroupId); |
| 4277 | |
| 4278 | UA_StatusCode |
| 4279 | UA_ReaderGroup_remove(UA_Server *server, UA_ReaderGroup *rg); |
| 4280 | |
| 4281 | UA_StatusCode |
| 4282 | UA_ReaderGroup_connect(UA_Server *server, UA_ReaderGroup *rg, UA_Boolean validate); |
| 4283 | |
| 4284 | void |
| 4285 | UA_ReaderGroup_disconnect(UA_ReaderGroup *rg); |
| 4286 | |
| 4287 | UA_StatusCode |
| 4288 | setReaderGroupEncryptionKeys(UA_Server *server, const UA_NodeId readerGroup, |
| 4289 | UA_UInt32 securityTokenId, |
| 4290 | const UA_ByteString signingKey, |
| 4291 | const UA_ByteString encryptingKey, |
| 4292 | const UA_ByteString keyNonce); |
| 4293 | |
| 4294 | UA_StatusCode |
| 4295 | UA_ReaderGroupConfig_copy(const UA_ReaderGroupConfig *src, |
| 4296 | UA_ReaderGroupConfig *dst); |
| 4297 | |
| 4298 | /* Prototypes for internal util functions - some functions maybe removed later |
| 4299 | * (currently moved from public to internal) */ |
| 4300 | UA_ReaderGroup * |
| 4301 | UA_ReaderGroup_findRGbyId(UA_Server *server, UA_NodeId identifier); |
| 4302 | |
| 4303 | UA_DataSetReader * |
| 4304 | UA_ReaderGroup_findDSRbyId(UA_Server *server, UA_NodeId identifier); |
| 4305 | |
| 4306 | UA_StatusCode |
| 4307 | UA_ReaderGroup_freezeConfiguration(UA_Server *server, UA_ReaderGroup *rg); |
| 4308 | |
| 4309 | UA_StatusCode |
| 4310 | UA_ReaderGroup_unfreezeConfiguration(UA_Server *server, UA_ReaderGroup *rg); |
| 4311 | |
| 4312 | UA_StatusCode |
| 4313 | UA_ReaderGroup_setPubSubState(UA_Server *server, |
| 4314 | UA_ReaderGroup *readerGroup, |
| 4315 | UA_PubSubState state, |
| 4316 | UA_StatusCode cause); |
| 4317 | |
| 4318 | UA_Boolean |
| 4319 | UA_ReaderGroup_decodeAndProcessRT(UA_Server *server, UA_ReaderGroup *readerGroup, |
| 4320 | UA_ByteString *buf); |
| 4321 | |
| 4322 | UA_Boolean |
| 4323 | UA_ReaderGroup_process(UA_Server *server, UA_ReaderGroup *readerGroup, |
| 4324 | UA_NetworkMessage *nm); |
| 4325 | |
| 4326 | #define UA_LOG_READERGROUP_INTERNAL(LOGGER, LEVEL, RG, MSG, ...) \ |
| 4327 | if(UA_LOGLEVEL <= UA_LOGLEVEL_##LEVEL) { \ |
| 4328 | UA_String idStr = UA_STRING_NULL; \ |
| 4329 | if(RG) \ |
| 4330 | UA_NodeId_print(&(RG)->identifier, &idStr); \ |
| 4331 | UA_LOG_##LEVEL(LOGGER, UA_LOGCATEGORY_PUBSUB, \ |
| 4332 | "ReaderGroup %.*s\t| " MSG "%.0s", (int)idStr.length, \ |
| 4333 | (char*)idStr.data, __VA_ARGS__); \ |
| 4334 | UA_String_clear(&idStr); \ |
| 4335 | } |
| 4336 | |
| 4337 | #define UA_LOG_TRACE_READERGROUP(LOGGER, READERGROUP, ...) \ |
| 4338 | UA_MACRO_EXPAND(UA_LOG_READERGROUP_INTERNAL(LOGGER, TRACE, READERGROUP, __VA_ARGS__, "")) |
| 4339 | #define UA_LOG_DEBUG_READERGROUP(LOGGER, READERGROUP, ...) \ |
| 4340 | UA_MACRO_EXPAND(UA_LOG_READERGROUP_INTERNAL(LOGGER, DEBUG, READERGROUP, __VA_ARGS__, "")) |
| 4341 | #define UA_LOG_INFO_READERGROUP(LOGGER, READERGROUP, ...) \ |
| 4342 | UA_MACRO_EXPAND(UA_LOG_READERGROUP_INTERNAL(LOGGER, INFO, READERGROUP, __VA_ARGS__, "")) |
| 4343 | #define UA_LOG_WARNING_READERGROUP(LOGGER, READERGROUP, ...) \ |
| 4344 | UA_MACRO_EXPAND(UA_LOG_READERGROUP_INTERNAL(LOGGER, WARNING, READERGROUP, __VA_ARGS__, "")) |
| 4345 | #define UA_LOG_ERROR_READERGROUP(LOGGER, READERGROUP, ...) \ |
| 4346 | UA_MACRO_EXPAND(UA_LOG_READERGROUP_INTERNAL(LOGGER, ERROR, READERGROUP, __VA_ARGS__, "")) |
| 4347 | #define UA_LOG_FATAL_READERGROUP(LOGGER, READERGROUP, ...) \ |
| 4348 | UA_MACRO_EXPAND(UA_LOG_READERGROUP_INTERNAL(LOGGER, FATAL, READERGROUP, __VA_ARGS__, "")) |
| 4349 | |
| 4350 | /*********************************************************/ |
| 4351 | /* Reading Message handling */ |
| 4352 | /*********************************************************/ |
| 4353 | |
| 4354 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 4355 | UA_StatusCode |
| 4356 | verifyAndDecrypt(const UA_Logger *logger, UA_ByteString *buffer, |
| 4357 | const size_t *currentPosition, const UA_NetworkMessage *nm, |
| 4358 | UA_Boolean doValidate, UA_Boolean doDecrypt, |
| 4359 | void *channelContext, UA_PubSubSecurityPolicy *securityPolicy); |
| 4360 | |
| 4361 | UA_StatusCode |
| 4362 | verifyAndDecryptNetworkMessage(const UA_Logger *logger, UA_ByteString *buffer, |
| 4363 | size_t *currentPosition, UA_NetworkMessage *nm, |
| 4364 | UA_ReaderGroup *readerGroup); |
| 4365 | #endif |
| 4366 | |
| 4367 | /* Takes a value (and not a pointer) to the buffer. The original buffer is |
| 4368 | const. Internally we may adjust the length during decryption. */ |
| 4369 | UA_StatusCode |
| 4370 | decodeNetworkMessage(UA_Server *server, UA_ByteString *buffer, size_t *pos, |
| 4371 | UA_NetworkMessage *nm, UA_PubSubConnection *connection); |
| 4372 | |
| 4373 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 4374 | /*********************************************************/ |
| 4375 | /* SecurityGroup */ |
| 4376 | /*********************************************************/ |
| 4377 | struct UA_SecurityGroup { |
| 4378 | UA_String securityGroupId; |
| 4379 | UA_SecurityGroupConfig config; |
| 4380 | UA_PubSubKeyStorage *keyStorage; |
| 4381 | UA_NodeId securityGroupNodeId; |
| 4382 | UA_UInt64 callbackId; |
| 4383 | UA_DateTime baseTime; |
| 4384 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 4385 | UA_NodeId securityGroupFolderId; |
| 4386 | #endif |
| 4387 | TAILQ_ENTRY(UA_SecurityGroup) listEntry; |
| 4388 | }; |
| 4389 | |
| 4390 | UA_StatusCode |
| 4391 | UA_SecurityGroupConfig_copy(const UA_SecurityGroupConfig *src, |
| 4392 | UA_SecurityGroupConfig *dst); |
| 4393 | |
| 4394 | /* finds the SecurityGroup within the server by SecurityGroup Name/Id*/ |
| 4395 | UA_SecurityGroup * |
| 4396 | UA_SecurityGroup_findSGbyName(UA_Server *server, UA_String securityGroupName); |
| 4397 | |
| 4398 | /* finds the SecurityGroup within the server by NodeId*/ |
| 4399 | UA_SecurityGroup * |
| 4400 | UA_SecurityGroup_findSGbyId(UA_Server *server, UA_NodeId identifier); |
| 4401 | |
| 4402 | void |
| 4403 | UA_SecurityGroup_delete(UA_SecurityGroup *securityGroup); |
| 4404 | |
| 4405 | void |
| 4406 | removeSecurityGroup(UA_Server *server, UA_SecurityGroup *securityGroup); |
| 4407 | |
| 4408 | #endif /* UA_ENABLE_PUBSUB_SKS */ |
| 4409 | |
| 4410 | /******************/ |
| 4411 | /* PubSub Manager */ |
| 4412 | /******************/ |
| 4413 | |
| 4414 | typedef struct UA_TopicAssign { |
| 4415 | UA_ReaderGroup *rgIdentifier; |
| 4416 | UA_String topic; |
| 4417 | TAILQ_ENTRY(UA_TopicAssign) listEntry; |
| 4418 | } UA_TopicAssign; |
| 4419 | |
| 4420 | typedef enum { |
| 4421 | UA_WRITER_GROUP = 0, |
| 4422 | UA_DATA_SET_WRITER = 1, |
| 4423 | } UA_ReserveIdType; |
| 4424 | |
| 4425 | typedef struct UA_ReserveId { |
| 4426 | UA_UInt16 id; |
| 4427 | UA_ReserveIdType reserveIdType; |
| 4428 | UA_String transportProfileUri; |
| 4429 | UA_NodeId sessionId; |
| 4430 | ZIP_ENTRY(UA_ReserveId) treeEntry; |
| 4431 | } UA_ReserveId; |
| 4432 | |
| 4433 | typedef ZIP_HEAD(UA_ReserveIdTree, UA_ReserveId) UA_ReserveIdTree; |
| 4434 | |
| 4435 | typedef struct UA_PubSubManager { |
| 4436 | UA_UInt64 defaultPublisherId; |
| 4437 | /* Connections and PublishedDataSets can exist alone (own lifecycle) -> top |
| 4438 | * level components */ |
| 4439 | size_t connectionsSize; |
| 4440 | TAILQ_HEAD(, UA_PubSubConnection) connections; |
| 4441 | |
| 4442 | size_t publishedDataSetsSize; |
| 4443 | TAILQ_HEAD(, UA_PublishedDataSet) publishedDataSets; |
| 4444 | |
| 4445 | size_t subscribedDataSetsSize; |
| 4446 | TAILQ_HEAD(, UA_StandaloneSubscribedDataSet) subscribedDataSets; |
| 4447 | |
| 4448 | size_t topicAssignSize; |
| 4449 | TAILQ_HEAD(, UA_TopicAssign) topicAssign; |
| 4450 | |
| 4451 | size_t reserveIdsSize; |
| 4452 | UA_ReserveIdTree reserveIds; |
| 4453 | |
| 4454 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 4455 | LIST_HEAD(, UA_PubSubKeyStorage) pubSubKeyList; |
| 4456 | |
| 4457 | size_t securityGroupsSize; |
| 4458 | TAILQ_HEAD(, UA_SecurityGroup) securityGroups; |
| 4459 | #endif |
| 4460 | |
| 4461 | #ifndef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 4462 | UA_UInt32 uniqueIdCount; |
| 4463 | #endif |
| 4464 | } UA_PubSubManager; |
| 4465 | |
| 4466 | UA_StatusCode |
| 4467 | UA_PubSubManager_addPubSubTopicAssign(UA_Server *server, UA_ReaderGroup *readerGroup, |
| 4468 | UA_String topic); |
| 4469 | |
| 4470 | UA_StatusCode |
| 4471 | UA_PubSubManager_reserveIds(UA_Server *server, UA_NodeId sessionId, UA_UInt16 numRegWriterGroupIds, |
| 4472 | UA_UInt16 numRegDataSetWriterIds, UA_String transportProfileUri, |
| 4473 | UA_UInt16 **writerGroupIds, UA_UInt16 **dataSetWriterIds); |
| 4474 | |
| 4475 | void |
| 4476 | UA_PubSubManager_freeIds(UA_Server *server); |
| 4477 | |
| 4478 | void |
| 4479 | UA_PubSubManager_init(UA_Server *server, UA_PubSubManager *pubSubManager); |
| 4480 | |
| 4481 | void |
| 4482 | UA_PubSubManager_shutdown(UA_Server *server, UA_PubSubManager *pubSubManager); |
| 4483 | |
| 4484 | void |
| 4485 | UA_PubSubManager_delete(UA_Server *server, UA_PubSubManager *pubSubManager); |
| 4486 | |
| 4487 | #ifndef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 4488 | void |
| 4489 | UA_PubSubManager_generateUniqueNodeId(UA_PubSubManager *psm, UA_NodeId *nodeId); |
| 4490 | #endif |
| 4491 | |
| 4492 | #ifdef UA_ENABLE_PUBSUB_FILE_CONFIG |
| 4493 | /* Decodes the information from the ByteString. If the decoded content is a |
| 4494 | * PubSubConfiguration in a UABinaryFileDataType-object. It will overwrite the |
| 4495 | * current PubSub configuration from the server. */ |
| 4496 | UA_StatusCode |
| 4497 | UA_PubSubManager_loadPubSubConfigFromByteString(UA_Server *server, |
| 4498 | const UA_ByteString buffer); |
| 4499 | |
| 4500 | /* Saves the current PubSub configuration of a server in a byteString. */ |
| 4501 | UA_StatusCode |
| 4502 | UA_PubSubManager_getEncodedPubSubConfiguration(UA_Server *server, |
| 4503 | UA_ByteString *buffer); |
| 4504 | #endif |
| 4505 | |
| 4506 | UA_Guid |
| 4507 | UA_PubSubManager_generateUniqueGuid(UA_Server *server); |
| 4508 | |
| 4509 | UA_UInt32 |
| 4510 | UA_PubSubConfigurationVersionTimeDifference(void); |
| 4511 | |
| 4512 | /*************************************************/ |
| 4513 | /* PubSub component monitoring */ |
| 4514 | /*************************************************/ |
| 4515 | |
| 4516 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 4517 | |
| 4518 | UA_StatusCode |
| 4519 | UA_PubSubManager_setDefaultMonitoringCallbacks(UA_PubSubMonitoringInterface *monitoringInterface); |
| 4520 | |
| 4521 | #endif /* UA_ENABLE_PUBSUB_MONITORING */ |
| 4522 | |
| 4523 | #endif /* UA_ENABLE_PUBSUB */ |
| 4524 | |
| 4525 | _UA_END_DECLS |
| 4526 | |
| 4527 | |
| 4528 | /**** amalgamated original file "/src/pubsub/ua_pubsub_ns0.h" ****/ |
| 4529 | |
| 4530 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 4531 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 4532 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 4533 | * |
| 4534 | * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner) |
| 4535 | * Copyright (c) 2019 Kalycito Infotech Private Limited |
| 4536 | * Copyright (c) 2022 Siemens AG (Author: Thomas Fischer) |
| 4537 | * Copyright (c) 2022 Linutronix GmbH (Author: Muddasir Shakil) |
| 4538 | */ |
| 4539 | |
| 4540 | #ifndef UA_PUBSUB_NS0_H_ |
| 4541 | #define UA_PUBSUB_NS0_H_ |
| 4542 | |
| 4543 | |
| 4544 | _UA_BEGIN_DECLS |
| 4545 | |
| 4546 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL /* conditional compilation */ |
| 4547 | |
| 4548 | UA_StatusCode |
| 4549 | initPubSubNS0(UA_Server *server); |
| 4550 | |
| 4551 | UA_StatusCode |
| 4552 | addPubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connection); |
| 4553 | |
| 4554 | UA_StatusCode |
| 4555 | addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup); |
| 4556 | |
| 4557 | UA_StatusCode |
| 4558 | addReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup); |
| 4559 | |
| 4560 | UA_StatusCode |
| 4561 | addDataSetWriterRepresentation(UA_Server *server, UA_DataSetWriter *dataSetWriter); |
| 4562 | |
| 4563 | UA_StatusCode |
| 4564 | addPublishedDataItemsRepresentation(UA_Server *server, UA_PublishedDataSet *publishedDataSet); |
| 4565 | |
| 4566 | UA_StatusCode |
| 4567 | addStandaloneSubscribedDataSetRepresentation(UA_Server *server, UA_StandaloneSubscribedDataSet *subscribedDataSet); |
| 4568 | |
| 4569 | UA_StatusCode |
| 4570 | addDataSetReaderRepresentation(UA_Server *server, UA_DataSetReader *dataSetReader); |
| 4571 | |
| 4572 | UA_StatusCode |
| 4573 | connectDataSetReaderToDataSet(UA_Server *server, UA_NodeId dsrId, UA_NodeId standaloneSdsId); |
| 4574 | |
| 4575 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 4576 | UA_StatusCode |
| 4577 | addSecurityGroupRepresentation(UA_Server *server, UA_SecurityGroup *securityGroup); |
| 4578 | #endif /* UA_ENABLE_PUBSUB_SKS */ |
| 4579 | |
| 4580 | #endif /* UA_ENABLE_PUBSUB_INFORMATIONMODEL */ |
| 4581 | |
| 4582 | _UA_END_DECLS |
| 4583 | |
| 4584 | #endif /* UA_PUBSUB_NS0_H_ */ |
| 4585 | |
| 4586 | /**** amalgamated original file "/src/pubsub/ua_pubsub_keystorage.h" ****/ |
| 4587 | |
| 4588 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 4589 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 4590 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 4591 | * |
| 4592 | * Copyright (c) 2019 ifak e.V. Magdeburg (Holger Zipper) |
| 4593 | * Copyright (c) 2022 Linutronix GmbH (Author: Muddasir Shakil) |
| 4594 | */ |
| 4595 | |
| 4596 | #ifndef UA_PUBSUB_KEYSTORAGE |
| 4597 | #define UA_PUBSUB_KEYSTORAGE |
| 4598 | |
| 4599 | |
| 4600 | |
| 4601 | _UA_BEGIN_DECLS |
| 4602 | |
| 4603 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 4604 | |
| 4605 | /** |
| 4606 | * PubSubKeyStorage |
| 4607 | * ================ |
| 4608 | * A PubSubKeyStorage provides a linked list to store all the keys used to |
| 4609 | * secure the messages. It keeps the records of old keys (past keys), current |
| 4610 | * key, new keys (futurekeys), time to move to next key and callback id. |
| 4611 | * |
| 4612 | * PubSubKeyListItem is the basic item stored in the KeyList of KeyStorage. It |
| 4613 | * provides keyId, Key, and pointer to the next key in KeyList. The KeyId is used |
| 4614 | * to identify and update currentKey in the keystorage. The KeyId is the SecurityTokenId |
| 4615 | * that appears in the header of messages secured with the CurrentKey. |
| 4616 | * |
| 4617 | * Working |
| 4618 | * ======= |
| 4619 | * +------------------------------+ |
| 4620 | * |AddReaderGroup/AddWriterGroup | |
| 4621 | * +------------------------------+ |
| 4622 | * | |
| 4623 | * V |
| 4624 | * +--------------------+ |
| 4625 | * |CheckSecurityGroupId| |
| 4626 | * +--------------------+ |
| 4627 | * |Yes |
| 4628 | * V |
| 4629 | * +--------------------+ |
| 4630 | * |InitializeKeyStorage| |
| 4631 | * +--------------------+ |
| 4632 | * | |
| 4633 | * V |
| 4634 | * +----------------------------+ |
| 4635 | * |store/updateKeysInKeyStorage| |
| 4636 | * +----------------------------+ |
| 4637 | * | |
| 4638 | * V |
| 4639 | * +------------------------------------------+ |
| 4640 | * |activateKeysToAllPubSubGroupChannelContext| |
| 4641 | * +------------------------------------------+ |
| 4642 | * | É… |
| 4643 | * V | |
| 4644 | * +-----------------------+ | |
| 4645 | * |addKeyRolloverCallbacks| | |
| 4646 | * +-----------------------+ | |
| 4647 | * | | |
| 4648 | * V | |
| 4649 | * +-------------------+ | |
| 4650 | * |keyRolloverCallback| | |
| 4651 | * +-------------------+ | |
| 4652 | * |CurrentKey!=LastItem | |
| 4653 | * -------------------------+ |
| 4654 | * |
| 4655 | * A KeyStorage is created and initialized when a ReaderGroup or WriterGroup is |
| 4656 | * created with securityGroupId and SecurityMode SignAndEncrypt. The new |
| 4657 | * KeyStorage is added to the server KeyStorageList. At this time KeyList is empty. |
| 4658 | * |
| 4659 | * UA_PubSubKeyStorage_storeSecurityKeys is used to push the keys into existing |
| 4660 | * keystorage. In order to update the KeyList of an existing keyStorage, |
| 4661 | * UA_PubSubKeyStorage_update is called. |
| 4662 | * |
| 4663 | * After adding/updating the keys to keystorage, the current key should be |
| 4664 | * activated to the associated PubSub Group's ChannelContext in the server. The |
| 4665 | * security Policy associated with PubSub Group will take the keys from |
| 4666 | * channel context and use them to secure the messages. |
| 4667 | * The UA_PubSubKeyStorage_storeSecurityKeys and UA_PubSubKeyStorage_update |
| 4668 | * method will be used by setSecurityKeysAction and getSecurityKeysAction to |
| 4669 | * retrieve the keys from SKS server and store keys in local storage. |
| 4670 | * |
| 4671 | * Each key has a life time, after which the current key is expired and move to |
| 4672 | * next key in the existing list. For this a callback function is added to the |
| 4673 | * server. The callback function keyRolloverCallback is added to the server as a |
| 4674 | * timed callback. The addKeyRolloverCallbacks function calculates the time |
| 4675 | * stamp to trigger the callback when the current Key expires and roll |
| 4676 | * over to the next key in existing list. |
| 4677 | * |
| 4678 | */ |
| 4679 | |
| 4680 | /** |
| 4681 | * @brief This structure holds the information about the keys |
| 4682 | */ |
| 4683 | typedef struct UA_PubSubKeyListItem { |
| 4684 | /* The SecurityTokenId associated with Key*/ |
| 4685 | UA_UInt32 keyID; |
| 4686 | |
| 4687 | /* This key is not used directly since the protocol associated with the PubSubGroup(s) |
| 4688 | * specifies an algorithm to generate distinct keys for different types of |
| 4689 | * cryptography operations*/ |
| 4690 | UA_ByteString key; |
| 4691 | |
| 4692 | /* Pointers to the key list entries*/ |
| 4693 | TAILQ_ENTRY(UA_PubSubKeyListItem) keyListEntry; |
| 4694 | } UA_PubSubKeyListItem; |
| 4695 | |
| 4696 | /* Queue Definition*/ |
| 4697 | typedef TAILQ_HEAD(keyListItems, UA_PubSubKeyListItem) keyListItems; |
| 4698 | |
| 4699 | /** |
| 4700 | * @brief It is used to hold configuration information required to connect an SKS server |
| 4701 | * and fetch the security keys |
| 4702 | */ |
| 4703 | typedef struct UA_PubSubSKSConfig { |
| 4704 | UA_ClientConfig clientConfig; |
| 4705 | const char *endpointUrl; |
| 4706 | UA_Server_sksPullRequestCallback userNotifyCallback; |
| 4707 | void *context; |
| 4708 | UA_UInt32 reqId; |
| 4709 | } UA_PubSubSKSConfig; |
| 4710 | |
| 4711 | /** |
| 4712 | * @brief This structure holds all info and keys related to one SecurityGroup. |
| 4713 | * it is used as a list. |
| 4714 | */ |
| 4715 | typedef struct UA_PubSubKeyStorage { |
| 4716 | |
| 4717 | /** |
| 4718 | * security group id of the security group related to this storage |
| 4719 | */ |
| 4720 | UA_String securityGroupID; |
| 4721 | |
| 4722 | /** |
| 4723 | * none-owning pointer to the security policy related to this storage |
| 4724 | */ |
| 4725 | UA_PubSubSecurityPolicy *policy; |
| 4726 | |
| 4727 | /** |
| 4728 | * in case of the SKS server, the key storage structure is deleted when removing the |
| 4729 | * security group. |
| 4730 | * in case of publisher / subscriber, one key storage structure is |
| 4731 | * referenced by multiple reader / writer groups have a reference count to manage free |
| 4732 | */ |
| 4733 | UA_UInt32 referenceCount; |
| 4734 | |
| 4735 | /** |
| 4736 | * array of keys. the elements inside this array have a next pointer. |
| 4737 | * keyList can therefore be used as linked list. |
| 4738 | */ |
| 4739 | keyListItems keyList; |
| 4740 | |
| 4741 | /** |
| 4742 | * size of the keyList |
| 4743 | */ |
| 4744 | size_t keyListSize; |
| 4745 | |
| 4746 | /** |
| 4747 | * The maximum number of Past keys a keystorage is allowed to store |
| 4748 | */ |
| 4749 | UA_UInt32 maxPastKeyCount; |
| 4750 | |
| 4751 | /** |
| 4752 | * The maximum number of Future keys a keyStorage is allowed to store |
| 4753 | */ |
| 4754 | UA_UInt32 maxFutureKeyCount; |
| 4755 | |
| 4756 | /* |
| 4757 | * The maximum keylist size, calculated from maxPastKeyCount and maxFutureKeyCount |
| 4758 | */ |
| 4759 | UA_UInt32 maxKeyListSize; |
| 4760 | |
| 4761 | /** |
| 4762 | * The SecurityTokenId that appears in the header of messages secured with the |
| 4763 | * CurrentKey. It starts at 1 and is incremented by 1 each time the KeyLifetime |
| 4764 | * elapses even if no keys are requested. If the CurrentTokenId increments past the |
| 4765 | * maximum value of UInt32 it restarts a 1. |
| 4766 | */ |
| 4767 | UA_UInt32 currentTokenId; |
| 4768 | |
| 4769 | /** |
| 4770 | * the current key used to secure the messages |
| 4771 | */ |
| 4772 | UA_PubSubKeyListItem *currentItem; |
| 4773 | |
| 4774 | /** |
| 4775 | * keyLifeTime used to update the CurrentKey from the Local KeyStorage |
| 4776 | */ |
| 4777 | UA_Duration keyLifeTime; |
| 4778 | |
| 4779 | /** |
| 4780 | * id used to register the callback to retrieve the keys related to this security |
| 4781 | * group |
| 4782 | */ |
| 4783 | UA_UInt64 callBackId; |
| 4784 | |
| 4785 | /** |
| 4786 | * used to store the sks related information to connect with SKS server and fetch security keys. |
| 4787 | */ |
| 4788 | UA_PubSubSKSConfig sksConfig; |
| 4789 | |
| 4790 | /** |
| 4791 | * Pointer to the key storage list |
| 4792 | */ |
| 4793 | LIST_ENTRY(UA_PubSubKeyStorage) keyStorageList; |
| 4794 | |
| 4795 | } UA_PubSubKeyStorage; |
| 4796 | |
| 4797 | /** |
| 4798 | * @brief Find the Keystorage from the Server KeyStorageList and returns the pointer to |
| 4799 | * the keystorage |
| 4800 | * |
| 4801 | * @param server holds the keystoragelist |
| 4802 | * @param securityGroupId of the keystorage to be found |
| 4803 | * @return Pointer to the keystorage on success, null pointer on failure |
| 4804 | */ |
| 4805 | UA_PubSubKeyStorage * |
| 4806 | UA_PubSubKeyStorage_findKeyStorage(UA_Server *server, UA_String securityGroupId); |
| 4807 | |
| 4808 | /** |
| 4809 | * @brief retreives the security policy pointer from the PubSub configuration by |
| 4810 | * SecurityPolicyUri |
| 4811 | * |
| 4812 | * @param server the server object |
| 4813 | * @param securityPolicyUri the URI of the security policy |
| 4814 | * @param policy the pointer to the security policy |
| 4815 | * @return UA_StatusCode return status code |
| 4816 | */ |
| 4817 | UA_PubSubSecurityPolicy * |
| 4818 | findPubSubSecurityPolicy(UA_Server *server, const UA_String *securityPolicyUri); |
| 4819 | |
| 4820 | /** |
| 4821 | * @brief Deletes the keystorage from the server and its members |
| 4822 | * |
| 4823 | * @param server where the keystorage is created |
| 4824 | * @param keyStorage pointer to the keystorage |
| 4825 | */ |
| 4826 | void |
| 4827 | UA_PubSubKeyStorage_delete(UA_Server *server, UA_PubSubKeyStorage *keyStorage); |
| 4828 | |
| 4829 | /** |
| 4830 | * @brief Initializes an empty Keystorage for the SecurityGroupId and add it to the Server |
| 4831 | * KeyStorageList |
| 4832 | * |
| 4833 | * @param server The server object |
| 4834 | * @param keyStorage Pointer to the keystorage to be initialized |
| 4835 | * @param securityGroupId The identifier of the SecurityGroup |
| 4836 | * @param policy The security policy assocaited with the security algorithm |
| 4837 | * @param maxPastKeyCount maximum number of past keys a keystorage is allowed to store |
| 4838 | * @param maxFutureKeyCount maximum number of future keys a keystorage is allowed to store |
| 4839 | * @return UA_StatusCode return status code |
| 4840 | */ |
| 4841 | UA_StatusCode |
| 4842 | UA_PubSubKeyStorage_init(UA_Server *server, UA_PubSubKeyStorage *keyStorage, |
| 4843 | const UA_String *securityGroupId, |
| 4844 | UA_PubSubSecurityPolicy *policy, |
| 4845 | UA_UInt32 maxPastKeyCount, UA_UInt32 maxFutureKeyCount); |
| 4846 | |
| 4847 | /** |
| 4848 | * @brief After Keystorage is initialized and added to the server, this method is called |
| 4849 | * to store the current Keys and futurekeys. |
| 4850 | * |
| 4851 | * @param server the server object |
| 4852 | * @param keyStorage pointer to the keyStorage |
| 4853 | * @param currentTokenId The token Id of the current key it starts with 1 and increaments |
| 4854 | * each time keylifetime expires |
| 4855 | * @param currentKey the key used for encrypt the current messages |
| 4856 | * @param futureKeys pointer to the future keys |
| 4857 | * @param futureKeyCount the number future keys provided |
| 4858 | * @param keyLifeTime the time period when the key expires and move to next future key in |
| 4859 | * milli seconds |
| 4860 | * @return UA_StatusCode the return status |
| 4861 | */ |
| 4862 | UA_StatusCode |
| 4863 | UA_PubSubKeyStorage_storeSecurityKeys(UA_Server *server, UA_PubSubKeyStorage *keyStorage, |
| 4864 | UA_UInt32 currentTokenId, const UA_ByteString *currentKey, |
| 4865 | UA_ByteString *futureKeys, size_t futureKeyCount, |
| 4866 | UA_Duration msKeyLifeTime); |
| 4867 | |
| 4868 | /** |
| 4869 | * @brief Finds the KeyItem from the KeyList by KeyId |
| 4870 | * |
| 4871 | * @param keyId the identifier of the Key |
| 4872 | * @param keyStorage pointer to the keystorage |
| 4873 | * @param keyItem returned pointer to the keyItem in the KeyList |
| 4874 | * @return UA_StatusCode return status code |
| 4875 | */ |
| 4876 | UA_StatusCode |
| 4877 | UA_PubSubKeyStorage_getKeyByKeyID(const UA_UInt32 keyId, UA_PubSubKeyStorage *keyStorage, |
| 4878 | UA_PubSubKeyListItem **keyItem); |
| 4879 | |
| 4880 | /** |
| 4881 | * @brief Adds a new KeyItem at the end of the KeyList |
| 4882 | * to the new KeyListItem. |
| 4883 | * |
| 4884 | * @param keyStorage pointer to the keystorage |
| 4885 | * @param key the key to be added |
| 4886 | * @param keyID the keyID associated with the key to be added |
| 4887 | */ |
| 4888 | UA_PubSubKeyListItem * |
| 4889 | UA_PubSubKeyStorage_push(UA_PubSubKeyStorage *keyStorage, const UA_ByteString *key, |
| 4890 | UA_UInt32 keyID); |
| 4891 | |
| 4892 | /** |
| 4893 | * @brief It calculates the time to trigger the callback to update current key, adds the |
| 4894 | * callback to the server and returns the callbackId. |
| 4895 | * |
| 4896 | * @param server the server object |
| 4897 | * @param keyStorage the pointer to the existing keystorage in the server |
| 4898 | * @param callback the callback function to be added to the server |
| 4899 | * @param timeToNextMs time in milli seconds to trigger the callback function |
| 4900 | * @param callbackID the returned callbackId of the added callback function |
| 4901 | * @return UA_StatusCode the return status |
| 4902 | */ |
| 4903 | UA_StatusCode |
| 4904 | UA_PubSubKeyStorage_addKeyRolloverCallback(UA_Server *server, |
| 4905 | UA_PubSubKeyStorage *keyStorage, |
| 4906 | UA_ServerCallback callback, |
| 4907 | UA_Duration timeToNextMs, |
| 4908 | UA_UInt64 *callbackID); |
| 4909 | |
| 4910 | /** |
| 4911 | * @brief It takes the current Key data, divide it into signing key, encrypting key and |
| 4912 | * keyNonce according to security policy associated with PubSub Group and set it in |
| 4913 | * channel context of the assocaited PubSub Group. In case of pubSubGroupId is |
| 4914 | * UA_NODEID_NULL, all the Reader/WriterGroup's channelcontext are updated with matching |
| 4915 | * SecurityGroupId. |
| 4916 | * |
| 4917 | * @param server The server object |
| 4918 | * @param pubSubGroupId the nodeId of the Reader/WirterGroup whose channel context to be |
| 4919 | * updated |
| 4920 | * @param securityGroupId The identifier for the SecurityGroup |
| 4921 | * @return UA_StatusCode return status code |
| 4922 | */ |
| 4923 | UA_StatusCode |
| 4924 | UA_PubSubKeyStorage_activateKeyToChannelContext(UA_Server *server, const UA_NodeId pubSubGroupId, |
| 4925 | const UA_String securityGroupId); |
| 4926 | |
| 4927 | /** |
| 4928 | * @brief The callback function to update the current key from keystorage in the server |
| 4929 | * and activate the current key into channel context of the associated PubSub Group |
| 4930 | * |
| 4931 | * @param server the server object |
| 4932 | * @param keyStorage the pointer to the keystorage |
| 4933 | */ |
| 4934 | void |
| 4935 | UA_PubSubKeyStorage_keyRolloverCallback(UA_Server *server, UA_PubSubKeyStorage *keyStorage); |
| 4936 | |
| 4937 | /** |
| 4938 | * @brief It updates/adds the current and future keys into the existing KeyStorage. |
| 4939 | * If the currentKeyID is known to existing keyStorage, then it is set as the currentKey |
| 4940 | * and any future keys are appended to the existing list. If the currentKeyId is not know |
| 4941 | * then, existing keyList is discarded and replaced with the new list. |
| 4942 | * |
| 4943 | * @param server the server object |
| 4944 | * @param keyStorage pointer to the keystorage |
| 4945 | * @param currentKey the currentKey data |
| 4946 | * @param currentKeyID the identifier of the current Key |
| 4947 | * @param futureKeySize the size of the future key list |
| 4948 | * @param futureKeys the pointer to the future keys list |
| 4949 | * @param msKeyLifeTime the updated time to move to next key |
| 4950 | * @return UA_StatusCode the return status |
| 4951 | */ |
| 4952 | UA_StatusCode |
| 4953 | UA_PubSubKeyStorage_update(UA_Server *server, UA_PubSubKeyStorage *keyStorage, |
| 4954 | const UA_ByteString *currentKey, UA_UInt32 currentKeyID, |
| 4955 | const size_t futureKeySize, UA_ByteString *futureKeys, |
| 4956 | UA_Duration msKeyLifeTime); |
| 4957 | |
| 4958 | /* KeyStorage must be referenced by atleast one PubSubGroup. This method reduces |
| 4959 | * the reference count by one. If no PubSubGroup uses the key storage, then it |
| 4960 | * is deleted. */ |
| 4961 | void |
| 4962 | UA_PubSubKeyStorage_detachKeyStorage(UA_Server *server, UA_PubSubKeyStorage *keyStorage); |
| 4963 | |
| 4964 | /*Calls get SecurityKeys Method and Store the returned keys into KeyStorage*/ |
| 4965 | UA_StatusCode |
| 4966 | getSecurityKeysAndStoreFetchedKeys(UA_Server *server, UA_PubSubKeyStorage *keyStorage); |
| 4967 | |
| 4968 | #endif |
| 4969 | |
| 4970 | _UA_END_DECLS |
| 4971 | |
| 4972 | #endif /* UA_ENABLE_PUBSUB */ |
| 4973 | |
| 4974 | /**** amalgamated original file "/src/server/ua_server_async.h" ****/ |
| 4975 | |
| 4976 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 4977 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 4978 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 4979 | * |
| 4980 | * Copyright 2019 (c) Fraunhofer IOSB (Author: Klaus Schick) |
| 4981 | * based on |
| 4982 | * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 4983 | * Copyright 2014, 2017 (c) Florian Palm |
| 4984 | * Copyright 2015 (c) Sten Grüner |
| 4985 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 4986 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 4987 | */ |
| 4988 | |
| 4989 | |
| 4990 | |
| 4991 | |
| 4992 | _UA_BEGIN_DECLS |
| 4993 | |
| 4994 | #if UA_MULTITHREADING >= 100 |
| 4995 | |
| 4996 | struct UA_AsyncResponse; |
| 4997 | typedef struct UA_AsyncResponse UA_AsyncResponse; |
| 4998 | |
| 4999 | /* A single operation (of a larger request) */ |
| 5000 | typedef struct UA_AsyncOperation { |
| 5001 | TAILQ_ENTRY(UA_AsyncOperation) pointers; |
| 5002 | UA_CallMethodRequest request; |
| 5003 | UA_CallMethodResult response; |
| 5004 | size_t index; /* Index of the operation in the array of ops in |
| 5005 | * request/response */ |
| 5006 | UA_AsyncResponse *parent; /* Always non-NULL. The parent is only removed |
| 5007 | * when its operations are removed */ |
| 5008 | } UA_AsyncOperation; |
| 5009 | |
| 5010 | struct UA_AsyncResponse { |
| 5011 | TAILQ_ENTRY(UA_AsyncResponse) pointers; /* Insert new at the end */ |
| 5012 | UA_UInt32 requestId; |
| 5013 | UA_NodeId sessionId; |
| 5014 | UA_UInt32 requestHandle; |
| 5015 | UA_DateTime timeout; |
| 5016 | UA_AsyncOperationType operationType; |
| 5017 | union { |
| 5018 | UA_CallResponse callResponse; |
| 5019 | UA_ReadResponse readResponse; |
| 5020 | UA_WriteResponse writeResponse; |
| 5021 | } response; |
| 5022 | UA_UInt32 opCountdown; /* Counter for outstanding operations. The AR can |
| 5023 | * only be deleted when all have returned. */ |
| 5024 | }; |
| 5025 | |
| 5026 | typedef TAILQ_HEAD(UA_AsyncOperationQueue, UA_AsyncOperation) UA_AsyncOperationQueue; |
| 5027 | |
| 5028 | typedef struct { |
| 5029 | /* Requests / Responses */ |
| 5030 | TAILQ_HEAD(, UA_AsyncResponse) asyncResponses; |
| 5031 | size_t asyncResponsesCount; |
| 5032 | |
| 5033 | /* Operations for the workers. The queues are all FIFO: Put in at the tail, |
| 5034 | * take out at the head.*/ |
| 5035 | UA_Lock queueLock; /* Either take this lock free-standing (with no other |
| 5036 | * locks). Or take server->serviceMutex first and then |
| 5037 | * the queueLock. Never take the server->serviceMutex |
| 5038 | * when the queueLock is already acquired (deadlock)! */ |
| 5039 | UA_AsyncOperationQueue newQueue; /* New operations for the workers */ |
| 5040 | UA_AsyncOperationQueue dispatchedQueue; /* Operations taken by a worker. When a result is |
| 5041 | * returned, we search for the op here to see if it |
| 5042 | * is still "alive" (not timed out). */ |
| 5043 | UA_AsyncOperationQueue resultQueue; /* Results to be integrated */ |
| 5044 | size_t opsCount; /* How many operations are transient (in one of the three queues)? */ |
| 5045 | |
| 5046 | UA_UInt64 checkTimeoutCallbackId; /* Registered repeated callbacks */ |
| 5047 | } UA_AsyncManager; |
| 5048 | |
| 5049 | void UA_AsyncManager_init(UA_AsyncManager *am, UA_Server *server); |
| 5050 | void UA_AsyncManager_clear(UA_AsyncManager *am, UA_Server *server); |
| 5051 | |
| 5052 | UA_StatusCode |
| 5053 | UA_AsyncManager_createAsyncResponse(UA_AsyncManager *am, UA_Server *server, |
| 5054 | const UA_NodeId *sessionId, |
| 5055 | const UA_UInt32 requestId, |
| 5056 | const UA_UInt32 requestHandle, |
| 5057 | const UA_AsyncOperationType operationType, |
| 5058 | UA_AsyncResponse **outAr); |
| 5059 | |
| 5060 | /* Only remove the AsyncResponse when the operation count is zero */ |
| 5061 | void |
| 5062 | UA_AsyncManager_removeAsyncResponse(UA_AsyncManager *am, UA_AsyncResponse *ar); |
| 5063 | |
| 5064 | UA_StatusCode |
| 5065 | UA_AsyncManager_createAsyncOp(UA_AsyncManager *am, UA_Server *server, |
| 5066 | UA_AsyncResponse *ar, size_t opIndex, |
| 5067 | const UA_CallMethodRequest *opRequest); |
| 5068 | |
| 5069 | /* Send out the response with status set. Also removes all outstanding |
| 5070 | * operations from the dispatch queue. The queuelock needs to be taken before |
| 5071 | * calling _cancel. */ |
| 5072 | UA_UInt32 |
| 5073 | UA_AsyncManager_cancel(UA_Server *server, UA_Session *session, UA_UInt32 requestHandle); |
| 5074 | |
| 5075 | typedef void (*UA_AsyncServiceOperation)(UA_Server *server, UA_Session *session, |
| 5076 | UA_UInt32 requestId, UA_UInt32 requestHandle, |
| 5077 | size_t opIndex, const void *requestOperation, |
| 5078 | void *responseOperation, UA_AsyncResponse **ar); |
| 5079 | |
| 5080 | /* Creates an AsyncResponse in-situ when an async operation is encountered. If |
| 5081 | * that is the case, the sync responses are moved to the AsyncResponse. */ |
| 5082 | UA_StatusCode |
| 5083 | UA_Server_processServiceOperationsAsync(UA_Server *server, UA_Session *session, |
| 5084 | UA_UInt32 requestId, UA_UInt32 requestHandle, |
| 5085 | UA_AsyncServiceOperation operationCallback, |
| 5086 | const size_t *requestOperations, |
| 5087 | const UA_DataType *requestOperationsType, |
| 5088 | size_t *responseOperations, |
| 5089 | const UA_DataType *responseOperationsType, |
| 5090 | UA_AsyncResponse **ar) |
| 5091 | UA_FUNC_ATTR_WARN_UNUSED_RESULT; |
| 5092 | |
| 5093 | #endif /* UA_MULTITHREADING >= 100 */ |
| 5094 | |
| 5095 | _UA_END_DECLS |
| 5096 | |
| 5097 | |
| 5098 | /**** amalgamated original file "/src/server/ua_server_internal.h" ****/ |
| 5099 | |
| 5100 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 5101 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 5102 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 5103 | * |
| 5104 | * Copyright 2019 (c) Fraunhofer IOSB (Author: Klaus Schick) |
| 5105 | * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 5106 | * Copyright 2014, 2017 (c) Florian Palm |
| 5107 | * Copyright 2015-2016 (c) Sten Grüner |
| 5108 | * Copyright 2015 (c) Chris Iatrou |
| 5109 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 5110 | * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH |
| 5111 | * Copyright 2017 (c) Julian Grothoff |
| 5112 | * Copyright 2019 (c) Kalycito Infotech Private Limited |
| 5113 | * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 5114 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
| 5115 | * Copyright 2022 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 5116 | */ |
| 5117 | |
| 5118 | |
| 5119 | #define UA_INTERNAL |
| 5120 | |
| 5121 | |
| 5122 | _UA_BEGIN_DECLS |
| 5123 | |
| 5124 | #ifdef UA_ENABLE_PUBSUB |
| 5125 | #endif |
| 5126 | |
| 5127 | #ifdef UA_ENABLE_DISCOVERY |
| 5128 | struct UA_DiscoveryManager; |
| 5129 | typedef struct UA_DiscoveryManager UA_DiscoveryManager; |
| 5130 | #endif |
| 5131 | |
| 5132 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 5133 | |
| 5134 | typedef struct { |
| 5135 | UA_MonitoredItem monitoredItem; |
| 5136 | void *context; |
| 5137 | union { |
| 5138 | UA_Server_DataChangeNotificationCallback dataChangeCallback; |
| 5139 | /* UA_Server_EventNotificationCallback eventCallback; */ |
| 5140 | } callback; |
| 5141 | } UA_LocalMonitoredItem; |
| 5142 | |
| 5143 | #endif /* !UA_ENABLE_SUBSCRIPTIONS */ |
| 5144 | |
| 5145 | /********************/ |
| 5146 | /* Server Component */ |
| 5147 | /********************/ |
| 5148 | |
| 5149 | /* ServerComponents have an explicit lifecycle. But they can only be started |
| 5150 | * when the underlying server is started. The starting/stopping of |
| 5151 | * ServerComponents is asynchronous. That is, they might require several |
| 5152 | * iterations of the EventLoop to finish starting/stopping. |
| 5153 | * |
| 5154 | * ServerComponents can only be deleted when they are STOPPED. The server will |
| 5155 | * not fully shut down as long as there is a component remaining. */ |
| 5156 | |
| 5157 | typedef struct UA_ServerComponent { |
| 5158 | UA_UInt64 identifier; |
| 5159 | UA_String name; |
| 5160 | ZIP_ENTRY(UA_ServerComponent) treeEntry; |
| 5161 | UA_LifecycleState state; |
| 5162 | |
| 5163 | /* Starting fails if the server is not also already started */ |
| 5164 | UA_StatusCode (*start)(UA_Server *server, |
| 5165 | struct UA_ServerComponent *sc); |
| 5166 | |
| 5167 | /* Stopping is asynchronous and might need a few iterations of the main-loop |
| 5168 | * to succeed. */ |
| 5169 | void (*stop)(UA_Server *server, |
| 5170 | struct UA_ServerComponent *sc); |
| 5171 | |
| 5172 | /* Clean up the ServerComponent. Can fail if it is not stopped. */ |
| 5173 | UA_StatusCode (*free)(UA_Server *server, |
| 5174 | struct UA_ServerComponent *sc); |
| 5175 | |
| 5176 | /* To be set by the server. So the component can notify the server about |
| 5177 | * asynchronous state changes. */ |
| 5178 | void (*notifyState)(UA_Server *server, struct UA_ServerComponent *sc, |
| 5179 | UA_LifecycleState state); |
| 5180 | } UA_ServerComponent; |
| 5181 | |
| 5182 | enum ZIP_CMP |
| 5183 | cmpServerComponent(const UA_UInt64 *a, const UA_UInt64 *b); |
| 5184 | |
| 5185 | typedef ZIP_HEAD(UA_ServerComponentTree, UA_ServerComponent) UA_ServerComponentTree; |
| 5186 | |
| 5187 | ZIP_FUNCTIONS(UA_ServerComponentTree, UA_ServerComponent, treeEntry, |
| 5188 | UA_UInt64, identifier, cmpServerComponent) |
| 5189 | |
| 5190 | /* Assigns the identifier if the pointer is non-NULL. |
| 5191 | * Starts the component if the server is started. */ |
| 5192 | void |
| 5193 | addServerComponent(UA_Server *server, UA_ServerComponent *sc, |
| 5194 | UA_UInt64 *identifier); |
| 5195 | |
| 5196 | UA_ServerComponent * |
| 5197 | getServerComponentByName(UA_Server *server, UA_String name); |
| 5198 | |
| 5199 | /********************/ |
| 5200 | /* Server Structure */ |
| 5201 | /********************/ |
| 5202 | |
| 5203 | typedef struct session_list_entry { |
| 5204 | UA_DelayedCallback cleanupCallback; |
| 5205 | LIST_ENTRY(session_list_entry) pointers; |
| 5206 | UA_Session session; |
| 5207 | } session_list_entry; |
| 5208 | |
| 5209 | struct UA_Server { |
| 5210 | /* Config */ |
| 5211 | UA_ServerConfig config; |
| 5212 | |
| 5213 | /* Runtime state */ |
| 5214 | UA_DateTime startTime; |
| 5215 | UA_DateTime endTime; /* Zeroed out. If a time is set, then the server shuts |
| 5216 | * down once the time has been reached */ |
| 5217 | |
| 5218 | UA_LifecycleState state; |
| 5219 | UA_UInt64 houseKeepingCallbackId; |
| 5220 | |
| 5221 | UA_UInt64 serverComponentIds; /* Counter to assign ids from */ |
| 5222 | UA_ServerComponentTree serverComponents; |
| 5223 | |
| 5224 | #if UA_MULTITHREADING >= 100 |
| 5225 | UA_AsyncManager asyncManager; |
| 5226 | #endif |
| 5227 | |
| 5228 | /* Session Management */ |
| 5229 | LIST_HEAD(session_list, session_list_entry) sessions; |
| 5230 | UA_UInt32 sessionCount; |
| 5231 | UA_UInt32 activeSessionCount; |
| 5232 | UA_Session adminSession; /* Local access to the services (for startup and |
| 5233 | * maintenance) uses this Session with all possible |
| 5234 | * access rights (Session Id: 1) */ |
| 5235 | |
| 5236 | /* Namespaces */ |
| 5237 | size_t namespacesSize; |
| 5238 | UA_String *namespaces; |
| 5239 | |
| 5240 | /* For bootstrapping, omit some consistency checks, creating a reference to |
| 5241 | * the parent and member instantiation */ |
| 5242 | UA_Boolean bootstrapNS0; |
| 5243 | |
| 5244 | /* Subscriptions */ |
| 5245 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 5246 | size_t subscriptionsSize; /* Number of active subscriptions */ |
| 5247 | size_t monitoredItemsSize; /* Number of active monitored items */ |
| 5248 | LIST_HEAD(, UA_Subscription) subscriptions; /* All subscriptions in the |
| 5249 | * server. They may be detached |
| 5250 | * from a session. */ |
| 5251 | UA_UInt32 lastSubscriptionId; /* To generate unique SubscriptionIds */ |
| 5252 | |
| 5253 | /* To be cast to UA_LocalMonitoredItem to get the callback and context */ |
| 5254 | LIST_HEAD(, UA_MonitoredItem) localMonitoredItems; |
| 5255 | UA_UInt32 lastLocalMonitoredItemId; |
| 5256 | |
| 5257 | # ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS |
| 5258 | LIST_HEAD(, UA_ConditionSource) conditionSources; |
| 5259 | UA_NodeId refreshEvents[2]; |
| 5260 | # endif |
| 5261 | #endif |
| 5262 | |
| 5263 | /* Publish/Subscribe */ |
| 5264 | #ifdef UA_ENABLE_PUBSUB |
| 5265 | UA_PubSubManager pubSubManager; |
| 5266 | #endif |
| 5267 | |
| 5268 | #if UA_MULTITHREADING >= 100 |
| 5269 | UA_Lock serviceMutex; |
| 5270 | #endif |
| 5271 | |
| 5272 | /* Statistics */ |
| 5273 | UA_SecureChannelStatistics secureChannelStatistics; |
| 5274 | UA_ServerDiagnosticsSummaryDataType serverDiagnosticsSummary; |
| 5275 | }; |
| 5276 | |
| 5277 | /***********************/ |
| 5278 | /* References Handling */ |
| 5279 | /***********************/ |
| 5280 | |
| 5281 | enum ZIP_CMP |
| 5282 | cmpRefTargetId(const void *a, const void *b); |
| 5283 | |
| 5284 | enum ZIP_CMP |
| 5285 | cmpRefTargetName(const void *a, const void *b); |
| 5286 | |
| 5287 | /* Static inline methods for tree handling */ |
| 5288 | typedef ZIP_HEAD(UA_ReferenceIdTree, UA_ReferenceTargetTreeElem) UA_ReferenceIdTree; |
| 5289 | ZIP_FUNCTIONS(UA_ReferenceIdTree, UA_ReferenceTargetTreeElem, idTreeEntry, |
| 5290 | UA_ReferenceTargetTreeElem, target, cmpRefTargetId) |
| 5291 | |
| 5292 | typedef ZIP_HEAD(UA_ReferenceNameTree, UA_ReferenceTargetTreeElem) UA_ReferenceNameTree; |
| 5293 | ZIP_FUNCTIONS(UA_ReferenceNameTree, UA_ReferenceTargetTreeElem, nameTreeEntry, |
| 5294 | UA_ReferenceTarget, target, cmpRefTargetName) |
| 5295 | |
| 5296 | /**************************/ |
| 5297 | /* SecureChannel Handling */ |
| 5298 | /**************************/ |
| 5299 | |
| 5300 | void |
| 5301 | serverNetworkCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 5302 | void *application, void **connectionContext, |
| 5303 | UA_ConnectionState state, |
| 5304 | const UA_KeyValueMap *params, |
| 5305 | UA_ByteString msg); |
| 5306 | |
| 5307 | UA_StatusCode |
| 5308 | sendServiceFault(UA_SecureChannel *channel, UA_UInt32 requestId, |
| 5309 | UA_UInt32 requestHandle, UA_StatusCode statusCode); |
| 5310 | |
| 5311 | /* Gets the a pointer to the context of a security policy supported by the |
| 5312 | * server matched by the security policy uri. */ |
| 5313 | UA_SecurityPolicy * |
| 5314 | getSecurityPolicyByUri(const UA_Server *server, |
| 5315 | const UA_ByteString *securityPolicyUri); |
| 5316 | |
| 5317 | UA_UInt32 |
| 5318 | generateSecureChannelTokenId(UA_Server *server); |
| 5319 | |
| 5320 | /********************/ |
| 5321 | /* Session Handling */ |
| 5322 | /********************/ |
| 5323 | |
| 5324 | UA_StatusCode |
| 5325 | getNamespaceByName(UA_Server *server, const UA_String namespaceUri, |
| 5326 | size_t *foundIndex); |
| 5327 | |
| 5328 | UA_StatusCode |
| 5329 | getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex, |
| 5330 | UA_String *foundUri); |
| 5331 | |
| 5332 | UA_StatusCode |
| 5333 | getBoundSession(UA_Server *server, const UA_SecureChannel *channel, |
| 5334 | const UA_NodeId *token, UA_Session **session); |
| 5335 | |
| 5336 | UA_StatusCode |
| 5337 | UA_Server_createSession(UA_Server *server, UA_SecureChannel *channel, |
| 5338 | const UA_CreateSessionRequest *request, UA_Session **session); |
| 5339 | |
| 5340 | void |
| 5341 | UA_Server_removeSession(UA_Server *server, session_list_entry *sentry, |
| 5342 | UA_ShutdownReason shutdownReason); |
| 5343 | |
| 5344 | UA_StatusCode |
| 5345 | UA_Server_removeSessionByToken(UA_Server *server, const UA_NodeId *token, |
| 5346 | UA_ShutdownReason shutdownReason); |
| 5347 | |
| 5348 | void |
| 5349 | UA_Server_cleanupSessions(UA_Server *server, UA_DateTime nowMonotonic); |
| 5350 | |
| 5351 | UA_Session * |
| 5352 | getSessionByToken(UA_Server *server, const UA_NodeId *token); |
| 5353 | |
| 5354 | UA_Session * |
| 5355 | getSessionById(UA_Server *server, const UA_NodeId *sessionId); |
| 5356 | |
| 5357 | /*****************/ |
| 5358 | /* Node Handling */ |
| 5359 | /*****************/ |
| 5360 | |
| 5361 | /* Calls the callback with the node retrieved from the nodestore on top of the |
| 5362 | * stack. Either a copy or the original node for in-situ editing. Depends on |
| 5363 | * multithreading and the nodestore.*/ |
| 5364 | typedef UA_StatusCode (*UA_EditNodeCallback)(UA_Server*, UA_Session*, |
| 5365 | UA_Node *node, void*); |
| 5366 | UA_StatusCode UA_Server_editNode(UA_Server *server, UA_Session *session, |
| 5367 | const UA_NodeId *nodeId, |
| 5368 | UA_EditNodeCallback callback, |
| 5369 | void *data); |
| 5370 | |
| 5371 | /*********************/ |
| 5372 | /* Utility Functions */ |
| 5373 | /*********************/ |
| 5374 | |
| 5375 | void setServerLifecycleState(UA_Server *server, UA_LifecycleState state); |
| 5376 | |
| 5377 | void setupNs1Uri(UA_Server *server); |
| 5378 | UA_UInt16 addNamespace(UA_Server *server, const UA_String name); |
| 5379 | |
| 5380 | UA_Boolean |
| 5381 | UA_Node_hasSubTypeOrInstances(const UA_NodeHead *head); |
| 5382 | |
| 5383 | /* Recursively searches "upwards" in the tree following specific reference types */ |
| 5384 | UA_Boolean |
| 5385 | isNodeInTree(UA_Server *server, const UA_NodeId *leafNode, |
| 5386 | const UA_NodeId *nodeToFind, const UA_ReferenceTypeSet *relevantRefs); |
| 5387 | |
| 5388 | /* Convenience function with just a single ReferenceTypeIndex */ |
| 5389 | UA_Boolean |
| 5390 | isNodeInTree_singleRef(UA_Server *server, const UA_NodeId *leafNode, |
| 5391 | const UA_NodeId *nodeToFind, const UA_Byte relevantRefTypeIndex); |
| 5392 | |
| 5393 | /* Returns an array with the hierarchy of nodes. The start nodes can be returned |
| 5394 | * as well. The returned array starts at the leaf and continues "upwards" or |
| 5395 | * "downwards". Duplicate entries are removed. */ |
| 5396 | UA_StatusCode |
| 5397 | browseRecursive(UA_Server *server, size_t startNodesSize, const UA_NodeId *startNodes, |
| 5398 | UA_BrowseDirection browseDirection, const UA_ReferenceTypeSet *refTypes, |
| 5399 | UA_UInt32 nodeClassMask, UA_Boolean includeStartNodes, |
| 5400 | size_t *resultsSize, UA_ExpandedNodeId **results); |
| 5401 | |
| 5402 | /* Get the bitfield indices of a ReferenceType and possibly its subtypes. |
| 5403 | * refType must point to a ReferenceTypeNode. */ |
| 5404 | UA_StatusCode |
| 5405 | referenceTypeIndices(UA_Server *server, const UA_NodeId *refType, |
| 5406 | UA_ReferenceTypeSet *indices, UA_Boolean includeSubtypes); |
| 5407 | |
| 5408 | /* Returns the recursive type and interface hierarchy of the node */ |
| 5409 | UA_StatusCode |
| 5410 | getParentTypeAndInterfaceHierarchy(UA_Server *server, const UA_NodeId *typeNode, |
| 5411 | UA_NodeId **typeHierarchy, size_t *typeHierarchySize); |
| 5412 | |
| 5413 | /* Returns the recursive interface hierarchy of the node */ |
| 5414 | UA_StatusCode |
| 5415 | getAllInterfaceChildNodeIds(UA_Server *server, const UA_NodeId *objectNode, const UA_NodeId *objectTypeNode, |
| 5416 | UA_NodeId **interfaceChildNodes, size_t *interfaceChildNodesSize); |
| 5417 | |
| 5418 | #ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS |
| 5419 | |
| 5420 | UA_StatusCode |
| 5421 | UA_getConditionId(UA_Server *server, const UA_NodeId *conditionNodeId, |
| 5422 | UA_NodeId *outConditionId); |
| 5423 | |
| 5424 | void |
| 5425 | UA_ConditionList_delete(UA_Server *server); |
| 5426 | |
| 5427 | UA_Boolean |
| 5428 | isConditionOrBranch(UA_Server *server, |
| 5429 | const UA_NodeId *condition, |
| 5430 | const UA_NodeId *conditionSource, |
| 5431 | UA_Boolean *isCallerAC); |
| 5432 | |
| 5433 | #endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */ |
| 5434 | |
| 5435 | /* Returns the type node from the node on the stack top. The type node is pushed |
| 5436 | * on the stack and returned. */ |
| 5437 | const UA_Node * |
| 5438 | getNodeType(UA_Server *server, const UA_NodeHead *nodeHead); |
| 5439 | |
| 5440 | UA_StatusCode |
| 5441 | sendResponse(UA_Server *server, UA_Session *session, UA_SecureChannel *channel, |
| 5442 | UA_UInt32 requestId, UA_Response *response, const UA_DataType *responseType); |
| 5443 | |
| 5444 | /* Many services come as an array of operations. This function generalizes the |
| 5445 | * processing of the operations. */ |
| 5446 | typedef void (*UA_ServiceOperation)(UA_Server *server, UA_Session *session, |
| 5447 | const void *context, |
| 5448 | const void *requestOperation, |
| 5449 | void *responseOperation); |
| 5450 | |
| 5451 | UA_StatusCode |
| 5452 | UA_Server_processServiceOperations(UA_Server *server, UA_Session *session, |
| 5453 | UA_ServiceOperation operationCallback, |
| 5454 | const void *context, |
| 5455 | const size_t *requestOperations, |
| 5456 | const UA_DataType *requestOperationsType, |
| 5457 | size_t *responseOperations, |
| 5458 | const UA_DataType *responseOperationsType) |
| 5459 | UA_FUNC_ATTR_WARN_UNUSED_RESULT; |
| 5460 | |
| 5461 | /*********************/ |
| 5462 | /* Locking/Unlocking */ |
| 5463 | /*********************/ |
| 5464 | |
| 5465 | /* In order to prevent deadlocks between the EventLoop mutex and the |
| 5466 | * server-mutex, we always take the EventLoop mutex first. */ |
| 5467 | |
| 5468 | void lockServer(UA_Server *server); |
| 5469 | void unlockServer(UA_Server *server); |
| 5470 | |
| 5471 | /******************************************/ |
| 5472 | /* Internal function calls, without locks */ |
| 5473 | /******************************************/ |
| 5474 | UA_StatusCode |
| 5475 | deleteNode(UA_Server *server, const UA_NodeId nodeId, |
| 5476 | UA_Boolean deleteReferences); |
| 5477 | |
| 5478 | UA_StatusCode |
| 5479 | addRef(UA_Server *server, const UA_NodeId sourceId, |
| 5480 | const UA_NodeId referenceTypeId, const UA_NodeId targetId, |
| 5481 | UA_Boolean forward); |
| 5482 | |
| 5483 | UA_StatusCode |
| 5484 | deleteReference(UA_Server *server, const UA_NodeId sourceNodeId, |
| 5485 | const UA_NodeId referenceTypeId, UA_Boolean isForward, |
| 5486 | const UA_ExpandedNodeId targetNodeId, |
| 5487 | UA_Boolean deleteBidirectional); |
| 5488 | |
| 5489 | UA_StatusCode |
| 5490 | addRefWithSession(UA_Server *server, UA_Session *session, const UA_NodeId *sourceId, |
| 5491 | const UA_NodeId *referenceTypeId, const UA_NodeId *targetId, |
| 5492 | UA_Boolean forward); |
| 5493 | |
| 5494 | UA_StatusCode |
| 5495 | setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId, |
| 5496 | const UA_DataSource dataSource); |
| 5497 | |
| 5498 | UA_StatusCode |
| 5499 | setVariableNode_valueCallback(UA_Server *server, const UA_NodeId nodeId, |
| 5500 | const UA_ValueCallback callback); |
| 5501 | |
| 5502 | UA_StatusCode |
| 5503 | setMethodNode_callback(UA_Server *server, const UA_NodeId methodNodeId, |
| 5504 | UA_MethodCallback methodCallback); |
| 5505 | |
| 5506 | UA_StatusCode |
| 5507 | setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId, |
| 5508 | UA_NodeTypeLifecycle lifecycle); |
| 5509 | |
| 5510 | void |
| 5511 | Operation_Write(UA_Server *server, UA_Session *session, void *context, |
| 5512 | const UA_WriteValue *wv, UA_StatusCode *result); |
| 5513 | |
| 5514 | UA_StatusCode |
| 5515 | writeAttribute(UA_Server *server, UA_Session *session, |
| 5516 | const UA_NodeId *nodeId, const UA_AttributeId attributeId, |
| 5517 | const void *attr, const UA_DataType *attr_type); |
| 5518 | |
| 5519 | #define UA_WRITEATTRIBUTEFUNCS(ATTR, ATTRID, TYPE, TYPENAME) \ |
| 5520 | static UA_INLINE UA_StatusCode \ |
| 5521 | write##ATTR##Attribute(UA_Server *server, const UA_NodeId nodeId, \ |
| 5522 | const TYPE value) { \ |
| 5523 | return writeAttribute(server, &server->adminSession, &nodeId, \ |
| 5524 | ATTRID, &value, &UA_TYPES[UA_TYPES_##TYPENAME]); \ |
| 5525 | } \ |
| 5526 | static UA_INLINE UA_StatusCode \ |
| 5527 | write##ATTR##AttributeWithSession(UA_Server *server, UA_Session *session, \ |
| 5528 | const UA_NodeId nodeId, const TYPE value) { \ |
| 5529 | return writeAttribute(server, session, &nodeId, ATTRID, &value, \ |
| 5530 | &UA_TYPES[UA_TYPES_##TYPENAME]); \ |
| 5531 | } |
| 5532 | |
| 5533 | static UA_INLINE UA_StatusCode |
| 5534 | writeValueAttribute(UA_Server *server, const UA_NodeId nodeId, |
| 5535 | const UA_Variant *value) { |
| 5536 | return writeAttribute(server, session: &server->adminSession, nodeId: &nodeId, |
| 5537 | attributeId: UA_ATTRIBUTEID_VALUE, attr: value, attr_type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 5538 | } |
| 5539 | |
| 5540 | UA_WRITEATTRIBUTEFUNCS(IsAbstract, UA_ATTRIBUTEID_ISABSTRACT, UA_Boolean, BOOLEAN) |
| 5541 | UA_WRITEATTRIBUTEFUNCS(ValueRank, UA_ATTRIBUTEID_VALUERANK, UA_Int32, INT32) |
| 5542 | UA_WRITEATTRIBUTEFUNCS(AccessLevel, UA_ATTRIBUTEID_ACCESSLEVEL, UA_Byte, BYTE) |
| 5543 | UA_WRITEATTRIBUTEFUNCS(MinimumSamplingInterval, UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL, |
| 5544 | UA_Double, DOUBLE) |
| 5545 | |
| 5546 | void |
| 5547 | Operation_Read(UA_Server *server, UA_Session *session, UA_TimestampsToReturn *ttr, |
| 5548 | const UA_ReadValueId *rvi, UA_DataValue *dv); |
| 5549 | |
| 5550 | UA_DataValue |
| 5551 | readWithSession(UA_Server *server, UA_Session *session, |
| 5552 | const UA_ReadValueId *item, |
| 5553 | UA_TimestampsToReturn timestampsToReturn); |
| 5554 | |
| 5555 | UA_StatusCode |
| 5556 | readWithReadValue(UA_Server *server, const UA_NodeId *nodeId, |
| 5557 | const UA_AttributeId attributeId, void *v); |
| 5558 | |
| 5559 | UA_StatusCode |
| 5560 | readObjectProperty(UA_Server *server, const UA_NodeId objectId, |
| 5561 | const UA_QualifiedName propertyName, |
| 5562 | UA_Variant *value); |
| 5563 | |
| 5564 | UA_BrowsePathResult |
| 5565 | translateBrowsePathToNodeIds(UA_Server *server, const UA_BrowsePath *browsePath); |
| 5566 | |
| 5567 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 5568 | |
| 5569 | void monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *mon); |
| 5570 | |
| 5571 | UA_Subscription * |
| 5572 | getSubscriptionById(UA_Server *server, UA_UInt32 subscriptionId); |
| 5573 | |
| 5574 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 5575 | |
| 5576 | UA_StatusCode |
| 5577 | createEvent(UA_Server *server, const UA_NodeId eventType, |
| 5578 | UA_NodeId *outNodeId); |
| 5579 | |
| 5580 | UA_StatusCode |
| 5581 | triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, |
| 5582 | const UA_NodeId origin, UA_ByteString *outEventId, |
| 5583 | const UA_Boolean deleteEventNode); |
| 5584 | |
| 5585 | /* Filters the given event with the given filter and writes the results into a |
| 5586 | * notification */ |
| 5587 | UA_StatusCode |
| 5588 | filterEvent(UA_Server *server, UA_Session *session, |
| 5589 | const UA_NodeId *eventNode, UA_EventFilter *filter, |
| 5590 | UA_EventFieldList *efl, UA_EventFilterResult *result); |
| 5591 | |
| 5592 | #endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */ |
| 5593 | |
| 5594 | #endif /* UA_ENABLE_SUBSCRIPTIONS */ |
| 5595 | |
| 5596 | /* Returns a configured SecurityPolicy with encryption. Use Basic256Sha256 if |
| 5597 | * available. Otherwise use any encrypted SecurityPolicy. */ |
| 5598 | UA_SecurityPolicy * |
| 5599 | getDefaultEncryptedSecurityPolicy(UA_Server *server); |
| 5600 | |
| 5601 | UA_StatusCode |
| 5602 | setCurrentEndPointsArray(UA_Server *server, const UA_String endpointURL, |
| 5603 | UA_String *profileUris, size_t profileUrisSize, |
| 5604 | UA_EndpointDescription **arr, size_t *arrSize); |
| 5605 | |
| 5606 | UA_BrowsePathResult |
| 5607 | browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin, |
| 5608 | size_t browsePathSize, const UA_QualifiedName *browsePath); |
| 5609 | |
| 5610 | UA_StatusCode |
| 5611 | writeObjectProperty(UA_Server *server, const UA_NodeId objectId, |
| 5612 | const UA_QualifiedName propertyName, const UA_Variant value); |
| 5613 | |
| 5614 | UA_StatusCode |
| 5615 | writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId, |
| 5616 | const UA_QualifiedName propertyName, |
| 5617 | const void *value, const UA_DataType *type); |
| 5618 | |
| 5619 | UA_StatusCode |
| 5620 | getNodeContext(UA_Server *server, UA_NodeId nodeId, void **nodeContext); |
| 5621 | |
| 5622 | UA_StatusCode |
| 5623 | setNodeContext(UA_Server *server, UA_NodeId nodeId, void *nodeContext); |
| 5624 | |
| 5625 | void |
| 5626 | removeCallback(UA_Server *server, UA_UInt64 callbackId); |
| 5627 | |
| 5628 | UA_StatusCode |
| 5629 | changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId, |
| 5630 | UA_Double interval_ms); |
| 5631 | |
| 5632 | UA_StatusCode |
| 5633 | addRepeatedCallback(UA_Server *server, UA_ServerCallback callback, |
| 5634 | void *data, UA_Double interval_ms, UA_UInt64 *callbackId); |
| 5635 | |
| 5636 | #ifdef UA_ENABLE_DISCOVERY |
| 5637 | UA_ServerComponent * |
| 5638 | UA_DiscoveryManager_new(UA_Server *server); |
| 5639 | #endif |
| 5640 | |
| 5641 | UA_String |
| 5642 | securityPolicyUriPostfix(const UA_String uri); |
| 5643 | |
| 5644 | UA_ServerComponent * |
| 5645 | UA_BinaryProtocolManager_new(UA_Server *server); |
| 5646 | |
| 5647 | /***********/ |
| 5648 | /* RefTree */ |
| 5649 | /***********/ |
| 5650 | |
| 5651 | /* A RefTree is a sorted set of NodeIds that ensures we consider each node just |
| 5652 | * once. It holds a single array for both the ExpandedNodeIds and the entries of |
| 5653 | * a tree-structure for fast lookup. A single realloc operation (with some |
| 5654 | * pointer repairing) can be used to increase the capacity of the RefTree. |
| 5655 | * |
| 5656 | * When the RefTree is complete, the tree-part at the end of the targets array |
| 5657 | * can be ignored / cut away to use it as a simple ExpandedNodeId array. |
| 5658 | * |
| 5659 | * The layout of the targets array is as follows: |
| 5660 | * |
| 5661 | * | Targets [ExpandedNodeId, n times] | Tree [RefEntry, n times] | */ |
| 5662 | |
| 5663 | #define UA_REFTREE_INITIAL_SIZE 16 |
| 5664 | |
| 5665 | typedef struct RefEntry { |
| 5666 | ZIP_ENTRY(RefEntry) zipfields; |
| 5667 | const UA_ExpandedNodeId *target; |
| 5668 | UA_UInt32 targetHash; /* Hash of the target nodeid */ |
| 5669 | } RefEntry; |
| 5670 | |
| 5671 | ZIP_HEAD(RefHead, RefEntry); |
| 5672 | typedef struct RefHead RefHead; |
| 5673 | |
| 5674 | typedef struct { |
| 5675 | UA_ExpandedNodeId *targets; |
| 5676 | RefHead head; |
| 5677 | size_t capacity; /* available space */ |
| 5678 | size_t size; /* used space */ |
| 5679 | } RefTree; |
| 5680 | |
| 5681 | UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT |
| 5682 | RefTree_init(RefTree *rt); |
| 5683 | |
| 5684 | void RefTree_clear(RefTree *rt); |
| 5685 | |
| 5686 | UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT |
| 5687 | RefTree_addNodeId(RefTree *rt, const UA_NodeId *target, UA_Boolean *duplicate); |
| 5688 | |
| 5689 | UA_Boolean |
| 5690 | RefTree_contains(RefTree *rt, const UA_ExpandedNodeId *target); |
| 5691 | |
| 5692 | UA_Boolean |
| 5693 | RefTree_containsNodeId(RefTree *rt, const UA_NodeId *target); |
| 5694 | |
| 5695 | /***************************************/ |
| 5696 | /* Check Information Model Consistency */ |
| 5697 | /***************************************/ |
| 5698 | |
| 5699 | /* Read a node attribute in the context of a "checked-out" node. So the |
| 5700 | * attribute will not be copied when possible. The variant then points into the |
| 5701 | * node and has UA_VARIANT_DATA_NODELETE set. */ |
| 5702 | void |
| 5703 | ReadWithNode(const UA_Node *node, UA_Server *server, UA_Session *session, |
| 5704 | UA_TimestampsToReturn timestampsToReturn, |
| 5705 | const UA_ReadValueId *id, UA_DataValue *v); |
| 5706 | |
| 5707 | UA_StatusCode |
| 5708 | readValueAttribute(UA_Server *server, UA_Session *session, |
| 5709 | const UA_VariableNode *vn, UA_DataValue *v); |
| 5710 | |
| 5711 | /* Test whether the value matches a variable definition given by |
| 5712 | * - datatype |
| 5713 | * - valuerank |
| 5714 | * - array dimensions. |
| 5715 | * Sometimes it can be necessary to transform the content of the value, e.g. |
| 5716 | * byte array to bytestring or uint32 to some enum. If editableValue is non-NULL, |
| 5717 | * we try to create a matching variant that points to the original data. |
| 5718 | * |
| 5719 | * The reason is set whenever the return value is false */ |
| 5720 | UA_Boolean |
| 5721 | compatibleValue(UA_Server *server, UA_Session *session, const UA_NodeId *targetDataTypeId, |
| 5722 | UA_Int32 targetValueRank, size_t targetArrayDimensionsSize, |
| 5723 | const UA_UInt32 *targetArrayDimensions, const UA_Variant *value, |
| 5724 | const UA_NumericRange *range, const char **reason); |
| 5725 | |
| 5726 | /* Is the DataType compatible */ |
| 5727 | UA_Boolean |
| 5728 | compatibleDataTypes(UA_Server *server, const UA_NodeId *dataType, |
| 5729 | const UA_NodeId *constraintDataType); |
| 5730 | |
| 5731 | /* Set to the target type if compatible */ |
| 5732 | void |
| 5733 | adjustValueType(UA_Server *server, UA_Variant *value, |
| 5734 | const UA_NodeId *targetDataTypeId); |
| 5735 | |
| 5736 | /* Is the Value compatible with the DataType? Can perform additional checks |
| 5737 | * compared to compatibleDataTypes. */ |
| 5738 | UA_Boolean |
| 5739 | compatibleValueDataType(UA_Server *server, const UA_DataType *dataType, |
| 5740 | const UA_NodeId *constraintDataType); |
| 5741 | |
| 5742 | |
| 5743 | UA_Boolean |
| 5744 | compatibleArrayDimensions(size_t constraintArrayDimensionsSize, |
| 5745 | const UA_UInt32 *constraintArrayDimensions, |
| 5746 | size_t testArrayDimensionsSize, |
| 5747 | const UA_UInt32 *testArrayDimensions); |
| 5748 | |
| 5749 | UA_Boolean |
| 5750 | compatibleValueArrayDimensions(const UA_Variant *value, size_t targetArrayDimensionsSize, |
| 5751 | const UA_UInt32 *targetArrayDimensions); |
| 5752 | |
| 5753 | UA_Boolean |
| 5754 | compatibleValueRankArrayDimensions(UA_Server *server, UA_Session *session, |
| 5755 | UA_Int32 valueRank, size_t arrayDimensionsSize); |
| 5756 | |
| 5757 | UA_Boolean |
| 5758 | compatibleValueRanks(UA_Int32 valueRank, UA_Int32 constraintValueRank); |
| 5759 | |
| 5760 | struct BrowseOpts { |
| 5761 | UA_UInt32 maxReferences; |
| 5762 | UA_Boolean recursive; |
| 5763 | }; |
| 5764 | |
| 5765 | void |
| 5766 | Operation_Browse(UA_Server *server, UA_Session *session, const UA_UInt32 *maxrefs, |
| 5767 | const UA_BrowseDescription *descr, UA_BrowseResult *result); |
| 5768 | |
| 5769 | /************/ |
| 5770 | /* AddNodes */ |
| 5771 | /************/ |
| 5772 | |
| 5773 | UA_StatusCode |
| 5774 | addNode(UA_Server *server, const UA_NodeClass nodeClass, |
| 5775 | const UA_NodeId requestedNewNodeId, |
| 5776 | const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, |
| 5777 | const UA_QualifiedName browseName, const UA_NodeId typeDefinition, |
| 5778 | const void *attr, const UA_DataType *attributeType, |
| 5779 | void *nodeContext, UA_NodeId *outNewNodeId); |
| 5780 | |
| 5781 | UA_StatusCode |
| 5782 | addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId, |
| 5783 | const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, |
| 5784 | const UA_QualifiedName browseName, |
| 5785 | const UA_MethodAttributes *attr, UA_MethodCallback method, |
| 5786 | size_t inputArgumentsSize, const UA_Argument *inputArguments, |
| 5787 | const UA_NodeId inputArgumentsRequestedNewNodeId, |
| 5788 | UA_NodeId *inputArgumentsOutNewNodeId, |
| 5789 | size_t outputArgumentsSize, const UA_Argument *outputArguments, |
| 5790 | const UA_NodeId outputArgumentsRequestedNewNodeId, |
| 5791 | UA_NodeId *outputArgumentsOutNewNodeId, |
| 5792 | void *nodeContext, UA_NodeId *outNewNodeId); |
| 5793 | |
| 5794 | UA_StatusCode |
| 5795 | addNode_begin(UA_Server *server, const UA_NodeClass nodeClass, |
| 5796 | const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, |
| 5797 | const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, |
| 5798 | const UA_NodeId typeDefinition, const void *attr, |
| 5799 | const UA_DataType *attributeType, void *nodeContext, |
| 5800 | UA_NodeId *outNewNodeId); |
| 5801 | |
| 5802 | /* Creates a new node in the nodestore. */ |
| 5803 | UA_StatusCode |
| 5804 | addNode_raw(UA_Server *server, UA_Session *session, void *nodeContext, |
| 5805 | const UA_AddNodesItem *item, UA_NodeId *outNewNodeId); |
| 5806 | |
| 5807 | /* Check the reference to the parent node; Add references. */ |
| 5808 | UA_StatusCode |
| 5809 | addNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId, |
| 5810 | const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId, |
| 5811 | const UA_NodeId *typeDefinitionId); |
| 5812 | |
| 5813 | /* Type-check type-definition; Run the constructors */ |
| 5814 | UA_StatusCode |
| 5815 | addNode_finish(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId); |
| 5816 | |
| 5817 | /**********************/ |
| 5818 | /* Create Namespace 0 */ |
| 5819 | /**********************/ |
| 5820 | |
| 5821 | UA_StatusCode initNS0(UA_Server *server); |
| 5822 | |
| 5823 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 5824 | void createSessionObject(UA_Server *server, UA_Session *session); |
| 5825 | |
| 5826 | void createSubscriptionObject(UA_Server *server, UA_Session *session, |
| 5827 | UA_Subscription *sub); |
| 5828 | |
| 5829 | UA_StatusCode |
| 5830 | readDiagnostics(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 5831 | const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp, |
| 5832 | const UA_NumericRange *range, UA_DataValue *value); |
| 5833 | |
| 5834 | UA_StatusCode |
| 5835 | readSubscriptionDiagnosticsArray(UA_Server *server, |
| 5836 | const UA_NodeId *sessionId, void *sessionContext, |
| 5837 | const UA_NodeId *nodeId, void *nodeContext, |
| 5838 | UA_Boolean sourceTimestamp, |
| 5839 | const UA_NumericRange *range, UA_DataValue *value); |
| 5840 | |
| 5841 | UA_StatusCode |
| 5842 | readSessionDiagnosticsArray(UA_Server *server, |
| 5843 | const UA_NodeId *sessionId, void *sessionContext, |
| 5844 | const UA_NodeId *nodeId, void *nodeContext, |
| 5845 | UA_Boolean sourceTimestamp, |
| 5846 | const UA_NumericRange *range, UA_DataValue *value); |
| 5847 | |
| 5848 | UA_StatusCode |
| 5849 | readSessionSecurityDiagnostics(UA_Server *server, |
| 5850 | const UA_NodeId *sessionId, void *sessionContext, |
| 5851 | const UA_NodeId *nodeId, void *nodeContext, |
| 5852 | UA_Boolean sourceTimestamp, |
| 5853 | const UA_NumericRange *range, UA_DataValue *value); |
| 5854 | #endif |
| 5855 | |
| 5856 | /***************************/ |
| 5857 | /* Nodestore Access Macros */ |
| 5858 | /***************************/ |
| 5859 | |
| 5860 | #define UA_NODESTORE_NEW(server, nodeClass) \ |
| 5861 | server->config.nodestore.newNode(server->config.nodestore.context, nodeClass) |
| 5862 | |
| 5863 | #define UA_NODESTORE_DELETE(server, node) \ |
| 5864 | server->config.nodestore.deleteNode(server->config.nodestore.context, node) |
| 5865 | |
| 5866 | /* Get the node with all attributes and references */ |
| 5867 | static UA_INLINE const UA_Node * |
| 5868 | UA_NODESTORE_GET(UA_Server *server, const UA_NodeId *nodeId) { |
| 5869 | return server->config.nodestore. |
| 5870 | getNode(server->config.nodestore.context, nodeId, UA_NODEATTRIBUTESMASK_ALL, |
| 5871 | UA_REFERENCETYPESET_ALL, UA_BROWSEDIRECTION_BOTH); |
| 5872 | } |
| 5873 | |
| 5874 | /* Get the node with all attributes and references */ |
| 5875 | static UA_INLINE const UA_Node * |
| 5876 | UA_NODESTORE_GETFROMREF(UA_Server *server, UA_NodePointer target) { |
| 5877 | return server->config.nodestore. |
| 5878 | getNodeFromPtr(server->config.nodestore.context, target, UA_NODEATTRIBUTESMASK_ALL, |
| 5879 | UA_REFERENCETYPESET_ALL, UA_BROWSEDIRECTION_BOTH); |
| 5880 | } |
| 5881 | |
| 5882 | #define UA_NODESTORE_GET_SELECTIVE(server, nodeid, attrMask, refs, refDirs) \ |
| 5883 | server->config.nodestore.getNode(server->config.nodestore.context, \ |
| 5884 | nodeid, attrMask, refs, refDirs) |
| 5885 | |
| 5886 | #define UA_NODESTORE_GETFROMREF_SELECTIVE(server, target, attrMask, refs, refDirs) \ |
| 5887 | server->config.nodestore.getNodeFromPtr(server->config.nodestore.context, \ |
| 5888 | target, attrMask, refs, refDirs) |
| 5889 | |
| 5890 | #define UA_NODESTORE_RELEASE(server, node) \ |
| 5891 | server->config.nodestore.releaseNode(server->config.nodestore.context, node) |
| 5892 | |
| 5893 | #define UA_NODESTORE_GETCOPY(server, nodeid, outnode) \ |
| 5894 | server->config.nodestore.getNodeCopy(server->config.nodestore.context, \ |
| 5895 | nodeid, outnode) |
| 5896 | |
| 5897 | #define UA_NODESTORE_INSERT(server, node, addedNodeId) \ |
| 5898 | server->config.nodestore.insertNode(server->config.nodestore.context, \ |
| 5899 | node, addedNodeId) |
| 5900 | |
| 5901 | #define UA_NODESTORE_REPLACE(server, node) \ |
| 5902 | server->config.nodestore.replaceNode(server->config.nodestore.context, node) |
| 5903 | |
| 5904 | #define UA_NODESTORE_REMOVE(server, nodeId) \ |
| 5905 | server->config.nodestore.removeNode(server->config.nodestore.context, nodeId) |
| 5906 | |
| 5907 | #define UA_NODESTORE_GETREFERENCETYPEID(server, index) \ |
| 5908 | server->config.nodestore.getReferenceTypeId(server->config.nodestore.context, \ |
| 5909 | index) |
| 5910 | |
| 5911 | /* Handling of Locales */ |
| 5912 | |
| 5913 | /* Returns a shallow copy */ |
| 5914 | UA_LocalizedText |
| 5915 | UA_Session_getNodeDisplayName(const UA_Session *session, |
| 5916 | const UA_NodeHead *head); |
| 5917 | |
| 5918 | UA_LocalizedText |
| 5919 | UA_Session_getNodeDescription(const UA_Session *session, |
| 5920 | const UA_NodeHead *head); |
| 5921 | |
| 5922 | UA_StatusCode |
| 5923 | UA_Node_insertOrUpdateDisplayName(UA_NodeHead *head, |
| 5924 | const UA_LocalizedText *value); |
| 5925 | |
| 5926 | UA_StatusCode |
| 5927 | UA_Node_insertOrUpdateDescription(UA_NodeHead *head, |
| 5928 | const UA_LocalizedText *value); |
| 5929 | |
| 5930 | _UA_END_DECLS |
| 5931 | |
| 5932 | |
| 5933 | /**** amalgamated original file "/src/server/ua_services.h" ****/ |
| 5934 | |
| 5935 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 5936 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 5937 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 5938 | * |
| 5939 | * Copyright 2014-2017, 2024 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 5940 | * Copyright 2014-2017 (c) Florian Palm |
| 5941 | * Copyright 2015 (c) Sten Grüner |
| 5942 | * Copyright 2014 (c) LEvertz |
| 5943 | * Copyright 2015 (c) Chris Iatrou |
| 5944 | * Copyright 2015 (c) Christian Fimmers |
| 5945 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 5946 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 5947 | */ |
| 5948 | |
| 5949 | |
| 5950 | |
| 5951 | _UA_BEGIN_DECLS |
| 5952 | |
| 5953 | typedef void (*UA_Service)(UA_Server*, UA_Session*, |
| 5954 | const void *request, void *response); |
| 5955 | |
| 5956 | typedef void (*UA_ChannelService)(UA_Server*, UA_SecureChannel*, |
| 5957 | const void *request, void *response); |
| 5958 | |
| 5959 | /** Discovery Service Set **/ |
| 5960 | void Service_FindServers(UA_Server *server, UA_Session *session, |
| 5961 | const UA_FindServersRequest *request, |
| 5962 | UA_FindServersResponse *response); |
| 5963 | |
| 5964 | void Service_GetEndpoints(UA_Server *server, UA_Session *session, |
| 5965 | const UA_GetEndpointsRequest *request, |
| 5966 | UA_GetEndpointsResponse *response); |
| 5967 | |
| 5968 | #ifdef UA_ENABLE_DISCOVERY |
| 5969 | |
| 5970 | void Service_RegisterServer(UA_Server *server, UA_Session *session, |
| 5971 | const UA_RegisterServerRequest *request, |
| 5972 | UA_RegisterServerResponse *response); |
| 5973 | |
| 5974 | void Service_RegisterServer2(UA_Server *server, UA_Session *session, |
| 5975 | const UA_RegisterServer2Request *request, |
| 5976 | UA_RegisterServer2Response *response); |
| 5977 | |
| 5978 | # ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 5979 | |
| 5980 | void Service_FindServersOnNetwork(UA_Server *server, UA_Session *session, |
| 5981 | const UA_FindServersOnNetworkRequest *request, |
| 5982 | UA_FindServersOnNetworkResponse *response); |
| 5983 | |
| 5984 | # endif /* UA_ENABLE_DISCOVERY_MULTICAST */ |
| 5985 | |
| 5986 | #endif /* UA_ENABLE_DISCOVERY */ |
| 5987 | |
| 5988 | /** SecureChannel Service Set **/ |
| 5989 | void Service_OpenSecureChannel(UA_Server *server, UA_SecureChannel* channel, |
| 5990 | UA_OpenSecureChannelRequest *request, |
| 5991 | UA_OpenSecureChannelResponse *response); |
| 5992 | |
| 5993 | void Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel); |
| 5994 | |
| 5995 | /** Session Service Set **/ |
| 5996 | void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel, |
| 5997 | const UA_CreateSessionRequest *request, |
| 5998 | UA_CreateSessionResponse *response); |
| 5999 | |
| 6000 | void Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel, |
| 6001 | const UA_ActivateSessionRequest *request, |
| 6002 | UA_ActivateSessionResponse *response); |
| 6003 | |
| 6004 | void Service_CloseSession(UA_Server *server, UA_SecureChannel *channel, |
| 6005 | const UA_CloseSessionRequest *request, |
| 6006 | UA_CloseSessionResponse *response); |
| 6007 | |
| 6008 | void Service_Cancel(UA_Server *server, UA_Session *session, |
| 6009 | const UA_CancelRequest *request, |
| 6010 | UA_CancelResponse *response); |
| 6011 | |
| 6012 | /** NodeManagement Service Set **/ |
| 6013 | void Service_AddNodes(UA_Server *server, UA_Session *session, |
| 6014 | const UA_AddNodesRequest *request, |
| 6015 | UA_AddNodesResponse *response); |
| 6016 | |
| 6017 | void Service_AddReferences(UA_Server *server, UA_Session *session, |
| 6018 | const UA_AddReferencesRequest *request, |
| 6019 | UA_AddReferencesResponse *response); |
| 6020 | |
| 6021 | void Service_DeleteNodes(UA_Server *server, UA_Session *session, |
| 6022 | const UA_DeleteNodesRequest *request, |
| 6023 | UA_DeleteNodesResponse *response); |
| 6024 | |
| 6025 | void Service_DeleteReferences(UA_Server *server, UA_Session *session, |
| 6026 | const UA_DeleteReferencesRequest *request, |
| 6027 | UA_DeleteReferencesResponse *response); |
| 6028 | |
| 6029 | /** View Service Set **/ |
| 6030 | void Service_Browse(UA_Server *server, UA_Session *session, |
| 6031 | const UA_BrowseRequest *request, |
| 6032 | UA_BrowseResponse *response); |
| 6033 | |
| 6034 | void Service_BrowseNext(UA_Server *server, UA_Session *session, |
| 6035 | const UA_BrowseNextRequest *request, |
| 6036 | UA_BrowseNextResponse *response); |
| 6037 | |
| 6038 | void Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session, |
| 6039 | const UA_TranslateBrowsePathsToNodeIdsRequest *request, |
| 6040 | UA_TranslateBrowsePathsToNodeIdsResponse *response); |
| 6041 | |
| 6042 | void Service_RegisterNodes(UA_Server *server, UA_Session *session, |
| 6043 | const UA_RegisterNodesRequest *request, |
| 6044 | UA_RegisterNodesResponse *response); |
| 6045 | |
| 6046 | void Service_UnregisterNodes(UA_Server *server, UA_Session *session, |
| 6047 | const UA_UnregisterNodesRequest *request, |
| 6048 | UA_UnregisterNodesResponse *response); |
| 6049 | |
| 6050 | /** Query Service Set (not implemented) **/ |
| 6051 | |
| 6052 | /** Attribute Service Set **/ |
| 6053 | void Service_Read(UA_Server *server, UA_Session *session, |
| 6054 | const UA_ReadRequest *request, |
| 6055 | UA_ReadResponse *response); |
| 6056 | |
| 6057 | void Service_Write(UA_Server *server, UA_Session *session, |
| 6058 | const UA_WriteRequest *request, |
| 6059 | UA_WriteResponse *response); |
| 6060 | |
| 6061 | #ifdef UA_ENABLE_HISTORIZING |
| 6062 | void Service_HistoryRead(UA_Server *server, UA_Session *session, |
| 6063 | const UA_HistoryReadRequest *request, |
| 6064 | UA_HistoryReadResponse *response); |
| 6065 | |
| 6066 | void Service_HistoryUpdate(UA_Server *server, UA_Session *session, |
| 6067 | const UA_HistoryUpdateRequest *request, |
| 6068 | UA_HistoryUpdateResponse *response); |
| 6069 | #endif |
| 6070 | |
| 6071 | /** Method Service Set **/ |
| 6072 | #ifdef UA_ENABLE_METHODCALLS |
| 6073 | void Service_Call(UA_Server *server, UA_Session *session, |
| 6074 | const UA_CallRequest *request, |
| 6075 | UA_CallResponse *response); |
| 6076 | |
| 6077 | # if UA_MULTITHREADING >= 100 |
| 6078 | void Service_CallAsync(UA_Server *server, UA_Session *session, UA_UInt32 requestId, |
| 6079 | const UA_CallRequest *request, UA_CallResponse *response, |
| 6080 | UA_Boolean *finished); |
| 6081 | #endif |
| 6082 | #endif |
| 6083 | |
| 6084 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 6085 | |
| 6086 | /** MonitoredItem Service Set **/ |
| 6087 | void Service_CreateMonitoredItems(UA_Server *server, UA_Session *session, |
| 6088 | const UA_CreateMonitoredItemsRequest *request, |
| 6089 | UA_CreateMonitoredItemsResponse *response); |
| 6090 | |
| 6091 | void Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session, |
| 6092 | const UA_DeleteMonitoredItemsRequest *request, |
| 6093 | UA_DeleteMonitoredItemsResponse *response); |
| 6094 | |
| 6095 | void Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session, |
| 6096 | const UA_ModifyMonitoredItemsRequest *request, |
| 6097 | UA_ModifyMonitoredItemsResponse *response); |
| 6098 | |
| 6099 | void Service_SetMonitoringMode(UA_Server *server, UA_Session *session, |
| 6100 | const UA_SetMonitoringModeRequest *request, |
| 6101 | UA_SetMonitoringModeResponse *response); |
| 6102 | |
| 6103 | void Service_SetTriggering(UA_Server *server, UA_Session *session, |
| 6104 | const UA_SetTriggeringRequest *request, |
| 6105 | UA_SetTriggeringResponse *response); |
| 6106 | |
| 6107 | /** Subscription Service Set **/ |
| 6108 | void Service_CreateSubscription(UA_Server *server, UA_Session *session, |
| 6109 | const UA_CreateSubscriptionRequest *request, |
| 6110 | UA_CreateSubscriptionResponse *response); |
| 6111 | |
| 6112 | void Service_ModifySubscription(UA_Server *server, UA_Session *session, |
| 6113 | const UA_ModifySubscriptionRequest *request, |
| 6114 | UA_ModifySubscriptionResponse *response); |
| 6115 | |
| 6116 | void Service_SetPublishingMode(UA_Server *server, UA_Session *session, |
| 6117 | const UA_SetPublishingModeRequest *request, |
| 6118 | UA_SetPublishingModeResponse *response); |
| 6119 | |
| 6120 | /* Special async service. Do not answer if StatusCode == Good. */ |
| 6121 | UA_StatusCode |
| 6122 | Service_Publish(UA_Server *server, UA_Session *session, |
| 6123 | const UA_PublishRequest *request, UA_UInt32 requestId); |
| 6124 | |
| 6125 | void Service_Republish(UA_Server *server, UA_Session *session, |
| 6126 | const UA_RepublishRequest *request, |
| 6127 | UA_RepublishResponse *response); |
| 6128 | |
| 6129 | void Service_DeleteSubscriptions(UA_Server *server, UA_Session *session, |
| 6130 | const UA_DeleteSubscriptionsRequest *request, |
| 6131 | UA_DeleteSubscriptionsResponse *response); |
| 6132 | |
| 6133 | void Service_TransferSubscriptions(UA_Server *server, UA_Session *session, |
| 6134 | const UA_TransferSubscriptionsRequest *request, |
| 6135 | UA_TransferSubscriptionsResponse *response); |
| 6136 | |
| 6137 | #endif /* UA_ENABLE_SUBSCRIPTIONS */ |
| 6138 | |
| 6139 | _UA_END_DECLS |
| 6140 | |
| 6141 | |
| 6142 | /**** amalgamated original file "/src/client/ua_client_internal.h" ****/ |
| 6143 | |
| 6144 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 6145 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 6146 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 6147 | * |
| 6148 | * Copyright 2015-2016 (c) Sten Grüner |
| 6149 | * Copyright 2015-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 6150 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 6151 | * Copyright 2016-2017 (c) Florian Palm |
| 6152 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 6153 | * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB |
| 6154 | */ |
| 6155 | |
| 6156 | |
| 6157 | #define UA_INTERNAL |
| 6158 | |
| 6159 | |
| 6160 | _UA_BEGIN_DECLS |
| 6161 | |
| 6162 | /**************************/ |
| 6163 | /* Subscriptions Handling */ |
| 6164 | /**************************/ |
| 6165 | |
| 6166 | typedef struct UA_Client_NotificationsAckNumber { |
| 6167 | LIST_ENTRY(UA_Client_NotificationsAckNumber) listEntry; |
| 6168 | UA_SubscriptionAcknowledgement subAck; |
| 6169 | } UA_Client_NotificationsAckNumber; |
| 6170 | |
| 6171 | typedef struct UA_Client_MonitoredItem { |
| 6172 | ZIP_ENTRY(UA_Client_MonitoredItem) zipfields; |
| 6173 | UA_UInt32 monitoredItemId; |
| 6174 | UA_UInt32 clientHandle; |
| 6175 | void *context; |
| 6176 | UA_Client_DeleteMonitoredItemCallback deleteCallback; |
| 6177 | union { |
| 6178 | UA_Client_DataChangeNotificationCallback dataChangeCallback; |
| 6179 | UA_Client_EventNotificationCallback eventCallback; |
| 6180 | } handler; |
| 6181 | UA_Boolean isEventMonitoredItem; /* Otherwise a DataChange MoniitoredItem */ |
| 6182 | } UA_Client_MonitoredItem; |
| 6183 | |
| 6184 | ZIP_HEAD(MonitorItemsTree, UA_Client_MonitoredItem); |
| 6185 | typedef struct MonitorItemsTree MonitorItemsTree; |
| 6186 | |
| 6187 | typedef struct UA_Client_Subscription { |
| 6188 | LIST_ENTRY(UA_Client_Subscription) listEntry; |
| 6189 | UA_UInt32 subscriptionId; |
| 6190 | void *context; |
| 6191 | UA_Double publishingInterval; |
| 6192 | UA_UInt32 maxKeepAliveCount; |
| 6193 | UA_Client_StatusChangeNotificationCallback statusChangeCallback; |
| 6194 | UA_Client_DeleteSubscriptionCallback deleteCallback; |
| 6195 | UA_UInt32 sequenceNumber; |
| 6196 | UA_DateTime lastActivity; |
| 6197 | MonitorItemsTree monitoredItems; |
| 6198 | } UA_Client_Subscription; |
| 6199 | |
| 6200 | void |
| 6201 | __Client_Subscriptions_clean(UA_Client *client); |
| 6202 | |
| 6203 | /* Exposed for fuzzing */ |
| 6204 | UA_StatusCode |
| 6205 | __Client_preparePublishRequest(UA_Client *client, UA_PublishRequest *request); |
| 6206 | |
| 6207 | void |
| 6208 | __Client_Subscriptions_backgroundPublish(UA_Client *client); |
| 6209 | |
| 6210 | void |
| 6211 | __Client_Subscriptions_backgroundPublishInactivityCheck(UA_Client *client); |
| 6212 | |
| 6213 | /**********/ |
| 6214 | /* Client */ |
| 6215 | /**********/ |
| 6216 | |
| 6217 | typedef struct AsyncServiceCall { |
| 6218 | LIST_ENTRY(AsyncServiceCall) pointers; |
| 6219 | UA_UInt32 requestId; /* Unique id */ |
| 6220 | UA_UInt32 requestHandle; /* Potentially non-unique if manually defined in |
| 6221 | * the request header*/ |
| 6222 | UA_ClientAsyncServiceCallback callback; |
| 6223 | const UA_DataType *responseType; |
| 6224 | void *userdata; |
| 6225 | UA_DateTime start; |
| 6226 | UA_UInt32 timeout; |
| 6227 | UA_Response *syncResponse; /* If non-null, then this is the synchronous |
| 6228 | * response to be filled. Set back to null to |
| 6229 | * indicate that the response was filled. */ |
| 6230 | } AsyncServiceCall; |
| 6231 | |
| 6232 | typedef LIST_HEAD(UA_AsyncServiceList, AsyncServiceCall) UA_AsyncServiceList; |
| 6233 | |
| 6234 | void |
| 6235 | __Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode); |
| 6236 | |
| 6237 | typedef struct CustomCallback { |
| 6238 | UA_UInt32 callbackId; |
| 6239 | |
| 6240 | UA_ClientAsyncServiceCallback userCallback; |
| 6241 | void *userData; |
| 6242 | |
| 6243 | void *clientData; |
| 6244 | } CustomCallback; |
| 6245 | |
| 6246 | struct UA_Client { |
| 6247 | UA_ClientConfig config; |
| 6248 | |
| 6249 | /* Callback ID to remove it from the EventLoop */ |
| 6250 | UA_UInt64 houseKeepingCallbackId; |
| 6251 | |
| 6252 | /* Overall connection status */ |
| 6253 | UA_StatusCode connectStatus; |
| 6254 | |
| 6255 | /* Old status to notify only changes */ |
| 6256 | UA_SecureChannelState oldChannelState; |
| 6257 | UA_SessionState oldSessionState; |
| 6258 | UA_StatusCode oldConnectStatus; |
| 6259 | |
| 6260 | UA_Boolean findServersHandshake; /* Ongoing FindServers */ |
| 6261 | UA_Boolean endpointsHandshake; /* Ongoing GetEndpoints */ |
| 6262 | |
| 6263 | /* The discoveryUrl can be different from the EndpointUrl in the client |
| 6264 | * configuration. The EndpointUrl is used to connect initially, then the |
| 6265 | * DiscoveryUrl is selected via FindServers. This triggers a reconnect if |
| 6266 | * EndpointUrl != DiscoveryUrl. */ |
| 6267 | UA_String discoveryUrl; |
| 6268 | |
| 6269 | /* Contains the Server description, etc. */ |
| 6270 | UA_EndpointDescription endpoint; |
| 6271 | |
| 6272 | /* SecureChannel */ |
| 6273 | UA_SecureChannel channel; |
| 6274 | UA_UInt32 requestId; /* Unique, internally defined for each request */ |
| 6275 | UA_DateTime nextChannelRenewal; |
| 6276 | |
| 6277 | /* Reverse connect (listen) connections */ |
| 6278 | UA_ConnectionManager *reverseConnectionCM; |
| 6279 | uintptr_t reverseConnectionIds[16]; |
| 6280 | |
| 6281 | /* Session */ |
| 6282 | UA_SessionState sessionState; |
| 6283 | UA_NodeId authenticationToken; |
| 6284 | UA_UInt32 requestHandle; /* Unique handles >100,000 are generated if the |
| 6285 | * request header contains a zero-handle. */ |
| 6286 | UA_ByteString serverSessionNonce; |
| 6287 | UA_ByteString clientSessionNonce; |
| 6288 | |
| 6289 | /* Connectivity check */ |
| 6290 | UA_DateTime lastConnectivityCheck; |
| 6291 | UA_Boolean pendingConnectivityCheck; |
| 6292 | |
| 6293 | /* Async Service */ |
| 6294 | UA_AsyncServiceList asyncServiceCalls; |
| 6295 | |
| 6296 | /* Subscriptions */ |
| 6297 | LIST_HEAD(, UA_Client_NotificationsAckNumber) pendingNotificationsAcks; |
| 6298 | LIST_HEAD(, UA_Client_Subscription) subscriptions; |
| 6299 | UA_UInt32 monitoredItemHandles; |
| 6300 | UA_UInt16 currentlyOutStandingPublishRequests; |
| 6301 | |
| 6302 | /* Internal locking for thread-safety. Methods starting with UA_Client_ that |
| 6303 | * are marked with UA_THREADSAFE take the lock. The lock is released before |
| 6304 | * dropping into the EventLoop and before calling user-defined callbacks. |
| 6305 | * That way user-defined callbacks can themselves call thread-safe client |
| 6306 | * methods. */ |
| 6307 | #if UA_MULTITHREADING >= 100 |
| 6308 | UA_Lock clientMutex; |
| 6309 | #endif |
| 6310 | }; |
| 6311 | |
| 6312 | /* In order to prevent deadlocks between the EventLoop mutex and the |
| 6313 | * client-mutex, we always take the EventLoop mutex first. */ |
| 6314 | |
| 6315 | void lockClient(UA_Client *client); |
| 6316 | void unlockClient(UA_Client *client); |
| 6317 | |
| 6318 | UA_StatusCode |
| 6319 | __Client_AsyncService(UA_Client *client, const void *request, |
| 6320 | const UA_DataType *requestType, |
| 6321 | UA_ClientAsyncServiceCallback callback, |
| 6322 | const UA_DataType *responseType, |
| 6323 | void *userdata, UA_UInt32 *requestId); |
| 6324 | |
| 6325 | void |
| 6326 | __Client_Service(UA_Client *client, const void *request, |
| 6327 | const UA_DataType *requestType, void *response, |
| 6328 | const UA_DataType *responseType); |
| 6329 | |
| 6330 | UA_StatusCode |
| 6331 | __UA_Client_startup(UA_Client *client); |
| 6332 | |
| 6333 | UA_StatusCode |
| 6334 | __Client_renewSecureChannel(UA_Client *client); |
| 6335 | |
| 6336 | UA_StatusCode |
| 6337 | processServiceResponse(UA_Client *client, UA_SecureChannel *channel, |
| 6338 | UA_MessageType messageType, UA_UInt32 requestId, |
| 6339 | UA_ByteString *message); |
| 6340 | |
| 6341 | UA_StatusCode connectInternal(UA_Client *client, UA_Boolean async); |
| 6342 | UA_StatusCode connectSecureChannel(UA_Client *client, const char *endpointUrl); |
| 6343 | UA_Boolean isFullyConnected(UA_Client *client); |
| 6344 | void connectSync(UA_Client *client); |
| 6345 | void notifyClientState(UA_Client *client); |
| 6346 | void processRHEMessage(UA_Client *client, const UA_ByteString *chunk); |
| 6347 | void processERRResponse(UA_Client *client, const UA_ByteString *chunk); |
| 6348 | void processACKResponse(UA_Client *client, const UA_ByteString *chunk); |
| 6349 | void processOPNResponse(UA_Client *client, const UA_ByteString *message); |
| 6350 | void closeSecureChannel(UA_Client *client); |
| 6351 | void cleanupSession(UA_Client *client); |
| 6352 | |
| 6353 | void |
| 6354 | Client_warnEndpointsResult(UA_Client *client, |
| 6355 | const UA_GetEndpointsResponse *response, |
| 6356 | const UA_String *endpointUrl); |
| 6357 | |
| 6358 | _UA_END_DECLS |
| 6359 | |
| 6360 | |
| 6361 | /**** amalgamated original file "/build/src_generated/open62541/namespace0_generated.h" ****/ |
| 6362 | |
| 6363 | /* WARNING: This is a generated file. |
| 6364 | * Any manual changes will be overwritten. */ |
| 6365 | |
| 6366 | #ifndef NAMESPACE0_GENERATED_H_ |
| 6367 | #define NAMESPACE0_GENERATED_H_ |
| 6368 | |
| 6369 | |
| 6370 | #ifdef UA_ENABLE_AMALGAMATION |
| 6371 | |
| 6372 | /* The following declarations are in the open62541.c file so here's needed when compiling nodesets externally */ |
| 6373 | |
| 6374 | # ifndef UA_INTERNAL //this definition is needed to hide this code in the amalgamated .c file |
| 6375 | |
| 6376 | typedef UA_StatusCode (*UA_exchangeEncodeBuffer)(void *handle, UA_Byte **bufPos, |
| 6377 | const UA_Byte **bufEnd); |
| 6378 | |
| 6379 | UA_StatusCode |
| 6380 | UA_encodeBinary(const void *src, const UA_DataType *type, |
| 6381 | UA_Byte **bufPos, const UA_Byte **bufEnd, |
| 6382 | UA_exchangeEncodeBuffer exchangeCallback, |
| 6383 | void *exchangeHandle) UA_FUNC_ATTR_WARN_UNUSED_RESULT; |
| 6384 | |
| 6385 | UA_StatusCode |
| 6386 | UA_decodeBinary(const UA_ByteString *src, size_t *offset, void *dst, |
| 6387 | const UA_DataType *type, size_t customTypesSize, |
| 6388 | const UA_DataType *customTypes) UA_FUNC_ATTR_WARN_UNUSED_RESULT; |
| 6389 | |
| 6390 | size_t |
| 6391 | UA_calcSizeBinary(void *p, const UA_DataType *type); |
| 6392 | |
| 6393 | const UA_DataType * |
| 6394 | UA_findDataTypeByBinary(const UA_NodeId *typeId); |
| 6395 | |
| 6396 | # endif // UA_INTERNAL |
| 6397 | |
| 6398 | #else // UA_ENABLE_AMALGAMATION |
| 6399 | #endif |
| 6400 | |
| 6401 | |
| 6402 | |
| 6403 | |
| 6404 | _UA_BEGIN_DECLS |
| 6405 | |
| 6406 | extern UA_StatusCode namespace0_generated(UA_Server *server); |
| 6407 | |
| 6408 | _UA_END_DECLS |
| 6409 | |
| 6410 | #endif /* NAMESPACE0_GENERATED_H_ */ |
| 6411 | |
| 6412 | /**** amalgamated original file "/deps/cj5.h" ****/ |
| 6413 | |
| 6414 | // MIT License |
| 6415 | // |
| 6416 | // Copyright (c) 2020 Sepehr Taghdisian |
| 6417 | // Copyright (c) 2022 Julius Pfrommer |
| 6418 | // |
| 6419 | // Permission is hereby granted, free of charge, to any person obtaining a copy |
| 6420 | // of this software and associated documentation files (the "Software"), to deal |
| 6421 | // in the Software without restriction, including without limitation the rights |
| 6422 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 6423 | // copies of the Software, and to permit persons to whom the Software is |
| 6424 | // furnished to do so, subject to the following conditions: |
| 6425 | // |
| 6426 | // The above copyright notice and this permission notice shall be included in all |
| 6427 | // copies or substantial portions of the Software. |
| 6428 | // |
| 6429 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 6430 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 6431 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 6432 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 6433 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 6434 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 6435 | // SOFTWARE. |
| 6436 | // |
| 6437 | // Very minimal single header JSON5 parser in C99, dervied from jsmn This is the |
| 6438 | // modified version of jsmn library Thus main parts of the code is taken from |
| 6439 | // jsmn project (https://github.com/zserge/jsmn). |
| 6440 | // |
| 6441 | // Compliance with JSON5: |
| 6442 | // [x] Object keys may be an ECMAScript 5.1 IdentifierName. |
| 6443 | // [x] Objects may have a single trailing comma. |
| 6444 | // [x] Strings may be single quoted. |
| 6445 | // [x] Strings may span multiple lines by escaping new line characters. |
| 6446 | // [x] Strings may include character escapes. |
| 6447 | // [x] Numbers may be hexadecimal. |
| 6448 | // [x] Numbers may have a leading or trailing decimal point. |
| 6449 | // [x] Numbers may be IEEE 754 positive infinity, negative infinity, and NaN. |
| 6450 | // [x] Numbers may begin with an explicit plus sign. |
| 6451 | // [x] Single and multi-line comments are allowed. |
| 6452 | // [x] Additional white space characters are allowed. |
| 6453 | // |
| 6454 | // Extensions to JSON5 (more permissive): |
| 6455 | // [x] Root objects can be an array or a primitive value |
| 6456 | // [x] The root object may omit the surrounding brackets |
| 6457 | // [x] Hash ('#') comments out until the end of the line. |
| 6458 | // [x] Strings may include unescaped utf8 bytes |
| 6459 | // [x] Optionally: Stop early when the first encountered JSON element (object, |
| 6460 | // array, value) has been successfully parsed. Do not return an error when |
| 6461 | // the input string was not processed to its full length. This allows the |
| 6462 | // detection of JSON sub-strings as part of an input "lexer". |
| 6463 | // |
| 6464 | // Usage: |
| 6465 | // The main function to parse json is `cj5_parse`. Like in jsmn, you provide |
| 6466 | // all tokens to be filled as an array and provide the maximum count The result |
| 6467 | // will be return in `cj5_result` struct, and `num_tokens` will represent the |
| 6468 | // actual token count that is parsed. In case of errors, cj_result.error will |
| 6469 | // be set to an error code Here's a quick example of the usage. |
| 6470 | // |
| 6471 | // #include "cj5.h" |
| 6472 | // |
| 6473 | // cj5_token tokens[32]; |
| 6474 | // cj5_result r = cj5_parse(g_json, (int)strlen(g_json), tokens, 32, NULL); |
| 6475 | // if(r.error != CJ5_ERROR_NONE) { |
| 6476 | // if(r.error == CJ5_ERROR_OVERFLOW) { |
| 6477 | // // you can use r.num_tokens to determine the actual token count and reparse |
| 6478 | // printf("Error: line: %d, col: %d\n", r.error_line, r.error_code); |
| 6479 | // } |
| 6480 | // } |
| 6481 | |
| 6482 | #ifndef __CJ5_H_ |
| 6483 | #define __CJ5_H_ |
| 6484 | |
| 6485 | #ifdef __cplusplus |
| 6486 | # define CJ5_API extern "C" |
| 6487 | #else |
| 6488 | # define CJ5_API |
| 6489 | #endif |
| 6490 | |
| 6491 | #if !defined(_MSC_VER) || _MSC_VER >= 1800 |
| 6492 | # include <stdint.h> |
| 6493 | # include <stdbool.h> |
| 6494 | #else |
| 6495 | # if !defined(__bool_true_false_are_defined) |
| 6496 | # define bool unsigned char |
| 6497 | # define true 1 |
| 6498 | # define false 0 |
| 6499 | # define __bool_true_false_are_defined |
| 6500 | # endif |
| 6501 | #endif |
| 6502 | |
| 6503 | typedef enum cj5_token_type { |
| 6504 | CJ5_TOKEN_OBJECT = 0, |
| 6505 | CJ5_TOKEN_ARRAY, |
| 6506 | CJ5_TOKEN_NUMBER, |
| 6507 | CJ5_TOKEN_STRING, |
| 6508 | CJ5_TOKEN_BOOL, |
| 6509 | CJ5_TOKEN_NULL |
| 6510 | } cj5_token_type; |
| 6511 | |
| 6512 | typedef enum cj5_error_code { |
| 6513 | CJ5_ERROR_NONE = 0, |
| 6514 | CJ5_ERROR_INVALID, // Invalid character/syntax |
| 6515 | CJ5_ERROR_INCOMPLETE, // Incomplete JSON string |
| 6516 | CJ5_ERROR_OVERFLOW, // Token buffer overflow (see cj5_result.num_tokens) |
| 6517 | CJ5_ERROR_NOTFOUND |
| 6518 | } cj5_error_code; |
| 6519 | |
| 6520 | typedef struct cj5_token { |
| 6521 | cj5_token_type type; |
| 6522 | unsigned int start; // Start position in the json5 string |
| 6523 | unsigned int end; // Position of the last character (included) |
| 6524 | unsigned int size; // For objects and arrays the number of direct |
| 6525 | // children. Note that this is *not* the number of |
| 6526 | // overall (recursively nested) child tokens. For |
| 6527 | // other tokens the length of token in the json |
| 6528 | // encoding. |
| 6529 | unsigned int parent_id; // The root object is at position zero. It is an |
| 6530 | // object that has itself as parent. |
| 6531 | } cj5_token; |
| 6532 | |
| 6533 | typedef struct cj5_result { |
| 6534 | cj5_error_code error; |
| 6535 | unsigned int error_line; |
| 6536 | unsigned int error_col; |
| 6537 | unsigned int num_tokens; |
| 6538 | const cj5_token* tokens; |
| 6539 | const char* json5; |
| 6540 | } cj5_result; |
| 6541 | |
| 6542 | typedef struct cj5_options { |
| 6543 | bool stop_early; /* Return when the first element was parsed. Otherwise an |
| 6544 | * error is returned if the input was not fully |
| 6545 | * processed. (default: false) */ |
| 6546 | } cj5_options; |
| 6547 | |
| 6548 | /* Options can be NULL */ |
| 6549 | CJ5_API cj5_result |
| 6550 | cj5_parse(const char *json5, unsigned int len, |
| 6551 | cj5_token *tokens, unsigned int max_tokens, |
| 6552 | cj5_options *options); |
| 6553 | |
| 6554 | CJ5_API cj5_error_code |
| 6555 | cj5_get_bool(const cj5_result *r, unsigned int tok_index, bool *out); |
| 6556 | |
| 6557 | CJ5_API cj5_error_code |
| 6558 | cj5_get_float(const cj5_result *r, unsigned int tok_index, double *out); |
| 6559 | |
| 6560 | CJ5_API cj5_error_code |
| 6561 | cj5_get_int(const cj5_result *r, unsigned int tok_index, int64_t *out); |
| 6562 | |
| 6563 | CJ5_API cj5_error_code |
| 6564 | cj5_get_uint(const cj5_result *r, unsigned int tok_index, uint64_t *out); |
| 6565 | |
| 6566 | // Replaces escape characters, utf8 codepoints, etc. |
| 6567 | // The buffer shall have a length of at least token->size + 1. |
| 6568 | // Upon success, the length is written to buflen. |
| 6569 | // The output string is terminated with \0. |
| 6570 | CJ5_API cj5_error_code |
| 6571 | cj5_get_str(const cj5_result *r, unsigned int tok_index, |
| 6572 | char *buf, unsigned int *buflen); |
| 6573 | |
| 6574 | // Skips the (nested) structure that starts at the current index. The index is |
| 6575 | // updated accordingly. Afterwards it points to the beginning of the following |
| 6576 | // structure. |
| 6577 | // |
| 6578 | // Attention! The index can point to the first element after the token array if |
| 6579 | // the root object is skipped. |
| 6580 | // |
| 6581 | // Cannot fail as long as the token array is the result of cj5_parse. |
| 6582 | CJ5_API void |
| 6583 | cj5_skip(const cj5_result *r, unsigned int *tok_index); |
| 6584 | |
| 6585 | // Lookup of a key within an object (linear search). |
| 6586 | // The current token (index) must point to an object. |
| 6587 | // The error code CJ5_ERROR_NOTFOUND is returned if the key is not present. |
| 6588 | // Otherwise the index is updated to point to the value associated with the key. |
| 6589 | CJ5_API cj5_error_code |
| 6590 | cj5_find(const cj5_result *r, unsigned int *tok_index, const char *key); |
| 6591 | |
| 6592 | #endif /* __CJ5_H_ */ |
| 6593 | |
| 6594 | /**** amalgamated original file "/deps/parse_num.h" ****/ |
| 6595 | |
| 6596 | #ifndef ATOI_H |
| 6597 | #define ATOI_H |
| 6598 | |
| 6599 | #ifdef __cplusplus |
| 6600 | extern "C"{ |
| 6601 | #endif |
| 6602 | |
| 6603 | #if !defined(_MSC_VER) || _MSC_VER >= 1800 |
| 6604 | # include <stddef.h> |
| 6605 | # include <stdint.h> |
| 6606 | # include <stdbool.h> /* C99 Boolean */ |
| 6607 | #else |
| 6608 | # if !defined(__bool_true_false_are_defined) |
| 6609 | # define bool unsigned char |
| 6610 | # define true 1 |
| 6611 | # define false 0 |
| 6612 | # define __bool_true_false_are_defined |
| 6613 | # endif |
| 6614 | #endif |
| 6615 | |
| 6616 | /* Parse integer numbers. Returns the number of parsed digits until the first |
| 6617 | * non-valid character. Returns 0 upon failure. |
| 6618 | * |
| 6619 | * Hex numbers start with 0x. |
| 6620 | * Signed numbers may have a +/- prefix. */ |
| 6621 | |
| 6622 | size_t parseUInt64(const char *str, size_t size, uint64_t *result); |
| 6623 | size_t parseInt64(const char *str, size_t size, int64_t *result); |
| 6624 | size_t parseDouble(const char *str, size_t size, double *result); |
| 6625 | |
| 6626 | #ifdef __cplusplus |
| 6627 | } |
| 6628 | #endif |
| 6629 | |
| 6630 | #endif /* ATOI_H */ |
| 6631 | |
| 6632 | |
| 6633 | /**** amalgamated original file "/src/ua_types_encoding_json.h" ****/ |
| 6634 | |
| 6635 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 6636 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 6637 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 6638 | * |
| 6639 | * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 6640 | * Copyright 2018 (c) Fraunhofer IOSB (Author: Lukas Meling) |
| 6641 | */ |
| 6642 | |
| 6643 | |
| 6644 | |
| 6645 | |
| 6646 | |
| 6647 | _UA_BEGIN_DECLS |
| 6648 | |
| 6649 | #define UA_JSON_MAXTOKENCOUNT 256 |
| 6650 | #define UA_JSON_ENCODING_MAX_RECURSION 100 |
| 6651 | |
| 6652 | typedef struct { |
| 6653 | uint8_t *pos; |
| 6654 | const uint8_t *end; |
| 6655 | |
| 6656 | uint16_t depth; /* How often did we en-/decoding recurse? */ |
| 6657 | UA_Boolean commaNeeded[UA_JSON_ENCODING_MAX_RECURSION]; |
| 6658 | UA_Boolean useReversible; |
| 6659 | UA_Boolean calcOnly; /* Only compute the length of the decoding */ |
| 6660 | |
| 6661 | size_t namespacesSize; |
| 6662 | const UA_String *namespaces; |
| 6663 | |
| 6664 | size_t serverUrisSize; |
| 6665 | const UA_String *serverUris; |
| 6666 | |
| 6667 | UA_Boolean prettyPrint; |
| 6668 | UA_Boolean unquotedKeys; |
| 6669 | UA_Boolean stringNodeIds; |
| 6670 | } CtxJson; |
| 6671 | |
| 6672 | UA_StatusCode writeJsonObjStart(CtxJson *ctx); |
| 6673 | UA_StatusCode writeJsonObjElm(CtxJson *ctx, const char *key, |
| 6674 | const void *value, const UA_DataType *type); |
| 6675 | UA_StatusCode writeJsonObjEnd(CtxJson *ctx); |
| 6676 | |
| 6677 | UA_StatusCode writeJsonArrStart(CtxJson *ctx); |
| 6678 | UA_StatusCode writeJsonArrElm(CtxJson *ctx, const void *value, |
| 6679 | const UA_DataType *type); |
| 6680 | UA_StatusCode writeJsonArrEnd(CtxJson *ctx); |
| 6681 | |
| 6682 | UA_StatusCode writeJsonKey(CtxJson *ctx, const char* key); |
| 6683 | |
| 6684 | /* Adds a comma if needed. Distinct elements go on a new line if pretty-printing |
| 6685 | * is enabled. */ |
| 6686 | UA_StatusCode writeJsonBeforeElement(CtxJson *ctx, UA_Boolean distinct); |
| 6687 | |
| 6688 | typedef struct { |
| 6689 | const char *json5; |
| 6690 | cj5_token *tokens; |
| 6691 | size_t tokensSize; |
| 6692 | size_t index; |
| 6693 | UA_Byte depth; |
| 6694 | |
| 6695 | size_t namespacesSize; |
| 6696 | const UA_String *namespaces; |
| 6697 | |
| 6698 | size_t serverUrisSize; |
| 6699 | const UA_String *serverUris; |
| 6700 | |
| 6701 | const UA_DataTypeArray *customTypes; |
| 6702 | |
| 6703 | /* Additonal data for special cases such as networkmessage/datasetmessage |
| 6704 | * Currently only used for dataSetWriterIds */ |
| 6705 | size_t numCustom; |
| 6706 | void * custom; |
| 6707 | size_t currentCustomIndex; |
| 6708 | } ParseCtx; |
| 6709 | |
| 6710 | typedef UA_StatusCode |
| 6711 | (*encodeJsonSignature)(CtxJson *ctx, const void *src, const UA_DataType *type); |
| 6712 | |
| 6713 | typedef UA_StatusCode |
| 6714 | (*decodeJsonSignature)(ParseCtx *ctx, void *dst, const UA_DataType *type); |
| 6715 | |
| 6716 | /* Map for decoding a Json Object. An array of this is passed to the |
| 6717 | * decodeFields function. If the key "fieldName" is found in the json object |
| 6718 | * (mark as found and) decode the value with the "function" and write result |
| 6719 | * into "fieldPointer" (destination). */ |
| 6720 | typedef struct { |
| 6721 | const char *fieldName; |
| 6722 | void *fieldPointer; |
| 6723 | decodeJsonSignature function; |
| 6724 | UA_Boolean found; |
| 6725 | const UA_DataType *type; /* Must be set for values that can be "null". If |
| 6726 | * the function is not set, decode via the |
| 6727 | * type->typeKind. */ |
| 6728 | } DecodeEntry; |
| 6729 | |
| 6730 | UA_StatusCode decodeFields(ParseCtx *ctx, DecodeEntry *entries, size_t entryCount); |
| 6731 | |
| 6732 | /* Expose the jump tables and some methods for PubSub JSON decoding */ |
| 6733 | extern const encodeJsonSignature encodeJsonJumpTable[UA_DATATYPEKINDS]; |
| 6734 | extern const decodeJsonSignature decodeJsonJumpTable[UA_DATATYPEKINDS]; |
| 6735 | |
| 6736 | UA_StatusCode lookAheadForKey(ParseCtx *ctx, const char *search, size_t *resultIndex); |
| 6737 | UA_StatusCode tokenize(ParseCtx *ctx, const UA_ByteString *src, size_t tokensSize); |
| 6738 | |
| 6739 | static UA_INLINE |
| 6740 | cj5_token_type currentTokenType(const ParseCtx *ctx) { |
| 6741 | return ctx->tokens[ctx->index].type; |
| 6742 | } |
| 6743 | |
| 6744 | static UA_INLINE |
| 6745 | size_t getTokenLength(const cj5_token *t) { |
| 6746 | return (size_t)(1u + t->end - t->start); |
| 6747 | } |
| 6748 | |
| 6749 | _UA_END_DECLS |
| 6750 | |
| 6751 | |
| 6752 | /**** amalgamated original file "/src/server/ua_discovery.h" ****/ |
| 6753 | |
| 6754 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 6755 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 6756 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 6757 | * |
| 6758 | * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 6759 | * Copyright 2014, 2017 (c) Florian Palm |
| 6760 | * Copyright 2015-2016 (c) Sten Grüner |
| 6761 | * Copyright 2015 (c) Chris Iatrou |
| 6762 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 6763 | * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH |
| 6764 | * Copyright 2017 (c) Julian Grothoff |
| 6765 | */ |
| 6766 | |
| 6767 | |
| 6768 | |
| 6769 | _UA_BEGIN_DECLS |
| 6770 | |
| 6771 | #ifdef UA_ENABLE_DISCOVERY |
| 6772 | |
| 6773 | typedef struct registeredServer_list_entry { |
| 6774 | LIST_ENTRY(registeredServer_list_entry) pointers; |
| 6775 | UA_RegisteredServer registeredServer; |
| 6776 | UA_DateTime lastSeen; |
| 6777 | } registeredServer_list_entry; |
| 6778 | |
| 6779 | /* Store async register service calls. So we can cancel outstanding requests |
| 6780 | * during shutdown. */ |
| 6781 | typedef struct { |
| 6782 | UA_DelayedCallback cleanupCallback; /* delayed cleanup */ |
| 6783 | UA_Server *server; |
| 6784 | UA_DiscoveryManager *dm; |
| 6785 | UA_Client *client; |
| 6786 | UA_String semaphoreFilePath; |
| 6787 | UA_Boolean unregister; |
| 6788 | |
| 6789 | UA_Boolean register2; |
| 6790 | UA_Boolean shutdown; |
| 6791 | UA_Boolean connectSuccess; |
| 6792 | } asyncRegisterRequest; |
| 6793 | #define UA_MAXREGISTERREQUESTS 4 |
| 6794 | |
| 6795 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 6796 | |
| 6797 | #define UA_MAXMDNSRECVSOCKETS 8 |
| 6798 | |
| 6799 | /** |
| 6800 | * TXT record: |
| 6801 | * [servername]-[hostname]._opcua-tcp._tcp.local. TXT path=/ caps=NA,DA,... |
| 6802 | * |
| 6803 | * A/AAAA record for all ip addresses: |
| 6804 | * [servername]-[hostname]._opcua-tcp._tcp.local. A [ip]. |
| 6805 | * [hostname]. A [ip]. |
| 6806 | */ |
| 6807 | |
| 6808 | typedef struct serverOnNetwork_list_entry { |
| 6809 | LIST_ENTRY(serverOnNetwork_list_entry) pointers; |
| 6810 | UA_ServerOnNetwork serverOnNetwork; |
| 6811 | UA_DateTime created; |
| 6812 | UA_DateTime lastSeen; |
| 6813 | UA_Boolean txtSet; |
| 6814 | UA_Boolean srvSet; |
| 6815 | char* pathTmp; |
| 6816 | } serverOnNetwork_list_entry; |
| 6817 | |
| 6818 | #define SERVER_ON_NETWORK_HASH_SIZE 1000 |
| 6819 | typedef struct serverOnNetwork_hash_entry { |
| 6820 | serverOnNetwork_list_entry* entry; |
| 6821 | struct serverOnNetwork_hash_entry* next; |
| 6822 | } serverOnNetwork_hash_entry; |
| 6823 | |
| 6824 | #endif |
| 6825 | |
| 6826 | struct UA_DiscoveryManager { |
| 6827 | UA_ServerComponent sc; |
| 6828 | |
| 6829 | UA_UInt64 discoveryCallbackId; |
| 6830 | |
| 6831 | /* Taken from the server config during startup */ |
| 6832 | const UA_Logger *logging; |
| 6833 | UA_ServerConfig *serverConfig; |
| 6834 | |
| 6835 | /* Outstanding requests. So they can be cancelled during shutdown. */ |
| 6836 | asyncRegisterRequest registerRequests[UA_MAXREGISTERREQUESTS]; |
| 6837 | |
| 6838 | LIST_HEAD(, registeredServer_list_entry) registeredServers; |
| 6839 | size_t registeredServersSize; |
| 6840 | UA_Server_registerServerCallback registerServerCallback; |
| 6841 | void* registerServerCallbackData; |
| 6842 | |
| 6843 | # ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 6844 | mdns_daemon_t *mdnsDaemon; |
| 6845 | UA_ConnectionManager *cm; |
| 6846 | uintptr_t mdnsSendConnection; |
| 6847 | uintptr_t mdnsRecvConnections[UA_MAXMDNSRECVSOCKETS]; |
| 6848 | size_t mdnsRecvConnectionsSize; |
| 6849 | UA_Boolean mdnsMainSrvAdded; |
| 6850 | |
| 6851 | /* Full Domain Name of server itself. Used to detect if received mDNS |
| 6852 | * message was from itself */ |
| 6853 | UA_String selfFqdnMdnsRecord; |
| 6854 | |
| 6855 | LIST_HEAD(, serverOnNetwork_list_entry) serverOnNetwork; |
| 6856 | |
| 6857 | UA_UInt32 serverOnNetworkRecordIdCounter; |
| 6858 | UA_DateTime serverOnNetworkRecordIdLastReset; |
| 6859 | |
| 6860 | /* hash mapping domain name to serverOnNetwork list entry */ |
| 6861 | struct serverOnNetwork_hash_entry* serverOnNetworkHash[SERVER_ON_NETWORK_HASH_SIZE]; |
| 6862 | |
| 6863 | UA_Server_serverOnNetworkCallback serverOnNetworkCallback; |
| 6864 | void *serverOnNetworkCallbackData; |
| 6865 | |
| 6866 | UA_UInt64 mdnsCallbackId; |
| 6867 | # endif /* UA_ENABLE_DISCOVERY_MULTICAST */ |
| 6868 | }; |
| 6869 | |
| 6870 | void |
| 6871 | UA_DiscoveryManager_setState(UA_Server *server, |
| 6872 | UA_DiscoveryManager *dm, |
| 6873 | UA_LifecycleState state); |
| 6874 | |
| 6875 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 6876 | |
| 6877 | /* Sends out a new mDNS package for the given server data. This Method is |
| 6878 | * normally called when another server calls the RegisterServer Service on this |
| 6879 | * server. Then this server is responsible to send out a new mDNS package to |
| 6880 | * announce it. |
| 6881 | * |
| 6882 | * Additionally this method also adds the given server to the internal |
| 6883 | * serversOnNetwork list so that a client finds it when calling |
| 6884 | * FindServersOnNetwork. */ |
| 6885 | void |
| 6886 | UA_Discovery_updateMdnsForDiscoveryUrl(UA_DiscoveryManager *dm, const UA_String *serverName, |
| 6887 | const UA_MdnsDiscoveryConfiguration *mdnsConfig, |
| 6888 | const UA_String *discoveryUrl, UA_Boolean isOnline, |
| 6889 | UA_Boolean updateTxt); |
| 6890 | |
| 6891 | void mdns_record_received(const struct resource *r, void *data); |
| 6892 | |
| 6893 | void mdns_create_txt(UA_DiscoveryManager *dm, const char *fullServiceDomain, |
| 6894 | const char *path, const UA_String *capabilites, |
| 6895 | const size_t capabilitiesSize, |
| 6896 | void (*conflict)(char *host, int type, void *arg)); |
| 6897 | |
| 6898 | void mdns_set_address_record(UA_DiscoveryManager *dm, const char *fullServiceDomain, |
| 6899 | const char *localDomain); |
| 6900 | |
| 6901 | mdns_record_t * |
| 6902 | mdns_find_record(mdns_daemon_t *mdnsDaemon, unsigned short type, |
| 6903 | const char *host, const char *rdname); |
| 6904 | |
| 6905 | void startMulticastDiscoveryServer(UA_Server *server); |
| 6906 | void stopMulticastDiscoveryServer(UA_Server *server); |
| 6907 | void sendMulticastMessages(UA_DiscoveryManager *dm); |
| 6908 | |
| 6909 | UA_StatusCode |
| 6910 | UA_DiscoveryManager_addEntryToServersOnNetwork(UA_DiscoveryManager *dm, |
| 6911 | const char *fqdnMdnsRecord, |
| 6912 | const char *serverName, |
| 6913 | size_t serverNameLen, |
| 6914 | struct serverOnNetwork_list_entry **addedEntry); |
| 6915 | |
| 6916 | UA_StatusCode |
| 6917 | UA_DiscoveryManager_removeEntryFromServersOnNetwork(UA_DiscoveryManager *dm, |
| 6918 | const char *fqdnMdnsRecord, |
| 6919 | const char *serverName, |
| 6920 | size_t serverNameLen); |
| 6921 | |
| 6922 | #endif /* UA_ENABLE_DISCOVERY_MULTICAST */ |
| 6923 | |
| 6924 | #endif /* UA_ENABLE_DISCOVERY */ |
| 6925 | |
| 6926 | _UA_END_DECLS |
| 6927 | |
| 6928 | |
| 6929 | /**** amalgamated original file "/src/ua_types.c" ****/ |
| 6930 | |
| 6931 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 6932 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 6933 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 6934 | * |
| 6935 | * Copyright 2020 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
| 6936 | * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 6937 | * Copyright 2014, 2016-2017 (c) Florian Palm |
| 6938 | * Copyright 2014-2016 (c) Sten Grüner |
| 6939 | * Copyright 2014 (c) Leon Urbas |
| 6940 | * Copyright 2015 (c) Chris Iatrou |
| 6941 | * Copyright 2015 (c) Markus Graube |
| 6942 | * Copyright 2015 (c) Reza Ebrahimi |
| 6943 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 6944 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 6945 | * Copyright 2016 (c) Lorenz Haas |
| 6946 | */ |
| 6947 | |
| 6948 | |
| 6949 | |
| 6950 | #define UA_MAX_ARRAY_DIMS 100 /* Max dimensions of an array */ |
| 6951 | |
| 6952 | /* Datatype Handling |
| 6953 | * ----------------- |
| 6954 | * This file contains handling functions for the builtin types and functions |
| 6955 | * handling of structured types and arrays. These need type descriptions in a |
| 6956 | * UA_DataType structure. The UA_DataType structures as well as all non-builtin |
| 6957 | * datatypes are autogenerated. */ |
| 6958 | |
| 6959 | /* Global definition of NULL type instances. These are always zeroed out, as |
| 6960 | * mandated by the C/C++ standard for global values with no initializer. */ |
| 6961 | const UA_String UA_STRING_NULL = {0, NULL}; |
| 6962 | const UA_ByteString UA_BYTESTRING_NULL = {0, NULL}; |
| 6963 | const UA_Guid UA_GUID_NULL = {0, 0, 0, {0,0,0,0,0,0,0,0}}; |
| 6964 | const UA_NodeId UA_NODEID_NULL = {0, UA_NODEIDTYPE_NUMERIC, {0}}; |
| 6965 | const UA_ExpandedNodeId UA_EXPANDEDNODEID_NULL = {{0, UA_NODEIDTYPE_NUMERIC, {0}}, {0, NULL}, 0}; |
| 6966 | |
| 6967 | typedef UA_StatusCode |
| 6968 | (*UA_copySignature)(const void *src, void *dst, const UA_DataType *type); |
| 6969 | extern const UA_copySignature copyJumpTable[UA_DATATYPEKINDS]; |
| 6970 | |
| 6971 | typedef void (*UA_clearSignature)(void *p, const UA_DataType *type); |
| 6972 | extern const UA_clearSignature clearJumpTable[UA_DATATYPEKINDS]; |
| 6973 | |
| 6974 | typedef UA_Order |
| 6975 | (*UA_orderSignature)(const void *p1, const void *p2, const UA_DataType *type); |
| 6976 | extern const UA_orderSignature orderJumpTable[UA_DATATYPEKINDS]; |
| 6977 | |
| 6978 | static UA_Order |
| 6979 | nodeIdOrder(const UA_NodeId *p1, const UA_NodeId *p2, const UA_DataType *_); |
| 6980 | static UA_Order |
| 6981 | expandedNodeIdOrder(const UA_ExpandedNodeId *p1, const UA_ExpandedNodeId *p2, |
| 6982 | const UA_DataType *_); |
| 6983 | static UA_Order |
| 6984 | guidOrder(const UA_Guid *p1, const UA_Guid *p2, const UA_DataType *_); |
| 6985 | |
| 6986 | const UA_DataType * |
| 6987 | UA_findDataTypeWithCustom(const UA_NodeId *typeId, |
| 6988 | const UA_DataTypeArray *customTypes) { |
| 6989 | /* Always look in built-in types first (may contain data types from all |
| 6990 | * namespaces). |
| 6991 | * |
| 6992 | * TODO: The standard-defined types are ordered. See if binary search is |
| 6993 | * more efficient. */ |
| 6994 | for(size_t i = 0; i < UA_TYPES_COUNT; ++i) { |
| 6995 | if(nodeIdOrder(p1: &UA_TYPES[i].typeId, p2: typeId, NULL) == UA_ORDER_EQ) |
| 6996 | return &UA_TYPES[i]; |
| 6997 | } |
| 6998 | |
| 6999 | /* Search in the customTypes */ |
| 7000 | while(customTypes) { |
| 7001 | for(size_t i = 0; i < customTypes->typesSize; ++i) { |
| 7002 | if(nodeIdOrder(p1: &customTypes->types[i].typeId, p2: typeId, NULL) == UA_ORDER_EQ) |
| 7003 | return &customTypes->types[i]; |
| 7004 | } |
| 7005 | customTypes = customTypes->next; |
| 7006 | } |
| 7007 | |
| 7008 | return NULL; |
| 7009 | } |
| 7010 | |
| 7011 | const UA_DataType * |
| 7012 | UA_findDataType(const UA_NodeId *typeId) { |
| 7013 | return UA_findDataTypeWithCustom(typeId, NULL); |
| 7014 | } |
| 7015 | |
| 7016 | void |
| 7017 | UA_cleanupDataTypeWithCustom(const UA_DataTypeArray *customTypes) { |
| 7018 | while (customTypes) { |
| 7019 | const UA_DataTypeArray *next = customTypes->next; |
| 7020 | if (customTypes->cleanup) { |
| 7021 | for(size_t i = 0; i < customTypes->typesSize; ++i) { |
| 7022 | const UA_DataType *type = &customTypes->types[i]; |
| 7023 | UA_free(ptr: (void*)(uintptr_t)type->typeName); |
| 7024 | for(size_t j = 0; j < type->membersSize; ++j) { |
| 7025 | const UA_DataTypeMember *m = &type->members[j]; |
| 7026 | UA_free(ptr: (void*)(uintptr_t)m->memberName); |
| 7027 | } |
| 7028 | UA_free(ptr: (void*)type->members); |
| 7029 | } |
| 7030 | UA_free(ptr: (void*)(uintptr_t)customTypes->types); |
| 7031 | UA_free(ptr: (void*)(uintptr_t)customTypes); |
| 7032 | } |
| 7033 | customTypes = next; |
| 7034 | } |
| 7035 | } |
| 7036 | |
| 7037 | /*****************/ |
| 7038 | /* Builtin Types */ |
| 7039 | /*****************/ |
| 7040 | |
| 7041 | UA_String |
| 7042 | UA_String_fromChars(const char *src) { |
| 7043 | UA_String s; s.length = 0; s.data = NULL; |
| 7044 | if(!src) |
| 7045 | return s; |
| 7046 | s.length = strlen(s: src); |
| 7047 | if(s.length > 0) { |
| 7048 | s.data = (u8*)UA_malloc(size: s.length); |
| 7049 | if(UA_UNLIKELY(!s.data)) { |
| 7050 | s.length = 0; |
| 7051 | return s; |
| 7052 | } |
| 7053 | memcpy(dest: s.data, src: src, n: s.length); |
| 7054 | } else { |
| 7055 | s.data = (u8*)UA_EMPTY_ARRAY_SENTINEL; |
| 7056 | } |
| 7057 | return s; |
| 7058 | } |
| 7059 | |
| 7060 | UA_Boolean |
| 7061 | UA_String_isEmpty(const UA_String *s) { |
| 7062 | return (s->length == 0 || s->data == NULL); |
| 7063 | } |
| 7064 | |
| 7065 | static UA_Byte |
| 7066 | lowercase(UA_Byte c) { |
| 7067 | if(((int)c) - 'A' < 26) return c | 32; |
| 7068 | return c; |
| 7069 | } |
| 7070 | |
| 7071 | static int |
| 7072 | casecmp(const UA_Byte *l, const UA_Byte *r, size_t n) { |
| 7073 | if(!n--) return 0; |
| 7074 | for(; *l && *r && n && (*l == *r || lowercase(c: *l) == lowercase(c: *r)); l++, r++, n--); |
| 7075 | return lowercase(c: *l) - lowercase(c: *r); |
| 7076 | } |
| 7077 | |
| 7078 | /* Do not expose UA_String_equal_ignorecase to public API as it currently only handles |
| 7079 | * ASCII strings, and not UTF8! */ |
| 7080 | UA_Boolean |
| 7081 | UA_String_equal_ignorecase(const UA_String *s1, const UA_String *s2) { |
| 7082 | if(s1->length != s2->length) |
| 7083 | return false; |
| 7084 | if(s1->length == 0) |
| 7085 | return true; |
| 7086 | if(s2->data == NULL) |
| 7087 | return false; |
| 7088 | |
| 7089 | return casecmp(l: s1->data, r: s2->data, n: s1->length) == 0; |
| 7090 | } |
| 7091 | |
| 7092 | static UA_StatusCode |
| 7093 | String_copy(UA_String const *src, UA_String *dst, const UA_DataType *_) { |
| 7094 | UA_StatusCode res = |
| 7095 | UA_Array_copy(src: src->data, size: src->length, dst: (void**)&dst->data, |
| 7096 | type: &UA_TYPES[UA_TYPES_BYTE]); |
| 7097 | if(res == UA_STATUSCODE_GOOD) |
| 7098 | dst->length = src->length; |
| 7099 | return res; |
| 7100 | } |
| 7101 | |
| 7102 | static void |
| 7103 | String_clear(UA_String *s, const UA_DataType *_) { |
| 7104 | UA_Array_delete(p: s->data, size: s->length, type: &UA_TYPES[UA_TYPES_BYTE]); |
| 7105 | } |
| 7106 | |
| 7107 | /* QualifiedName */ |
| 7108 | static UA_StatusCode |
| 7109 | QualifiedName_copy(const UA_QualifiedName *src, UA_QualifiedName *dst, |
| 7110 | const UA_DataType *_) { |
| 7111 | dst->namespaceIndex = src->namespaceIndex; |
| 7112 | return String_copy(src: &src->name, dst: &dst->name, NULL); |
| 7113 | } |
| 7114 | |
| 7115 | static void |
| 7116 | QualifiedName_clear(UA_QualifiedName *p, const UA_DataType *_) { |
| 7117 | String_clear(s: &p->name, NULL); |
| 7118 | } |
| 7119 | |
| 7120 | u32 |
| 7121 | UA_QualifiedName_hash(const UA_QualifiedName *q) { |
| 7122 | return UA_ByteString_hash(initialHashValue: q->namespaceIndex, |
| 7123 | data: q->name.data, size: q->name.length); |
| 7124 | } |
| 7125 | |
| 7126 | /* DateTime */ |
| 7127 | UA_DateTimeStruct |
| 7128 | UA_DateTime_toStruct(UA_DateTime t) { |
| 7129 | /* Divide, then subtract -> avoid underflow. Also, negative numbers are |
| 7130 | * rounded up, not down. */ |
| 7131 | long long secSinceUnixEpoch = (long long)(t / UA_DATETIME_SEC) |
| 7132 | - (long long)(UA_DATETIME_UNIX_EPOCH / UA_DATETIME_SEC); |
| 7133 | |
| 7134 | /* Negative fractions of a second? Remove one full second from the epoch |
| 7135 | * distance and allow only a positive fraction. */ |
| 7136 | UA_DateTime frac = t % UA_DATETIME_SEC; |
| 7137 | if(frac < 0) { |
| 7138 | secSinceUnixEpoch--; |
| 7139 | frac += UA_DATETIME_SEC; |
| 7140 | } |
| 7141 | |
| 7142 | struct musl_tm ts; |
| 7143 | memset(s: &ts, c: 0, n: sizeof(struct musl_tm)); |
| 7144 | musl_secs_to_tm(t: secSinceUnixEpoch, tm: &ts); |
| 7145 | |
| 7146 | UA_DateTimeStruct dateTimeStruct; |
| 7147 | dateTimeStruct.year = (i16)(ts.tm_year + 1900); |
| 7148 | dateTimeStruct.month = (u16)(ts.tm_mon + 1); |
| 7149 | dateTimeStruct.day = (u16)ts.tm_mday; |
| 7150 | dateTimeStruct.hour = (u16)ts.tm_hour; |
| 7151 | dateTimeStruct.min = (u16)ts.tm_min; |
| 7152 | dateTimeStruct.sec = (u16)ts.tm_sec; |
| 7153 | dateTimeStruct.milliSec = (u16)((frac % 10000000) / 10000); |
| 7154 | dateTimeStruct.microSec = (u16)((frac % 10000) / 10); |
| 7155 | dateTimeStruct.nanoSec = (u16)((frac % 10) * 100); |
| 7156 | return dateTimeStruct; |
| 7157 | } |
| 7158 | |
| 7159 | UA_DateTime |
| 7160 | UA_DateTime_fromStruct(UA_DateTimeStruct ts) { |
| 7161 | /* Seconds since the Unix epoch */ |
| 7162 | struct musl_tm tm; |
| 7163 | memset(s: &tm, c: 0, n: sizeof(struct musl_tm)); |
| 7164 | tm.tm_year = ts.year - 1900; |
| 7165 | tm.tm_mon = ts.month - 1; |
| 7166 | tm.tm_mday = ts.day; |
| 7167 | tm.tm_hour = ts.hour; |
| 7168 | tm.tm_min = ts.min; |
| 7169 | tm.tm_sec = ts.sec; |
| 7170 | long long sec_epoch = musl_tm_to_secs(tm: &tm); |
| 7171 | |
| 7172 | UA_DateTime t = UA_DATETIME_UNIX_EPOCH; |
| 7173 | t += sec_epoch * UA_DATETIME_SEC; |
| 7174 | t += ts.milliSec * UA_DATETIME_MSEC; |
| 7175 | t += ts.microSec * UA_DATETIME_USEC; |
| 7176 | t += ts.nanoSec / 100; |
| 7177 | return t; |
| 7178 | } |
| 7179 | |
| 7180 | /* Guid */ |
| 7181 | static const u8 hexmapLower[16] = |
| 7182 | {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; |
| 7183 | static const u8 hexmapUpper[16] = |
| 7184 | {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; |
| 7185 | |
| 7186 | void |
| 7187 | UA_Guid_to_hex(const UA_Guid *guid, u8* out, UA_Boolean lower) { |
| 7188 | const u8 *hexmap = (lower) ? hexmapLower : hexmapUpper; |
| 7189 | size_t i = 0, j = 28; |
| 7190 | for(; i<8;i++,j-=4) /* pos 0-7, 4byte, (a) */ |
| 7191 | out[i] = hexmap[(guid->data1 >> j) & 0x0Fu]; |
| 7192 | out[i++] = '-'; /* pos 8 */ |
| 7193 | for(j=12; i<13;i++,j-=4) /* pos 9-12, 2byte, (b) */ |
| 7194 | out[i] = hexmap[(uint16_t)(guid->data2 >> j) & 0x0Fu]; |
| 7195 | out[i++] = '-'; /* pos 13 */ |
| 7196 | for(j=12; i<18;i++,j-=4) /* pos 14-17, 2byte (c) */ |
| 7197 | out[i] = hexmap[(uint16_t)(guid->data3 >> j) & 0x0Fu]; |
| 7198 | out[i++] = '-'; /* pos 18 */ |
| 7199 | for(j=0;i<23;i+=2,j++) { /* pos 19-22, 2byte (d) */ |
| 7200 | out[i] = hexmap[(guid->data4[j] & 0xF0u) >> 4u]; |
| 7201 | out[i+1] = hexmap[guid->data4[j] & 0x0Fu]; |
| 7202 | } |
| 7203 | out[i++] = '-'; /* pos 23 */ |
| 7204 | for(j=2; i<36;i+=2,j++) { /* pos 24-35, 6byte (e) */ |
| 7205 | out[i] = hexmap[(guid->data4[j] & 0xF0u) >> 4u]; |
| 7206 | out[i+1] = hexmap[guid->data4[j] & 0x0Fu]; |
| 7207 | } |
| 7208 | } |
| 7209 | |
| 7210 | UA_StatusCode |
| 7211 | UA_Guid_print(const UA_Guid *guid, UA_String *output) { |
| 7212 | if(output->length == 0) { |
| 7213 | UA_StatusCode res = |
| 7214 | UA_ByteString_allocBuffer(bs: (UA_ByteString*)output, length: 36); |
| 7215 | if(res != UA_STATUSCODE_GOOD) |
| 7216 | return res; |
| 7217 | } else { |
| 7218 | if(output->length < 36) |
| 7219 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 7220 | output->length = 36; |
| 7221 | } |
| 7222 | UA_Guid_to_hex(guid, out: output->data, true); |
| 7223 | return UA_STATUSCODE_GOOD; |
| 7224 | } |
| 7225 | |
| 7226 | /* ByteString */ |
| 7227 | UA_StatusCode |
| 7228 | UA_ByteString_allocBuffer(UA_ByteString *bs, size_t length) { |
| 7229 | UA_ByteString_init(p: bs); |
| 7230 | if(length == 0) |
| 7231 | return UA_STATUSCODE_GOOD; |
| 7232 | bs->data = (u8*)UA_malloc(size: length); |
| 7233 | if(UA_UNLIKELY(!bs->data)) |
| 7234 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 7235 | bs->length = length; |
| 7236 | return UA_STATUSCODE_GOOD; |
| 7237 | } |
| 7238 | |
| 7239 | /* NodeId */ |
| 7240 | static void |
| 7241 | NodeId_clear(UA_NodeId *p, const UA_DataType *_) { |
| 7242 | switch(p->identifierType) { |
| 7243 | case UA_NODEIDTYPE_STRING: |
| 7244 | case UA_NODEIDTYPE_BYTESTRING: |
| 7245 | String_clear(s: &p->identifier.string, NULL); |
| 7246 | break; |
| 7247 | default: break; |
| 7248 | } |
| 7249 | } |
| 7250 | |
| 7251 | static UA_StatusCode |
| 7252 | NodeId_copy(UA_NodeId const *src, UA_NodeId *dst, const UA_DataType *_) { |
| 7253 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 7254 | switch(src->identifierType) { |
| 7255 | case UA_NODEIDTYPE_NUMERIC: |
| 7256 | *dst = *src; |
| 7257 | return UA_STATUSCODE_GOOD; |
| 7258 | case UA_NODEIDTYPE_STRING: |
| 7259 | case UA_NODEIDTYPE_BYTESTRING: |
| 7260 | retval |= String_copy(src: &src->identifier.string, |
| 7261 | dst: &dst->identifier.string, NULL); |
| 7262 | break; |
| 7263 | case UA_NODEIDTYPE_GUID: |
| 7264 | dst->identifier.guid = src->identifier.guid; |
| 7265 | break; |
| 7266 | default: |
| 7267 | return UA_STATUSCODE_BADINTERNALERROR; |
| 7268 | } |
| 7269 | dst->namespaceIndex = src->namespaceIndex; |
| 7270 | dst->identifierType = src->identifierType; |
| 7271 | return retval; |
| 7272 | } |
| 7273 | |
| 7274 | UA_Boolean |
| 7275 | UA_NodeId_isNull(const UA_NodeId *p) { |
| 7276 | if(p->namespaceIndex != 0) |
| 7277 | return false; |
| 7278 | switch (p->identifierType) { |
| 7279 | case UA_NODEIDTYPE_NUMERIC: |
| 7280 | return (p->identifier.numeric == 0); |
| 7281 | case UA_NODEIDTYPE_STRING: |
| 7282 | case UA_NODEIDTYPE_BYTESTRING: |
| 7283 | return (p->identifier.string.length == 0); /* Null and empty string */ |
| 7284 | case UA_NODEIDTYPE_GUID: |
| 7285 | return (guidOrder(p1: &p->identifier.guid, p2: &UA_GUID_NULL, NULL) == UA_ORDER_EQ); |
| 7286 | } |
| 7287 | return false; |
| 7288 | } |
| 7289 | |
| 7290 | UA_Order |
| 7291 | UA_NodeId_order(const UA_NodeId *n1, const UA_NodeId *n2) { |
| 7292 | return nodeIdOrder(p1: n1, p2: n2, NULL); |
| 7293 | } |
| 7294 | |
| 7295 | /* sdbm-hash (http://www.cse.yorku.ca/~oz/hash.html) */ |
| 7296 | u32 |
| 7297 | UA_ByteString_hash(u32 initialHashValue, |
| 7298 | const u8 *data, size_t size) { |
| 7299 | u32 h = initialHashValue; |
| 7300 | for(size_t i = 0; i < size; i++) |
| 7301 | h = data[i] + (h << 6) + (h << 16) - h; |
| 7302 | return h; |
| 7303 | } |
| 7304 | |
| 7305 | u32 |
| 7306 | UA_NodeId_hash(const UA_NodeId *n) { |
| 7307 | switch(n->identifierType) { |
| 7308 | case UA_NODEIDTYPE_NUMERIC: |
| 7309 | default: |
| 7310 | return UA_ByteString_hash(initialHashValue: n->namespaceIndex, data: (const u8*)&n->identifier.numeric, |
| 7311 | size: sizeof(UA_UInt32)); |
| 7312 | case UA_NODEIDTYPE_STRING: |
| 7313 | case UA_NODEIDTYPE_BYTESTRING: |
| 7314 | return UA_ByteString_hash(initialHashValue: n->namespaceIndex, data: n->identifier.string.data, |
| 7315 | size: n->identifier.string.length); |
| 7316 | case UA_NODEIDTYPE_GUID: |
| 7317 | return UA_ByteString_hash(initialHashValue: n->namespaceIndex, data: (const u8*)&n->identifier.guid, |
| 7318 | size: sizeof(UA_Guid)); |
| 7319 | } |
| 7320 | } |
| 7321 | |
| 7322 | /* Computes length for the encoding size and pre-encodes the numeric values */ |
| 7323 | static size_t |
| 7324 | nodeIdSize(const UA_NodeId *id, |
| 7325 | char *nsStr, size_t *nsStrSize, |
| 7326 | char *numIdStr, size_t *numIdStrSize) { |
| 7327 | /* Namespace length */ |
| 7328 | size_t len = 0; |
| 7329 | if(id->namespaceIndex != 0) { |
| 7330 | len += 4; /* ns=; */ |
| 7331 | *nsStrSize = itoaUnsigned(value: id->namespaceIndex, buffer: nsStr, base: 10); |
| 7332 | len += *nsStrSize; |
| 7333 | } |
| 7334 | |
| 7335 | switch (id->identifierType) { |
| 7336 | case UA_NODEIDTYPE_NUMERIC: |
| 7337 | *numIdStrSize = itoaUnsigned(value: id->identifier.numeric, buffer: numIdStr, base: 10); |
| 7338 | len += 2 + *numIdStrSize; |
| 7339 | break; |
| 7340 | case UA_NODEIDTYPE_STRING: |
| 7341 | len += 2 + id->identifier.string.length; |
| 7342 | break; |
| 7343 | case UA_NODEIDTYPE_GUID: |
| 7344 | len += 2 + 36; |
| 7345 | break; |
| 7346 | case UA_NODEIDTYPE_BYTESTRING: |
| 7347 | len += 2 + (4*((id->identifier.byteString.length + 2) / 3)); |
| 7348 | break; |
| 7349 | default: |
| 7350 | len = 0; |
| 7351 | } |
| 7352 | return len; |
| 7353 | } |
| 7354 | |
| 7355 | #define PRINT_NODEID \ |
| 7356 | /* Encode the namespace */ \ |
| 7357 | if(id->namespaceIndex != 0) { \ |
| 7358 | memcpy(pos, "ns=", 3); \ |
| 7359 | pos += 3; \ |
| 7360 | memcpy(pos, nsStr, nsStrSize); \ |
| 7361 | pos += nsStrSize; \ |
| 7362 | *pos++ = ';'; \ |
| 7363 | } \ |
| 7364 | \ |
| 7365 | /* Encode the identifier */ \ |
| 7366 | switch(id->identifierType) { \ |
| 7367 | case UA_NODEIDTYPE_NUMERIC: \ |
| 7368 | memcpy(pos, "i=", 2); \ |
| 7369 | pos += 2; \ |
| 7370 | memcpy(pos, numIdStr, numIdStrSize); \ |
| 7371 | pos += numIdStrSize; \ |
| 7372 | break; \ |
| 7373 | case UA_NODEIDTYPE_STRING: \ |
| 7374 | memcpy(pos, "s=", 2); \ |
| 7375 | pos += 2; \ |
| 7376 | memcpy(pos, id->identifier.string.data, \ |
| 7377 | id->identifier.string.length); \ |
| 7378 | pos += id->identifier.string.length; \ |
| 7379 | break; \ |
| 7380 | case UA_NODEIDTYPE_GUID: \ |
| 7381 | memcpy(pos, "g=", 2); \ |
| 7382 | pos += 2; \ |
| 7383 | UA_Guid_to_hex(&id->identifier.guid, \ |
| 7384 | (unsigned char*)pos, true); \ |
| 7385 | pos += 36; \ |
| 7386 | break; \ |
| 7387 | case UA_NODEIDTYPE_BYTESTRING: \ |
| 7388 | memcpy(pos, "b=", 2); \ |
| 7389 | pos += 2; \ |
| 7390 | pos += UA_base64_buf(id->identifier.byteString.data, \ |
| 7391 | id->identifier.byteString.length, \ |
| 7392 | (unsigned char*)pos); \ |
| 7393 | break; \ |
| 7394 | } \ |
| 7395 | do { } while(false) |
| 7396 | |
| 7397 | UA_StatusCode |
| 7398 | UA_NodeId_print(const UA_NodeId *id, UA_String *output) { |
| 7399 | /* Compute the string length */ |
| 7400 | char nsStr[6]; |
| 7401 | size_t nsStrSize = 0; |
| 7402 | char numIdStr[11]; |
| 7403 | size_t numIdStrSize = 0; |
| 7404 | size_t idLen = nodeIdSize(id, nsStr, nsStrSize: &nsStrSize, numIdStr, numIdStrSize: &numIdStrSize); |
| 7405 | if(idLen == 0) |
| 7406 | return UA_STATUSCODE_BADINTERNALERROR; |
| 7407 | |
| 7408 | /* Allocate memory if required */ |
| 7409 | if(output->length == 0) { |
| 7410 | UA_StatusCode res = UA_ByteString_allocBuffer(bs: (UA_ByteString*)output, length: idLen); |
| 7411 | if(res != UA_STATUSCODE_GOOD) |
| 7412 | return res; |
| 7413 | } else { |
| 7414 | if(output->length < idLen) |
| 7415 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 7416 | output->length = idLen; |
| 7417 | } |
| 7418 | |
| 7419 | /* Print the NodeId */ |
| 7420 | char *pos = (char*)output->data; |
| 7421 | PRINT_NODEID; |
| 7422 | |
| 7423 | UA_assert(output->length == (size_t)((UA_Byte*)pos - output->data)); |
| 7424 | return UA_STATUSCODE_GOOD; |
| 7425 | } |
| 7426 | |
| 7427 | /* ExpandedNodeId */ |
| 7428 | static void |
| 7429 | ExpandedNodeId_clear(UA_ExpandedNodeId *p, const UA_DataType *_) { |
| 7430 | NodeId_clear(p: &p->nodeId, _); |
| 7431 | String_clear(s: &p->namespaceUri, NULL); |
| 7432 | } |
| 7433 | |
| 7434 | static UA_StatusCode |
| 7435 | ExpandedNodeId_copy(UA_ExpandedNodeId const *src, UA_ExpandedNodeId *dst, |
| 7436 | const UA_DataType *_) { |
| 7437 | UA_StatusCode retval = NodeId_copy(src: &src->nodeId, dst: &dst->nodeId, NULL); |
| 7438 | retval |= String_copy(src: &src->namespaceUri, dst: &dst->namespaceUri, NULL); |
| 7439 | dst->serverIndex = src->serverIndex; |
| 7440 | return retval; |
| 7441 | } |
| 7442 | |
| 7443 | UA_Boolean |
| 7444 | UA_ExpandedNodeId_isLocal(const UA_ExpandedNodeId *n) { |
| 7445 | return (n->namespaceUri.length == 0 && n->serverIndex == 0); |
| 7446 | } |
| 7447 | |
| 7448 | UA_Order |
| 7449 | UA_ExpandedNodeId_order(const UA_ExpandedNodeId *n1, |
| 7450 | const UA_ExpandedNodeId *n2) { |
| 7451 | return expandedNodeIdOrder(p1: n1, p2: n2, NULL); |
| 7452 | } |
| 7453 | |
| 7454 | u32 |
| 7455 | UA_ExpandedNodeId_hash(const UA_ExpandedNodeId *n) { |
| 7456 | u32 h = UA_NodeId_hash(n: &n->nodeId); |
| 7457 | if(n->serverIndex != 0) |
| 7458 | h = UA_ByteString_hash(initialHashValue: h, data: (const UA_Byte*)&n->serverIndex, size: 4); |
| 7459 | if(n->namespaceUri.length != 0) |
| 7460 | h = UA_ByteString_hash(initialHashValue: h, data: n->namespaceUri.data, size: n->namespaceUri.length); |
| 7461 | return h; |
| 7462 | } |
| 7463 | |
| 7464 | UA_StatusCode |
| 7465 | UA_ExpandedNodeId_print(const UA_ExpandedNodeId *eid, UA_String *output) { |
| 7466 | /* Don't print the namespace-index if a NamespaceUri is set */ |
| 7467 | UA_NodeId stackid = eid->nodeId; |
| 7468 | UA_NodeId *id = &stackid; /* for the print-macro below */ |
| 7469 | if(eid->namespaceUri.data != NULL) |
| 7470 | id->namespaceIndex = 0; |
| 7471 | |
| 7472 | /* Compute the string length */ |
| 7473 | char nsStr[6]; |
| 7474 | size_t nsStrSize = 0; |
| 7475 | char numIdStr[11]; |
| 7476 | size_t numIdStrSize = 0; |
| 7477 | size_t idLen = nodeIdSize(id, nsStr, nsStrSize: &nsStrSize, numIdStr, numIdStrSize: &numIdStrSize); |
| 7478 | if(idLen == 0) |
| 7479 | return UA_STATUSCODE_BADINTERNALERROR; |
| 7480 | |
| 7481 | char srvIdxStr[11]; |
| 7482 | size_t srvIdxSize = 0; |
| 7483 | if(eid->serverIndex != 0) { |
| 7484 | idLen += 5; /* svr=; */ |
| 7485 | srvIdxSize = itoaUnsigned(value: eid->serverIndex, buffer: srvIdxStr, base: 10); |
| 7486 | idLen += srvIdxSize; |
| 7487 | } |
| 7488 | |
| 7489 | if(eid->namespaceUri.data != NULL) { |
| 7490 | idLen += 5; /* nsu=; */ |
| 7491 | idLen += eid->namespaceUri.length; |
| 7492 | } |
| 7493 | |
| 7494 | /* Allocate memory if required */ |
| 7495 | if(output->length == 0) { |
| 7496 | UA_StatusCode res = UA_ByteString_allocBuffer(bs: (UA_ByteString*)output, length: idLen); |
| 7497 | if(res != UA_STATUSCODE_GOOD) |
| 7498 | return res; |
| 7499 | } else { |
| 7500 | if(output->length < idLen) |
| 7501 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 7502 | output->length = idLen; |
| 7503 | } |
| 7504 | |
| 7505 | /* Encode the ServerIndex */ |
| 7506 | char *pos = (char*)output->data; |
| 7507 | if(eid->serverIndex != 0) { |
| 7508 | memcpy(dest: pos, src: "svr=", n: 4); |
| 7509 | pos += 4; |
| 7510 | memcpy(dest: pos, src: srvIdxStr, n: srvIdxSize); |
| 7511 | pos += srvIdxSize; |
| 7512 | *pos++ = ';'; |
| 7513 | } |
| 7514 | |
| 7515 | /* Encode the NamespaceUri */ |
| 7516 | if(eid->namespaceUri.data != NULL) { |
| 7517 | memcpy(dest: pos, src: "nsu=", n: 4); |
| 7518 | pos += 4; |
| 7519 | memcpy(dest: pos, src: eid->namespaceUri.data, n: eid->namespaceUri.length); |
| 7520 | pos += eid->namespaceUri.length; |
| 7521 | *pos++ = ';'; |
| 7522 | } |
| 7523 | |
| 7524 | /* Print the NodeId */ |
| 7525 | PRINT_NODEID; |
| 7526 | |
| 7527 | UA_assert(output->length == (size_t)((UA_Byte*)pos - output->data)); |
| 7528 | return UA_STATUSCODE_GOOD; |
| 7529 | } |
| 7530 | |
| 7531 | /* ExtensionObject */ |
| 7532 | static void |
| 7533 | ExtensionObject_clear(UA_ExtensionObject *p, const UA_DataType *_) { |
| 7534 | switch(p->encoding) { |
| 7535 | case UA_EXTENSIONOBJECT_ENCODED_NOBODY: |
| 7536 | case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING: |
| 7537 | case UA_EXTENSIONOBJECT_ENCODED_XML: |
| 7538 | NodeId_clear(p: &p->content.encoded.typeId, NULL); |
| 7539 | String_clear(s: &p->content.encoded.body, NULL); |
| 7540 | break; |
| 7541 | case UA_EXTENSIONOBJECT_DECODED: |
| 7542 | if(p->content.decoded.data) |
| 7543 | UA_delete(p: p->content.decoded.data, type: p->content.decoded.type); |
| 7544 | break; |
| 7545 | default: |
| 7546 | break; |
| 7547 | } |
| 7548 | } |
| 7549 | |
| 7550 | static UA_StatusCode |
| 7551 | ExtensionObject_copy(UA_ExtensionObject const *src, UA_ExtensionObject *dst, |
| 7552 | const UA_DataType *_) { |
| 7553 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 7554 | switch(src->encoding) { |
| 7555 | case UA_EXTENSIONOBJECT_ENCODED_NOBODY: |
| 7556 | case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING: |
| 7557 | case UA_EXTENSIONOBJECT_ENCODED_XML: |
| 7558 | dst->encoding = src->encoding; |
| 7559 | retval = NodeId_copy(src: &src->content.encoded.typeId, |
| 7560 | dst: &dst->content.encoded.typeId, NULL); |
| 7561 | /* ByteString -> copy as string */ |
| 7562 | retval |= String_copy(src: &src->content.encoded.body, |
| 7563 | dst: &dst->content.encoded.body, NULL); |
| 7564 | break; |
| 7565 | case UA_EXTENSIONOBJECT_DECODED: |
| 7566 | case UA_EXTENSIONOBJECT_DECODED_NODELETE: |
| 7567 | if(!src->content.decoded.type || !src->content.decoded.data) |
| 7568 | return UA_STATUSCODE_BADINTERNALERROR; |
| 7569 | dst->encoding = UA_EXTENSIONOBJECT_DECODED; |
| 7570 | dst->content.decoded.type = src->content.decoded.type; |
| 7571 | retval = UA_Array_copy(src: src->content.decoded.data, size: 1, |
| 7572 | dst: &dst->content.decoded.data, type: src->content.decoded.type); |
| 7573 | break; |
| 7574 | default: |
| 7575 | break; |
| 7576 | } |
| 7577 | return retval; |
| 7578 | } |
| 7579 | |
| 7580 | void |
| 7581 | UA_ExtensionObject_setValue(UA_ExtensionObject *eo, |
| 7582 | void * UA_RESTRICT p, |
| 7583 | const UA_DataType *type) { |
| 7584 | UA_ExtensionObject_init(p: eo); |
| 7585 | eo->content.decoded.data = p; |
| 7586 | eo->content.decoded.type = type; |
| 7587 | eo->encoding = UA_EXTENSIONOBJECT_DECODED; |
| 7588 | } |
| 7589 | |
| 7590 | void |
| 7591 | UA_ExtensionObject_setValueNoDelete(UA_ExtensionObject *eo, |
| 7592 | void * UA_RESTRICT p, |
| 7593 | const UA_DataType *type) { |
| 7594 | UA_ExtensionObject_init(p: eo); |
| 7595 | eo->content.decoded.data = p; |
| 7596 | eo->content.decoded.type = type; |
| 7597 | eo->encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE; |
| 7598 | } |
| 7599 | |
| 7600 | UA_StatusCode |
| 7601 | UA_ExtensionObject_setValueCopy(UA_ExtensionObject *eo, |
| 7602 | void * UA_RESTRICT p, |
| 7603 | const UA_DataType *type) { |
| 7604 | UA_ExtensionObject_init(p: eo); |
| 7605 | |
| 7606 | /* Make a copy of the value */ |
| 7607 | void *val = UA_malloc(size: type->memSize); |
| 7608 | if(UA_UNLIKELY(!val)) |
| 7609 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 7610 | UA_StatusCode res = UA_copy(src: p, dst: val, type); |
| 7611 | if(UA_UNLIKELY(res != UA_STATUSCODE_GOOD)) { |
| 7612 | UA_free(ptr: val); |
| 7613 | return res; |
| 7614 | } |
| 7615 | |
| 7616 | /* Set the ExtensionObject */ |
| 7617 | eo->content.decoded.data = val; |
| 7618 | eo->content.decoded.type = type; |
| 7619 | eo->encoding = UA_EXTENSIONOBJECT_DECODED; |
| 7620 | return UA_STATUSCODE_GOOD; |
| 7621 | } |
| 7622 | |
| 7623 | /* Variant */ |
| 7624 | static void |
| 7625 | Variant_clear(UA_Variant *p, const UA_DataType *_) { |
| 7626 | /* The content is "borrowed" */ |
| 7627 | if(p->storageType == UA_VARIANT_DATA_NODELETE) |
| 7628 | return; |
| 7629 | |
| 7630 | /* Delete the value */ |
| 7631 | if(p->type && p->data > UA_EMPTY_ARRAY_SENTINEL) { |
| 7632 | if(p->arrayLength == 0) |
| 7633 | p->arrayLength = 1; |
| 7634 | UA_Array_delete(p: p->data, size: p->arrayLength, type: p->type); |
| 7635 | p->data = NULL; |
| 7636 | } |
| 7637 | |
| 7638 | /* Delete the array dimensions */ |
| 7639 | if((void*)p->arrayDimensions > UA_EMPTY_ARRAY_SENTINEL) |
| 7640 | UA_free(ptr: p->arrayDimensions); |
| 7641 | } |
| 7642 | |
| 7643 | static UA_StatusCode |
| 7644 | Variant_copy(UA_Variant const *src, UA_Variant *dst, const UA_DataType *_) { |
| 7645 | size_t length = src->arrayLength; |
| 7646 | if(UA_Variant_isScalar(v: src)) |
| 7647 | length = 1; |
| 7648 | UA_StatusCode retval = UA_Array_copy(src: src->data, size: length, |
| 7649 | dst: &dst->data, type: src->type); |
| 7650 | if(retval != UA_STATUSCODE_GOOD) |
| 7651 | return retval; |
| 7652 | dst->arrayLength = src->arrayLength; |
| 7653 | dst->type = src->type; |
| 7654 | if(src->arrayDimensions) { |
| 7655 | retval = UA_Array_copy(src: src->arrayDimensions, size: src->arrayDimensionsSize, |
| 7656 | dst: (void**)&dst->arrayDimensions, type: &UA_TYPES[UA_TYPES_INT32]); |
| 7657 | if(retval != UA_STATUSCODE_GOOD) |
| 7658 | return retval; |
| 7659 | dst->arrayDimensionsSize = src->arrayDimensionsSize; |
| 7660 | } |
| 7661 | return UA_STATUSCODE_GOOD; |
| 7662 | } |
| 7663 | |
| 7664 | void |
| 7665 | UA_Variant_setScalar(UA_Variant *v, void * UA_RESTRICT p, |
| 7666 | const UA_DataType *type) { |
| 7667 | UA_Variant_init(p: v); |
| 7668 | v->type = type; |
| 7669 | v->arrayLength = 0; |
| 7670 | v->data = p; |
| 7671 | } |
| 7672 | |
| 7673 | UA_StatusCode |
| 7674 | UA_Variant_setScalarCopy(UA_Variant *v, const void * UA_RESTRICT p, |
| 7675 | const UA_DataType *type) { |
| 7676 | void *n = UA_malloc(size: type->memSize); |
| 7677 | if(UA_UNLIKELY(!n)) |
| 7678 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 7679 | UA_StatusCode retval = UA_copy(src: p, dst: n, type); |
| 7680 | if(UA_UNLIKELY(retval != UA_STATUSCODE_GOOD)) { |
| 7681 | UA_free(ptr: n); |
| 7682 | //cppcheck-suppress memleak |
| 7683 | return retval; |
| 7684 | } |
| 7685 | UA_Variant_setScalar(v, p: n, type); |
| 7686 | //cppcheck-suppress memleak |
| 7687 | return UA_STATUSCODE_GOOD; |
| 7688 | } |
| 7689 | |
| 7690 | void UA_Variant_setArray(UA_Variant *v, void * UA_RESTRICT array, |
| 7691 | size_t arraySize, const UA_DataType *type) { |
| 7692 | UA_Variant_init(p: v); |
| 7693 | v->data = array; |
| 7694 | v->arrayLength = arraySize; |
| 7695 | v->type = type; |
| 7696 | } |
| 7697 | |
| 7698 | UA_StatusCode |
| 7699 | UA_Variant_setArrayCopy(UA_Variant *v, const void * UA_RESTRICT array, |
| 7700 | size_t arraySize, const UA_DataType *type) { |
| 7701 | UA_Variant_init(p: v); |
| 7702 | UA_StatusCode retval = UA_Array_copy(src: array, size: arraySize, dst: &v->data, type); |
| 7703 | if(retval != UA_STATUSCODE_GOOD) |
| 7704 | return retval; |
| 7705 | v->arrayLength = arraySize; |
| 7706 | v->type = type; |
| 7707 | return UA_STATUSCODE_GOOD; |
| 7708 | } |
| 7709 | |
| 7710 | /* Test if a range is compatible with a variant. This may adjust the upper bound |
| 7711 | * (max) in order to fit the variant. */ |
| 7712 | static UA_StatusCode |
| 7713 | checkAdjustRange(const UA_Variant *v, UA_NumericRange *range) { |
| 7714 | /* Test for max array size (64bit only) */ |
| 7715 | #if (SIZE_MAX > 0xffffffff) |
| 7716 | if(v->arrayLength > UA_UINT32_MAX) |
| 7717 | return UA_STATUSCODE_BADINTERNALERROR; |
| 7718 | #endif |
| 7719 | u32 arrayLength = (u32)v->arrayLength; |
| 7720 | |
| 7721 | /* Assume one array dimension if none defined */ |
| 7722 | const u32 *dims = v->arrayDimensions; |
| 7723 | size_t dims_count = v->arrayDimensionsSize; |
| 7724 | if(v->arrayDimensionsSize == 0) { |
| 7725 | dims_count = 1; |
| 7726 | dims = &arrayLength; |
| 7727 | } |
| 7728 | |
| 7729 | /* Does the range match the dimension of the variant? */ |
| 7730 | if(range->dimensionsSize != dims_count) |
| 7731 | return UA_STATUSCODE_BADINDEXRANGENODATA; |
| 7732 | |
| 7733 | /* Check that the number of elements in the variant matches the array |
| 7734 | * dimensions */ |
| 7735 | size_t elements = 1; |
| 7736 | for(size_t i = 0; i < dims_count; ++i) |
| 7737 | elements *= dims[i]; |
| 7738 | if(elements != v->arrayLength) |
| 7739 | return UA_STATUSCODE_BADINTERNALERROR; |
| 7740 | |
| 7741 | /* Test the integrity of the range and compute the max index used for every |
| 7742 | * dimension. The standard says in Part 4, Section 7.22: |
| 7743 | * |
| 7744 | * When reading a value, the indexes may not specify a range that is within |
| 7745 | * the bounds of the array. The Server shall return a partial result if some |
| 7746 | * elements exist within the range. */ |
| 7747 | for(size_t i = 0; i < dims_count; ++i) { |
| 7748 | if(range->dimensions[i].min > range->dimensions[i].max) |
| 7749 | return UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 7750 | if(range->dimensions[i].min >= dims[i]) |
| 7751 | return UA_STATUSCODE_BADINDEXRANGENODATA; |
| 7752 | |
| 7753 | /* Reduce the max to fit the variant */ |
| 7754 | if(range->dimensions[i].max >= dims[i]) |
| 7755 | range->dimensions[i].max = dims[i] - 1; |
| 7756 | } |
| 7757 | |
| 7758 | return UA_STATUSCODE_GOOD; |
| 7759 | } |
| 7760 | |
| 7761 | /* Computes the stride for copying the range elements. |
| 7762 | * - total: how many elements are in the range |
| 7763 | * - block: how big is each contiguous block of elements in the variant that |
| 7764 | * maps into the range |
| 7765 | * - stride: how many elements are between the blocks (beginning to beginning) |
| 7766 | * - first: where does the first block begin */ |
| 7767 | static void |
| 7768 | computeStrides(const UA_Variant *v, const UA_NumericRange range, |
| 7769 | size_t *total, size_t *block, size_t *stride, size_t *first) { |
| 7770 | /* Number of total elements to be copied */ |
| 7771 | size_t count = 1; |
| 7772 | for(size_t i = 0; i < range.dimensionsSize; ++i) |
| 7773 | count *= (range.dimensions[i].max - range.dimensions[i].min) + 1; |
| 7774 | *total = count; |
| 7775 | |
| 7776 | /* Assume one array dimension if none defined */ |
| 7777 | u32 arrayLength = (u32)v->arrayLength; |
| 7778 | const u32 *dims = v->arrayDimensions; |
| 7779 | size_t dims_count = v->arrayDimensionsSize; |
| 7780 | if(v->arrayDimensionsSize == 0) { |
| 7781 | dims_count = 1; |
| 7782 | dims = &arrayLength; |
| 7783 | } |
| 7784 | |
| 7785 | /* Compute the stride length and the position of the first element */ |
| 7786 | *block = count; /* Assume the range describes the entire array. */ |
| 7787 | *stride = v->arrayLength; /* So it can be copied as a contiguous block. */ |
| 7788 | *first = 0; |
| 7789 | size_t running_dimssize = 1; |
| 7790 | UA_Boolean found_contiguous = false; |
| 7791 | for(size_t k = dims_count; k > 0;) { |
| 7792 | --k; |
| 7793 | size_t dimrange = 1 + range.dimensions[k].max - range.dimensions[k].min; |
| 7794 | if(!found_contiguous && dimrange != dims[k]) { |
| 7795 | /* Found the maximum block that can be copied contiguously */ |
| 7796 | found_contiguous = true; |
| 7797 | *block = running_dimssize * dimrange; |
| 7798 | *stride = running_dimssize * dims[k]; |
| 7799 | } |
| 7800 | *first += running_dimssize * range.dimensions[k].min; |
| 7801 | running_dimssize *= dims[k]; |
| 7802 | } |
| 7803 | } |
| 7804 | |
| 7805 | /* Is the type string-like? */ |
| 7806 | static UA_Boolean |
| 7807 | isStringLike(const UA_DataType *type) { |
| 7808 | if(type == &UA_TYPES[UA_TYPES_STRING] || |
| 7809 | type == &UA_TYPES[UA_TYPES_BYTESTRING] || |
| 7810 | type == &UA_TYPES[UA_TYPES_XMLELEMENT]) |
| 7811 | return true; |
| 7812 | return false; |
| 7813 | } |
| 7814 | |
| 7815 | /* Returns the part of the string that lies within the rangedimension */ |
| 7816 | static UA_StatusCode |
| 7817 | copySubString(const UA_String *src, UA_String *dst, |
| 7818 | const UA_NumericRangeDimension *dim) { |
| 7819 | if(dim->min > dim->max) |
| 7820 | return UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 7821 | if(dim->min >= src->length) |
| 7822 | return UA_STATUSCODE_BADINDEXRANGENODATA; |
| 7823 | |
| 7824 | size_t length; |
| 7825 | if(dim->max < src->length) |
| 7826 | length = dim->max - dim->min + 1; |
| 7827 | else |
| 7828 | length = src->length - dim->min; |
| 7829 | |
| 7830 | UA_StatusCode retval = UA_ByteString_allocBuffer(bs: dst, length); |
| 7831 | if(retval != UA_STATUSCODE_GOOD) |
| 7832 | return retval; |
| 7833 | |
| 7834 | memcpy(dest: dst->data, src: &src->data[dim->min], n: length); |
| 7835 | return UA_STATUSCODE_GOOD; |
| 7836 | } |
| 7837 | |
| 7838 | UA_StatusCode |
| 7839 | UA_Variant_copyRange(const UA_Variant *src, UA_Variant * UA_RESTRICT dst, |
| 7840 | const UA_NumericRange range) { |
| 7841 | if(!src->type) |
| 7842 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 7843 | |
| 7844 | UA_Boolean isScalar = UA_Variant_isScalar(v: src); |
| 7845 | UA_Boolean stringLike = isStringLike(type: src->type); |
| 7846 | |
| 7847 | /* Upper bound of the dimensions for stack-allocation */ |
| 7848 | if(range.dimensionsSize > UA_MAX_ARRAY_DIMS) |
| 7849 | return UA_STATUSCODE_BADINTERNALERROR; |
| 7850 | |
| 7851 | /* Copy the const range to a mutable stack location */ |
| 7852 | UA_NumericRangeDimension thisrangedims[UA_MAX_ARRAY_DIMS]; |
| 7853 | memcpy(dest: thisrangedims, src: range.dimensions, n: sizeof(UA_NumericRangeDimension) * range.dimensionsSize); |
| 7854 | UA_NumericRange thisrange = {range.dimensionsSize, thisrangedims}; |
| 7855 | |
| 7856 | UA_NumericRangeDimension scalarThisDimension = {0,0}; /* a single entry */ |
| 7857 | UA_NumericRange nextrange = {0, NULL}; |
| 7858 | |
| 7859 | /* Extract the range for copying at this level. The remaining range is dealt |
| 7860 | * with in the "scalar" type that may define an array by itself (string, |
| 7861 | * variant, ...). */ |
| 7862 | UA_Variant arraySrc; |
| 7863 | if(isScalar) { |
| 7864 | /* Replace scalar src with array of length 1 */ |
| 7865 | arraySrc = *src; |
| 7866 | arraySrc.arrayLength = 1; |
| 7867 | src = &arraySrc; |
| 7868 | /* Deal with all range dimensions within the scalar */ |
| 7869 | thisrange.dimensions = &scalarThisDimension; |
| 7870 | thisrange.dimensionsSize = 1; |
| 7871 | nextrange = range; |
| 7872 | } else { |
| 7873 | /* Deal with as many range dimensions as possible right now */ |
| 7874 | size_t dims = src->arrayDimensionsSize; |
| 7875 | if(dims == 0) |
| 7876 | dims = 1; |
| 7877 | if(dims > range.dimensionsSize) |
| 7878 | return UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 7879 | thisrange.dimensionsSize = dims; |
| 7880 | nextrange.dimensions = &range.dimensions[dims]; |
| 7881 | nextrange.dimensionsSize = range.dimensionsSize - dims; |
| 7882 | } |
| 7883 | |
| 7884 | UA_StatusCode retval = checkAdjustRange(v: src, range: &thisrange); |
| 7885 | if(retval != UA_STATUSCODE_GOOD) |
| 7886 | return retval; |
| 7887 | |
| 7888 | /* Compute the strides */ |
| 7889 | size_t count, block, stride, first; |
| 7890 | computeStrides(v: src, range: thisrange, total: &count, block: &block, stride: &stride, first: &first); |
| 7891 | UA_assert(block > 0); |
| 7892 | |
| 7893 | /* Allocate the array */ |
| 7894 | UA_Variant_init(p: dst); |
| 7895 | dst->data = UA_Array_new(size: count, type: src->type); |
| 7896 | if(!dst->data) |
| 7897 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 7898 | |
| 7899 | /* Copy the range */ |
| 7900 | size_t block_count = count / block; |
| 7901 | size_t elem_size = src->type->memSize; |
| 7902 | uintptr_t nextdst = (uintptr_t)dst->data; |
| 7903 | uintptr_t nextsrc = (uintptr_t)src->data + (elem_size * first); |
| 7904 | if(nextrange.dimensionsSize == 0) { |
| 7905 | /* no nextrange */ |
| 7906 | if(src->type->pointerFree) { |
| 7907 | for(size_t i = 0; i < block_count; ++i) { |
| 7908 | memcpy(dest: (void*)nextdst, src: (void*)nextsrc, n: elem_size * block); |
| 7909 | nextdst += block * elem_size; |
| 7910 | nextsrc += stride * elem_size; |
| 7911 | } |
| 7912 | } else { |
| 7913 | for(size_t i = 0; i < block_count; ++i) { |
| 7914 | for(size_t j = 0; j < block; ++j) { |
| 7915 | retval = UA_copy(src: (const void*)nextsrc, |
| 7916 | dst: (void*)nextdst, type: src->type); |
| 7917 | nextdst += elem_size; |
| 7918 | nextsrc += elem_size; |
| 7919 | } |
| 7920 | nextsrc += (stride - block) * elem_size; |
| 7921 | } |
| 7922 | } |
| 7923 | } else { |
| 7924 | /* nextrange can only be used for variants and stringlike with remaining |
| 7925 | * range of dimension 1 */ |
| 7926 | if(src->type != &UA_TYPES[UA_TYPES_VARIANT]) { |
| 7927 | if(!stringLike) |
| 7928 | retval = UA_STATUSCODE_BADINDEXRANGENODATA; |
| 7929 | if(nextrange.dimensionsSize != 1) |
| 7930 | retval = UA_STATUSCODE_BADINDEXRANGENODATA; |
| 7931 | } |
| 7932 | |
| 7933 | /* Copy the content */ |
| 7934 | for(size_t i = 0; i < block_count; ++i) { |
| 7935 | for(size_t j = 0; j < block && retval == UA_STATUSCODE_GOOD; ++j) { |
| 7936 | if(stringLike) |
| 7937 | retval = copySubString(src: (const UA_String*)nextsrc, |
| 7938 | dst: (UA_String*)nextdst, |
| 7939 | dim: nextrange.dimensions); |
| 7940 | else |
| 7941 | retval = UA_Variant_copyRange(src: (const UA_Variant*)nextsrc, |
| 7942 | dst: (UA_Variant*)nextdst, |
| 7943 | range: nextrange); |
| 7944 | nextdst += elem_size; |
| 7945 | nextsrc += elem_size; |
| 7946 | } |
| 7947 | nextsrc += (stride - block) * elem_size; |
| 7948 | } |
| 7949 | } |
| 7950 | |
| 7951 | /* Clean up if copying failed */ |
| 7952 | if(retval != UA_STATUSCODE_GOOD) { |
| 7953 | UA_Array_delete(p: dst->data, size: count, type: src->type); |
| 7954 | dst->data = NULL; |
| 7955 | return retval; |
| 7956 | } |
| 7957 | |
| 7958 | /* Done if scalar */ |
| 7959 | dst->type = src->type; |
| 7960 | if(isScalar) |
| 7961 | return retval; |
| 7962 | |
| 7963 | /* Copy array dimensions */ |
| 7964 | dst->arrayLength = count; |
| 7965 | if(src->arrayDimensionsSize > 0) { |
| 7966 | dst->arrayDimensions = |
| 7967 | (u32*)UA_Array_new(size: thisrange.dimensionsSize, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 7968 | if(!dst->arrayDimensions) { |
| 7969 | Variant_clear(p: dst, NULL); |
| 7970 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 7971 | } |
| 7972 | dst->arrayDimensionsSize = thisrange.dimensionsSize; |
| 7973 | for(size_t k = 0; k < thisrange.dimensionsSize; ++k) |
| 7974 | dst->arrayDimensions[k] = |
| 7975 | thisrange.dimensions[k].max - thisrange.dimensions[k].min + 1; |
| 7976 | } |
| 7977 | return UA_STATUSCODE_GOOD; |
| 7978 | } |
| 7979 | |
| 7980 | /* TODO: Allow ranges to reach inside a scalars that are array-like, e.g. |
| 7981 | * variant and strings. This is already possible for reading... */ |
| 7982 | static UA_StatusCode |
| 7983 | Variant_setRange(UA_Variant *v, void *array, size_t arraySize, |
| 7984 | const UA_NumericRange range, UA_Boolean copy) { |
| 7985 | if(!v->type) |
| 7986 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 7987 | |
| 7988 | /* Upper bound of the dimensions for stack-allocation */ |
| 7989 | if(range.dimensionsSize > UA_MAX_ARRAY_DIMS) |
| 7990 | return UA_STATUSCODE_BADINTERNALERROR; |
| 7991 | |
| 7992 | /* Copy the const range to a mutable stack location */ |
| 7993 | UA_NumericRangeDimension thisrangedims[UA_MAX_ARRAY_DIMS]; |
| 7994 | memcpy(dest: thisrangedims, src: range.dimensions, n: sizeof(UA_NumericRangeDimension) * range.dimensionsSize); |
| 7995 | UA_NumericRange thisrange = {range.dimensionsSize, thisrangedims}; |
| 7996 | |
| 7997 | UA_StatusCode retval = checkAdjustRange(v, range: &thisrange); |
| 7998 | if(retval != UA_STATUSCODE_GOOD) |
| 7999 | return retval; |
| 8000 | |
| 8001 | /* Compute the strides */ |
| 8002 | size_t count, block, stride, first; |
| 8003 | computeStrides(v, range, total: &count, block: &block, stride: &stride, first: &first); |
| 8004 | if(count != arraySize) |
| 8005 | return UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 8006 | |
| 8007 | /* Move/copy the elements */ |
| 8008 | size_t block_count = count / block; |
| 8009 | size_t elem_size = v->type->memSize; |
| 8010 | uintptr_t nextdst = (uintptr_t)v->data + (first * elem_size); |
| 8011 | uintptr_t nextsrc = (uintptr_t)array; |
| 8012 | if(v->type->pointerFree || !copy) { |
| 8013 | for(size_t i = 0; i < block_count; ++i) { |
| 8014 | memcpy(dest: (void*)nextdst, src: (void*)nextsrc, n: elem_size * block); |
| 8015 | nextsrc += block * elem_size; |
| 8016 | nextdst += stride * elem_size; |
| 8017 | } |
| 8018 | } else { |
| 8019 | for(size_t i = 0; i < block_count; ++i) { |
| 8020 | for(size_t j = 0; j < block; ++j) { |
| 8021 | clearJumpTable[v->type->typeKind]((void*)nextdst, v->type); |
| 8022 | retval |= UA_copy(src: (void*)nextsrc, dst: (void*)nextdst, type: v->type); |
| 8023 | nextdst += elem_size; |
| 8024 | nextsrc += elem_size; |
| 8025 | } |
| 8026 | nextdst += (stride - block) * elem_size; |
| 8027 | } |
| 8028 | } |
| 8029 | |
| 8030 | /* If members were moved, initialize original array to prevent reuse */ |
| 8031 | if(!copy && !v->type->pointerFree) |
| 8032 | memset(s: array, c: 0, n: sizeof(elem_size)*arraySize); |
| 8033 | |
| 8034 | return retval; |
| 8035 | } |
| 8036 | |
| 8037 | UA_StatusCode |
| 8038 | UA_Variant_setRange(UA_Variant *v, void * UA_RESTRICT array, |
| 8039 | size_t arraySize, const UA_NumericRange range) { |
| 8040 | return Variant_setRange(v, array, arraySize, range, false); |
| 8041 | } |
| 8042 | |
| 8043 | UA_StatusCode |
| 8044 | UA_Variant_setRangeCopy(UA_Variant *v, const void * UA_RESTRICT array, |
| 8045 | size_t arraySize, const UA_NumericRange range) { |
| 8046 | return Variant_setRange(v, array: (void*)(uintptr_t)array, |
| 8047 | arraySize, range, true); |
| 8048 | } |
| 8049 | |
| 8050 | /* LocalizedText */ |
| 8051 | static void |
| 8052 | LocalizedText_clear(UA_LocalizedText *p, const UA_DataType *_) { |
| 8053 | String_clear(s: &p->locale, NULL); |
| 8054 | String_clear(s: &p->text, NULL); |
| 8055 | } |
| 8056 | |
| 8057 | static UA_StatusCode |
| 8058 | LocalizedText_copy(UA_LocalizedText const *src, UA_LocalizedText *dst, |
| 8059 | const UA_DataType *_) { |
| 8060 | UA_StatusCode retval = String_copy(src: &src->locale, dst: &dst->locale, NULL); |
| 8061 | retval |= String_copy(src: &src->text, dst: &dst->text, NULL); |
| 8062 | return retval; |
| 8063 | } |
| 8064 | |
| 8065 | /* DataValue */ |
| 8066 | static void |
| 8067 | DataValue_clear(UA_DataValue *p, const UA_DataType *_) { |
| 8068 | Variant_clear(p: &p->value, NULL); |
| 8069 | } |
| 8070 | |
| 8071 | static UA_StatusCode |
| 8072 | DataValue_copy(UA_DataValue const *src, UA_DataValue *dst, |
| 8073 | const UA_DataType *_) { |
| 8074 | memcpy(dest: dst, src: src, n: sizeof(UA_DataValue)); |
| 8075 | UA_Variant_init(p: &dst->value); |
| 8076 | UA_StatusCode retval = Variant_copy(src: &src->value, dst: &dst->value, NULL); |
| 8077 | if(retval != UA_STATUSCODE_GOOD) |
| 8078 | DataValue_clear(p: dst, NULL); |
| 8079 | return retval; |
| 8080 | } |
| 8081 | |
| 8082 | UA_StatusCode |
| 8083 | UA_DataValue_copyVariantRange(const UA_DataValue *src, UA_DataValue * UA_RESTRICT dst, |
| 8084 | const UA_NumericRange range) { |
| 8085 | memcpy(dest: dst, src: src, n: sizeof(UA_DataValue)); |
| 8086 | UA_Variant_init(p: &dst->value); |
| 8087 | UA_StatusCode retval = UA_Variant_copyRange(src: &src->value, dst: &dst->value, range); |
| 8088 | if(retval != UA_STATUSCODE_GOOD) |
| 8089 | DataValue_clear(p: dst, NULL); |
| 8090 | return retval; |
| 8091 | } |
| 8092 | |
| 8093 | /* DiagnosticInfo */ |
| 8094 | static void |
| 8095 | DiagnosticInfo_clear(UA_DiagnosticInfo *p, const UA_DataType *_) { |
| 8096 | String_clear(s: &p->additionalInfo, NULL); |
| 8097 | if(p->hasInnerDiagnosticInfo && p->innerDiagnosticInfo) { |
| 8098 | DiagnosticInfo_clear(p: p->innerDiagnosticInfo, NULL); |
| 8099 | UA_free(ptr: p->innerDiagnosticInfo); |
| 8100 | } |
| 8101 | } |
| 8102 | |
| 8103 | static UA_StatusCode |
| 8104 | DiagnosticInfo_copy(UA_DiagnosticInfo const *src, UA_DiagnosticInfo *dst, |
| 8105 | const UA_DataType *_) { |
| 8106 | memcpy(dest: dst, src: src, n: sizeof(UA_DiagnosticInfo)); |
| 8107 | UA_String_init(p: &dst->additionalInfo); |
| 8108 | dst->innerDiagnosticInfo = NULL; |
| 8109 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 8110 | if(src->hasAdditionalInfo) |
| 8111 | retval = String_copy(src: &src->additionalInfo, dst: &dst->additionalInfo, NULL); |
| 8112 | if(src->hasInnerDiagnosticInfo && src->innerDiagnosticInfo) { |
| 8113 | dst->innerDiagnosticInfo = (UA_DiagnosticInfo*) |
| 8114 | UA_malloc(size: sizeof(UA_DiagnosticInfo)); |
| 8115 | if(UA_LIKELY(dst->innerDiagnosticInfo != NULL)) { |
| 8116 | retval |= DiagnosticInfo_copy(src: src->innerDiagnosticInfo, |
| 8117 | dst: dst->innerDiagnosticInfo, NULL); |
| 8118 | dst->hasInnerDiagnosticInfo = true; |
| 8119 | } else { |
| 8120 | dst->hasInnerDiagnosticInfo = false; |
| 8121 | retval |= UA_STATUSCODE_BADOUTOFMEMORY; |
| 8122 | } |
| 8123 | } |
| 8124 | return retval; |
| 8125 | } |
| 8126 | |
| 8127 | /********************/ |
| 8128 | /* Structured Types */ |
| 8129 | /********************/ |
| 8130 | |
| 8131 | void * |
| 8132 | UA_new(const UA_DataType *type) { |
| 8133 | void *p = UA_calloc(nmemb: 1, size: type->memSize); |
| 8134 | return p; |
| 8135 | } |
| 8136 | |
| 8137 | static UA_StatusCode |
| 8138 | copyByte(const u8 *src, u8 *dst, const UA_DataType *_) { |
| 8139 | *dst = *src; |
| 8140 | return UA_STATUSCODE_GOOD; |
| 8141 | } |
| 8142 | |
| 8143 | static UA_StatusCode |
| 8144 | copy2Byte(const u16 *src, u16 *dst, const UA_DataType *_) { |
| 8145 | *dst = *src; |
| 8146 | return UA_STATUSCODE_GOOD; |
| 8147 | } |
| 8148 | |
| 8149 | static UA_StatusCode |
| 8150 | copy4Byte(const u32 *src, u32 *dst, const UA_DataType *_) { |
| 8151 | *dst = *src; |
| 8152 | return UA_STATUSCODE_GOOD; |
| 8153 | } |
| 8154 | |
| 8155 | static UA_StatusCode |
| 8156 | copy8Byte(const u64 *src, u64 *dst, const UA_DataType *_) { |
| 8157 | *dst = *src; |
| 8158 | return UA_STATUSCODE_GOOD; |
| 8159 | } |
| 8160 | |
| 8161 | static UA_StatusCode |
| 8162 | copyGuid(const UA_Guid *src, UA_Guid *dst, const UA_DataType *_) { |
| 8163 | *dst = *src; |
| 8164 | return UA_STATUSCODE_GOOD; |
| 8165 | } |
| 8166 | |
| 8167 | static UA_StatusCode |
| 8168 | copyStructure(const void *src, void *dst, const UA_DataType *type) { |
| 8169 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 8170 | uintptr_t ptrs = (uintptr_t)src; |
| 8171 | uintptr_t ptrd = (uintptr_t)dst; |
| 8172 | for(size_t i = 0; i < type->membersSize; ++i) { |
| 8173 | const UA_DataTypeMember *m = &type->members[i]; |
| 8174 | const UA_DataType *mt = m->memberType; |
| 8175 | ptrs += m->padding; |
| 8176 | ptrd += m->padding; |
| 8177 | if(!m->isOptional) { |
| 8178 | if(!m->isArray) { |
| 8179 | retval |= copyJumpTable[mt->typeKind]((const void *)ptrs, (void *)ptrd, mt); |
| 8180 | ptrs += mt->memSize; |
| 8181 | ptrd += mt->memSize; |
| 8182 | } else { |
| 8183 | size_t *dst_size = (size_t*)ptrd; |
| 8184 | const size_t size = *((const size_t*)ptrs); |
| 8185 | ptrs += sizeof(size_t); |
| 8186 | ptrd += sizeof(size_t); |
| 8187 | retval |= UA_Array_copy(src: *(void* const*)ptrs, size, dst: (void**)ptrd, type: mt); |
| 8188 | if(retval == UA_STATUSCODE_GOOD) |
| 8189 | *dst_size = size; |
| 8190 | else |
| 8191 | *dst_size = 0; |
| 8192 | ptrs += sizeof(void*); |
| 8193 | ptrd += sizeof(void*); |
| 8194 | } |
| 8195 | } else { |
| 8196 | if(!m->isArray) { |
| 8197 | if(*(void* const*)ptrs != NULL) |
| 8198 | retval |= UA_Array_copy(src: *(void* const*)ptrs, size: 1, dst: (void**)ptrd, type: mt); |
| 8199 | } else { |
| 8200 | if(*(void* const*)(ptrs+sizeof(size_t)) != NULL) { |
| 8201 | size_t *dst_size = (size_t*)ptrd; |
| 8202 | const size_t size = *((const size_t*)ptrs); |
| 8203 | ptrs += sizeof(size_t); |
| 8204 | ptrd += sizeof(size_t); |
| 8205 | retval |= UA_Array_copy(src: *(void* const*)ptrs, size, dst: (void**)ptrd, type: mt); |
| 8206 | if(retval == UA_STATUSCODE_GOOD) |
| 8207 | *dst_size = size; |
| 8208 | else |
| 8209 | *dst_size = 0; |
| 8210 | } else { |
| 8211 | ptrs += sizeof(size_t); |
| 8212 | ptrd += sizeof(size_t); |
| 8213 | } |
| 8214 | } |
| 8215 | ptrs += sizeof(void*); |
| 8216 | ptrd += sizeof(void*); |
| 8217 | } |
| 8218 | } |
| 8219 | return retval; |
| 8220 | } |
| 8221 | |
| 8222 | static UA_StatusCode |
| 8223 | copyUnion(const void *src, void *dst, const UA_DataType *type) { |
| 8224 | uintptr_t ptrs = (uintptr_t) src; |
| 8225 | uintptr_t ptrd = (uintptr_t) dst; |
| 8226 | UA_UInt32 selection = *(UA_UInt32 *)ptrs; |
| 8227 | UA_copy(src: (const UA_UInt32 *) ptrs, dst: (UA_UInt32 *) ptrd, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 8228 | if(selection == 0) |
| 8229 | return UA_STATUSCODE_GOOD; |
| 8230 | const UA_DataTypeMember *m = &type->members[selection-1]; |
| 8231 | const UA_DataType *mt = m->memberType; |
| 8232 | ptrs += m->padding; |
| 8233 | ptrd += m->padding; |
| 8234 | |
| 8235 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 8236 | |
| 8237 | if (m->isArray) { |
| 8238 | size_t *dst_size = (size_t*)ptrd; |
| 8239 | const size_t size = *((const size_t*)ptrs); |
| 8240 | ptrs += sizeof(size_t); |
| 8241 | ptrd += sizeof(size_t); |
| 8242 | retval = UA_Array_copy(src: *(void* const*)ptrs, size, dst: (void**)ptrd, type: mt); |
| 8243 | if(retval == UA_STATUSCODE_GOOD) |
| 8244 | *dst_size = size; |
| 8245 | else |
| 8246 | *dst_size = 0; |
| 8247 | } else { |
| 8248 | retval = copyJumpTable[mt->typeKind]((const void *)ptrs, (void *)ptrd, mt); |
| 8249 | } |
| 8250 | |
| 8251 | return retval; |
| 8252 | } |
| 8253 | |
| 8254 | static UA_StatusCode |
| 8255 | copyNotImplemented(const void *src, void *dst, const UA_DataType *type) { |
| 8256 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 8257 | } |
| 8258 | |
| 8259 | const UA_copySignature copyJumpTable[UA_DATATYPEKINDS] = { |
| 8260 | (UA_copySignature)copyByte, /* Boolean */ |
| 8261 | (UA_copySignature)copyByte, /* SByte */ |
| 8262 | (UA_copySignature)copyByte, /* Byte */ |
| 8263 | (UA_copySignature)copy2Byte, /* Int16 */ |
| 8264 | (UA_copySignature)copy2Byte, /* UInt16 */ |
| 8265 | (UA_copySignature)copy4Byte, /* Int32 */ |
| 8266 | (UA_copySignature)copy4Byte, /* UInt32 */ |
| 8267 | (UA_copySignature)copy8Byte, /* Int64 */ |
| 8268 | (UA_copySignature)copy8Byte, /* UInt64 */ |
| 8269 | (UA_copySignature)copy4Byte, /* Float */ |
| 8270 | (UA_copySignature)copy8Byte, /* Double */ |
| 8271 | (UA_copySignature)String_copy, |
| 8272 | (UA_copySignature)copy8Byte, /* DateTime */ |
| 8273 | (UA_copySignature)copyGuid, /* Guid */ |
| 8274 | (UA_copySignature)String_copy, /* ByteString */ |
| 8275 | (UA_copySignature)String_copy, /* XmlElement */ |
| 8276 | (UA_copySignature)NodeId_copy, |
| 8277 | (UA_copySignature)ExpandedNodeId_copy, |
| 8278 | (UA_copySignature)copy4Byte, /* StatusCode */ |
| 8279 | (UA_copySignature)QualifiedName_copy, |
| 8280 | (UA_copySignature)LocalizedText_copy, |
| 8281 | (UA_copySignature)ExtensionObject_copy, |
| 8282 | (UA_copySignature)DataValue_copy, |
| 8283 | (UA_copySignature)Variant_copy, |
| 8284 | (UA_copySignature)DiagnosticInfo_copy, |
| 8285 | (UA_copySignature)copyNotImplemented, /* Decimal */ |
| 8286 | (UA_copySignature)copy4Byte, /* Enumeration */ |
| 8287 | (UA_copySignature)copyStructure, |
| 8288 | (UA_copySignature)copyStructure, /* Structure with Optional Fields */ |
| 8289 | (UA_copySignature)copyUnion, /* Union */ |
| 8290 | (UA_copySignature)copyNotImplemented /* BitfieldCluster*/ |
| 8291 | }; |
| 8292 | |
| 8293 | UA_StatusCode |
| 8294 | UA_copy(const void *src, void *dst, const UA_DataType *type) { |
| 8295 | memset(s: dst, c: 0, n: type->memSize); /* init */ |
| 8296 | UA_StatusCode retval = copyJumpTable[type->typeKind](src, dst, type); |
| 8297 | if(retval != UA_STATUSCODE_GOOD) |
| 8298 | UA_clear(p: dst, type); |
| 8299 | return retval; |
| 8300 | } |
| 8301 | |
| 8302 | static void |
| 8303 | clearStructure(void *p, const UA_DataType *type) { |
| 8304 | uintptr_t ptr = (uintptr_t)p; |
| 8305 | for(size_t i = 0; i < type->membersSize; ++i) { |
| 8306 | const UA_DataTypeMember *m = &type->members[i]; |
| 8307 | const UA_DataType *mt = m->memberType; |
| 8308 | ptr += m->padding; |
| 8309 | if(!m->isOptional) { |
| 8310 | if(!m->isArray) { |
| 8311 | clearJumpTable[mt->typeKind]((void*)ptr, mt); |
| 8312 | ptr += mt->memSize; |
| 8313 | } else { |
| 8314 | size_t length = *(size_t*)ptr; |
| 8315 | ptr += sizeof(size_t); |
| 8316 | UA_Array_delete(p: *(void**)ptr, size: length, type: mt); |
| 8317 | ptr += sizeof(void*); |
| 8318 | } |
| 8319 | } else { /* field is optional */ |
| 8320 | if(!m->isArray) { |
| 8321 | /* optional scalar field is contained */ |
| 8322 | if((*(void *const *)ptr != NULL)) |
| 8323 | UA_Array_delete(p: *(void **)ptr, size: 1, type: mt); |
| 8324 | ptr += sizeof(void *); |
| 8325 | } else { |
| 8326 | /* optional array field is contained */ |
| 8327 | if((*(void *const *)(ptr + sizeof(size_t)) != NULL)) { |
| 8328 | size_t length = *(size_t *)ptr; |
| 8329 | ptr += sizeof(size_t); |
| 8330 | UA_Array_delete(p: *(void **)ptr, size: length, type: mt); |
| 8331 | ptr += sizeof(void *); |
| 8332 | } else { /* optional array field not contained */ |
| 8333 | ptr += sizeof(size_t); |
| 8334 | ptr += sizeof(void *); |
| 8335 | } |
| 8336 | } |
| 8337 | } |
| 8338 | } |
| 8339 | } |
| 8340 | |
| 8341 | static void |
| 8342 | clearUnion(void *p, const UA_DataType *type) { |
| 8343 | uintptr_t ptr = (uintptr_t) p; |
| 8344 | UA_UInt32 selection = *(UA_UInt32 *)ptr; |
| 8345 | if(selection == 0) |
| 8346 | return; |
| 8347 | const UA_DataTypeMember *m = &type->members[selection-1]; |
| 8348 | const UA_DataType *mt = m->memberType; |
| 8349 | ptr += m->padding; |
| 8350 | if (m->isArray) { |
| 8351 | size_t length = *(size_t *)ptr; |
| 8352 | ptr += sizeof(size_t); |
| 8353 | UA_Array_delete(p: *(void **)ptr, size: length, type: mt); |
| 8354 | } else { |
| 8355 | UA_clear(p: (void *) ptr, type: mt); |
| 8356 | } |
| 8357 | } |
| 8358 | |
| 8359 | static void nopClear(void *p, const UA_DataType *type) { } |
| 8360 | |
| 8361 | const |
| 8362 | UA_clearSignature clearJumpTable[UA_DATATYPEKINDS] = { |
| 8363 | (UA_clearSignature)nopClear, /* Boolean */ |
| 8364 | (UA_clearSignature)nopClear, /* SByte */ |
| 8365 | (UA_clearSignature)nopClear, /* Byte */ |
| 8366 | (UA_clearSignature)nopClear, /* Int16 */ |
| 8367 | (UA_clearSignature)nopClear, /* UInt16 */ |
| 8368 | (UA_clearSignature)nopClear, /* Int32 */ |
| 8369 | (UA_clearSignature)nopClear, /* UInt32 */ |
| 8370 | (UA_clearSignature)nopClear, /* Int64 */ |
| 8371 | (UA_clearSignature)nopClear, /* UInt64 */ |
| 8372 | (UA_clearSignature)nopClear, /* Float */ |
| 8373 | (UA_clearSignature)nopClear, /* Double */ |
| 8374 | (UA_clearSignature)String_clear, /* String */ |
| 8375 | (UA_clearSignature)nopClear, /* DateTime */ |
| 8376 | (UA_clearSignature)nopClear, /* Guid */ |
| 8377 | (UA_clearSignature)String_clear, /* ByteString */ |
| 8378 | (UA_clearSignature)String_clear, /* XmlElement */ |
| 8379 | (UA_clearSignature)NodeId_clear, |
| 8380 | (UA_clearSignature)ExpandedNodeId_clear, |
| 8381 | (UA_clearSignature)nopClear, /* StatusCode */ |
| 8382 | (UA_clearSignature)QualifiedName_clear, |
| 8383 | (UA_clearSignature)LocalizedText_clear, |
| 8384 | (UA_clearSignature)ExtensionObject_clear, |
| 8385 | (UA_clearSignature)DataValue_clear, |
| 8386 | (UA_clearSignature)Variant_clear, |
| 8387 | (UA_clearSignature)DiagnosticInfo_clear, |
| 8388 | (UA_clearSignature)nopClear, /* Decimal, not implemented */ |
| 8389 | (UA_clearSignature)nopClear, /* Enumeration */ |
| 8390 | (UA_clearSignature)clearStructure, |
| 8391 | (UA_clearSignature)clearStructure, /* Struct with Optional Fields*/ |
| 8392 | (UA_clearSignature)clearUnion, /* Union*/ |
| 8393 | (UA_clearSignature)nopClear /* BitfieldCluster, not implemented*/ |
| 8394 | }; |
| 8395 | |
| 8396 | void |
| 8397 | UA_clear(void *p, const UA_DataType *type) { |
| 8398 | clearJumpTable[type->typeKind](p, type); |
| 8399 | memset(s: p, c: 0, n: type->memSize); /* init */ |
| 8400 | } |
| 8401 | |
| 8402 | void |
| 8403 | UA_delete(void *p, const UA_DataType *type) { |
| 8404 | clearJumpTable[type->typeKind](p, type); |
| 8405 | UA_free(ptr: p); |
| 8406 | } |
| 8407 | |
| 8408 | /******************/ |
| 8409 | /* Value Ordering */ |
| 8410 | /******************/ |
| 8411 | |
| 8412 | #define UA_NUMERICORDER(NAME, TYPE) \ |
| 8413 | static UA_Order \ |
| 8414 | NAME(const TYPE *p1, const TYPE *p2, const UA_DataType *type) { \ |
| 8415 | if(*p1 != *p2) \ |
| 8416 | return (*p1 < *p2) ? UA_ORDER_LESS : UA_ORDER_MORE; \ |
| 8417 | return UA_ORDER_EQ; \ |
| 8418 | } |
| 8419 | |
| 8420 | UA_NUMERICORDER(booleanOrder, UA_Boolean) |
| 8421 | UA_NUMERICORDER(sByteOrder, UA_SByte) |
| 8422 | UA_NUMERICORDER(byteOrder, UA_Byte) |
| 8423 | UA_NUMERICORDER(int16Order, UA_Int16) |
| 8424 | UA_NUMERICORDER(uInt16Order, UA_UInt16) |
| 8425 | UA_NUMERICORDER(int32Order, UA_Int32) |
| 8426 | UA_NUMERICORDER(uInt32Order, UA_UInt32) |
| 8427 | UA_NUMERICORDER(int64Order, UA_Int64) |
| 8428 | UA_NUMERICORDER(uInt64Order, UA_UInt64) |
| 8429 | |
| 8430 | #define UA_FLOATORDER(NAME, TYPE) \ |
| 8431 | static UA_Order \ |
| 8432 | NAME(const TYPE *p1, const TYPE *p2, const UA_DataType *type) { \ |
| 8433 | if(*p1 != *p2) { \ |
| 8434 | /* p1 is NaN */ \ |
| 8435 | if(*p1 != *p1) { \ |
| 8436 | if(*p2 != *p2) \ |
| 8437 | return UA_ORDER_EQ; \ |
| 8438 | return UA_ORDER_LESS; \ |
| 8439 | } \ |
| 8440 | /* p2 is NaN */ \ |
| 8441 | if(*p2 != *p2) \ |
| 8442 | return UA_ORDER_MORE; \ |
| 8443 | return (*p1 < *p2) ? UA_ORDER_LESS : UA_ORDER_MORE; \ |
| 8444 | } \ |
| 8445 | return UA_ORDER_EQ; \ |
| 8446 | } |
| 8447 | |
| 8448 | UA_FLOATORDER(floatOrder, UA_Float) |
| 8449 | UA_FLOATORDER(doubleOrder, UA_Double) |
| 8450 | |
| 8451 | static UA_Order |
| 8452 | guidOrder(const UA_Guid *p1, const UA_Guid *p2, const UA_DataType *type) { |
| 8453 | if(p1->data1 != p2->data1) |
| 8454 | return (p1->data1 < p2->data1) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8455 | if(p1->data2 != p2->data2) |
| 8456 | return (p1->data2 < p2->data2) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8457 | if(p1->data3 != p2->data3) |
| 8458 | return (p1->data3 < p2->data3) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8459 | int cmp = memcmp(s1: p1->data4, s2: p2->data4, n: 8); |
| 8460 | if(cmp != 0) |
| 8461 | return (cmp < 0) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8462 | return UA_ORDER_EQ; |
| 8463 | } |
| 8464 | |
| 8465 | static UA_Order |
| 8466 | stringOrder(const UA_String *p1, const UA_String *p2, const UA_DataType *type) { |
| 8467 | if(p1->length != p2->length) |
| 8468 | return (p1->length < p2->length) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8469 | /* For zero-length arrays, every pointer not NULL is considered a |
| 8470 | * UA_EMPTY_ARRAY_SENTINEL. */ |
| 8471 | if(p1->data == p2->data) return UA_ORDER_EQ; |
| 8472 | if(p1->data == NULL) return UA_ORDER_LESS; |
| 8473 | if(p2->data == NULL) return UA_ORDER_MORE; |
| 8474 | int cmp = memcmp(s1: (const char*)p1->data, s2: (const char*)p2->data, n: p1->length); |
| 8475 | if(cmp != 0) |
| 8476 | return (cmp < 0) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8477 | return UA_ORDER_EQ; |
| 8478 | } |
| 8479 | |
| 8480 | static UA_Order |
| 8481 | nodeIdOrder(const UA_NodeId *p1, const UA_NodeId *p2, const UA_DataType *_) { |
| 8482 | /* Compare namespaceIndex */ |
| 8483 | if(p1->namespaceIndex != p2->namespaceIndex) |
| 8484 | return (p1->namespaceIndex < p2->namespaceIndex) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8485 | |
| 8486 | /* Compare identifierType */ |
| 8487 | if(p1->identifierType != p2->identifierType) |
| 8488 | return (p1->identifierType < p2->identifierType) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8489 | |
| 8490 | /* Compare the identifier */ |
| 8491 | switch(p1->identifierType) { |
| 8492 | case UA_NODEIDTYPE_NUMERIC: |
| 8493 | default: |
| 8494 | if(p1->identifier.numeric != p2->identifier.numeric) |
| 8495 | return (p1->identifier.numeric < p2->identifier.numeric) ? |
| 8496 | UA_ORDER_LESS : UA_ORDER_MORE; |
| 8497 | return UA_ORDER_EQ; |
| 8498 | case UA_NODEIDTYPE_GUID: |
| 8499 | return guidOrder(p1: &p1->identifier.guid, p2: &p2->identifier.guid, NULL); |
| 8500 | case UA_NODEIDTYPE_STRING: |
| 8501 | case UA_NODEIDTYPE_BYTESTRING: |
| 8502 | return stringOrder(p1: &p1->identifier.string, p2: &p2->identifier.string, NULL); |
| 8503 | } |
| 8504 | } |
| 8505 | |
| 8506 | static UA_Order |
| 8507 | expandedNodeIdOrder(const UA_ExpandedNodeId *p1, const UA_ExpandedNodeId *p2, |
| 8508 | const UA_DataType *_) { |
| 8509 | if(p1->serverIndex != p2->serverIndex) |
| 8510 | return (p1->serverIndex < p2->serverIndex) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8511 | UA_Order o = stringOrder(p1: &p1->namespaceUri, p2: &p2->namespaceUri, NULL); |
| 8512 | if(o != UA_ORDER_EQ) |
| 8513 | return o; |
| 8514 | return nodeIdOrder(p1: &p1->nodeId, p2: &p2->nodeId, NULL); |
| 8515 | } |
| 8516 | |
| 8517 | static UA_Order |
| 8518 | qualifiedNameOrder(const UA_QualifiedName *p1, const UA_QualifiedName *p2, |
| 8519 | const UA_DataType *_) { |
| 8520 | if(p1->namespaceIndex != p2->namespaceIndex) |
| 8521 | return (p1->namespaceIndex < p2->namespaceIndex) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8522 | return stringOrder(p1: &p1->name, p2: &p2->name, NULL); |
| 8523 | } |
| 8524 | |
| 8525 | static UA_Order |
| 8526 | localizedTextOrder(const UA_LocalizedText *p1, const UA_LocalizedText *p2, |
| 8527 | const UA_DataType *_) { |
| 8528 | UA_Order o = stringOrder(p1: &p1->locale, p2: &p2->locale, NULL); |
| 8529 | if(o != UA_ORDER_EQ) |
| 8530 | return o; |
| 8531 | return stringOrder(p1: &p1->text, p2: &p2->text, NULL); |
| 8532 | } |
| 8533 | |
| 8534 | static UA_Order |
| 8535 | extensionObjectOrder(const UA_ExtensionObject *p1, const UA_ExtensionObject *p2, |
| 8536 | const UA_DataType *_) { |
| 8537 | UA_ExtensionObjectEncoding enc1 = p1->encoding; |
| 8538 | UA_ExtensionObjectEncoding enc2 = p2->encoding; |
| 8539 | if(enc1 > UA_EXTENSIONOBJECT_DECODED) |
| 8540 | enc1 = UA_EXTENSIONOBJECT_DECODED; |
| 8541 | if(enc2 > UA_EXTENSIONOBJECT_DECODED) |
| 8542 | enc2 = UA_EXTENSIONOBJECT_DECODED; |
| 8543 | if(enc1 != enc2) |
| 8544 | return (enc1 < enc2) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8545 | |
| 8546 | switch(enc1) { |
| 8547 | case UA_EXTENSIONOBJECT_ENCODED_NOBODY: |
| 8548 | return UA_ORDER_EQ; |
| 8549 | |
| 8550 | case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING: |
| 8551 | case UA_EXTENSIONOBJECT_ENCODED_XML: { |
| 8552 | UA_Order o = nodeIdOrder(p1: &p1->content.encoded.typeId, |
| 8553 | p2: &p2->content.encoded.typeId, NULL); |
| 8554 | if(o != UA_ORDER_EQ) |
| 8555 | return o; |
| 8556 | return stringOrder(p1: (const UA_String*)&p1->content.encoded.body, |
| 8557 | p2: (const UA_String*)&p2->content.encoded.body, NULL); |
| 8558 | } |
| 8559 | |
| 8560 | case UA_EXTENSIONOBJECT_DECODED: |
| 8561 | default: { |
| 8562 | const UA_DataType *type1 = p1->content.decoded.type; |
| 8563 | const UA_DataType *type2 = p2->content.decoded.type; |
| 8564 | if(type1 != type2) |
| 8565 | return ((uintptr_t)type1 < (uintptr_t)type2) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8566 | if(!type1) |
| 8567 | return UA_ORDER_EQ; |
| 8568 | return orderJumpTable[type1->typeKind] |
| 8569 | (p1->content.decoded.data, p2->content.decoded.data, type1); |
| 8570 | } |
| 8571 | } |
| 8572 | } |
| 8573 | |
| 8574 | /* Part 4: When testing for equality, a Server shall treat null and empty arrays |
| 8575 | * as equal. |
| 8576 | * |
| 8577 | * Don't compare overlayable types as "binary blobs". We have specific order |
| 8578 | * rules also for some overlayable types. For example how NaN floats are |
| 8579 | * compared. */ |
| 8580 | static UA_Order |
| 8581 | arrayOrder(const void *p1, size_t p1Length, |
| 8582 | const void *p2, size_t p2Length, |
| 8583 | const UA_DataType *type) { |
| 8584 | if(p1Length != p2Length) |
| 8585 | return (p1Length < p2Length) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8586 | uintptr_t u1 = (uintptr_t)p1; |
| 8587 | uintptr_t u2 = (uintptr_t)p2; |
| 8588 | for(size_t i = 0; i < p1Length; i++) { |
| 8589 | UA_Order o = orderJumpTable[type->typeKind]((const void*)u1, (const void*)u2, type); |
| 8590 | if(o != UA_ORDER_EQ) |
| 8591 | return o; |
| 8592 | u1 += type->memSize; |
| 8593 | u2 += type->memSize; |
| 8594 | } |
| 8595 | return UA_ORDER_EQ; |
| 8596 | } |
| 8597 | |
| 8598 | static UA_Order |
| 8599 | variantOrder(const UA_Variant *p1, const UA_Variant *p2, const UA_DataType *_) { |
| 8600 | if(p1->type != p2->type) |
| 8601 | return ((uintptr_t)p1->type < (uintptr_t)p2->type) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8602 | |
| 8603 | UA_Order o; |
| 8604 | if(p1->type != NULL) { |
| 8605 | /* Check if both variants are scalars or arrays */ |
| 8606 | UA_Boolean s1 = UA_Variant_isScalar(v: p1); |
| 8607 | UA_Boolean s2 = UA_Variant_isScalar(v: p2); |
| 8608 | if(s1 != s2) |
| 8609 | return s1 ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8610 | if(s1) { |
| 8611 | o = orderJumpTable[p1->type->typeKind](p1->data, p2->data, p1->type); |
| 8612 | } else { |
| 8613 | /* Mismatching array length? */ |
| 8614 | if(p1->arrayLength != p2->arrayLength) |
| 8615 | return (p1->arrayLength < p2->arrayLength) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8616 | o = arrayOrder(p1: p1->data, p1Length: p1->arrayLength, p2: p2->data, p2Length: p2->arrayLength, type: p1->type); |
| 8617 | } |
| 8618 | if(o != UA_ORDER_EQ) |
| 8619 | return o; |
| 8620 | } |
| 8621 | |
| 8622 | if(p1->arrayDimensionsSize != p2->arrayDimensionsSize) |
| 8623 | return (p1->arrayDimensionsSize < p2->arrayDimensionsSize) ? |
| 8624 | UA_ORDER_LESS : UA_ORDER_MORE; |
| 8625 | o = UA_ORDER_EQ; |
| 8626 | if(p1->arrayDimensionsSize > 0) |
| 8627 | o = arrayOrder(p1: p1->arrayDimensions, p1Length: p1->arrayDimensionsSize, |
| 8628 | p2: p2->arrayDimensions, p2Length: p2->arrayDimensionsSize, |
| 8629 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 8630 | return o; |
| 8631 | } |
| 8632 | |
| 8633 | static UA_Order |
| 8634 | dataValueOrder(const UA_DataValue *p1, const UA_DataValue *p2, const UA_DataType *_) { |
| 8635 | /* Value */ |
| 8636 | if(p1->hasValue != p2->hasValue) |
| 8637 | return (!p1->hasValue) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8638 | if(p1->hasValue) { |
| 8639 | UA_Order o = variantOrder(p1: &p1->value, p2: &p2->value, NULL); |
| 8640 | if(o != UA_ORDER_EQ) |
| 8641 | return o; |
| 8642 | } |
| 8643 | |
| 8644 | /* Status */ |
| 8645 | if(p1->hasStatus != p2->hasStatus) |
| 8646 | return (!p1->hasStatus) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8647 | if(p1->hasStatus && p1->status != p2->status) |
| 8648 | return (p1->status < p2->status) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8649 | |
| 8650 | /* SourceTimestamp */ |
| 8651 | if(p1->hasSourceTimestamp != p2->hasSourceTimestamp) |
| 8652 | return (!p1->hasSourceTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8653 | if(p1->hasSourceTimestamp && p1->sourceTimestamp != p2->sourceTimestamp) |
| 8654 | return (p1->sourceTimestamp < p2->sourceTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8655 | |
| 8656 | /* ServerTimestamp */ |
| 8657 | if(p1->hasServerTimestamp != p2->hasServerTimestamp) |
| 8658 | return (!p1->hasServerTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8659 | if(p1->hasServerTimestamp && p1->serverTimestamp != p2->serverTimestamp) |
| 8660 | return (p1->serverTimestamp < p2->serverTimestamp) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8661 | |
| 8662 | /* SourcePicoseconds */ |
| 8663 | if(p1->hasSourcePicoseconds != p2->hasSourcePicoseconds) |
| 8664 | return (!p1->hasSourcePicoseconds) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8665 | if(p1->hasSourcePicoseconds && p1->sourcePicoseconds != p2->sourcePicoseconds) |
| 8666 | return (p1->sourcePicoseconds < p2->sourcePicoseconds) ? |
| 8667 | UA_ORDER_LESS : UA_ORDER_MORE; |
| 8668 | |
| 8669 | /* ServerPicoseconds */ |
| 8670 | if(p1->hasServerPicoseconds != p2->hasServerPicoseconds) |
| 8671 | return (!p1->hasServerPicoseconds) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8672 | if(p1->hasServerPicoseconds && p1->serverPicoseconds != p2->serverPicoseconds) |
| 8673 | return (p1->serverPicoseconds < p2->serverPicoseconds) ? |
| 8674 | UA_ORDER_LESS : UA_ORDER_MORE; |
| 8675 | |
| 8676 | return UA_ORDER_EQ; |
| 8677 | } |
| 8678 | |
| 8679 | static UA_Order |
| 8680 | diagnosticInfoOrder(const UA_DiagnosticInfo *p1, const UA_DiagnosticInfo *p2, |
| 8681 | const UA_DataType *_) { |
| 8682 | /* SymbolicId */ |
| 8683 | if(p1->hasSymbolicId != p2->hasSymbolicId) |
| 8684 | return (!p1->hasSymbolicId) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8685 | if(p1->hasSymbolicId && p1->symbolicId != p2->symbolicId) |
| 8686 | return (p1->symbolicId < p2->symbolicId) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8687 | |
| 8688 | /* NamespaceUri */ |
| 8689 | if(p1->hasNamespaceUri != p2->hasNamespaceUri) |
| 8690 | return (!p1->hasNamespaceUri) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8691 | if(p1->hasNamespaceUri && p1->namespaceUri != p2->namespaceUri) |
| 8692 | return (p1->namespaceUri < p2->namespaceUri) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8693 | |
| 8694 | /* LocalizedText */ |
| 8695 | if(p1->hasLocalizedText != p2->hasLocalizedText) |
| 8696 | return (!p1->hasLocalizedText) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8697 | if(p1->hasLocalizedText && p1->localizedText != p2->localizedText) |
| 8698 | return (p1->localizedText < p2->localizedText) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8699 | |
| 8700 | /* Locale */ |
| 8701 | if(p1->hasLocale != p2->hasLocale) |
| 8702 | return (!p1->hasLocale) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8703 | if(p1->hasLocale && p1->locale != p2->locale) |
| 8704 | return (p1->locale < p2->locale) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8705 | |
| 8706 | /* AdditionalInfo */ |
| 8707 | if(p1->hasAdditionalInfo != p2->hasAdditionalInfo) |
| 8708 | return (!p1->hasAdditionalInfo) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8709 | if(p1->hasAdditionalInfo) { |
| 8710 | UA_Order o = stringOrder(p1: &p1->additionalInfo, p2: &p2->additionalInfo, NULL); |
| 8711 | if(o != UA_ORDER_EQ) |
| 8712 | return o; |
| 8713 | } |
| 8714 | |
| 8715 | /* InnerStatusCode */ |
| 8716 | if(p1->hasInnerStatusCode != p2->hasInnerStatusCode) |
| 8717 | return (!p1->hasInnerStatusCode) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8718 | if(p1->hasInnerStatusCode && p1->innerStatusCode != p2->innerStatusCode) |
| 8719 | return (p1->innerStatusCode < p2->innerStatusCode) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8720 | |
| 8721 | /* InnerDiagnosticInfo */ |
| 8722 | if(p1->hasInnerDiagnosticInfo != p2->hasInnerDiagnosticInfo) |
| 8723 | return (!p1->hasInnerDiagnosticInfo) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8724 | if(p1->innerDiagnosticInfo == p2->innerDiagnosticInfo) |
| 8725 | return UA_ORDER_EQ; |
| 8726 | if(!p1->innerDiagnosticInfo || !p2->innerDiagnosticInfo) |
| 8727 | return (!p1->innerDiagnosticInfo) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8728 | return diagnosticInfoOrder(p1: p1->innerDiagnosticInfo, p2: p2->innerDiagnosticInfo, NULL); |
| 8729 | } |
| 8730 | |
| 8731 | static UA_Order |
| 8732 | structureOrder(const void *p1, const void *p2, const UA_DataType *type) { |
| 8733 | uintptr_t u1 = (uintptr_t)p1; |
| 8734 | uintptr_t u2 = (uintptr_t)p2; |
| 8735 | UA_Order o = UA_ORDER_EQ; |
| 8736 | for(size_t i = 0; i < type->membersSize; ++i) { |
| 8737 | const UA_DataTypeMember *m = &type->members[i]; |
| 8738 | const UA_DataType *mt = m->memberType; |
| 8739 | u1 += m->padding; |
| 8740 | u2 += m->padding; |
| 8741 | if(!m->isOptional) { |
| 8742 | if(!m->isArray) { |
| 8743 | o = orderJumpTable[mt->typeKind]((const void *)u1, (const void *)u2, mt); |
| 8744 | u1 += mt->memSize; |
| 8745 | u2 += mt->memSize; |
| 8746 | } else { |
| 8747 | size_t size1 = *(size_t*)u1; |
| 8748 | size_t size2 = *(size_t*)u2; |
| 8749 | u1 += sizeof(size_t); |
| 8750 | u2 += sizeof(size_t); |
| 8751 | o = arrayOrder(p1: *(void* const*)u1, p1Length: size1, p2: *(void* const*)u2, p2Length: size2, type: mt); |
| 8752 | u1 += sizeof(void*); |
| 8753 | u2 += sizeof(void*); |
| 8754 | } |
| 8755 | } else { |
| 8756 | if(!m->isArray) { |
| 8757 | const void *pp1 = *(void* const*)u1; |
| 8758 | const void *pp2 = *(void* const*)u2; |
| 8759 | if(pp1 == pp2) { |
| 8760 | o = UA_ORDER_EQ; |
| 8761 | } else if(pp1 == NULL) { |
| 8762 | o = UA_ORDER_LESS; |
| 8763 | } else if(pp2 == NULL) { |
| 8764 | o = UA_ORDER_MORE; |
| 8765 | } else { |
| 8766 | o = orderJumpTable[mt->typeKind](pp1, pp2, mt); |
| 8767 | } |
| 8768 | } else { |
| 8769 | size_t sa1 = *(size_t*)u1; |
| 8770 | size_t sa2 = *(size_t*)u2; |
| 8771 | u1 += sizeof(size_t); |
| 8772 | u2 += sizeof(size_t); |
| 8773 | o = arrayOrder(p1: *(void* const*)u1, p1Length: sa1, p2: *(void* const*)u2, p2Length: sa2, type: mt); |
| 8774 | } |
| 8775 | u1 += sizeof(void*); |
| 8776 | u2 += sizeof(void*); |
| 8777 | } |
| 8778 | |
| 8779 | if(o != UA_ORDER_EQ) |
| 8780 | break; |
| 8781 | } |
| 8782 | return o; |
| 8783 | } |
| 8784 | |
| 8785 | static UA_Order |
| 8786 | unionOrder(const void *p1, const void *p2, const UA_DataType *type) { |
| 8787 | UA_UInt32 sel1 = *(const UA_UInt32 *)p1; |
| 8788 | UA_UInt32 sel2 = *(const UA_UInt32 *)p2; |
| 8789 | if(sel1 != sel2) |
| 8790 | return (sel1 < sel2) ? UA_ORDER_LESS : UA_ORDER_MORE; |
| 8791 | |
| 8792 | if(sel1 == 0) { |
| 8793 | return UA_ORDER_EQ; |
| 8794 | } |
| 8795 | |
| 8796 | const UA_DataTypeMember *m = &type->members[sel1-1]; |
| 8797 | const UA_DataType *mt = m->memberType; |
| 8798 | |
| 8799 | uintptr_t u1 = ((uintptr_t)p1) + m->padding; /* includes switchfield length */ |
| 8800 | uintptr_t u2 = ((uintptr_t)p2) + m->padding; |
| 8801 | if(m->isArray) { |
| 8802 | size_t sa1 = *(size_t*)u1; |
| 8803 | size_t sa2 = *(size_t*)u2; |
| 8804 | u1 += sizeof(size_t); |
| 8805 | u2 += sizeof(size_t); |
| 8806 | return arrayOrder(p1: *(void* const*)u1, p1Length: sa1, p2: *(void* const*)u2, p2Length: sa2, type: mt); |
| 8807 | } |
| 8808 | return orderJumpTable[mt->typeKind]((const void*)u1, (const void*)u2, mt); |
| 8809 | } |
| 8810 | |
| 8811 | static UA_Order |
| 8812 | notImplementedOrder(const void *p1, const void *p2, const UA_DataType *type) { |
| 8813 | return UA_ORDER_EQ; |
| 8814 | } |
| 8815 | |
| 8816 | const |
| 8817 | UA_orderSignature orderJumpTable[UA_DATATYPEKINDS] = { |
| 8818 | (UA_orderSignature)booleanOrder, |
| 8819 | (UA_orderSignature)sByteOrder, |
| 8820 | (UA_orderSignature)byteOrder, |
| 8821 | (UA_orderSignature)int16Order, |
| 8822 | (UA_orderSignature)uInt16Order, |
| 8823 | (UA_orderSignature)int32Order, |
| 8824 | (UA_orderSignature)uInt32Order, |
| 8825 | (UA_orderSignature)int64Order, |
| 8826 | (UA_orderSignature)uInt64Order, |
| 8827 | (UA_orderSignature)floatOrder, |
| 8828 | (UA_orderSignature)doubleOrder, |
| 8829 | (UA_orderSignature)stringOrder, |
| 8830 | (UA_orderSignature)int64Order, /* DateTime */ |
| 8831 | (UA_orderSignature)guidOrder, |
| 8832 | (UA_orderSignature)stringOrder, /* ByteString */ |
| 8833 | (UA_orderSignature)stringOrder, /* XmlElement */ |
| 8834 | (UA_orderSignature)nodeIdOrder, |
| 8835 | (UA_orderSignature)expandedNodeIdOrder, |
| 8836 | (UA_orderSignature)uInt32Order, /* StatusCode */ |
| 8837 | (UA_orderSignature)qualifiedNameOrder, |
| 8838 | (UA_orderSignature)localizedTextOrder, |
| 8839 | (UA_orderSignature)extensionObjectOrder, |
| 8840 | (UA_orderSignature)dataValueOrder, |
| 8841 | (UA_orderSignature)variantOrder, |
| 8842 | (UA_orderSignature)diagnosticInfoOrder, |
| 8843 | notImplementedOrder, /* Decimal, not implemented */ |
| 8844 | (UA_orderSignature)uInt32Order, /* Enumeration */ |
| 8845 | (UA_orderSignature)structureOrder, |
| 8846 | (UA_orderSignature)structureOrder, /* Struct with Optional Fields*/ |
| 8847 | (UA_orderSignature)unionOrder, /* Union*/ |
| 8848 | notImplementedOrder /* BitfieldCluster, not implemented */ |
| 8849 | }; |
| 8850 | |
| 8851 | UA_Order UA_order(const void *p1, const void *p2, const UA_DataType *type) { |
| 8852 | return orderJumpTable[type->typeKind](p1, p2, type); |
| 8853 | } |
| 8854 | |
| 8855 | /******************/ |
| 8856 | /* Array Handling */ |
| 8857 | /******************/ |
| 8858 | |
| 8859 | void * |
| 8860 | UA_Array_new(size_t size, const UA_DataType *type) { |
| 8861 | if(size > UA_INT32_MAX) |
| 8862 | return NULL; |
| 8863 | if(size == 0) |
| 8864 | return UA_EMPTY_ARRAY_SENTINEL; |
| 8865 | return UA_calloc(nmemb: size, size: type->memSize); |
| 8866 | } |
| 8867 | |
| 8868 | UA_StatusCode |
| 8869 | UA_Array_copy(const void *src, size_t size, |
| 8870 | void **dst, const UA_DataType *type) { |
| 8871 | if(size == 0) { |
| 8872 | if(src == NULL) |
| 8873 | *dst = NULL; |
| 8874 | else |
| 8875 | *dst= UA_EMPTY_ARRAY_SENTINEL; |
| 8876 | return UA_STATUSCODE_GOOD; |
| 8877 | } |
| 8878 | |
| 8879 | /* Check the array consistency -- defensive programming in case the user |
| 8880 | * manually created an inconsistent array */ |
| 8881 | if(UA_UNLIKELY(!type || !src)) |
| 8882 | return UA_STATUSCODE_BADINTERNALERROR; |
| 8883 | |
| 8884 | /* calloc, so we don't have to check retval in every iteration of copying */ |
| 8885 | *dst = UA_calloc(nmemb: size, size: type->memSize); |
| 8886 | if(!*dst) |
| 8887 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 8888 | |
| 8889 | if(type->pointerFree) { |
| 8890 | memcpy(dest: *dst, src: src, n: type->memSize * size); |
| 8891 | return UA_STATUSCODE_GOOD; |
| 8892 | } |
| 8893 | |
| 8894 | uintptr_t ptrs = (uintptr_t)src; |
| 8895 | uintptr_t ptrd = (uintptr_t)*dst; |
| 8896 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 8897 | for(size_t i = 0; i < size; ++i) { |
| 8898 | retval |= UA_copy(src: (void*)ptrs, dst: (void*)ptrd, type); |
| 8899 | ptrs += type->memSize; |
| 8900 | ptrd += type->memSize; |
| 8901 | } |
| 8902 | if(retval != UA_STATUSCODE_GOOD) { |
| 8903 | UA_Array_delete(p: *dst, size, type); |
| 8904 | *dst = NULL; |
| 8905 | } |
| 8906 | return retval; |
| 8907 | } |
| 8908 | |
| 8909 | UA_StatusCode |
| 8910 | UA_Array_resize(void **p, size_t *size, size_t newSize, |
| 8911 | const UA_DataType *type) { |
| 8912 | if(*size == newSize) |
| 8913 | return UA_STATUSCODE_GOOD; |
| 8914 | |
| 8915 | /* Empty array? */ |
| 8916 | if(newSize == 0) { |
| 8917 | UA_Array_delete(p: *p, size: *size, type); |
| 8918 | *p = UA_EMPTY_ARRAY_SENTINEL; |
| 8919 | *size = 0; |
| 8920 | return UA_STATUSCODE_GOOD; |
| 8921 | } |
| 8922 | |
| 8923 | /* Make a copy of the members that shall be removed. Realloc can fail during |
| 8924 | * trimming. So we cannot clear the members already here. */ |
| 8925 | void *deleteMembers = NULL; |
| 8926 | if(newSize < *size && !type->pointerFree) { |
| 8927 | size_t deleteSize = *size - newSize; |
| 8928 | deleteMembers = UA_malloc(size: deleteSize * type->memSize); |
| 8929 | if(!deleteMembers) |
| 8930 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 8931 | memcpy(dest: deleteMembers, src: (void*)((uintptr_t)*p + (newSize * type->memSize)), |
| 8932 | n: deleteSize * type->memSize); /* shallow copy */ |
| 8933 | } |
| 8934 | |
| 8935 | void *oldP = *p; |
| 8936 | if(oldP == UA_EMPTY_ARRAY_SENTINEL) |
| 8937 | oldP = NULL; |
| 8938 | |
| 8939 | /* Realloc */ |
| 8940 | void *newP = UA_realloc(ptr: oldP, size: newSize * type->memSize); |
| 8941 | if(!newP) { |
| 8942 | if(deleteMembers) |
| 8943 | UA_free(ptr: deleteMembers); |
| 8944 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 8945 | } |
| 8946 | |
| 8947 | /* Clear removed members or initialize the new ones. Note that deleteMembers |
| 8948 | * depends on type->pointerFree. */ |
| 8949 | if(newSize > *size) |
| 8950 | memset(s: (void*)((uintptr_t)newP + (*size * type->memSize)), c: 0, |
| 8951 | n: (newSize - *size) * type->memSize); |
| 8952 | else if(deleteMembers) |
| 8953 | UA_Array_delete(p: deleteMembers, size: *size - newSize, type); |
| 8954 | |
| 8955 | /* Set the new array */ |
| 8956 | *p = newP; |
| 8957 | *size = newSize; |
| 8958 | return UA_STATUSCODE_GOOD; |
| 8959 | } |
| 8960 | |
| 8961 | UA_StatusCode |
| 8962 | UA_Array_append(void **p, size_t *size, void *newElem, |
| 8963 | const UA_DataType *type) { |
| 8964 | /* Resize the array */ |
| 8965 | size_t oldSize = *size; |
| 8966 | UA_StatusCode res = UA_Array_resize(p, size, newSize: oldSize+1, type); |
| 8967 | if(res != UA_STATUSCODE_GOOD) |
| 8968 | return res; |
| 8969 | |
| 8970 | /* Move the value */ |
| 8971 | memcpy(dest: (void*)((uintptr_t)*p + (oldSize * type->memSize)), |
| 8972 | src: newElem, n: type->memSize); |
| 8973 | UA_init(p: newElem, type); |
| 8974 | return UA_STATUSCODE_GOOD; |
| 8975 | } |
| 8976 | |
| 8977 | UA_StatusCode |
| 8978 | UA_Array_appendCopy(void **p, size_t *size, const void *newElem, |
| 8979 | const UA_DataType *type) { |
| 8980 | char scratch[512]; |
| 8981 | if(type->memSize > 512) |
| 8982 | return UA_STATUSCODE_BADINTERNALERROR; |
| 8983 | |
| 8984 | /* Copy the value */ |
| 8985 | UA_StatusCode res = UA_copy(src: newElem, dst: (void*)scratch, type); |
| 8986 | if(res != UA_STATUSCODE_GOOD) |
| 8987 | return res; |
| 8988 | |
| 8989 | /* Append */ |
| 8990 | res = UA_Array_append(p, size, newElem: (void*)scratch, type); |
| 8991 | if(res != UA_STATUSCODE_GOOD) |
| 8992 | UA_clear(p: (void*)scratch, type); |
| 8993 | return res; |
| 8994 | } |
| 8995 | |
| 8996 | void |
| 8997 | UA_Array_delete(void *p, size_t size, const UA_DataType *type) { |
| 8998 | if(!type->pointerFree) { |
| 8999 | uintptr_t ptr = (uintptr_t)p; |
| 9000 | for(size_t i = 0; i < size; ++i) { |
| 9001 | UA_clear(p: (void*)ptr, type); |
| 9002 | ptr += type->memSize; |
| 9003 | } |
| 9004 | } |
| 9005 | UA_free(ptr: (void*)((uintptr_t)p & ~(uintptr_t)UA_EMPTY_ARRAY_SENTINEL)); |
| 9006 | } |
| 9007 | |
| 9008 | #ifdef UA_ENABLE_TYPEDESCRIPTION |
| 9009 | UA_Boolean |
| 9010 | UA_DataType_getStructMember(const UA_DataType *type, const char *memberName, |
| 9011 | size_t *outOffset, const UA_DataType **outMemberType, |
| 9012 | UA_Boolean *outIsArray) { |
| 9013 | if(type->typeKind != UA_DATATYPEKIND_STRUCTURE && |
| 9014 | type->typeKind != UA_DATATYPEKIND_OPTSTRUCT) |
| 9015 | return false; |
| 9016 | |
| 9017 | size_t offset = 0; |
| 9018 | for(size_t i = 0; i < type->membersSize; ++i) { |
| 9019 | const UA_DataTypeMember *m = &type->members[i]; |
| 9020 | const UA_DataType *mt = m->memberType; |
| 9021 | offset += m->padding; |
| 9022 | |
| 9023 | if(strcmp(s1: memberName, s2: m->memberName) == 0) { |
| 9024 | *outOffset = offset; |
| 9025 | *outMemberType = mt; |
| 9026 | *outIsArray = m->isArray; |
| 9027 | return true; |
| 9028 | } |
| 9029 | |
| 9030 | if(!m->isOptional) { |
| 9031 | if(!m->isArray) { |
| 9032 | offset += mt->memSize; |
| 9033 | } else { |
| 9034 | offset += sizeof(size_t); |
| 9035 | offset += sizeof(void*); |
| 9036 | } |
| 9037 | } else { /* field is optional */ |
| 9038 | if(!m->isArray) { |
| 9039 | offset += sizeof(void *); |
| 9040 | } else { |
| 9041 | offset += sizeof(size_t); |
| 9042 | offset += sizeof(void *); |
| 9043 | } |
| 9044 | } |
| 9045 | } |
| 9046 | |
| 9047 | return false; |
| 9048 | } |
| 9049 | #endif |
| 9050 | |
| 9051 | UA_Boolean |
| 9052 | UA_DataType_isNumeric(const UA_DataType *type) { |
| 9053 | switch(type->typeKind) { |
| 9054 | case UA_DATATYPEKIND_SBYTE: |
| 9055 | case UA_DATATYPEKIND_BYTE: |
| 9056 | case UA_DATATYPEKIND_INT16: |
| 9057 | case UA_DATATYPEKIND_UINT16: |
| 9058 | case UA_DATATYPEKIND_INT32: |
| 9059 | case UA_DATATYPEKIND_UINT32: |
| 9060 | case UA_DATATYPEKIND_INT64: |
| 9061 | case UA_DATATYPEKIND_UINT64: |
| 9062 | case UA_DATATYPEKIND_FLOAT: |
| 9063 | case UA_DATATYPEKIND_DOUBLE: |
| 9064 | /* not implemented: UA_DATATYPEKIND_DECIMAL */ |
| 9065 | return true; |
| 9066 | default: |
| 9067 | return false; |
| 9068 | } |
| 9069 | } |
| 9070 | |
| 9071 | /**********************/ |
| 9072 | /* Parse NumericRange */ |
| 9073 | /**********************/ |
| 9074 | |
| 9075 | static size_t |
| 9076 | readDimension(UA_Byte *buf, size_t buflen, UA_NumericRangeDimension *dim) { |
| 9077 | size_t progress = UA_readNumber(buf, buflen, number: &dim->min); |
| 9078 | if(progress == 0) |
| 9079 | return 0; |
| 9080 | if(buflen <= progress + 1 || buf[progress] != ':') { |
| 9081 | dim->max = dim->min; |
| 9082 | return progress; |
| 9083 | } |
| 9084 | |
| 9085 | ++progress; |
| 9086 | size_t progress2 = UA_readNumber(buf: &buf[progress], buflen: buflen - progress, number: &dim->max); |
| 9087 | if(progress2 == 0) |
| 9088 | return 0; |
| 9089 | |
| 9090 | /* invalid range */ |
| 9091 | if(dim->min >= dim->max) |
| 9092 | return 0; |
| 9093 | |
| 9094 | return progress + progress2; |
| 9095 | } |
| 9096 | |
| 9097 | UA_StatusCode |
| 9098 | UA_NumericRange_parse(UA_NumericRange *range, const UA_String str) { |
| 9099 | size_t idx = 0; |
| 9100 | size_t dimensionsMax = 0; |
| 9101 | UA_NumericRangeDimension *dimensions = NULL; |
| 9102 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 9103 | size_t offset = 0; |
| 9104 | while(true) { |
| 9105 | /* alloc dimensions */ |
| 9106 | if(idx >= dimensionsMax) { |
| 9107 | UA_NumericRangeDimension *newds; |
| 9108 | size_t newdssize = sizeof(UA_NumericRangeDimension) * (dimensionsMax + 2); |
| 9109 | newds = (UA_NumericRangeDimension*)UA_realloc(ptr: dimensions, size: newdssize); |
| 9110 | if(!newds) { |
| 9111 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 9112 | break; |
| 9113 | } |
| 9114 | dimensions = newds; |
| 9115 | dimensionsMax = dimensionsMax + 2; |
| 9116 | } |
| 9117 | |
| 9118 | /* read the dimension */ |
| 9119 | size_t progress = readDimension(buf: &str.data[offset], buflen: str.length - offset, |
| 9120 | dim: &dimensions[idx]); |
| 9121 | if(progress == 0) { |
| 9122 | retval = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 9123 | break; |
| 9124 | } |
| 9125 | offset += progress; |
| 9126 | ++idx; |
| 9127 | |
| 9128 | /* loop into the next dimension */ |
| 9129 | if(offset >= str.length) |
| 9130 | break; |
| 9131 | |
| 9132 | if(str.data[offset] != ',') { |
| 9133 | retval = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 9134 | break; |
| 9135 | } |
| 9136 | ++offset; |
| 9137 | } |
| 9138 | |
| 9139 | if(retval == UA_STATUSCODE_GOOD && idx > 0) { |
| 9140 | range->dimensions = dimensions; |
| 9141 | range->dimensionsSize = idx; |
| 9142 | } else { |
| 9143 | UA_free(ptr: dimensions); |
| 9144 | } |
| 9145 | |
| 9146 | return retval; |
| 9147 | } |
| 9148 | |
| 9149 | /**** amalgamated original file "/src/ua_types_encoding_binary.c" ****/ |
| 9150 | |
| 9151 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 9152 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 9153 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 9154 | * |
| 9155 | * Copyright 2020 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
| 9156 | * Copyright 2020 (c) Grigory Friedman |
| 9157 | * Copyright 2014-2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 9158 | * Copyright 2014-2017 (c) Florian Palm |
| 9159 | * Copyright 2014-2016 (c) Sten Grüner |
| 9160 | * Copyright 2014 (c) Leon Urbas |
| 9161 | * Copyright 2015 (c) LEvertz |
| 9162 | * Copyright 2015 (c) Chris Iatrou |
| 9163 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 9164 | * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH |
| 9165 | * Copyright 2016 (c) Lorenz Haas |
| 9166 | * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB |
| 9167 | * Copyright 2017 (c) Henrik Norrman |
| 9168 | */ |
| 9169 | |
| 9170 | |
| 9171 | |
| 9172 | /** |
| 9173 | * Type Encoding and Decoding |
| 9174 | * -------------------------- |
| 9175 | * The following methods contain encoding and decoding functions for the builtin |
| 9176 | * data types and generic functions that operate on all types and arrays. This |
| 9177 | * requires the type description from a UA_DataType structure. |
| 9178 | * |
| 9179 | * Breaking a message up into chunks is integrated with the encoding. When the |
| 9180 | * end of a buffer is reached, a callback is executed that sends the current |
| 9181 | * buffer as a chunk and exchanges the encoding buffer "underneath" the ongoing |
| 9182 | * encoding. This reduces the RAM requirements and unnecessary copying. */ |
| 9183 | |
| 9184 | /* Part 6 §5.1.5: Decoders shall support at least 100 nesting levels */ |
| 9185 | #define UA_ENCODING_MAX_RECURSION 100 |
| 9186 | |
| 9187 | typedef struct { |
| 9188 | /* Pointers to the current and last buffer position */ |
| 9189 | u8 *pos; |
| 9190 | const u8 *end; |
| 9191 | |
| 9192 | /* How often did we en-/decoding recurse? */ |
| 9193 | u16 depth; |
| 9194 | |
| 9195 | const UA_DataTypeArray *customTypes; |
| 9196 | UA_exchangeEncodeBuffer exchangeBufferCallback; |
| 9197 | void *exchangeBufferCallbackHandle; |
| 9198 | } Ctx; |
| 9199 | |
| 9200 | typedef status |
| 9201 | (*encodeBinarySignature)(const void *UA_RESTRICT src, const UA_DataType *type, |
| 9202 | Ctx *UA_RESTRICT ctx); |
| 9203 | typedef status |
| 9204 | (*decodeBinarySignature)(void *UA_RESTRICT dst, const UA_DataType *type, |
| 9205 | Ctx *UA_RESTRICT ctx); |
| 9206 | typedef size_t |
| 9207 | (*calcSizeBinarySignature)(const void *UA_RESTRICT p, const UA_DataType *type); |
| 9208 | |
| 9209 | #define ENCODE_BINARY(TYPE) static status \ |
| 9210 | TYPE##_encodeBinary(const UA_##TYPE *UA_RESTRICT src, \ |
| 9211 | const UA_DataType *type, Ctx *UA_RESTRICT ctx) |
| 9212 | #define DECODE_BINARY(TYPE) static status \ |
| 9213 | TYPE##_decodeBinary(UA_##TYPE *UA_RESTRICT dst, \ |
| 9214 | const UA_DataType *type, Ctx *UA_RESTRICT ctx) |
| 9215 | #define CALCSIZE_BINARY(TYPE) static size_t \ |
| 9216 | TYPE##_calcSizeBinary(const UA_##TYPE *UA_RESTRICT src, const UA_DataType *_) |
| 9217 | #define ENCODE_DIRECT(SRC, TYPE) TYPE##_encodeBinary((const UA_##TYPE*)SRC, NULL, ctx) |
| 9218 | #define DECODE_DIRECT(DST, TYPE) TYPE##_decodeBinary((UA_##TYPE*)DST, NULL, ctx) |
| 9219 | |
| 9220 | /* Jumptables for de-/encoding and computing the buffer length. The methods in |
| 9221 | * the decoding jumptable do not all clean up their allocated memory when an |
| 9222 | * error occurs. So a final _clear needs to be called before returning to the |
| 9223 | * user. */ |
| 9224 | extern const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS]; |
| 9225 | extern const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS]; |
| 9226 | extern const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_DATATYPEKINDS]; |
| 9227 | |
| 9228 | /* Send the current chunk and replace the buffer */ |
| 9229 | static status exchangeBuffer(Ctx *ctx) { |
| 9230 | if(!ctx->exchangeBufferCallback) |
| 9231 | return UA_STATUSCODE_BADENCODINGERROR; |
| 9232 | return ctx->exchangeBufferCallback(ctx->exchangeBufferCallbackHandle, |
| 9233 | &ctx->pos, &ctx->end); |
| 9234 | } |
| 9235 | |
| 9236 | /* If encoding fails, exchange the buffer and try again. */ |
| 9237 | static status |
| 9238 | encodeWithExchangeBuffer(const void *ptr, const UA_DataType *type, Ctx *ctx) { |
| 9239 | u8 *oldpos = ctx->pos; /* Last known good position */ |
| 9240 | #ifndef NDEBUG |
| 9241 | /* We have to ensure that the buffer was not exchanged AND |
| 9242 | * BADENCODINGLIMITSEXCEEDED was returned. If that were the case, oldpos |
| 9243 | * would be invalid. That means, a type encoding must never return |
| 9244 | * BADENCODINGLIMITSEXCEEDED once the buffer could have been exchanged. This |
| 9245 | * is achieved by the use of encodeWithExchangeBuffer. */ |
| 9246 | const u8 *oldend = ctx->end; |
| 9247 | (void)oldend; /* For compilers who don't understand NDEBUG... */ |
| 9248 | #endif |
| 9249 | status ret = encodeBinaryJumpTable[type->typeKind](ptr, type, ctx); |
| 9250 | if(ret == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED) { |
| 9251 | UA_assert(ctx->end == oldend); |
| 9252 | ctx->pos = oldpos; /* Set to the last known good position and exchange */ |
| 9253 | ret = exchangeBuffer(ctx); |
| 9254 | UA_CHECK_STATUS(ret, return ret); |
| 9255 | ret = encodeBinaryJumpTable[type->typeKind](ptr, type, ctx); |
| 9256 | } |
| 9257 | return ret; |
| 9258 | } |
| 9259 | |
| 9260 | /*****************/ |
| 9261 | /* Integer Types */ |
| 9262 | /*****************/ |
| 9263 | |
| 9264 | #if !UA_BINARY_OVERLAYABLE_INTEGER |
| 9265 | |
| 9266 | #pragma message "Integer endianness could not be detected to be little endian. Use slow generic encoding." |
| 9267 | |
| 9268 | /* These en/decoding functions are only used when the architecture isn't little-endian. */ |
| 9269 | static void |
| 9270 | UA_encode16(const u16 v, u8 buf[2]) { |
| 9271 | buf[0] = (u8)v; |
| 9272 | buf[1] = (u8)(v >> 8); |
| 9273 | } |
| 9274 | |
| 9275 | static void |
| 9276 | UA_decode16(const u8 buf[2], u16 *v) { |
| 9277 | *v = (u16)((u16)buf[0] + (((u16)buf[1]) << 8)); |
| 9278 | } |
| 9279 | |
| 9280 | static void |
| 9281 | UA_encode32(const u32 v, u8 buf[4]) { |
| 9282 | buf[0] = (u8)v; |
| 9283 | buf[1] = (u8)(v >> 8); |
| 9284 | buf[2] = (u8)(v >> 16); |
| 9285 | buf[3] = (u8)(v >> 24); |
| 9286 | } |
| 9287 | |
| 9288 | static void |
| 9289 | UA_decode32(const u8 buf[4], u32 *v) { |
| 9290 | *v = (u32)((u32)buf[0] + (((u32)buf[1]) << 8) + |
| 9291 | (((u32)buf[2]) << 16) + (((u32)buf[3]) << 24)); |
| 9292 | } |
| 9293 | |
| 9294 | static void |
| 9295 | UA_encode64(const u64 v, u8 buf[8]) { |
| 9296 | buf[0] = (u8)v; |
| 9297 | buf[1] = (u8)(v >> 8); |
| 9298 | buf[2] = (u8)(v >> 16); |
| 9299 | buf[3] = (u8)(v >> 24); |
| 9300 | buf[4] = (u8)(v >> 32); |
| 9301 | buf[5] = (u8)(v >> 40); |
| 9302 | buf[6] = (u8)(v >> 48); |
| 9303 | buf[7] = (u8)(v >> 56); |
| 9304 | } |
| 9305 | |
| 9306 | static void |
| 9307 | UA_decode64(const u8 buf[8], u64 *v) { |
| 9308 | *v = (u64)((u64)buf[0] + (((u64)buf[1]) << 8) + |
| 9309 | (((u64)buf[2]) << 16) + (((u64)buf[3]) << 24) + |
| 9310 | (((u64)buf[4]) << 32) + (((u64)buf[5]) << 40) + |
| 9311 | (((u64)buf[6]) << 48) + (((u64)buf[7]) << 56)); |
| 9312 | } |
| 9313 | |
| 9314 | #endif /* !UA_BINARY_OVERLAYABLE_INTEGER */ |
| 9315 | |
| 9316 | /* Boolean */ |
| 9317 | /* Note that sizeof(bool) != 1 on some platforms. Overlayable integer encoding |
| 9318 | * is disabled in those cases. */ |
| 9319 | ENCODE_BINARY(Boolean) { |
| 9320 | UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9321 | *ctx->pos = *(const u8*)src; |
| 9322 | ++ctx->pos; |
| 9323 | return UA_STATUSCODE_GOOD; |
| 9324 | } |
| 9325 | |
| 9326 | DECODE_BINARY(Boolean) { |
| 9327 | UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADDECODINGERROR); |
| 9328 | *dst = (*ctx->pos > 0) ? true : false; |
| 9329 | ++ctx->pos; |
| 9330 | return UA_STATUSCODE_GOOD; |
| 9331 | } |
| 9332 | |
| 9333 | /* Byte */ |
| 9334 | ENCODE_BINARY(Byte) { |
| 9335 | UA_CHECK(ctx->pos + sizeof(u8) <= ctx->end, |
| 9336 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9337 | *ctx->pos = *(const u8*)src; |
| 9338 | ++ctx->pos; |
| 9339 | return UA_STATUSCODE_GOOD; |
| 9340 | } |
| 9341 | |
| 9342 | DECODE_BINARY(Byte) { |
| 9343 | UA_CHECK(ctx->pos + sizeof(u8) <= ctx->end, |
| 9344 | return UA_STATUSCODE_BADDECODINGERROR); |
| 9345 | *dst = *ctx->pos; |
| 9346 | ++ctx->pos; |
| 9347 | return UA_STATUSCODE_GOOD; |
| 9348 | } |
| 9349 | |
| 9350 | /* UInt16 */ |
| 9351 | ENCODE_BINARY(UInt16) { |
| 9352 | UA_CHECK(ctx->pos + sizeof(u16) <= ctx->end, |
| 9353 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9354 | #if UA_BINARY_OVERLAYABLE_INTEGER |
| 9355 | memcpy(dest: ctx->pos, src: src, n: sizeof(u16)); |
| 9356 | #else |
| 9357 | UA_encode16(*src, ctx->pos); |
| 9358 | #endif |
| 9359 | ctx->pos += 2; |
| 9360 | return UA_STATUSCODE_GOOD; |
| 9361 | } |
| 9362 | |
| 9363 | DECODE_BINARY(UInt16) { |
| 9364 | UA_CHECK(ctx->pos + sizeof(u16) <= ctx->end, |
| 9365 | return UA_STATUSCODE_BADDECODINGERROR); |
| 9366 | #if UA_BINARY_OVERLAYABLE_INTEGER |
| 9367 | memcpy(dest: dst, src: ctx->pos, n: sizeof(u16)); |
| 9368 | #else |
| 9369 | UA_decode16(ctx->pos, dst); |
| 9370 | #endif |
| 9371 | ctx->pos += 2; |
| 9372 | return UA_STATUSCODE_GOOD; |
| 9373 | } |
| 9374 | |
| 9375 | /* UInt32 */ |
| 9376 | ENCODE_BINARY(UInt32) { |
| 9377 | UA_CHECK(ctx->pos + sizeof(u32) <= ctx->end, |
| 9378 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9379 | #if UA_BINARY_OVERLAYABLE_INTEGER |
| 9380 | memcpy(dest: ctx->pos, src: src, n: sizeof(u32)); |
| 9381 | #else |
| 9382 | UA_encode32(*src, ctx->pos); |
| 9383 | #endif |
| 9384 | ctx->pos += 4; |
| 9385 | return UA_STATUSCODE_GOOD; |
| 9386 | } |
| 9387 | |
| 9388 | DECODE_BINARY(UInt32) { |
| 9389 | UA_CHECK(ctx->pos + sizeof(u32) <= ctx->end, |
| 9390 | return UA_STATUSCODE_BADDECODINGERROR); |
| 9391 | #if UA_BINARY_OVERLAYABLE_INTEGER |
| 9392 | memcpy(dest: dst, src: ctx->pos, n: sizeof(u32)); |
| 9393 | #else |
| 9394 | UA_decode32(ctx->pos, dst); |
| 9395 | #endif |
| 9396 | ctx->pos += 4; |
| 9397 | return UA_STATUSCODE_GOOD; |
| 9398 | } |
| 9399 | |
| 9400 | /* UInt64 */ |
| 9401 | ENCODE_BINARY(UInt64) { |
| 9402 | UA_CHECK(ctx->pos + sizeof(u64) <= ctx->end, |
| 9403 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9404 | #if UA_BINARY_OVERLAYABLE_INTEGER |
| 9405 | memcpy(dest: ctx->pos, src: src, n: sizeof(u64)); |
| 9406 | #else |
| 9407 | UA_encode64(*src, ctx->pos); |
| 9408 | #endif |
| 9409 | ctx->pos += 8; |
| 9410 | return UA_STATUSCODE_GOOD; |
| 9411 | } |
| 9412 | |
| 9413 | DECODE_BINARY(UInt64) { |
| 9414 | UA_CHECK(ctx->pos + sizeof(u64) <= ctx->end, |
| 9415 | return UA_STATUSCODE_BADDECODINGERROR); |
| 9416 | #if UA_BINARY_OVERLAYABLE_INTEGER |
| 9417 | memcpy(dest: dst, src: ctx->pos, n: sizeof(u64)); |
| 9418 | #else |
| 9419 | UA_decode64(ctx->pos, dst); |
| 9420 | #endif |
| 9421 | ctx->pos += 8; |
| 9422 | return UA_STATUSCODE_GOOD; |
| 9423 | } |
| 9424 | |
| 9425 | /************************/ |
| 9426 | /* Floating Point Types */ |
| 9427 | /************************/ |
| 9428 | |
| 9429 | /* Can we reuse the integer encoding mechanism by casting floating point |
| 9430 | * values? */ |
| 9431 | #if (UA_FLOAT_IEEE754 == 1) && (UA_LITTLE_ENDIAN == UA_FLOAT_LITTLE_ENDIAN) |
| 9432 | # define Float_encodeBinary UInt32_encodeBinary |
| 9433 | # define Float_decodeBinary UInt32_decodeBinary |
| 9434 | # define Double_encodeBinary UInt64_encodeBinary |
| 9435 | # define Double_decodeBinary UInt64_decodeBinary |
| 9436 | #else |
| 9437 | |
| 9438 | #include <math.h> |
| 9439 | |
| 9440 | #pragma message "No native IEEE 754 format detected. Use slow generic encoding." |
| 9441 | |
| 9442 | /* Handling of IEEE754 floating point values was taken from Beej's Guide to |
| 9443 | * Network Programming (http://beej.us/guide/bgnet/) and enhanced to cover the |
| 9444 | * edge cases +/-0, +/-inf and nan. */ |
| 9445 | static uint64_t |
| 9446 | pack754(long double f, unsigned bits, unsigned expbits) { |
| 9447 | unsigned significandbits = bits - expbits - 1; |
| 9448 | long double fnorm; |
| 9449 | long long sign; |
| 9450 | if(f < 0) { sign = 1; fnorm = -f; } |
| 9451 | else { sign = 0; fnorm = f; } |
| 9452 | int shift = 0; |
| 9453 | while(fnorm >= 2.0) { fnorm /= 2.0; ++shift; } |
| 9454 | while(fnorm < 1.0) { fnorm *= 2.0; --shift; } |
| 9455 | fnorm = fnorm - 1.0; |
| 9456 | long long significand = (long long)(fnorm * ((float)(1LL<<significandbits) + 0.5f)); |
| 9457 | long long exponent = shift + ((1<<(expbits-1)) - 1); |
| 9458 | return (uint64_t)((sign<<(bits-1)) | (exponent<<(bits-expbits-1)) | significand); |
| 9459 | } |
| 9460 | |
| 9461 | static long double |
| 9462 | unpack754(uint64_t i, unsigned bits, unsigned expbits) { |
| 9463 | unsigned significandbits = bits - expbits - 1; |
| 9464 | long double result = (long double)(i&(uint64_t)((1LL<<significandbits)-1)); |
| 9465 | result /= (long double)(1LL<<significandbits); |
| 9466 | result += 1.0f; |
| 9467 | unsigned bias = (unsigned)(1<<(expbits-1)) - 1; |
| 9468 | long long shift = (long long)((i>>significandbits) & (uint64_t)((1LL<<expbits)-1)) - bias; |
| 9469 | while(shift > 0) { result *= 2.0; --shift; } |
| 9470 | while(shift < 0) { result /= 2.0; ++shift; } |
| 9471 | result *= ((i>>(bits-1))&1)? -1.0: 1.0; |
| 9472 | return result; |
| 9473 | } |
| 9474 | |
| 9475 | /* Float */ |
| 9476 | #define FLOAT_NAN 0xffc00000 |
| 9477 | #define FLOAT_INF 0x7f800000 |
| 9478 | #define FLOAT_NEG_INF 0xff800000 |
| 9479 | #define FLOAT_NEG_ZERO 0x80000000 |
| 9480 | |
| 9481 | ENCODE_BINARY(Float) { |
| 9482 | UA_Float f = *src; |
| 9483 | u32 encoded; |
| 9484 | /* cppcheck-suppress duplicateExpression */ |
| 9485 | if(f != f) encoded = FLOAT_NAN; |
| 9486 | else if(f == 0.0f) encoded = signbit(f) ? FLOAT_NEG_ZERO : 0; |
| 9487 | else if(f/f != f/f) encoded = f > 0 ? FLOAT_INF : FLOAT_NEG_INF; |
| 9488 | else encoded = (u32)pack754(f, 32, 8); |
| 9489 | return ENCODE_DIRECT(&encoded, UInt32); |
| 9490 | } |
| 9491 | |
| 9492 | DECODE_BINARY(Float) { |
| 9493 | u32 decoded; |
| 9494 | status ret = DECODE_DIRECT(&decoded, UInt32); |
| 9495 | if(ret != UA_STATUSCODE_GOOD) |
| 9496 | return ret; |
| 9497 | if(decoded == 0) *dst = 0.0f; |
| 9498 | else if(decoded == FLOAT_NEG_ZERO) *dst = -0.0f; |
| 9499 | else if(decoded == FLOAT_INF) *dst = INFINITY; |
| 9500 | else if(decoded == FLOAT_NEG_INF) *dst = -INFINITY; |
| 9501 | else if((decoded >= 0x7f800001 && decoded <= 0x7fffffff) || |
| 9502 | (decoded >= 0xff800001)) *dst = NAN; |
| 9503 | else *dst = (UA_Float)unpack754(decoded, 32, 8); |
| 9504 | return UA_STATUSCODE_GOOD; |
| 9505 | } |
| 9506 | |
| 9507 | /* Double */ |
| 9508 | #define DOUBLE_NAN 0xfff8000000000000L |
| 9509 | #define DOUBLE_INF 0x7ff0000000000000L |
| 9510 | #define DOUBLE_NEG_INF 0xfff0000000000000L |
| 9511 | #define DOUBLE_NEG_ZERO 0x8000000000000000L |
| 9512 | |
| 9513 | ENCODE_BINARY(Double) { |
| 9514 | UA_Double d = *src; |
| 9515 | u64 encoded; |
| 9516 | /* cppcheck-suppress duplicateExpression */ |
| 9517 | if(d != d) encoded = DOUBLE_NAN; |
| 9518 | else if(d == 0.0) encoded = signbit(d) ? DOUBLE_NEG_ZERO : 0; |
| 9519 | else if(d/d != d/d) encoded = d > 0 ? DOUBLE_INF : DOUBLE_NEG_INF; |
| 9520 | else encoded = pack754(d, 64, 11); |
| 9521 | return ENCODE_DIRECT(&encoded, UInt64); |
| 9522 | } |
| 9523 | |
| 9524 | DECODE_BINARY(Double) { |
| 9525 | u64 decoded; |
| 9526 | status ret = DECODE_DIRECT(&decoded, UInt64); |
| 9527 | UA_CHECK_STATUS(ret, return ret); |
| 9528 | if(decoded == 0) *dst = 0.0; |
| 9529 | else if(decoded == DOUBLE_NEG_ZERO) *dst = -0.0; |
| 9530 | else if(decoded == DOUBLE_INF) *dst = INFINITY; |
| 9531 | else if(decoded == DOUBLE_NEG_INF) *dst = -INFINITY; |
| 9532 | else if((decoded >= 0x7ff0000000000001L && decoded <= 0x7fffffffffffffffL) || |
| 9533 | (decoded >= 0xfff0000000000001L)) *dst = NAN; |
| 9534 | else *dst = (UA_Double)unpack754(decoded, 64, 11); |
| 9535 | return UA_STATUSCODE_GOOD; |
| 9536 | } |
| 9537 | |
| 9538 | #endif |
| 9539 | |
| 9540 | /******************/ |
| 9541 | /* Array Handling */ |
| 9542 | /******************/ |
| 9543 | |
| 9544 | static status |
| 9545 | Array_encodeBinaryOverlayable(uintptr_t ptr, size_t memSize, Ctx *ctx) { |
| 9546 | /* Loop as long as more elements remain than fit into the chunk */ |
| 9547 | while(ctx->end < ctx->pos + memSize) { |
| 9548 | size_t possible = ((uintptr_t)ctx->end - (uintptr_t)ctx->pos); |
| 9549 | memcpy(dest: ctx->pos, src: (void*)ptr, n: possible); |
| 9550 | ctx->pos += possible; |
| 9551 | ptr += possible; |
| 9552 | status ret = exchangeBuffer(ctx); |
| 9553 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9554 | UA_CHECK_STATUS(ret, return ret); |
| 9555 | memSize -= possible; |
| 9556 | } |
| 9557 | |
| 9558 | /* Encode the remaining elements */ |
| 9559 | memcpy(dest: ctx->pos, src: (void*)ptr, n: memSize); |
| 9560 | ctx->pos += memSize; |
| 9561 | return UA_STATUSCODE_GOOD; |
| 9562 | } |
| 9563 | |
| 9564 | static status |
| 9565 | Array_encodeBinaryComplex(uintptr_t ptr, size_t length, |
| 9566 | const UA_DataType *type, Ctx *ctx) { |
| 9567 | /* Encode every element */ |
| 9568 | for(size_t i = 0; i < length; ++i) { |
| 9569 | status ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type, ctx); |
| 9570 | ptr += type->memSize; |
| 9571 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9572 | UA_CHECK_STATUS(ret, return ret); /* Unrecoverable fail */ |
| 9573 | } |
| 9574 | return UA_STATUSCODE_GOOD; |
| 9575 | } |
| 9576 | |
| 9577 | static status |
| 9578 | Array_encodeBinary(const void *src, size_t length, const UA_DataType *type, Ctx *ctx) { |
| 9579 | /* Check and convert the array length to int32 */ |
| 9580 | i32 signed_length = -1; |
| 9581 | if(length > UA_INT32_MAX) |
| 9582 | return UA_STATUSCODE_BADINTERNALERROR; |
| 9583 | if(length > 0) |
| 9584 | signed_length = (i32)length; |
| 9585 | else if(src >= UA_EMPTY_ARRAY_SENTINEL) /* src != NULL */ |
| 9586 | signed_length = 0; |
| 9587 | |
| 9588 | /* Encode the array length */ |
| 9589 | status ret = encodeWithExchangeBuffer(ptr: &signed_length, type: &UA_TYPES[UA_TYPES_INT32], ctx); |
| 9590 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9591 | UA_CHECK_STATUS(ret, return ret); |
| 9592 | |
| 9593 | /* Encode the content */ |
| 9594 | if(length > 0) { |
| 9595 | if(type->overlayable) |
| 9596 | ret = Array_encodeBinaryOverlayable(ptr: (uintptr_t)src, memSize: length * type->memSize, ctx); |
| 9597 | else |
| 9598 | ret = Array_encodeBinaryComplex(ptr: (uintptr_t)src, length, type, ctx); |
| 9599 | } |
| 9600 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9601 | return ret; |
| 9602 | } |
| 9603 | |
| 9604 | static status |
| 9605 | Array_decodeBinary(void *UA_RESTRICT *UA_RESTRICT dst, size_t *out_length, |
| 9606 | const UA_DataType *type, Ctx *ctx) { |
| 9607 | /* Decode the length */ |
| 9608 | i32 signed_length; |
| 9609 | status ret = DECODE_DIRECT(&signed_length, UInt32); /* Int32 */ |
| 9610 | UA_CHECK_STATUS(ret, return ret); |
| 9611 | |
| 9612 | /* Return early for empty arrays */ |
| 9613 | if(signed_length <= 0) { |
| 9614 | *out_length = 0; |
| 9615 | if(signed_length < 0) |
| 9616 | *dst = NULL; |
| 9617 | else |
| 9618 | *dst = UA_EMPTY_ARRAY_SENTINEL; |
| 9619 | return UA_STATUSCODE_GOOD; |
| 9620 | } |
| 9621 | |
| 9622 | /* Filter out arrays that can obviously not be decoded, because the message |
| 9623 | * is too small for the array length. This prevents the allocation of very |
| 9624 | * long arrays for bogus messages. |
| 9625 | * |
| 9626 | * The worst known case (so far) is UA_DataValue. It has |
| 9627 | * sizeof(UA_DataValue) == 80 and an empty DataValue is encoded with just |
| 9628 | * one byte. We use 128 as the smallest power of 2 larger than 80. */ |
| 9629 | size_t length = (size_t)signed_length; |
| 9630 | UA_CHECK(ctx->pos + ((type->memSize * length) / 128) <= ctx->end, |
| 9631 | return UA_STATUSCODE_BADDECODINGERROR); |
| 9632 | |
| 9633 | /* Allocate memory */ |
| 9634 | *dst = UA_calloc(nmemb: length, size: type->memSize); |
| 9635 | UA_CHECK_MEM(*dst, return UA_STATUSCODE_BADOUTOFMEMORY); |
| 9636 | |
| 9637 | if(type->overlayable) { |
| 9638 | /* memcpy overlayable array */ |
| 9639 | UA_CHECK(ctx->pos + (type->memSize * length) <= ctx->end, |
| 9640 | UA_free(*dst); *dst = NULL; return UA_STATUSCODE_BADDECODINGERROR); |
| 9641 | memcpy(dest: *dst, src: ctx->pos, n: type->memSize * length); |
| 9642 | ctx->pos += type->memSize * length; |
| 9643 | } else { |
| 9644 | /* Decode array members */ |
| 9645 | uintptr_t ptr = (uintptr_t)*dst; |
| 9646 | for(size_t i = 0; i < length; ++i) { |
| 9647 | ret = decodeBinaryJumpTable[type->typeKind]((void*)ptr, type, ctx); |
| 9648 | UA_CHECK_STATUS(ret, /* +1 because last element is also already initialized */ |
| 9649 | UA_Array_delete(*dst, i+1, type); *dst = NULL; return ret); |
| 9650 | ptr += type->memSize; |
| 9651 | } |
| 9652 | } |
| 9653 | *out_length = length; |
| 9654 | return UA_STATUSCODE_GOOD; |
| 9655 | } |
| 9656 | |
| 9657 | /*****************/ |
| 9658 | /* Builtin Types */ |
| 9659 | /*****************/ |
| 9660 | |
| 9661 | ENCODE_BINARY(String) { |
| 9662 | return Array_encodeBinary(src: src->data, length: src->length, type: &UA_TYPES[UA_TYPES_BYTE], ctx); |
| 9663 | } |
| 9664 | |
| 9665 | DECODE_BINARY(String) { |
| 9666 | return Array_decodeBinary(dst: (void**)&dst->data, out_length: &dst->length, type: &UA_TYPES[UA_TYPES_BYTE], ctx); |
| 9667 | } |
| 9668 | |
| 9669 | /* Guid */ |
| 9670 | ENCODE_BINARY(Guid) { |
| 9671 | status ret = UA_STATUSCODE_GOOD; |
| 9672 | ret |= ENCODE_DIRECT(&src->data1, UInt32); |
| 9673 | ret |= ENCODE_DIRECT(&src->data2, UInt16); |
| 9674 | ret |= ENCODE_DIRECT(&src->data3, UInt16); |
| 9675 | UA_CHECK(ctx->pos + (8*sizeof(u8)) <= ctx->end, |
| 9676 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9677 | memcpy(dest: ctx->pos, src: src->data4, n: 8*sizeof(u8)); |
| 9678 | ctx->pos += 8; |
| 9679 | return ret; |
| 9680 | } |
| 9681 | |
| 9682 | DECODE_BINARY(Guid) { |
| 9683 | status ret = UA_STATUSCODE_GOOD; |
| 9684 | ret |= DECODE_DIRECT(&dst->data1, UInt32); |
| 9685 | ret |= DECODE_DIRECT(&dst->data2, UInt16); |
| 9686 | ret |= DECODE_DIRECT(&dst->data3, UInt16); |
| 9687 | UA_CHECK(ctx->pos + (8*sizeof(u8)) <= ctx->end, |
| 9688 | return UA_STATUSCODE_BADDECODINGERROR); |
| 9689 | memcpy(dest: dst->data4, src: ctx->pos, n: 8*sizeof(u8)); |
| 9690 | ctx->pos += 8; |
| 9691 | return ret; |
| 9692 | } |
| 9693 | |
| 9694 | /* NodeId */ |
| 9695 | #define UA_NODEIDTYPE_NUMERIC_TWOBYTE 0u |
| 9696 | #define UA_NODEIDTYPE_NUMERIC_FOURBYTE 1u |
| 9697 | #define UA_NODEIDTYPE_NUMERIC_COMPLETE 2u |
| 9698 | |
| 9699 | #define UA_EXPANDEDNODEID_SERVERINDEX_FLAG 0x40u |
| 9700 | #define UA_EXPANDEDNODEID_NAMESPACEURI_FLAG 0x80u |
| 9701 | |
| 9702 | /* For ExpandedNodeId, we prefill the encoding mask. */ |
| 9703 | static status |
| 9704 | NodeId_encodeBinaryWithEncodingMask(UA_NodeId const *src, u8 encoding, Ctx *ctx) { |
| 9705 | status ret = UA_STATUSCODE_GOOD; |
| 9706 | switch(src->identifierType) { |
| 9707 | case UA_NODEIDTYPE_NUMERIC: |
| 9708 | if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) { |
| 9709 | encoding |= UA_NODEIDTYPE_NUMERIC_COMPLETE; |
| 9710 | ret |= ENCODE_DIRECT(&encoding, Byte); |
| 9711 | ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16); |
| 9712 | ret |= ENCODE_DIRECT(&src->identifier.numeric, UInt32); |
| 9713 | } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) { |
| 9714 | encoding |= UA_NODEIDTYPE_NUMERIC_FOURBYTE; |
| 9715 | ret |= ENCODE_DIRECT(&encoding, Byte); |
| 9716 | u8 nsindex = (u8)src->namespaceIndex; |
| 9717 | ret |= ENCODE_DIRECT(&nsindex, Byte); |
| 9718 | u16 identifier16 = (u16)src->identifier.numeric; |
| 9719 | ret |= ENCODE_DIRECT(&identifier16, UInt16); |
| 9720 | } else { |
| 9721 | encoding |= UA_NODEIDTYPE_NUMERIC_TWOBYTE; |
| 9722 | ret |= ENCODE_DIRECT(&encoding, Byte); |
| 9723 | u8 identifier8 = (u8)src->identifier.numeric; |
| 9724 | ret |= ENCODE_DIRECT(&identifier8, Byte); |
| 9725 | } |
| 9726 | break; |
| 9727 | case UA_NODEIDTYPE_STRING: |
| 9728 | encoding |= (u8)UA_NODEIDTYPE_STRING; |
| 9729 | ret |= ENCODE_DIRECT(&encoding, Byte); |
| 9730 | ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16); |
| 9731 | UA_CHECK_STATUS(ret, return ret); |
| 9732 | /* Can exchange the buffer */ |
| 9733 | ret = ENCODE_DIRECT(&src->identifier.string, String); |
| 9734 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9735 | break; |
| 9736 | case UA_NODEIDTYPE_GUID: |
| 9737 | encoding |= (u8)UA_NODEIDTYPE_GUID; |
| 9738 | ret |= ENCODE_DIRECT(&encoding, Byte); |
| 9739 | ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16); |
| 9740 | ret |= ENCODE_DIRECT(&src->identifier.guid, Guid); |
| 9741 | break; |
| 9742 | case UA_NODEIDTYPE_BYTESTRING: |
| 9743 | encoding |= (u8)UA_NODEIDTYPE_BYTESTRING; |
| 9744 | ret |= ENCODE_DIRECT(&encoding, Byte); |
| 9745 | ret |= ENCODE_DIRECT(&src->namespaceIndex, UInt16); |
| 9746 | UA_CHECK_STATUS(ret, return ret); |
| 9747 | /* Can exchange the buffer */ |
| 9748 | ret = ENCODE_DIRECT(&src->identifier.byteString, String); /* ByteString */ |
| 9749 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9750 | break; |
| 9751 | default: |
| 9752 | return UA_STATUSCODE_BADINTERNALERROR; |
| 9753 | } |
| 9754 | return ret; |
| 9755 | } |
| 9756 | |
| 9757 | ENCODE_BINARY(NodeId) { |
| 9758 | return NodeId_encodeBinaryWithEncodingMask(src, encoding: 0, ctx); |
| 9759 | } |
| 9760 | |
| 9761 | DECODE_BINARY(NodeId) { |
| 9762 | u8 dstByte = 0, encodingByte = 0; |
| 9763 | u16 dstUInt16 = 0; |
| 9764 | |
| 9765 | /* Decode the encoding bitfield */ |
| 9766 | status ret = DECODE_DIRECT(&encodingByte, Byte); |
| 9767 | UA_CHECK_STATUS(ret, return ret); |
| 9768 | |
| 9769 | /* Filter out the bits used only for ExpandedNodeIds */ |
| 9770 | encodingByte &= (u8)~(u8)(UA_EXPANDEDNODEID_SERVERINDEX_FLAG | |
| 9771 | UA_EXPANDEDNODEID_NAMESPACEURI_FLAG); |
| 9772 | |
| 9773 | /* Decode the namespace and identifier */ |
| 9774 | switch(encodingByte) { |
| 9775 | case UA_NODEIDTYPE_NUMERIC_TWOBYTE: |
| 9776 | dst->identifierType = UA_NODEIDTYPE_NUMERIC; |
| 9777 | ret = DECODE_DIRECT(&dstByte, Byte); |
| 9778 | dst->identifier.numeric = dstByte; |
| 9779 | dst->namespaceIndex = 0; |
| 9780 | break; |
| 9781 | case UA_NODEIDTYPE_NUMERIC_FOURBYTE: |
| 9782 | dst->identifierType = UA_NODEIDTYPE_NUMERIC; |
| 9783 | ret |= DECODE_DIRECT(&dstByte, Byte); |
| 9784 | dst->namespaceIndex = dstByte; |
| 9785 | ret |= DECODE_DIRECT(&dstUInt16, UInt16); |
| 9786 | dst->identifier.numeric = dstUInt16; |
| 9787 | break; |
| 9788 | case UA_NODEIDTYPE_NUMERIC_COMPLETE: |
| 9789 | dst->identifierType = UA_NODEIDTYPE_NUMERIC; |
| 9790 | ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16); |
| 9791 | ret |= DECODE_DIRECT(&dst->identifier.numeric, UInt32); |
| 9792 | break; |
| 9793 | case UA_NODEIDTYPE_STRING: |
| 9794 | dst->identifierType = UA_NODEIDTYPE_STRING; |
| 9795 | ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16); |
| 9796 | ret |= DECODE_DIRECT(&dst->identifier.string, String); |
| 9797 | break; |
| 9798 | case UA_NODEIDTYPE_GUID: |
| 9799 | dst->identifierType = UA_NODEIDTYPE_GUID; |
| 9800 | ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16); |
| 9801 | ret |= DECODE_DIRECT(&dst->identifier.guid, Guid); |
| 9802 | break; |
| 9803 | case UA_NODEIDTYPE_BYTESTRING: |
| 9804 | dst->identifierType = UA_NODEIDTYPE_BYTESTRING; |
| 9805 | ret |= DECODE_DIRECT(&dst->namespaceIndex, UInt16); |
| 9806 | ret |= DECODE_DIRECT(&dst->identifier.byteString, String); /* ByteString */ |
| 9807 | break; |
| 9808 | default: |
| 9809 | ret |= UA_STATUSCODE_BADINTERNALERROR; |
| 9810 | break; |
| 9811 | } |
| 9812 | return ret; |
| 9813 | } |
| 9814 | |
| 9815 | /* ExpandedNodeId */ |
| 9816 | ENCODE_BINARY(ExpandedNodeId) { |
| 9817 | /* Set up the encoding mask */ |
| 9818 | u8 encoding = 0; |
| 9819 | if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL) |
| 9820 | encoding |= UA_EXPANDEDNODEID_NAMESPACEURI_FLAG; |
| 9821 | if(src->serverIndex > 0) |
| 9822 | encoding |= UA_EXPANDEDNODEID_SERVERINDEX_FLAG; |
| 9823 | |
| 9824 | /* Encode the NodeId. Can exchange the buffer. */ |
| 9825 | status ret = NodeId_encodeBinaryWithEncodingMask(src: &src->nodeId, encoding, ctx); |
| 9826 | UA_CHECK_STATUS(ret, return ret); |
| 9827 | |
| 9828 | /* Encode the namespace. Internally uses encodeWithExchangeBuffer |
| 9829 | * everywhere. So it will never return |
| 9830 | * UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. */ |
| 9831 | if((void*)src->namespaceUri.data > UA_EMPTY_ARRAY_SENTINEL) { |
| 9832 | ret = ENCODE_DIRECT(&src->namespaceUri, String); |
| 9833 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9834 | UA_CHECK_STATUS(ret, return ret); |
| 9835 | } |
| 9836 | |
| 9837 | /* Encode the serverIndex */ |
| 9838 | if(src->serverIndex > 0) |
| 9839 | ret = encodeWithExchangeBuffer(ptr: &src->serverIndex, type: &UA_TYPES[UA_TYPES_UINT32], ctx); |
| 9840 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9841 | return ret; |
| 9842 | } |
| 9843 | |
| 9844 | DECODE_BINARY(ExpandedNodeId) { |
| 9845 | /* Decode the encoding mask */ |
| 9846 | UA_CHECK(ctx->pos + 1 <= ctx->end, return UA_STATUSCODE_BADDECODINGERROR); |
| 9847 | u8 encoding = *ctx->pos; |
| 9848 | |
| 9849 | /* Decode the NodeId */ |
| 9850 | status ret = DECODE_DIRECT(&dst->nodeId, NodeId); |
| 9851 | |
| 9852 | /* Decode the NamespaceUri */ |
| 9853 | if(encoding & UA_EXPANDEDNODEID_NAMESPACEURI_FLAG) { |
| 9854 | dst->nodeId.namespaceIndex = 0; |
| 9855 | ret |= DECODE_DIRECT(&dst->namespaceUri, String); |
| 9856 | } |
| 9857 | |
| 9858 | /* Decode the ServerIndex */ |
| 9859 | if(encoding & UA_EXPANDEDNODEID_SERVERINDEX_FLAG) |
| 9860 | ret |= DECODE_DIRECT(&dst->serverIndex, UInt32); |
| 9861 | return ret; |
| 9862 | } |
| 9863 | |
| 9864 | /* QualifiedName */ |
| 9865 | ENCODE_BINARY(QualifiedName) { |
| 9866 | status ret = ENCODE_DIRECT(&src->namespaceIndex, UInt16); |
| 9867 | /* Must check here so we can exchange the buffer in the string encoding */ |
| 9868 | UA_CHECK_STATUS(ret, return ret); |
| 9869 | ret |= ENCODE_DIRECT(&src->name, String); |
| 9870 | return ret; |
| 9871 | } |
| 9872 | |
| 9873 | DECODE_BINARY(QualifiedName) { |
| 9874 | status ret = DECODE_DIRECT(&dst->namespaceIndex, UInt16); |
| 9875 | ret |= DECODE_DIRECT(&dst->name, String); |
| 9876 | return ret; |
| 9877 | } |
| 9878 | |
| 9879 | /* LocalizedText */ |
| 9880 | #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE 0x01u |
| 9881 | #define UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT 0x02u |
| 9882 | |
| 9883 | ENCODE_BINARY(LocalizedText) { |
| 9884 | /* Set up the encoding mask */ |
| 9885 | u8 encoding = 0; |
| 9886 | if(src->locale.data) |
| 9887 | encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE; |
| 9888 | if(src->text.data) |
| 9889 | encoding |= UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT; |
| 9890 | |
| 9891 | /* Encode the encoding byte */ |
| 9892 | status ret = ENCODE_DIRECT(&encoding, Byte); |
| 9893 | /* Must check here so we can exchange the buffer in the string encoding */ |
| 9894 | UA_CHECK_STATUS(ret, return ret); |
| 9895 | |
| 9896 | /* Encode the strings */ |
| 9897 | if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE) |
| 9898 | ret |= ENCODE_DIRECT(&src->locale, String); |
| 9899 | if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT) |
| 9900 | ret |= ENCODE_DIRECT(&src->text, String); |
| 9901 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9902 | return ret; |
| 9903 | } |
| 9904 | |
| 9905 | DECODE_BINARY(LocalizedText) { |
| 9906 | /* Decode the encoding mask */ |
| 9907 | u8 encoding = 0; |
| 9908 | status ret = DECODE_DIRECT(&encoding, Byte); |
| 9909 | |
| 9910 | /* Decode the content */ |
| 9911 | if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_LOCALE) |
| 9912 | ret |= DECODE_DIRECT(&dst->locale, String); |
| 9913 | if(encoding & UA_LOCALIZEDTEXT_ENCODINGMASKTYPE_TEXT) |
| 9914 | ret |= DECODE_DIRECT(&dst->text, String); |
| 9915 | return ret; |
| 9916 | } |
| 9917 | |
| 9918 | /* The binary encoding has a different nodeid from the data type. So it is not |
| 9919 | * possible to reuse UA_findDataType */ |
| 9920 | static const UA_DataType * |
| 9921 | UA_findDataTypeByBinaryInternal(const UA_NodeId *typeId, Ctx *ctx) { |
| 9922 | /* Always look in the built-in types first. Assume that only numeric |
| 9923 | * identifiers are used for the builtin types. (They may contain data types |
| 9924 | * from all namespaces though.) */ |
| 9925 | if(typeId->identifierType == UA_NODEIDTYPE_NUMERIC) { |
| 9926 | for(size_t i = 0; i < UA_TYPES_COUNT; ++i) { |
| 9927 | if(UA_TYPES[i].binaryEncodingId.identifier.numeric == typeId->identifier.numeric && |
| 9928 | UA_TYPES[i].binaryEncodingId.namespaceIndex == typeId->namespaceIndex) |
| 9929 | return &UA_TYPES[i]; |
| 9930 | } |
| 9931 | } |
| 9932 | |
| 9933 | const UA_DataTypeArray *customTypes = ctx->customTypes; |
| 9934 | while(customTypes) { |
| 9935 | for(size_t i = 0; i < customTypes->typesSize; ++i) { |
| 9936 | if(UA_NodeId_equal(p1: typeId, p2: &customTypes->types[i].binaryEncodingId)) |
| 9937 | return &customTypes->types[i]; |
| 9938 | } |
| 9939 | customTypes = customTypes->next; |
| 9940 | } |
| 9941 | |
| 9942 | return NULL; |
| 9943 | } |
| 9944 | |
| 9945 | const UA_DataType * |
| 9946 | UA_findDataTypeByBinary(const UA_NodeId *typeId) { |
| 9947 | Ctx ctx; |
| 9948 | ctx.customTypes = NULL; |
| 9949 | return UA_findDataTypeByBinaryInternal(typeId, ctx: &ctx); |
| 9950 | } |
| 9951 | |
| 9952 | /* ExtensionObject */ |
| 9953 | ENCODE_BINARY(ExtensionObject) { |
| 9954 | u8 encoding = (u8)src->encoding; |
| 9955 | |
| 9956 | /* No content or already encoded content. */ |
| 9957 | if(encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) { |
| 9958 | /* Can exchange the buffer */ |
| 9959 | status ret = ENCODE_DIRECT(&src->content.encoded.typeId, NodeId); |
| 9960 | UA_CHECK_STATUS(ret, return ret); |
| 9961 | ret = encodeWithExchangeBuffer(ptr: &encoding, type: &UA_TYPES[UA_TYPES_BYTE], ctx); |
| 9962 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9963 | UA_CHECK_STATUS(ret, return ret); |
| 9964 | switch(src->encoding) { |
| 9965 | case UA_EXTENSIONOBJECT_ENCODED_NOBODY: |
| 9966 | break; |
| 9967 | case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING: |
| 9968 | case UA_EXTENSIONOBJECT_ENCODED_XML: |
| 9969 | /* ByteString in disguise. Array encoding can exchange the buffer */ |
| 9970 | ret = ENCODE_DIRECT(&src->content.encoded.body, String); |
| 9971 | break; |
| 9972 | default: |
| 9973 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 9974 | } |
| 9975 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9976 | return ret; |
| 9977 | } |
| 9978 | |
| 9979 | /* Cannot encode with no data or no type description */ |
| 9980 | if(!src->content.decoded.type || !src->content.decoded.data) |
| 9981 | return UA_STATUSCODE_BADENCODINGERROR; |
| 9982 | |
| 9983 | /* Write the NodeId for the binary encoded type. This could perform a buffer |
| 9984 | * exchange, but can also return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. */ |
| 9985 | status ret = ENCODE_DIRECT(&src->content.decoded.type->binaryEncodingId, NodeId); |
| 9986 | UA_CHECK_STATUS(ret, return ret); |
| 9987 | |
| 9988 | /* Encode the encoding byte */ |
| 9989 | encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING; |
| 9990 | ret = encodeWithExchangeBuffer(ptr: &encoding, type: &UA_TYPES[UA_TYPES_BYTE], ctx); |
| 9991 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 9992 | UA_CHECK_STATUS(ret, return ret); |
| 9993 | |
| 9994 | /* Encode the content length */ |
| 9995 | const UA_DataType *contentType = src->content.decoded.type; |
| 9996 | size_t len = UA_calcSizeBinary(p: src->content.decoded.data, type: contentType); |
| 9997 | UA_CHECK(len <= UA_INT32_MAX, return UA_STATUSCODE_BADENCODINGERROR); |
| 9998 | i32 signed_len = (i32)len; |
| 9999 | ret = encodeWithExchangeBuffer(ptr: &signed_len, type: &UA_TYPES[UA_TYPES_INT32], ctx); |
| 10000 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10001 | UA_CHECK_STATUS(ret, return ret); |
| 10002 | |
| 10003 | /* Encode the content */ |
| 10004 | ret = encodeWithExchangeBuffer(ptr: src->content.decoded.data, type: contentType, ctx); |
| 10005 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10006 | return ret; |
| 10007 | } |
| 10008 | |
| 10009 | static status |
| 10010 | ExtensionObject_decodeBinaryContent(UA_ExtensionObject *dst, const UA_NodeId *typeId, |
| 10011 | Ctx *ctx) { |
| 10012 | /* Lookup the datatype */ |
| 10013 | const UA_DataType *type = UA_findDataTypeByBinaryInternal(typeId, ctx); |
| 10014 | |
| 10015 | /* Unknown type, just take the binary content */ |
| 10016 | if(!type) { |
| 10017 | dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING; |
| 10018 | UA_NodeId_copy(src: typeId, dst: &dst->content.encoded.typeId); |
| 10019 | return DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */ |
| 10020 | } |
| 10021 | |
| 10022 | /* Allocate memory */ |
| 10023 | dst->content.decoded.data = UA_new(type); |
| 10024 | UA_CHECK_MEM(dst->content.decoded.data, return UA_STATUSCODE_BADOUTOFMEMORY); |
| 10025 | |
| 10026 | /* Jump over the length field (TODO: check if the decoded length matches) */ |
| 10027 | ctx->pos += 4; |
| 10028 | |
| 10029 | /* Decode */ |
| 10030 | dst->encoding = UA_EXTENSIONOBJECT_DECODED; |
| 10031 | dst->content.decoded.type = type; |
| 10032 | return decodeBinaryJumpTable[type->typeKind](dst->content.decoded.data, type, ctx); |
| 10033 | } |
| 10034 | |
| 10035 | DECODE_BINARY(ExtensionObject) { |
| 10036 | u8 encoding = 0; |
| 10037 | UA_NodeId binTypeId; |
| 10038 | UA_NodeId_init(p: &binTypeId); |
| 10039 | |
| 10040 | status ret = UA_STATUSCODE_GOOD; |
| 10041 | ret |= DECODE_DIRECT(&binTypeId, NodeId); |
| 10042 | ret |= DECODE_DIRECT(&encoding, Byte); |
| 10043 | UA_CHECK_STATUS(ret, UA_NodeId_clear(&binTypeId); return ret); |
| 10044 | |
| 10045 | switch(encoding) { |
| 10046 | case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING: |
| 10047 | ret = ExtensionObject_decodeBinaryContent(dst, typeId: &binTypeId, ctx); |
| 10048 | UA_NodeId_clear(p: &binTypeId); |
| 10049 | break; |
| 10050 | case UA_EXTENSIONOBJECT_ENCODED_NOBODY: |
| 10051 | dst->encoding = (UA_ExtensionObjectEncoding)encoding; |
| 10052 | dst->content.encoded.typeId = binTypeId; /* move to dst */ |
| 10053 | dst->content.encoded.body = UA_BYTESTRING_NULL; |
| 10054 | break; |
| 10055 | case UA_EXTENSIONOBJECT_ENCODED_XML: |
| 10056 | dst->encoding = (UA_ExtensionObjectEncoding)encoding; |
| 10057 | dst->content.encoded.typeId = binTypeId; /* move to dst */ |
| 10058 | ret = DECODE_DIRECT(&dst->content.encoded.body, String); /* ByteString */ |
| 10059 | UA_CHECK_STATUS(ret, UA_NodeId_clear(&dst->content.encoded.typeId)); |
| 10060 | break; |
| 10061 | default: |
| 10062 | UA_NodeId_clear(p: &binTypeId); |
| 10063 | ret = UA_STATUSCODE_BADDECODINGERROR; |
| 10064 | break; |
| 10065 | } |
| 10066 | |
| 10067 | return ret; |
| 10068 | } |
| 10069 | |
| 10070 | /* Variant */ |
| 10071 | |
| 10072 | static status |
| 10073 | Variant_encodeBinaryWrapExtensionObject(const UA_Variant *src, |
| 10074 | const UA_Boolean isArray, Ctx *ctx) { |
| 10075 | size_t length = 1; /* Default to 1 for a scalar. */ |
| 10076 | |
| 10077 | /* Encode the array length if required */ |
| 10078 | status ret = UA_STATUSCODE_GOOD; |
| 10079 | if(isArray) { |
| 10080 | UA_CHECK(src->arrayLength <= UA_INT32_MAX, return UA_STATUSCODE_BADENCODINGERROR); |
| 10081 | length = src->arrayLength; |
| 10082 | |
| 10083 | i32 encodedLength = (i32)src->arrayLength; |
| 10084 | ret = encodeWithExchangeBuffer(ptr: &encodedLength, type: &UA_TYPES[UA_TYPES_INT32], ctx); |
| 10085 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10086 | UA_CHECK_STATUS(ret, return ret); |
| 10087 | } |
| 10088 | |
| 10089 | /* Set up the ExtensionObject */ |
| 10090 | UA_ExtensionObject eo; |
| 10091 | UA_ExtensionObject_init(p: &eo); |
| 10092 | eo.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 10093 | eo.content.decoded.type = src->type; |
| 10094 | const u16 memSize = src->type->memSize; |
| 10095 | uintptr_t ptr = (uintptr_t)src->data; |
| 10096 | |
| 10097 | /* Iterate over the array */ |
| 10098 | for(size_t i = 0; i < length && ret == UA_STATUSCODE_GOOD; ++i) { |
| 10099 | eo.content.decoded.data = (void*)ptr; |
| 10100 | ret = encodeWithExchangeBuffer(ptr: &eo, type: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], ctx); |
| 10101 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10102 | ptr += memSize; |
| 10103 | } |
| 10104 | return ret; |
| 10105 | } |
| 10106 | |
| 10107 | enum UA_VARIANT_ENCODINGMASKTYPE { |
| 10108 | UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK = 0x3Fu, /* bits 0:5 */ |
| 10109 | UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS = (u8)(0x01u << 6u), /* bit 6 */ |
| 10110 | UA_VARIANT_ENCODINGMASKTYPE_ARRAY = (u8)(0x01u << 7u) /* bit 7 */ |
| 10111 | }; |
| 10112 | |
| 10113 | ENCODE_BINARY(Variant) { |
| 10114 | /* Quit early for the empty variant */ |
| 10115 | u8 encoding = 0; |
| 10116 | if(!src->type) |
| 10117 | return ENCODE_DIRECT(&encoding, Byte); |
| 10118 | |
| 10119 | /* Set the content type in the encoding mask */ |
| 10120 | const UA_Boolean isBuiltin = (src->type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO); |
| 10121 | const UA_Boolean isEnum = (src->type->typeKind == UA_DATATYPEKIND_ENUM); |
| 10122 | if(isBuiltin) |
| 10123 | encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(src->type->typeKind + 1u))); |
| 10124 | else if(isEnum) |
| 10125 | encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(UA_TYPES_INT32 + 1u))); |
| 10126 | else |
| 10127 | encoding = (u8)(encoding | (u8)((u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK & (u8)(UA_TYPES_EXTENSIONOBJECT + 1u))); |
| 10128 | |
| 10129 | /* Set the array type in the encoding mask */ |
| 10130 | const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL; |
| 10131 | const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0; |
| 10132 | if(isArray) { |
| 10133 | encoding |= (u8)UA_VARIANT_ENCODINGMASKTYPE_ARRAY; |
| 10134 | if(hasDimensions) { |
| 10135 | encoding |= (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS; |
| 10136 | size_t totalRequiredSize = 1; |
| 10137 | for(size_t i = 0; i < src->arrayDimensionsSize; ++i) |
| 10138 | totalRequiredSize *= src->arrayDimensions[i]; |
| 10139 | if(totalRequiredSize != src->arrayLength) return UA_STATUSCODE_BADENCODINGERROR; |
| 10140 | } |
| 10141 | } |
| 10142 | |
| 10143 | /* Encode the encoding byte */ |
| 10144 | status ret = ENCODE_DIRECT(&encoding, Byte); |
| 10145 | UA_CHECK_STATUS(ret, return ret); |
| 10146 | |
| 10147 | /* Encode the content. This can exchange the buffer. */ |
| 10148 | if(!isBuiltin && !isEnum) { |
| 10149 | /* This could return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED. But we |
| 10150 | * have not exchanged the buffer so far. */ |
| 10151 | ret = Variant_encodeBinaryWrapExtensionObject(src, isArray, ctx); |
| 10152 | } else if(!isArray) { |
| 10153 | ret = encodeWithExchangeBuffer(ptr: src->data, type: src->type, ctx); |
| 10154 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10155 | } else { |
| 10156 | ret = Array_encodeBinary(src: src->data, length: src->arrayLength, type: src->type, ctx); |
| 10157 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10158 | } |
| 10159 | UA_CHECK_STATUS(ret, return ret); |
| 10160 | |
| 10161 | /* Encode the array dimensions */ |
| 10162 | if(hasDimensions && ret == UA_STATUSCODE_GOOD) |
| 10163 | ret = Array_encodeBinary(src: src->arrayDimensions, length: src->arrayDimensionsSize, |
| 10164 | type: &UA_TYPES[UA_TYPES_INT32], ctx); |
| 10165 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10166 | return ret; |
| 10167 | } |
| 10168 | |
| 10169 | static status |
| 10170 | Variant_decodeBinaryUnwrapExtensionObject(UA_Variant *dst, Ctx *ctx) { |
| 10171 | /* Save the position in the ByteString. If unwrapping is not possible, start |
| 10172 | * from here to decode a normal ExtensionObject. */ |
| 10173 | u8 *old_pos = ctx->pos; |
| 10174 | |
| 10175 | /* Decode the DataType */ |
| 10176 | UA_NodeId typeId; |
| 10177 | UA_NodeId_init(p: &typeId); |
| 10178 | status ret = DECODE_DIRECT(&typeId, NodeId); |
| 10179 | UA_CHECK_STATUS(ret, return ret); |
| 10180 | |
| 10181 | /* Decode the EncodingByte */ |
| 10182 | u8 encoding; |
| 10183 | ret = DECODE_DIRECT(&encoding, Byte); |
| 10184 | UA_CHECK_STATUS(ret, UA_NodeId_clear(&typeId); return ret); |
| 10185 | |
| 10186 | /* Search for the datatype. Default to ExtensionObject. */ |
| 10187 | if(encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING && |
| 10188 | (dst->type = UA_findDataTypeByBinaryInternal(typeId: &typeId, ctx)) != NULL) { |
| 10189 | /* Jump over the length field (TODO: check if length matches) */ |
| 10190 | ctx->pos += 4; |
| 10191 | } else { |
| 10192 | /* Reset and decode as ExtensionObject */ |
| 10193 | dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]; |
| 10194 | ctx->pos = old_pos; |
| 10195 | } |
| 10196 | UA_NodeId_clear(p: &typeId); |
| 10197 | |
| 10198 | /* Allocate memory */ |
| 10199 | dst->data = UA_new(type: dst->type); |
| 10200 | UA_CHECK_MEM(dst->data, return UA_STATUSCODE_BADOUTOFMEMORY); |
| 10201 | |
| 10202 | /* Decode the content */ |
| 10203 | return decodeBinaryJumpTable[dst->type->typeKind](dst->data, dst->type, ctx); |
| 10204 | } |
| 10205 | |
| 10206 | /* Unwraps all ExtensionObjects in an array if they have the same type. |
| 10207 | * For that we check whether all ExtensionObjects have the same header. */ |
| 10208 | static status |
| 10209 | Variant_decodeBinaryUnwrapExtensionObjectArray(void *UA_RESTRICT *UA_RESTRICT dst, |
| 10210 | size_t *out_length, const UA_DataType **type, |
| 10211 | Ctx *ctx) { |
| 10212 | u8 *orig_pos = ctx->pos; |
| 10213 | |
| 10214 | /* Decode the length */ |
| 10215 | i32 signed_length; |
| 10216 | status ret = DECODE_DIRECT(&signed_length, UInt32); /* Int32 */ |
| 10217 | UA_CHECK_STATUS(ret, return ret); |
| 10218 | |
| 10219 | /* Return early for empty arrays */ |
| 10220 | if(signed_length <= 0) { |
| 10221 | *out_length = 0; |
| 10222 | if(signed_length < 0) |
| 10223 | *dst = NULL; |
| 10224 | else |
| 10225 | *dst = UA_EMPTY_ARRAY_SENTINEL; |
| 10226 | /* The *type field stays an ExtensionObject, as we did not decode any |
| 10227 | * member who's type is known. */ |
| 10228 | return UA_STATUSCODE_GOOD; |
| 10229 | } |
| 10230 | |
| 10231 | /* Protect against memory exhaustion by unrealistic array lengths. An |
| 10232 | * ExtensionObject is at least 4 byte long (3 byte NodeId + 1 Byte encoding |
| 10233 | * field). */ |
| 10234 | size_t length = (size_t)signed_length; |
| 10235 | UA_CHECK(ctx->pos + ((4 * length) / 32) <= ctx->end, |
| 10236 | return UA_STATUSCODE_BADDECODINGERROR); |
| 10237 | |
| 10238 | /* Decode the type NodeId of the first member */ |
| 10239 | UA_NodeId binTypeId; |
| 10240 | UA_NodeId_init(p: &binTypeId); |
| 10241 | ret |= DECODE_DIRECT(&binTypeId, NodeId); |
| 10242 | UA_CHECK_STATUS(ret, return ret); |
| 10243 | |
| 10244 | /* Lookup the data type */ |
| 10245 | const UA_DataType *contentType = UA_findDataTypeByBinaryInternal(typeId: &binTypeId, ctx); |
| 10246 | UA_NodeId_clear(p: &binTypeId); |
| 10247 | if(!contentType) { |
| 10248 | /* DataType unknown, decode as ExtensionObject array */ |
| 10249 | ctx->pos = orig_pos; |
| 10250 | return Array_decodeBinary(dst, out_length, type: *type, ctx); |
| 10251 | } |
| 10252 | |
| 10253 | /* Check that the encoding is binary */ |
| 10254 | u8 encoding = 0; |
| 10255 | ret |= DECODE_DIRECT(&encoding, Byte); |
| 10256 | UA_CHECK_STATUS(ret, return ret); |
| 10257 | if(encoding != UA_EXTENSIONOBJECT_ENCODED_BYTESTRING) { |
| 10258 | /* Encoding format is not automatically decoded, decode as |
| 10259 | * ExtensionObject array */ |
| 10260 | ctx->pos = orig_pos; |
| 10261 | return Array_decodeBinary(dst, out_length, type: *type, ctx); |
| 10262 | } |
| 10263 | |
| 10264 | /* Compare the header of all array members if the array can be unwrapped */ |
| 10265 | UA_ByteString header = {(uintptr_t)ctx->pos - (uintptr_t)orig_pos - 4, &orig_pos[4]}; |
| 10266 | UA_ByteString compare_header = header; |
| 10267 | ctx->pos = &orig_pos[4]; |
| 10268 | |
| 10269 | for(size_t i = 0; i < length; i++) { |
| 10270 | compare_header.data = ctx->pos; |
| 10271 | UA_CHECK(compare_header.data + compare_header.length <= ctx->end, |
| 10272 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10273 | if(!UA_ByteString_equal(p1: &header, p2: &compare_header)) { |
| 10274 | /* Different member types, decode as ExtensionObject array */ |
| 10275 | ctx->pos = orig_pos; |
| 10276 | return Array_decodeBinary(dst, out_length, type: *type, ctx); |
| 10277 | } |
| 10278 | |
| 10279 | /* Decode the length field and jump to the next element */ |
| 10280 | ctx->pos += header.length; |
| 10281 | u32 member_length = 0; |
| 10282 | ret = DECODE_DIRECT(&member_length, UInt32); |
| 10283 | UA_CHECK_STATUS(ret, return ret); |
| 10284 | ctx->pos += member_length; |
| 10285 | } |
| 10286 | |
| 10287 | /* Allocate memory for the unwrapped members */ |
| 10288 | *dst = UA_calloc(nmemb: length, size: contentType->memSize); |
| 10289 | UA_CHECK_MEM(*dst, return UA_STATUSCODE_BADOUTOFMEMORY); |
| 10290 | *out_length = length; |
| 10291 | *type = contentType; |
| 10292 | |
| 10293 | /* Decode unwrapped members */ |
| 10294 | uintptr_t array_pos = (uintptr_t)*dst; |
| 10295 | ctx->pos = &orig_pos[4]; |
| 10296 | for(size_t i = 0; i < length && ret == UA_STATUSCODE_GOOD; i++) { |
| 10297 | ctx->pos += header.length + 4; /* Jump over the header and length field */ |
| 10298 | ret = decodeBinaryJumpTable[contentType->typeKind] |
| 10299 | ((void*)array_pos, contentType, ctx); |
| 10300 | array_pos += contentType->memSize; |
| 10301 | } |
| 10302 | return ret; |
| 10303 | } |
| 10304 | |
| 10305 | /* The resulting variant always has the storagetype UA_VARIANT_DATA. */ |
| 10306 | DECODE_BINARY(Variant) { |
| 10307 | /* Decode the encoding byte */ |
| 10308 | u8 encodingByte; |
| 10309 | status ret = DECODE_DIRECT(&encodingByte, Byte); |
| 10310 | UA_CHECK_STATUS(ret, return ret); |
| 10311 | |
| 10312 | /* Return early for an empty variant (was already _inited) */ |
| 10313 | if(encodingByte == 0) |
| 10314 | return UA_STATUSCODE_GOOD; |
| 10315 | |
| 10316 | /* Does the variant contain an array? */ |
| 10317 | const UA_Boolean isArray = (encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_ARRAY) > 0; |
| 10318 | |
| 10319 | /* Get the datatype of the content. The type must be a builtin data type. |
| 10320 | * All not-builtin types are wrapped in an ExtensionObject. The "type kind" |
| 10321 | * for types up to DiagnsticInfo equals to the index in the encoding |
| 10322 | * byte. */ |
| 10323 | size_t typeKind = (size_t)((encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_TYPEID_MASK) - 1); |
| 10324 | UA_CHECK(typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO, return UA_STATUSCODE_BADDECODINGERROR); |
| 10325 | |
| 10326 | /* A variant cannot contain a variant. But it can contain an array of |
| 10327 | * variants */ |
| 10328 | UA_CHECK(typeKind != UA_DATATYPEKIND_VARIANT || isArray, |
| 10329 | return UA_STATUSCODE_BADDECODINGERROR); |
| 10330 | |
| 10331 | /* Check the recursion limit */ |
| 10332 | UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR); |
| 10333 | ctx->depth++; |
| 10334 | |
| 10335 | /* Decode the content */ |
| 10336 | dst->type = &UA_TYPES[typeKind]; |
| 10337 | if(!isArray) { |
| 10338 | /* Decode scalar */ |
| 10339 | if(typeKind != UA_DATATYPEKIND_EXTENSIONOBJECT) { |
| 10340 | dst->data = UA_new(type: dst->type); |
| 10341 | UA_CHECK_MEM(dst->data, ctx->depth--; return UA_STATUSCODE_BADOUTOFMEMORY); |
| 10342 | ret = decodeBinaryJumpTable[typeKind](dst->data, dst->type, ctx); |
| 10343 | } else { |
| 10344 | ret = Variant_decodeBinaryUnwrapExtensionObject(dst, ctx); |
| 10345 | } |
| 10346 | } else { |
| 10347 | /* Decode array */ |
| 10348 | if(typeKind != UA_DATATYPEKIND_EXTENSIONOBJECT) { |
| 10349 | ret = Array_decodeBinary(dst: &dst->data, out_length: &dst->arrayLength, type: dst->type, ctx); |
| 10350 | } else { |
| 10351 | ret = Variant_decodeBinaryUnwrapExtensionObjectArray(dst: &dst->data, out_length: &dst->arrayLength, |
| 10352 | type: &dst->type, ctx); |
| 10353 | } |
| 10354 | |
| 10355 | /* Decode array dimensions */ |
| 10356 | if((encodingByte & (u8)UA_VARIANT_ENCODINGMASKTYPE_DIMENSIONS) > 0) { |
| 10357 | ret |= Array_decodeBinary(dst: (void**)&dst->arrayDimensions, out_length: &dst->arrayDimensionsSize, |
| 10358 | type: &UA_TYPES[UA_TYPES_INT32], ctx); |
| 10359 | /* Validate array length against array dimensions */ |
| 10360 | size_t totalSize = 1; |
| 10361 | for(size_t i = 0; i < dst->arrayDimensionsSize; ++i) { |
| 10362 | if(dst->arrayDimensions[i] == 0) |
| 10363 | ret = UA_STATUSCODE_BADDECODINGERROR; |
| 10364 | totalSize *= dst->arrayDimensions[i]; |
| 10365 | } |
| 10366 | UA_CHECK(totalSize == dst->arrayLength, ret = UA_STATUSCODE_BADDECODINGERROR); |
| 10367 | } |
| 10368 | } |
| 10369 | |
| 10370 | ctx->depth--; |
| 10371 | return ret; |
| 10372 | } |
| 10373 | |
| 10374 | /* DataValue */ |
| 10375 | ENCODE_BINARY(DataValue) { |
| 10376 | /* Set up the encoding mask */ |
| 10377 | u8 encodingMask = src->hasValue; |
| 10378 | encodingMask |= (u8)(src->hasStatus << 1u); |
| 10379 | encodingMask |= (u8)(src->hasSourceTimestamp << 2u); |
| 10380 | encodingMask |= (u8)(src->hasServerTimestamp << 3u); |
| 10381 | encodingMask |= (u8)(src->hasSourcePicoseconds << 4u); |
| 10382 | encodingMask |= (u8)(src->hasServerPicoseconds << 5u); |
| 10383 | |
| 10384 | /* Encode the encoding byte */ |
| 10385 | status ret = ENCODE_DIRECT(&encodingMask, Byte); |
| 10386 | UA_CHECK_STATUS(ret, return ret); |
| 10387 | |
| 10388 | /* Encode the variant. */ |
| 10389 | if(src->hasValue) { |
| 10390 | ret = ENCODE_DIRECT(&src->value, Variant); |
| 10391 | if(ret != UA_STATUSCODE_GOOD) |
| 10392 | return ret; |
| 10393 | } |
| 10394 | |
| 10395 | if(src->hasStatus) |
| 10396 | ret |= encodeWithExchangeBuffer(ptr: &src->status, type: &UA_TYPES[UA_TYPES_STATUSCODE], ctx); |
| 10397 | if(src->hasSourceTimestamp) |
| 10398 | ret |= encodeWithExchangeBuffer(ptr: &src->sourceTimestamp, type: &UA_TYPES[UA_TYPES_DATETIME], ctx); |
| 10399 | if(src->hasSourcePicoseconds) |
| 10400 | ret |= encodeWithExchangeBuffer(ptr: &src->sourcePicoseconds, type: &UA_TYPES[UA_TYPES_UINT16], ctx); |
| 10401 | if(src->hasServerTimestamp) |
| 10402 | ret |= encodeWithExchangeBuffer(ptr: &src->serverTimestamp, type: &UA_TYPES[UA_TYPES_DATETIME], ctx); |
| 10403 | if(src->hasServerPicoseconds) |
| 10404 | ret |= encodeWithExchangeBuffer(ptr: &src->serverPicoseconds, type: &UA_TYPES[UA_TYPES_UINT16], ctx); |
| 10405 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10406 | return ret; |
| 10407 | } |
| 10408 | |
| 10409 | #define MAX_PICO_SECONDS 9999 |
| 10410 | |
| 10411 | DECODE_BINARY(DataValue) { |
| 10412 | /* Decode the encoding mask */ |
| 10413 | u8 encodingMask; |
| 10414 | status ret = DECODE_DIRECT(&encodingMask, Byte); |
| 10415 | UA_CHECK_STATUS(ret, return ret); |
| 10416 | |
| 10417 | /* Check the recursion limit */ |
| 10418 | UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR); |
| 10419 | ctx->depth++; |
| 10420 | |
| 10421 | /* Decode the content */ |
| 10422 | if(encodingMask & 0x01u) { |
| 10423 | dst->hasValue = true; |
| 10424 | ret |= DECODE_DIRECT(&dst->value, Variant); |
| 10425 | } |
| 10426 | if(encodingMask & 0x02u) { |
| 10427 | dst->hasStatus = true; |
| 10428 | ret |= DECODE_DIRECT(&dst->status, UInt32); /* StatusCode */ |
| 10429 | } |
| 10430 | if(encodingMask & 0x04u) { |
| 10431 | dst->hasSourceTimestamp = true; |
| 10432 | ret |= DECODE_DIRECT(&dst->sourceTimestamp, UInt64); /* DateTime */ |
| 10433 | } |
| 10434 | if(encodingMask & 0x10u) { |
| 10435 | dst->hasSourcePicoseconds = true; |
| 10436 | ret |= DECODE_DIRECT(&dst->sourcePicoseconds, UInt16); |
| 10437 | if(dst->sourcePicoseconds > MAX_PICO_SECONDS) |
| 10438 | dst->sourcePicoseconds = MAX_PICO_SECONDS; |
| 10439 | } |
| 10440 | if(encodingMask & 0x08u) { |
| 10441 | dst->hasServerTimestamp = true; |
| 10442 | ret |= DECODE_DIRECT(&dst->serverTimestamp, UInt64); /* DateTime */ |
| 10443 | } |
| 10444 | if(encodingMask & 0x20u) { |
| 10445 | dst->hasServerPicoseconds = true; |
| 10446 | ret |= DECODE_DIRECT(&dst->serverPicoseconds, UInt16); |
| 10447 | if(dst->serverPicoseconds > MAX_PICO_SECONDS) |
| 10448 | dst->serverPicoseconds = MAX_PICO_SECONDS; |
| 10449 | } |
| 10450 | |
| 10451 | ctx->depth--; |
| 10452 | return ret; |
| 10453 | } |
| 10454 | |
| 10455 | /* DiagnosticInfo */ |
| 10456 | ENCODE_BINARY(DiagnosticInfo) { |
| 10457 | /* Set up the encoding mask */ |
| 10458 | u8 encodingMask = src->hasSymbolicId; |
| 10459 | encodingMask |= (u8)(src->hasNamespaceUri << 1u); |
| 10460 | encodingMask |= (u8)(src->hasLocalizedText << 2u); |
| 10461 | encodingMask |= (u8)(src->hasLocale << 3u); |
| 10462 | encodingMask |= (u8)(src->hasAdditionalInfo << 4u); |
| 10463 | encodingMask |= (u8)(src->hasInnerStatusCode << 5u); |
| 10464 | encodingMask |= (u8)(src->hasInnerDiagnosticInfo << 6u); |
| 10465 | |
| 10466 | /* Encode the numeric content */ |
| 10467 | status ret = ENCODE_DIRECT(&encodingMask, Byte); |
| 10468 | if(src->hasSymbolicId) |
| 10469 | ret |= ENCODE_DIRECT(&src->symbolicId, UInt32); /* Int32 */ |
| 10470 | if(src->hasNamespaceUri) |
| 10471 | ret |= ENCODE_DIRECT(&src->namespaceUri, UInt32); /* Int32 */ |
| 10472 | if(src->hasLocale) |
| 10473 | ret |= ENCODE_DIRECT(&src->locale, UInt32); /* Int32 */ |
| 10474 | if(src->hasLocalizedText) |
| 10475 | ret |= ENCODE_DIRECT(&src->localizedText, UInt32); /* Int32 */ |
| 10476 | if(ret != UA_STATUSCODE_GOOD) |
| 10477 | return ret; |
| 10478 | |
| 10479 | /* Encode the additional info. Can exchange the buffer. */ |
| 10480 | if(src->hasAdditionalInfo) { |
| 10481 | ret = ENCODE_DIRECT(&src->additionalInfo, String); |
| 10482 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10483 | UA_CHECK_STATUS(ret, return ret); |
| 10484 | } |
| 10485 | |
| 10486 | /* Encode the inner status code */ |
| 10487 | if(src->hasInnerStatusCode) { |
| 10488 | ret = encodeWithExchangeBuffer(ptr: &src->innerStatusCode, type: &UA_TYPES[UA_TYPES_UINT32], ctx); |
| 10489 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10490 | UA_CHECK_STATUS(ret, return ret); |
| 10491 | } |
| 10492 | |
| 10493 | /* Encode the inner diagnostic info */ |
| 10494 | if(src->hasInnerDiagnosticInfo) { |
| 10495 | ret = encodeWithExchangeBuffer(ptr: src->innerDiagnosticInfo, |
| 10496 | type: &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], ctx); |
| 10497 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10498 | } |
| 10499 | |
| 10500 | return ret; |
| 10501 | } |
| 10502 | |
| 10503 | DECODE_BINARY(DiagnosticInfo) { |
| 10504 | /* Decode the encoding mask */ |
| 10505 | u8 encodingMask; |
| 10506 | status ret = DECODE_DIRECT(&encodingMask, Byte); |
| 10507 | UA_CHECK_STATUS(ret, return ret); |
| 10508 | |
| 10509 | /* Decode the content */ |
| 10510 | if(encodingMask & 0x01u) { |
| 10511 | dst->hasSymbolicId = true; |
| 10512 | ret |= DECODE_DIRECT(&dst->symbolicId, UInt32); /* Int32 */ |
| 10513 | } |
| 10514 | if(encodingMask & 0x02u) { |
| 10515 | dst->hasNamespaceUri = true; |
| 10516 | ret |= DECODE_DIRECT(&dst->namespaceUri, UInt32); /* Int32 */ |
| 10517 | } |
| 10518 | if(encodingMask & 0x08u) { |
| 10519 | dst->hasLocale = true; |
| 10520 | ret |= DECODE_DIRECT(&dst->locale, UInt32); /* Int32 */ |
| 10521 | } |
| 10522 | if(encodingMask & 0x04u) { |
| 10523 | dst->hasLocalizedText = true; |
| 10524 | ret |= DECODE_DIRECT(&dst->localizedText, UInt32); /* Int32 */ |
| 10525 | } |
| 10526 | if(encodingMask & 0x10u) { |
| 10527 | dst->hasAdditionalInfo = true; |
| 10528 | ret |= DECODE_DIRECT(&dst->additionalInfo, String); |
| 10529 | } |
| 10530 | if(encodingMask & 0x20u) { |
| 10531 | dst->hasInnerStatusCode = true; |
| 10532 | ret |= DECODE_DIRECT(&dst->innerStatusCode, UInt32); /* StatusCode */ |
| 10533 | } |
| 10534 | if(encodingMask & 0x40u) { |
| 10535 | /* innerDiagnosticInfo is allocated on the heap */ |
| 10536 | dst->innerDiagnosticInfo = (UA_DiagnosticInfo*) |
| 10537 | UA_calloc(nmemb: 1, size: sizeof(UA_DiagnosticInfo)); |
| 10538 | UA_CHECK_MEM(dst->innerDiagnosticInfo, return UA_STATUSCODE_BADOUTOFMEMORY); |
| 10539 | dst->hasInnerDiagnosticInfo = true; |
| 10540 | |
| 10541 | /* Check the recursion limit */ |
| 10542 | UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, |
| 10543 | return UA_STATUSCODE_BADENCODINGERROR); |
| 10544 | |
| 10545 | ctx->depth++; |
| 10546 | ret |= DECODE_DIRECT(dst->innerDiagnosticInfo, DiagnosticInfo); |
| 10547 | ctx->depth--; |
| 10548 | } |
| 10549 | return ret; |
| 10550 | } |
| 10551 | |
| 10552 | /********************/ |
| 10553 | /* Structured Types */ |
| 10554 | /********************/ |
| 10555 | |
| 10556 | static status |
| 10557 | encodeBinaryStruct(const void *src, const UA_DataType *type, Ctx *ctx) { |
| 10558 | /* Check the recursion limit */ |
| 10559 | UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, |
| 10560 | return UA_STATUSCODE_BADENCODINGERROR); |
| 10561 | ctx->depth++; |
| 10562 | |
| 10563 | /* Loop over members */ |
| 10564 | uintptr_t ptr = (uintptr_t)src; |
| 10565 | status ret = UA_STATUSCODE_GOOD; |
| 10566 | for(size_t i = 0; i < type->membersSize && ret == UA_STATUSCODE_GOOD; ++i) { |
| 10567 | const UA_DataTypeMember *m = &type->members[i]; |
| 10568 | const UA_DataType *mt = m->memberType; |
| 10569 | ptr += m->padding; |
| 10570 | |
| 10571 | /* Array. Buffer-exchange is done inside Array_encodeBinary if required. */ |
| 10572 | if(m->isArray) { |
| 10573 | const size_t length = *((const size_t*)ptr); |
| 10574 | ptr += sizeof(size_t); |
| 10575 | ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: mt, ctx); |
| 10576 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10577 | ptr += sizeof(void*); |
| 10578 | continue; |
| 10579 | } |
| 10580 | |
| 10581 | /* Scalar */ |
| 10582 | ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type: mt, ctx); |
| 10583 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10584 | ptr += mt->memSize; |
| 10585 | } |
| 10586 | |
| 10587 | ctx->depth--; |
| 10588 | return ret; |
| 10589 | } |
| 10590 | |
| 10591 | static status |
| 10592 | encodeBinaryStructWithOptFields(const void *src, const UA_DataType *type, Ctx *ctx) { |
| 10593 | /* Check the recursion limit */ |
| 10594 | if(ctx->depth > UA_ENCODING_MAX_RECURSION) |
| 10595 | return UA_STATUSCODE_BADENCODINGERROR; |
| 10596 | ctx->depth++; |
| 10597 | |
| 10598 | /* Creating the encoding mask, marking the available optional fields */ |
| 10599 | uintptr_t ptr = (uintptr_t)src; |
| 10600 | size_t optFieldCounter = 0; |
| 10601 | UA_UInt32 encodingMask = 0; |
| 10602 | for(size_t j = 0; j < type->membersSize; ++j) { |
| 10603 | const UA_DataTypeMember *m = &type->members[j]; |
| 10604 | const UA_DataType *mt = m->memberType; |
| 10605 | ptr += m->padding; |
| 10606 | if(m->isOptional) { |
| 10607 | if(m->isArray) |
| 10608 | ptr += sizeof(size_t); |
| 10609 | if(*(void* const*)ptr != NULL) |
| 10610 | encodingMask |= (UA_UInt32) 1 << optFieldCounter; |
| 10611 | ptr += sizeof(void *); |
| 10612 | optFieldCounter++; |
| 10613 | } else if (m->isArray) { |
| 10614 | ptr += sizeof(size_t); |
| 10615 | ptr += sizeof(void *); |
| 10616 | } else { |
| 10617 | ptr += mt->memSize; |
| 10618 | } |
| 10619 | } |
| 10620 | |
| 10621 | /* Encode the mask */ |
| 10622 | status ret = ENCODE_DIRECT(&encodingMask, UInt32); |
| 10623 | UA_CHECK_STATUS(ret, ctx->depth--; return ret); |
| 10624 | |
| 10625 | /* Loop over members */ |
| 10626 | ptr = (uintptr_t)src; |
| 10627 | for(size_t i = 0, o = 0; i < type->membersSize && UA_LIKELY(ret == UA_STATUSCODE_GOOD); ++i) { |
| 10628 | const UA_DataTypeMember *m = &type->members[i]; |
| 10629 | const UA_DataType *mt = m->memberType; |
| 10630 | ptr += m->padding; |
| 10631 | |
| 10632 | if(m->isOptional) { |
| 10633 | if(!(encodingMask & (UA_UInt32) ( (UA_UInt32) 1<<(o++)))) { |
| 10634 | /* Optional and not contained */ |
| 10635 | if(m->isArray) |
| 10636 | ptr += sizeof(size_t); |
| 10637 | } else if(m->isArray) { |
| 10638 | /* Optional Array */ |
| 10639 | const size_t length = *((const size_t *) ptr); |
| 10640 | ptr += sizeof(size_t); |
| 10641 | ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *) ptr, length, type: mt, ctx); |
| 10642 | } else { |
| 10643 | /* Optional Scalar */ |
| 10644 | ret = encodeWithExchangeBuffer(ptr: *(void* const*) ptr, type: mt, ctx); |
| 10645 | } |
| 10646 | ptr += sizeof(void *); |
| 10647 | continue; |
| 10648 | } |
| 10649 | |
| 10650 | /* Mandatory Array */ |
| 10651 | if(m->isArray) { |
| 10652 | const size_t length = *((const size_t *) ptr); |
| 10653 | ptr += sizeof(size_t); |
| 10654 | ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *) ptr, length, type: mt, ctx); |
| 10655 | ptr += sizeof(void *); |
| 10656 | continue; |
| 10657 | } |
| 10658 | |
| 10659 | /* Mandatory Scalar */ |
| 10660 | ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type: mt, ctx); |
| 10661 | ptr += mt->memSize; |
| 10662 | } |
| 10663 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10664 | |
| 10665 | ctx->depth--; |
| 10666 | return ret; |
| 10667 | } |
| 10668 | |
| 10669 | static status |
| 10670 | encodeBinaryUnion(const void *src, const UA_DataType *type, Ctx *ctx) { |
| 10671 | /* Check the recursion limit */ |
| 10672 | UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, |
| 10673 | return UA_STATUSCODE_BADENCODINGERROR); |
| 10674 | ctx->depth++; |
| 10675 | |
| 10676 | /* Encode the selection */ |
| 10677 | const UA_UInt32 selection = *(const UA_UInt32*)src; |
| 10678 | status ret = ENCODE_DIRECT(&selection, UInt32); |
| 10679 | if(UA_UNLIKELY(ret != UA_STATUSCODE_GOOD) || selection == 0) { |
| 10680 | ctx->depth--; |
| 10681 | return ret; |
| 10682 | } |
| 10683 | |
| 10684 | /* Select the member */ |
| 10685 | const UA_DataTypeMember *m = &type->members[selection-1]; |
| 10686 | const UA_DataType *mt = m->memberType; |
| 10687 | |
| 10688 | /* Encode the member */ |
| 10689 | uintptr_t ptr = ((uintptr_t)src) + m->padding; /* includes the switchfield length */ |
| 10690 | if(!m->isArray) { |
| 10691 | ret = encodeWithExchangeBuffer(ptr: (const void*)ptr, type: mt, ctx); |
| 10692 | } else { |
| 10693 | const size_t length = *((const size_t*)ptr); |
| 10694 | ptr += sizeof(size_t); |
| 10695 | ret = Array_encodeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: mt, ctx); |
| 10696 | } |
| 10697 | |
| 10698 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10699 | |
| 10700 | ctx->depth--; |
| 10701 | return ret; |
| 10702 | } |
| 10703 | |
| 10704 | static status |
| 10705 | encodeBinaryNotImplemented(const void *src, const UA_DataType *type, Ctx *ctx) { |
| 10706 | (void)src, (void)type, (void)ctx; |
| 10707 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 10708 | } |
| 10709 | |
| 10710 | const encodeBinarySignature encodeBinaryJumpTable[UA_DATATYPEKINDS] = { |
| 10711 | (encodeBinarySignature)Boolean_encodeBinary, |
| 10712 | (encodeBinarySignature)Byte_encodeBinary, /* SByte */ |
| 10713 | (encodeBinarySignature)Byte_encodeBinary, |
| 10714 | (encodeBinarySignature)UInt16_encodeBinary, /* Int16 */ |
| 10715 | (encodeBinarySignature)UInt16_encodeBinary, |
| 10716 | (encodeBinarySignature)UInt32_encodeBinary, /* Int32 */ |
| 10717 | (encodeBinarySignature)UInt32_encodeBinary, |
| 10718 | (encodeBinarySignature)UInt64_encodeBinary, /* Int64 */ |
| 10719 | (encodeBinarySignature)UInt64_encodeBinary, |
| 10720 | (encodeBinarySignature)Float_encodeBinary, |
| 10721 | (encodeBinarySignature)Double_encodeBinary, |
| 10722 | (encodeBinarySignature)String_encodeBinary, |
| 10723 | (encodeBinarySignature)UInt64_encodeBinary, /* DateTime */ |
| 10724 | (encodeBinarySignature)Guid_encodeBinary, |
| 10725 | (encodeBinarySignature)String_encodeBinary, /* ByteString */ |
| 10726 | (encodeBinarySignature)String_encodeBinary, /* XmlElement */ |
| 10727 | (encodeBinarySignature)NodeId_encodeBinary, |
| 10728 | (encodeBinarySignature)ExpandedNodeId_encodeBinary, |
| 10729 | (encodeBinarySignature)UInt32_encodeBinary, /* StatusCode */ |
| 10730 | (encodeBinarySignature)QualifiedName_encodeBinary, |
| 10731 | (encodeBinarySignature)LocalizedText_encodeBinary, |
| 10732 | (encodeBinarySignature)ExtensionObject_encodeBinary, |
| 10733 | (encodeBinarySignature)DataValue_encodeBinary, |
| 10734 | (encodeBinarySignature)Variant_encodeBinary, |
| 10735 | (encodeBinarySignature)DiagnosticInfo_encodeBinary, |
| 10736 | (encodeBinarySignature)encodeBinaryNotImplemented, /* Decimal */ |
| 10737 | (encodeBinarySignature)UInt32_encodeBinary, /* Enumeration */ |
| 10738 | (encodeBinarySignature)encodeBinaryStruct, |
| 10739 | (encodeBinarySignature)encodeBinaryStructWithOptFields, /* Structure with Optional Fields */ |
| 10740 | (encodeBinarySignature)encodeBinaryUnion, /* Union */ |
| 10741 | (encodeBinarySignature)encodeBinaryStruct /* BitfieldCluster */ |
| 10742 | }; |
| 10743 | |
| 10744 | status |
| 10745 | UA_encodeBinaryInternal(const void *src, const UA_DataType *type, |
| 10746 | u8 **bufPos, const u8 **bufEnd, |
| 10747 | UA_exchangeEncodeBuffer exchangeCallback, |
| 10748 | void *exchangeHandle) { |
| 10749 | if(!type || !src) |
| 10750 | return UA_STATUSCODE_BADENCODINGERROR; |
| 10751 | |
| 10752 | /* Set up the context */ |
| 10753 | Ctx ctx; |
| 10754 | ctx.pos = *bufPos; |
| 10755 | ctx.end = *bufEnd; |
| 10756 | ctx.depth = 0; |
| 10757 | ctx.exchangeBufferCallback = exchangeCallback; |
| 10758 | ctx.exchangeBufferCallbackHandle = exchangeHandle; |
| 10759 | |
| 10760 | UA_CHECK_MEM(ctx.pos, return UA_STATUSCODE_BADINVALIDARGUMENT); |
| 10761 | |
| 10762 | /* Encode */ |
| 10763 | status ret = encodeWithExchangeBuffer(ptr: src, type, ctx: &ctx); |
| 10764 | UA_assert(ret != UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED); |
| 10765 | |
| 10766 | /* Set the new buffer position for the output. Beware that the buffer might |
| 10767 | * have been exchanged internally. */ |
| 10768 | *bufPos = ctx.pos; |
| 10769 | *bufEnd = ctx.end; |
| 10770 | return ret; |
| 10771 | } |
| 10772 | |
| 10773 | UA_StatusCode |
| 10774 | UA_encodeBinary(const void *p, const UA_DataType *type, |
| 10775 | UA_ByteString *outBuf) { |
| 10776 | /* Allocate buffer */ |
| 10777 | UA_Boolean allocated = false; |
| 10778 | status res = UA_STATUSCODE_GOOD; |
| 10779 | if(outBuf->length == 0) { |
| 10780 | size_t len = UA_calcSizeBinary(p, type); |
| 10781 | res = UA_ByteString_allocBuffer(bs: outBuf, length: len); |
| 10782 | if(res != UA_STATUSCODE_GOOD) |
| 10783 | return res; |
| 10784 | allocated = true; |
| 10785 | } |
| 10786 | |
| 10787 | /* Encode */ |
| 10788 | u8 *pos = outBuf->data; |
| 10789 | const u8 *posEnd = &outBuf->data[outBuf->length]; |
| 10790 | res = UA_encodeBinaryInternal(src: p, type, bufPos: &pos, bufEnd: &posEnd, NULL, NULL); |
| 10791 | |
| 10792 | /* Clean up */ |
| 10793 | if(res == UA_STATUSCODE_GOOD) { |
| 10794 | outBuf->length = (size_t)((uintptr_t)pos - (uintptr_t)outBuf->data); |
| 10795 | } else if(allocated) { |
| 10796 | UA_ByteString_clear(p: outBuf); |
| 10797 | } |
| 10798 | return res; |
| 10799 | } |
| 10800 | |
| 10801 | static status |
| 10802 | decodeBinaryNotImplemented(void *dst, const UA_DataType *type, Ctx *ctx) { |
| 10803 | (void)dst, (void)type, (void)ctx; |
| 10804 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 10805 | } |
| 10806 | |
| 10807 | static status |
| 10808 | decodeBinaryStructure(void *dst, const UA_DataType *type, Ctx *ctx) { |
| 10809 | /* Check the recursion limit */ |
| 10810 | UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, |
| 10811 | return UA_STATUSCODE_BADENCODINGERROR); |
| 10812 | ctx->depth++; |
| 10813 | |
| 10814 | uintptr_t ptr = (uintptr_t)dst; |
| 10815 | status ret = UA_STATUSCODE_GOOD; |
| 10816 | u8 membersSize = type->membersSize; |
| 10817 | |
| 10818 | /* Loop over members */ |
| 10819 | for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) { |
| 10820 | const UA_DataTypeMember *m = &type->members[i]; |
| 10821 | const UA_DataType *mt = m->memberType; |
| 10822 | ptr += m->padding; |
| 10823 | |
| 10824 | /* Array */ |
| 10825 | if(m->isArray) { |
| 10826 | size_t *length = (size_t*)ptr; |
| 10827 | ptr += sizeof(size_t); |
| 10828 | ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt , ctx); |
| 10829 | ptr += sizeof(void*); |
| 10830 | continue; |
| 10831 | } |
| 10832 | |
| 10833 | /* Scalar */ |
| 10834 | ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx); |
| 10835 | ptr += mt->memSize; |
| 10836 | } |
| 10837 | |
| 10838 | ctx->depth--; |
| 10839 | return ret; |
| 10840 | } |
| 10841 | |
| 10842 | static status |
| 10843 | decodeBinaryStructureWithOptFields(void *dst, const UA_DataType *type, Ctx *ctx) { |
| 10844 | /* Check the recursion limit */ |
| 10845 | UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, return UA_STATUSCODE_BADENCODINGERROR); |
| 10846 | ctx->depth++; |
| 10847 | |
| 10848 | uintptr_t ptr = (uintptr_t)dst; |
| 10849 | UA_UInt32 encodingMask = 0; |
| 10850 | status ret = UInt32_decodeBinary(dst: &encodingMask, type: &UA_TYPES[UA_TYPES_UINT32], ctx); |
| 10851 | UA_CHECK_STATUS(ret, ctx->depth--; return ret); |
| 10852 | |
| 10853 | /* Loop over members */ |
| 10854 | for(size_t i = 0, o = 0; i < type->membersSize && ret == UA_STATUSCODE_GOOD; ++i) { |
| 10855 | const UA_DataTypeMember *m = &type->members[i]; |
| 10856 | const UA_DataType *mt = m->memberType; |
| 10857 | ptr += m->padding; |
| 10858 | if(m->isOptional) { |
| 10859 | if(!(encodingMask & (UA_UInt32) ( (UA_UInt32) 1<<(o++)))) { |
| 10860 | /* Optional field is not contained */ |
| 10861 | if(m->isArray) |
| 10862 | ptr += sizeof(size_t); |
| 10863 | } else if(m->isArray) { |
| 10864 | /* Optional Array */ |
| 10865 | size_t *length = (size_t*)ptr; |
| 10866 | ptr += sizeof(size_t); |
| 10867 | ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt , ctx); |
| 10868 | } else { |
| 10869 | /* Optional Scalar */ |
| 10870 | *(void *UA_RESTRICT *UA_RESTRICT) ptr = UA_calloc(nmemb: 1, size: mt->memSize); |
| 10871 | UA_CHECK_MEM(*(void *UA_RESTRICT *UA_RESTRICT) ptr, return UA_STATUSCODE_BADOUTOFMEMORY); |
| 10872 | ret = decodeBinaryJumpTable[mt->typeKind](*(void *UA_RESTRICT *UA_RESTRICT) ptr, mt, ctx); |
| 10873 | } |
| 10874 | ptr += sizeof(void *); |
| 10875 | continue; |
| 10876 | } |
| 10877 | |
| 10878 | /* Array */ |
| 10879 | if(m->isArray) { |
| 10880 | size_t *length = (size_t *)ptr; |
| 10881 | ptr += sizeof(size_t); |
| 10882 | ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt, ctx); |
| 10883 | ptr += sizeof(void *); |
| 10884 | continue; |
| 10885 | } |
| 10886 | |
| 10887 | /* Scalar */ |
| 10888 | ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx); |
| 10889 | ptr += mt->memSize; |
| 10890 | } |
| 10891 | ctx->depth--; |
| 10892 | return ret; |
| 10893 | } |
| 10894 | |
| 10895 | static status |
| 10896 | decodeBinaryUnion(void *UA_RESTRICT dst, const UA_DataType *type, Ctx *ctx) { |
| 10897 | /* Check the recursion limit */ |
| 10898 | UA_CHECK(ctx->depth <= UA_ENCODING_MAX_RECURSION, |
| 10899 | return UA_STATUSCODE_BADENCODINGERROR); |
| 10900 | |
| 10901 | /* Decode the selection directly into the switchfield */ |
| 10902 | status ret = DECODE_DIRECT(dst, UInt32); |
| 10903 | UA_CHECK_STATUS(ret, return ret); |
| 10904 | |
| 10905 | /* No content? */ |
| 10906 | UA_UInt32 selection = *(UA_UInt32*)dst; |
| 10907 | if(selection == 0) |
| 10908 | return UA_STATUSCODE_GOOD; |
| 10909 | |
| 10910 | /* Sanity check the selection */ |
| 10911 | UA_CHECK(selection-1 < type->membersSize, |
| 10912 | return UA_STATUSCODE_BADDECODINGERROR); |
| 10913 | |
| 10914 | /* Select the member */ |
| 10915 | const UA_DataTypeMember *m = &type->members[selection-1]; |
| 10916 | const UA_DataType *mt = m->memberType; |
| 10917 | |
| 10918 | /* Decode */ |
| 10919 | ctx->depth++; |
| 10920 | uintptr_t ptr = ((uintptr_t)dst) + m->padding; /* includes the switchfield */ |
| 10921 | if(!m->isArray) { |
| 10922 | ret = decodeBinaryJumpTable[mt->typeKind]((void *UA_RESTRICT)ptr, mt, ctx); |
| 10923 | } else { |
| 10924 | size_t *length = (size_t *)ptr; |
| 10925 | ptr += sizeof(size_t); |
| 10926 | ret = Array_decodeBinary(dst: (void *UA_RESTRICT *UA_RESTRICT)ptr, out_length: length, type: mt, ctx); |
| 10927 | } |
| 10928 | ctx->depth--; |
| 10929 | return ret; |
| 10930 | } |
| 10931 | |
| 10932 | const decodeBinarySignature decodeBinaryJumpTable[UA_DATATYPEKINDS] = { |
| 10933 | (decodeBinarySignature)Boolean_decodeBinary, |
| 10934 | (decodeBinarySignature)Byte_decodeBinary, /* SByte */ |
| 10935 | (decodeBinarySignature)Byte_decodeBinary, |
| 10936 | (decodeBinarySignature)UInt16_decodeBinary, /* Int16 */ |
| 10937 | (decodeBinarySignature)UInt16_decodeBinary, |
| 10938 | (decodeBinarySignature)UInt32_decodeBinary, /* Int32 */ |
| 10939 | (decodeBinarySignature)UInt32_decodeBinary, |
| 10940 | (decodeBinarySignature)UInt64_decodeBinary, /* Int64 */ |
| 10941 | (decodeBinarySignature)UInt64_decodeBinary, |
| 10942 | (decodeBinarySignature)Float_decodeBinary, |
| 10943 | (decodeBinarySignature)Double_decodeBinary, |
| 10944 | (decodeBinarySignature)String_decodeBinary, |
| 10945 | (decodeBinarySignature)UInt64_decodeBinary, /* DateTime */ |
| 10946 | (decodeBinarySignature)Guid_decodeBinary, |
| 10947 | (decodeBinarySignature)String_decodeBinary, /* ByteString */ |
| 10948 | (decodeBinarySignature)String_decodeBinary, /* XmlElement */ |
| 10949 | (decodeBinarySignature)NodeId_decodeBinary, |
| 10950 | (decodeBinarySignature)ExpandedNodeId_decodeBinary, |
| 10951 | (decodeBinarySignature)UInt32_decodeBinary, /* StatusCode */ |
| 10952 | (decodeBinarySignature)QualifiedName_decodeBinary, |
| 10953 | (decodeBinarySignature)LocalizedText_decodeBinary, |
| 10954 | (decodeBinarySignature)ExtensionObject_decodeBinary, |
| 10955 | (decodeBinarySignature)DataValue_decodeBinary, |
| 10956 | (decodeBinarySignature)Variant_decodeBinary, |
| 10957 | (decodeBinarySignature)DiagnosticInfo_decodeBinary, |
| 10958 | (decodeBinarySignature)decodeBinaryNotImplemented, /* Decimal */ |
| 10959 | (decodeBinarySignature)UInt32_decodeBinary, /* Enumeration */ |
| 10960 | (decodeBinarySignature)decodeBinaryStructure, |
| 10961 | (decodeBinarySignature)decodeBinaryStructureWithOptFields, /* Structure with optional fields */ |
| 10962 | (decodeBinarySignature)decodeBinaryUnion, /* Union */ |
| 10963 | (decodeBinarySignature)decodeBinaryNotImplemented /* BitfieldCluster */ |
| 10964 | }; |
| 10965 | |
| 10966 | status |
| 10967 | UA_decodeBinaryInternal(const UA_ByteString *src, size_t *offset, |
| 10968 | void *dst, const UA_DataType *type, |
| 10969 | const UA_DataTypeArray *customTypes) { |
| 10970 | /* Set up the context */ |
| 10971 | Ctx ctx; |
| 10972 | ctx.pos = &src->data[*offset]; |
| 10973 | ctx.end = &src->data[src->length]; |
| 10974 | ctx.depth = 0; |
| 10975 | ctx.customTypes = customTypes; |
| 10976 | |
| 10977 | /* Decode */ |
| 10978 | memset(s: dst, c: 0, n: type->memSize); /* Initialize the value */ |
| 10979 | status ret = decodeBinaryJumpTable[type->typeKind](dst, type, &ctx); |
| 10980 | |
| 10981 | if(UA_LIKELY(ret == UA_STATUSCODE_GOOD)) { |
| 10982 | /* Set the new offset */ |
| 10983 | *offset = (size_t)(ctx.pos - src->data) / sizeof(u8); |
| 10984 | } else { |
| 10985 | /* Clean up */ |
| 10986 | UA_clear(p: dst, type); |
| 10987 | memset(s: dst, c: 0, n: type->memSize); |
| 10988 | } |
| 10989 | return ret; |
| 10990 | } |
| 10991 | |
| 10992 | UA_StatusCode |
| 10993 | UA_decodeBinary(const UA_ByteString *inBuf, |
| 10994 | void *p, const UA_DataType *type, |
| 10995 | const UA_DecodeBinaryOptions *options) { |
| 10996 | size_t offset = 0; |
| 10997 | const UA_DataTypeArray *customTypes = options ? options->customTypes : NULL; |
| 10998 | return UA_decodeBinaryInternal(src: inBuf, offset: &offset, dst: p, type, customTypes); |
| 10999 | } |
| 11000 | |
| 11001 | /** |
| 11002 | * Compute the Message Size |
| 11003 | * ------------------------ |
| 11004 | * The following methods are used to compute the length of a datum in binary |
| 11005 | * encoding. */ |
| 11006 | |
| 11007 | static size_t |
| 11008 | Array_calcSizeBinary(const void *src, size_t length, const UA_DataType *type) { |
| 11009 | size_t s = 4; /* length */ |
| 11010 | if(type->overlayable) { |
| 11011 | s += type->memSize * length; |
| 11012 | return s; |
| 11013 | } |
| 11014 | uintptr_t ptr = (uintptr_t)src; |
| 11015 | for(size_t i = 0; i < length; ++i) { |
| 11016 | s += calcSizeBinaryJumpTable[type->typeKind]((const void*)ptr, type); |
| 11017 | ptr += type->memSize; |
| 11018 | } |
| 11019 | return s; |
| 11020 | } |
| 11021 | |
| 11022 | static size_t calcSizeBinary1(const void *_, const UA_DataType *__) { (void)_, (void)__; return 1; } |
| 11023 | static size_t calcSizeBinary2(const void *_, const UA_DataType *__) { (void)_, (void)__; return 2; } |
| 11024 | static size_t calcSizeBinary4(const void *_, const UA_DataType *__) { (void)_, (void)__; return 4; } |
| 11025 | static size_t calcSizeBinary8(const void *_, const UA_DataType *__) { (void)_, (void)__; return 8; } |
| 11026 | |
| 11027 | CALCSIZE_BINARY(String) { return 4 + src->length; } |
| 11028 | |
| 11029 | CALCSIZE_BINARY(Guid) { return 16; } |
| 11030 | |
| 11031 | CALCSIZE_BINARY(NodeId) { |
| 11032 | size_t s = 1; /* Encoding byte */ |
| 11033 | switch(src->identifierType) { |
| 11034 | case UA_NODEIDTYPE_NUMERIC: |
| 11035 | if(src->identifier.numeric > UA_UINT16_MAX || src->namespaceIndex > UA_BYTE_MAX) { |
| 11036 | s += 6; |
| 11037 | } else if(src->identifier.numeric > UA_BYTE_MAX || src->namespaceIndex > 0) { |
| 11038 | s += 3; |
| 11039 | } else { |
| 11040 | s += 1; |
| 11041 | } |
| 11042 | break; |
| 11043 | case UA_NODEIDTYPE_BYTESTRING: |
| 11044 | case UA_NODEIDTYPE_STRING: |
| 11045 | s += 2; |
| 11046 | s += String_calcSizeBinary(src: &src->identifier.string, NULL); |
| 11047 | break; |
| 11048 | case UA_NODEIDTYPE_GUID: |
| 11049 | s += 18; |
| 11050 | break; |
| 11051 | default: |
| 11052 | return 0; |
| 11053 | } |
| 11054 | return s; |
| 11055 | } |
| 11056 | |
| 11057 | CALCSIZE_BINARY(ExpandedNodeId) { |
| 11058 | size_t s = NodeId_calcSizeBinary(src: &src->nodeId, NULL); |
| 11059 | if(src->namespaceUri.length > 0) |
| 11060 | s += String_calcSizeBinary(src: &src->namespaceUri, NULL); |
| 11061 | if(src->serverIndex > 0) |
| 11062 | s += 4; |
| 11063 | return s; |
| 11064 | } |
| 11065 | |
| 11066 | CALCSIZE_BINARY(QualifiedName) { |
| 11067 | return 2 + String_calcSizeBinary(src: &src->name, NULL); |
| 11068 | } |
| 11069 | |
| 11070 | CALCSIZE_BINARY(LocalizedText) { |
| 11071 | size_t s = 1; /* Encoding byte */ |
| 11072 | if(src->locale.data) |
| 11073 | s += String_calcSizeBinary(src: &src->locale, NULL); |
| 11074 | if(src->text.data) |
| 11075 | s += String_calcSizeBinary(src: &src->text, NULL); |
| 11076 | return s; |
| 11077 | } |
| 11078 | |
| 11079 | CALCSIZE_BINARY(ExtensionObject) { |
| 11080 | size_t s = 1; /* Encoding byte */ |
| 11081 | |
| 11082 | /* Encoded content */ |
| 11083 | if(src->encoding <= UA_EXTENSIONOBJECT_ENCODED_XML) { |
| 11084 | s += NodeId_calcSizeBinary(src: &src->content.encoded.typeId, NULL); |
| 11085 | switch(src->encoding) { |
| 11086 | case UA_EXTENSIONOBJECT_ENCODED_NOBODY: |
| 11087 | break; |
| 11088 | case UA_EXTENSIONOBJECT_ENCODED_BYTESTRING: |
| 11089 | case UA_EXTENSIONOBJECT_ENCODED_XML: |
| 11090 | s += String_calcSizeBinary(src: &src->content.encoded.body, NULL); |
| 11091 | break; |
| 11092 | default: |
| 11093 | return 0; |
| 11094 | } |
| 11095 | return s; |
| 11096 | } |
| 11097 | |
| 11098 | /* Decoded content */ |
| 11099 | if(!src->content.decoded.type || !src->content.decoded.data) |
| 11100 | return 0; |
| 11101 | if(src->content.decoded.type->typeId.identifierType != UA_NODEIDTYPE_NUMERIC) |
| 11102 | return 0; |
| 11103 | |
| 11104 | s += NodeId_calcSizeBinary(src: &src->content.decoded.type->binaryEncodingId, NULL); /* Type encoding length */ |
| 11105 | s += 4; /* Encoding length field */ |
| 11106 | const UA_DataType *type = src->content.decoded.type; |
| 11107 | s += calcSizeBinaryJumpTable[type->typeKind](src->content.decoded.data, type); /* Encoding length */ |
| 11108 | return s; |
| 11109 | } |
| 11110 | |
| 11111 | CALCSIZE_BINARY(Variant) { |
| 11112 | size_t s = 1; /* Encoding byte */ |
| 11113 | if(!src->type) |
| 11114 | return s; |
| 11115 | |
| 11116 | const UA_Boolean isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL; |
| 11117 | if(isArray) |
| 11118 | s += Array_calcSizeBinary(src: src->data, length: src->arrayLength, type: src->type); |
| 11119 | else |
| 11120 | s += calcSizeBinaryJumpTable[src->type->typeKind](src->data, src->type); |
| 11121 | |
| 11122 | const UA_Boolean isBuiltin = (src->type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO); |
| 11123 | const UA_Boolean isEnum = (src->type->typeKind == UA_DATATYPEKIND_ENUM); |
| 11124 | if(!isBuiltin && !isEnum) { |
| 11125 | /* The type is wrapped inside an extensionobject */ |
| 11126 | /* (NodeId + encoding byte + extension object length) * array length */ |
| 11127 | size_t length = isArray ? src->arrayLength : 1; |
| 11128 | s += (NodeId_calcSizeBinary(src: &src->type->binaryEncodingId, NULL) + 1 + 4) * length; |
| 11129 | } |
| 11130 | |
| 11131 | const UA_Boolean hasDimensions = isArray && src->arrayDimensionsSize > 0; |
| 11132 | if(hasDimensions) |
| 11133 | s += Array_calcSizeBinary(src: src->arrayDimensions, length: src->arrayDimensionsSize, |
| 11134 | type: &UA_TYPES[UA_TYPES_INT32]); |
| 11135 | return s; |
| 11136 | } |
| 11137 | |
| 11138 | CALCSIZE_BINARY(DataValue) { |
| 11139 | size_t s = 1; /* Encoding byte */ |
| 11140 | if(src->hasValue) |
| 11141 | s += Variant_calcSizeBinary(src: &src->value, NULL); |
| 11142 | if(src->hasStatus) |
| 11143 | s += 4; |
| 11144 | if(src->hasSourceTimestamp) |
| 11145 | s += 8; |
| 11146 | if(src->hasSourcePicoseconds) |
| 11147 | s += 2; |
| 11148 | if(src->hasServerTimestamp) |
| 11149 | s += 8; |
| 11150 | if(src->hasServerPicoseconds) |
| 11151 | s += 2; |
| 11152 | return s; |
| 11153 | } |
| 11154 | |
| 11155 | CALCSIZE_BINARY(DiagnosticInfo) { |
| 11156 | size_t s = 1; /* Encoding byte */ |
| 11157 | if(src->hasSymbolicId) |
| 11158 | s += 4; |
| 11159 | if(src->hasNamespaceUri) |
| 11160 | s += 4; |
| 11161 | if(src->hasLocalizedText) |
| 11162 | s += 4; |
| 11163 | if(src->hasLocale) |
| 11164 | s += 4; |
| 11165 | if(src->hasAdditionalInfo) |
| 11166 | s += String_calcSizeBinary(src: &src->additionalInfo, NULL); |
| 11167 | if(src->hasInnerStatusCode) |
| 11168 | s += 4; |
| 11169 | if(src->hasInnerDiagnosticInfo) |
| 11170 | s += DiagnosticInfo_calcSizeBinary(src: src->innerDiagnosticInfo, NULL); |
| 11171 | return s; |
| 11172 | } |
| 11173 | |
| 11174 | static size_t |
| 11175 | calcSizeBinaryStructure(const void *p, const UA_DataType *type) { |
| 11176 | size_t s = 0; |
| 11177 | uintptr_t ptr = (uintptr_t)p; |
| 11178 | u8 membersSize = type->membersSize; |
| 11179 | |
| 11180 | /* Loop over members */ |
| 11181 | for(size_t i = 0; i < membersSize; ++i) { |
| 11182 | const UA_DataTypeMember *member = &type->members[i]; |
| 11183 | const UA_DataType *membertype = member->memberType; |
| 11184 | ptr += member->padding; |
| 11185 | |
| 11186 | /* Array */ |
| 11187 | if(member->isArray) { |
| 11188 | const size_t length = *((const size_t*)ptr); |
| 11189 | ptr += sizeof(size_t); |
| 11190 | s += Array_calcSizeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: membertype); |
| 11191 | ptr += sizeof(void*); |
| 11192 | continue; |
| 11193 | } |
| 11194 | |
| 11195 | /* Scalar */ |
| 11196 | s += calcSizeBinaryJumpTable[membertype->typeKind]((const void*)ptr, membertype); |
| 11197 | ptr += membertype->memSize; |
| 11198 | } |
| 11199 | |
| 11200 | return s; |
| 11201 | } |
| 11202 | |
| 11203 | static size_t |
| 11204 | calcSizeBinaryStructureWithOptFields(const void *p, const UA_DataType *type) { |
| 11205 | /* Start with the size of the encoding mask */ |
| 11206 | size_t s = sizeof(UA_UInt32); |
| 11207 | |
| 11208 | /* Loop over members */ |
| 11209 | uintptr_t ptr = (uintptr_t)p; |
| 11210 | for(size_t i = 0; i < type->membersSize; ++i) { |
| 11211 | const UA_DataTypeMember *member = &type->members[i]; |
| 11212 | const UA_DataType *membertype = member->memberType; |
| 11213 | ptr += member->padding; |
| 11214 | if(member->isOptional) { |
| 11215 | if((member->isArray && ((*(void* const*)(ptr+sizeof(size_t))) == NULL)) || |
| 11216 | (!member->isArray && (*(void* const*)ptr == NULL))) { |
| 11217 | /* Optional member not contained */ |
| 11218 | if(member->isArray) |
| 11219 | ptr += sizeof(size_t); |
| 11220 | ptr += sizeof(void *); |
| 11221 | continue; |
| 11222 | } |
| 11223 | /* Fallthrough to take the size into account */ |
| 11224 | } |
| 11225 | /* Array */ |
| 11226 | if(member->isArray) { |
| 11227 | const size_t length = *((const size_t*)ptr); |
| 11228 | ptr += sizeof(size_t); |
| 11229 | s += Array_calcSizeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: membertype); |
| 11230 | ptr += sizeof(void*); |
| 11231 | continue; |
| 11232 | } |
| 11233 | /* Scalar */ |
| 11234 | if (member->isOptional) { |
| 11235 | s += calcSizeBinaryJumpTable[membertype->typeKind](*(void* const*)ptr, membertype); |
| 11236 | ptr += sizeof(void *); |
| 11237 | } else { |
| 11238 | s += calcSizeBinaryJumpTable[membertype->typeKind]((const void*)ptr, membertype); |
| 11239 | ptr += membertype->memSize; |
| 11240 | } |
| 11241 | } |
| 11242 | return s; |
| 11243 | } |
| 11244 | |
| 11245 | static size_t |
| 11246 | calcSizeBinaryUnion(const void *p, const UA_DataType *type) { |
| 11247 | size_t s = 4; /* UA_TYPES[UA_TYPES_UINT32].memSize; */ |
| 11248 | const UA_UInt32 selection = *(const UA_UInt32 *)p; |
| 11249 | if(selection == 0) |
| 11250 | return s; |
| 11251 | |
| 11252 | const UA_DataTypeMember *m = &type->members[selection-1]; |
| 11253 | const UA_DataType *mt = m->memberType; |
| 11254 | |
| 11255 | uintptr_t ptr = ((uintptr_t)p) + m->padding; /* includes switchfield length */ |
| 11256 | if(!m->isArray) { |
| 11257 | s += UA_calcSizeBinary(p: (const void*)ptr, type: mt); |
| 11258 | } else { |
| 11259 | const size_t length = *((const size_t*)ptr); |
| 11260 | ptr += sizeof(size_t); |
| 11261 | s += Array_calcSizeBinary(src: *(void *UA_RESTRICT const *)ptr, length, type: mt); |
| 11262 | } |
| 11263 | return s; |
| 11264 | } |
| 11265 | |
| 11266 | static size_t |
| 11267 | calcSizeBinaryNotImplemented(const void *p, const UA_DataType *type) { |
| 11268 | (void)p, (void)type; |
| 11269 | return 0; |
| 11270 | } |
| 11271 | |
| 11272 | const calcSizeBinarySignature calcSizeBinaryJumpTable[UA_DATATYPEKINDS] = { |
| 11273 | (calcSizeBinarySignature)calcSizeBinary1, /* Boolean */ |
| 11274 | (calcSizeBinarySignature)calcSizeBinary1, /* SByte */ |
| 11275 | (calcSizeBinarySignature)calcSizeBinary1, /* Byte */ |
| 11276 | (calcSizeBinarySignature)calcSizeBinary2, /* Int16 */ |
| 11277 | (calcSizeBinarySignature)calcSizeBinary2, /* UInt16 */ |
| 11278 | (calcSizeBinarySignature)calcSizeBinary4, /* Int32 */ |
| 11279 | (calcSizeBinarySignature)calcSizeBinary4, /* UInt32 */ |
| 11280 | (calcSizeBinarySignature)calcSizeBinary8, /* Int64 */ |
| 11281 | (calcSizeBinarySignature)calcSizeBinary8, /* UInt64 */ |
| 11282 | (calcSizeBinarySignature)calcSizeBinary4, /* Float */ |
| 11283 | (calcSizeBinarySignature)calcSizeBinary8, /* Double */ |
| 11284 | (calcSizeBinarySignature)String_calcSizeBinary, |
| 11285 | (calcSizeBinarySignature)calcSizeBinary8, /* DateTime */ |
| 11286 | (calcSizeBinarySignature)Guid_calcSizeBinary, |
| 11287 | (calcSizeBinarySignature)String_calcSizeBinary, /* ByteString */ |
| 11288 | (calcSizeBinarySignature)String_calcSizeBinary, /* XmlElement */ |
| 11289 | (calcSizeBinarySignature)NodeId_calcSizeBinary, |
| 11290 | (calcSizeBinarySignature)ExpandedNodeId_calcSizeBinary, |
| 11291 | (calcSizeBinarySignature)calcSizeBinary4, /* StatusCode */ |
| 11292 | (calcSizeBinarySignature)QualifiedName_calcSizeBinary, |
| 11293 | (calcSizeBinarySignature)LocalizedText_calcSizeBinary, |
| 11294 | (calcSizeBinarySignature)ExtensionObject_calcSizeBinary, |
| 11295 | (calcSizeBinarySignature)DataValue_calcSizeBinary, |
| 11296 | (calcSizeBinarySignature)Variant_calcSizeBinary, |
| 11297 | (calcSizeBinarySignature)DiagnosticInfo_calcSizeBinary, |
| 11298 | (calcSizeBinarySignature)calcSizeBinaryNotImplemented, /* Decimal */ |
| 11299 | (calcSizeBinarySignature)calcSizeBinary4, /* Enumeration */ |
| 11300 | (calcSizeBinarySignature)calcSizeBinaryStructure, |
| 11301 | (calcSizeBinarySignature)calcSizeBinaryStructureWithOptFields, /* Structure with Optional Fields */ |
| 11302 | (calcSizeBinarySignature)calcSizeBinaryUnion, /* Union */ |
| 11303 | (calcSizeBinarySignature)calcSizeBinaryNotImplemented /* BitfieldCluster */ |
| 11304 | }; |
| 11305 | |
| 11306 | size_t |
| 11307 | UA_calcSizeBinary(const void *p, const UA_DataType *type) { |
| 11308 | return calcSizeBinaryJumpTable[type->typeKind](p, type); |
| 11309 | } |
| 11310 | |
| 11311 | /**** amalgamated original file "/build/src_generated/open62541/types_generated.c" ****/ |
| 11312 | |
| 11313 | /********************************** |
| 11314 | * Autogenerated -- do not modify * |
| 11315 | **********************************/ |
| 11316 | |
| 11317 | |
| 11318 | /* Boolean */ |
| 11319 | #define Boolean_members NULL |
| 11320 | |
| 11321 | /* SByte */ |
| 11322 | #define SByte_members NULL |
| 11323 | |
| 11324 | /* Byte */ |
| 11325 | #define Byte_members NULL |
| 11326 | |
| 11327 | /* Int16 */ |
| 11328 | #define Int16_members NULL |
| 11329 | |
| 11330 | /* UInt16 */ |
| 11331 | #define UInt16_members NULL |
| 11332 | |
| 11333 | /* Int32 */ |
| 11334 | #define Int32_members NULL |
| 11335 | |
| 11336 | /* UInt32 */ |
| 11337 | #define UInt32_members NULL |
| 11338 | |
| 11339 | /* Int64 */ |
| 11340 | #define Int64_members NULL |
| 11341 | |
| 11342 | /* UInt64 */ |
| 11343 | #define UInt64_members NULL |
| 11344 | |
| 11345 | /* Float */ |
| 11346 | #define Float_members NULL |
| 11347 | |
| 11348 | /* Double */ |
| 11349 | #define Double_members NULL |
| 11350 | |
| 11351 | /* String */ |
| 11352 | #define String_members NULL |
| 11353 | |
| 11354 | /* DateTime */ |
| 11355 | #define DateTime_members NULL |
| 11356 | |
| 11357 | /* Guid */ |
| 11358 | #define Guid_members NULL |
| 11359 | |
| 11360 | /* ByteString */ |
| 11361 | #define ByteString_members NULL |
| 11362 | |
| 11363 | /* XmlElement */ |
| 11364 | #define XmlElement_members NULL |
| 11365 | |
| 11366 | /* NodeId */ |
| 11367 | #define NodeId_members NULL |
| 11368 | |
| 11369 | /* ExpandedNodeId */ |
| 11370 | #define ExpandedNodeId_members NULL |
| 11371 | |
| 11372 | /* StatusCode */ |
| 11373 | #define StatusCode_members NULL |
| 11374 | |
| 11375 | /* QualifiedName */ |
| 11376 | #define QualifiedName_members NULL |
| 11377 | |
| 11378 | /* LocalizedText */ |
| 11379 | #define LocalizedText_members NULL |
| 11380 | |
| 11381 | /* ExtensionObject */ |
| 11382 | #define ExtensionObject_members NULL |
| 11383 | |
| 11384 | /* DataValue */ |
| 11385 | #define DataValue_members NULL |
| 11386 | |
| 11387 | /* Variant */ |
| 11388 | #define Variant_members NULL |
| 11389 | |
| 11390 | /* DiagnosticInfo */ |
| 11391 | #define DiagnosticInfo_members NULL |
| 11392 | |
| 11393 | /* NamingRuleType */ |
| 11394 | #define NamingRuleType_members NULL |
| 11395 | |
| 11396 | /* Enumeration */ |
| 11397 | #define Enumeration_members NULL |
| 11398 | |
| 11399 | /* ImageBMP */ |
| 11400 | #define ImageBMP_members NULL |
| 11401 | |
| 11402 | /* ImageGIF */ |
| 11403 | #define ImageGIF_members NULL |
| 11404 | |
| 11405 | /* ImageJPG */ |
| 11406 | #define ImageJPG_members NULL |
| 11407 | |
| 11408 | /* ImagePNG */ |
| 11409 | #define ImagePNG_members NULL |
| 11410 | |
| 11411 | /* AudioDataType */ |
| 11412 | #define AudioDataType_members NULL |
| 11413 | |
| 11414 | /* UriString */ |
| 11415 | #define UriString_members NULL |
| 11416 | |
| 11417 | /* BitFieldMaskDataType */ |
| 11418 | #define BitFieldMaskDataType_members NULL |
| 11419 | |
| 11420 | /* SemanticVersionString */ |
| 11421 | #define SemanticVersionString_members NULL |
| 11422 | |
| 11423 | /* KeyValuePair */ |
| 11424 | static UA_DataTypeMember KeyValuePair_members[2] = { |
| 11425 | { |
| 11426 | UA_TYPENAME("Key") /* .memberName */ |
| 11427 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 11428 | 0, /* .padding */ |
| 11429 | false, /* .isArray */ |
| 11430 | false /* .isOptional */ |
| 11431 | }, |
| 11432 | { |
| 11433 | UA_TYPENAME("Value") /* .memberName */ |
| 11434 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 11435 | offsetof(UA_KeyValuePair, value) - offsetof(UA_KeyValuePair, key) - sizeof(UA_QualifiedName), /* .padding */ |
| 11436 | false, /* .isArray */ |
| 11437 | false /* .isOptional */ |
| 11438 | },}; |
| 11439 | |
| 11440 | /* AdditionalParametersType */ |
| 11441 | static UA_DataTypeMember AdditionalParametersType_members[1] = { |
| 11442 | { |
| 11443 | UA_TYPENAME("Parameters") /* .memberName */ |
| 11444 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 11445 | 0, /* .padding */ |
| 11446 | true, /* .isArray */ |
| 11447 | false /* .isOptional */ |
| 11448 | },}; |
| 11449 | |
| 11450 | /* EphemeralKeyType */ |
| 11451 | static UA_DataTypeMember EphemeralKeyType_members[2] = { |
| 11452 | { |
| 11453 | UA_TYPENAME("PublicKey") /* .memberName */ |
| 11454 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 11455 | 0, /* .padding */ |
| 11456 | false, /* .isArray */ |
| 11457 | false /* .isOptional */ |
| 11458 | }, |
| 11459 | { |
| 11460 | UA_TYPENAME("Signature") /* .memberName */ |
| 11461 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 11462 | offsetof(UA_EphemeralKeyType, signature) - offsetof(UA_EphemeralKeyType, publicKey) - sizeof(UA_ByteString), /* .padding */ |
| 11463 | false, /* .isArray */ |
| 11464 | false /* .isOptional */ |
| 11465 | },}; |
| 11466 | |
| 11467 | /* RationalNumber */ |
| 11468 | static UA_DataTypeMember RationalNumber_members[2] = { |
| 11469 | { |
| 11470 | UA_TYPENAME("Numerator") /* .memberName */ |
| 11471 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 11472 | 0, /* .padding */ |
| 11473 | false, /* .isArray */ |
| 11474 | false /* .isOptional */ |
| 11475 | }, |
| 11476 | { |
| 11477 | UA_TYPENAME("Denominator") /* .memberName */ |
| 11478 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 11479 | offsetof(UA_RationalNumber, denominator) - offsetof(UA_RationalNumber, numerator) - sizeof(UA_Int32), /* .padding */ |
| 11480 | false, /* .isArray */ |
| 11481 | false /* .isOptional */ |
| 11482 | },}; |
| 11483 | |
| 11484 | /* ThreeDVector */ |
| 11485 | static UA_DataTypeMember ThreeDVector_members[3] = { |
| 11486 | { |
| 11487 | UA_TYPENAME("X") /* .memberName */ |
| 11488 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11489 | 0, /* .padding */ |
| 11490 | false, /* .isArray */ |
| 11491 | false /* .isOptional */ |
| 11492 | }, |
| 11493 | { |
| 11494 | UA_TYPENAME("Y") /* .memberName */ |
| 11495 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11496 | offsetof(UA_ThreeDVector, y) - offsetof(UA_ThreeDVector, x) - sizeof(UA_Double), /* .padding */ |
| 11497 | false, /* .isArray */ |
| 11498 | false /* .isOptional */ |
| 11499 | }, |
| 11500 | { |
| 11501 | UA_TYPENAME("Z") /* .memberName */ |
| 11502 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11503 | offsetof(UA_ThreeDVector, z) - offsetof(UA_ThreeDVector, y) - sizeof(UA_Double), /* .padding */ |
| 11504 | false, /* .isArray */ |
| 11505 | false /* .isOptional */ |
| 11506 | },}; |
| 11507 | |
| 11508 | /* ThreeDCartesianCoordinates */ |
| 11509 | static UA_DataTypeMember ThreeDCartesianCoordinates_members[3] = { |
| 11510 | { |
| 11511 | UA_TYPENAME("X") /* .memberName */ |
| 11512 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11513 | 0, /* .padding */ |
| 11514 | false, /* .isArray */ |
| 11515 | false /* .isOptional */ |
| 11516 | }, |
| 11517 | { |
| 11518 | UA_TYPENAME("Y") /* .memberName */ |
| 11519 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11520 | offsetof(UA_ThreeDCartesianCoordinates, y) - offsetof(UA_ThreeDCartesianCoordinates, x) - sizeof(UA_Double), /* .padding */ |
| 11521 | false, /* .isArray */ |
| 11522 | false /* .isOptional */ |
| 11523 | }, |
| 11524 | { |
| 11525 | UA_TYPENAME("Z") /* .memberName */ |
| 11526 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11527 | offsetof(UA_ThreeDCartesianCoordinates, z) - offsetof(UA_ThreeDCartesianCoordinates, y) - sizeof(UA_Double), /* .padding */ |
| 11528 | false, /* .isArray */ |
| 11529 | false /* .isOptional */ |
| 11530 | },}; |
| 11531 | |
| 11532 | /* ThreeDOrientation */ |
| 11533 | static UA_DataTypeMember ThreeDOrientation_members[3] = { |
| 11534 | { |
| 11535 | UA_TYPENAME("A") /* .memberName */ |
| 11536 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11537 | 0, /* .padding */ |
| 11538 | false, /* .isArray */ |
| 11539 | false /* .isOptional */ |
| 11540 | }, |
| 11541 | { |
| 11542 | UA_TYPENAME("B") /* .memberName */ |
| 11543 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11544 | offsetof(UA_ThreeDOrientation, b) - offsetof(UA_ThreeDOrientation, a) - sizeof(UA_Double), /* .padding */ |
| 11545 | false, /* .isArray */ |
| 11546 | false /* .isOptional */ |
| 11547 | }, |
| 11548 | { |
| 11549 | UA_TYPENAME("C") /* .memberName */ |
| 11550 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11551 | offsetof(UA_ThreeDOrientation, c) - offsetof(UA_ThreeDOrientation, b) - sizeof(UA_Double), /* .padding */ |
| 11552 | false, /* .isArray */ |
| 11553 | false /* .isOptional */ |
| 11554 | },}; |
| 11555 | |
| 11556 | /* ThreeDFrame */ |
| 11557 | static UA_DataTypeMember ThreeDFrame_members[2] = { |
| 11558 | { |
| 11559 | UA_TYPENAME("CartesianCoordinates") /* .memberName */ |
| 11560 | &UA_TYPES[UA_TYPES_THREEDCARTESIANCOORDINATES], /* .memberType */ |
| 11561 | 0, /* .padding */ |
| 11562 | false, /* .isArray */ |
| 11563 | false /* .isOptional */ |
| 11564 | }, |
| 11565 | { |
| 11566 | UA_TYPENAME("Orientation") /* .memberName */ |
| 11567 | &UA_TYPES[UA_TYPES_THREEDORIENTATION], /* .memberType */ |
| 11568 | offsetof(UA_ThreeDFrame, orientation) - offsetof(UA_ThreeDFrame, cartesianCoordinates) - sizeof(UA_ThreeDCartesianCoordinates), /* .padding */ |
| 11569 | false, /* .isArray */ |
| 11570 | false /* .isOptional */ |
| 11571 | },}; |
| 11572 | |
| 11573 | /* OpenFileMode */ |
| 11574 | #define OpenFileMode_members NULL |
| 11575 | |
| 11576 | /* IdentityCriteriaType */ |
| 11577 | #define IdentityCriteriaType_members NULL |
| 11578 | |
| 11579 | /* IdentityMappingRuleType */ |
| 11580 | static UA_DataTypeMember IdentityMappingRuleType_members[2] = { |
| 11581 | { |
| 11582 | UA_TYPENAME("CriteriaType") /* .memberName */ |
| 11583 | &UA_TYPES[UA_TYPES_IDENTITYCRITERIATYPE], /* .memberType */ |
| 11584 | 0, /* .padding */ |
| 11585 | false, /* .isArray */ |
| 11586 | false /* .isOptional */ |
| 11587 | }, |
| 11588 | { |
| 11589 | UA_TYPENAME("Criteria") /* .memberName */ |
| 11590 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11591 | offsetof(UA_IdentityMappingRuleType, criteria) - offsetof(UA_IdentityMappingRuleType, criteriaType) - sizeof(UA_IdentityCriteriaType), /* .padding */ |
| 11592 | false, /* .isArray */ |
| 11593 | false /* .isOptional */ |
| 11594 | },}; |
| 11595 | |
| 11596 | /* CurrencyUnitType */ |
| 11597 | static UA_DataTypeMember CurrencyUnitType_members[4] = { |
| 11598 | { |
| 11599 | UA_TYPENAME("NumericCode") /* .memberName */ |
| 11600 | &UA_TYPES[UA_TYPES_INT16], /* .memberType */ |
| 11601 | 0, /* .padding */ |
| 11602 | false, /* .isArray */ |
| 11603 | false /* .isOptional */ |
| 11604 | }, |
| 11605 | { |
| 11606 | UA_TYPENAME("Exponent") /* .memberName */ |
| 11607 | &UA_TYPES[UA_TYPES_SBYTE], /* .memberType */ |
| 11608 | offsetof(UA_CurrencyUnitType, exponent) - offsetof(UA_CurrencyUnitType, numericCode) - sizeof(UA_Int16), /* .padding */ |
| 11609 | false, /* .isArray */ |
| 11610 | false /* .isOptional */ |
| 11611 | }, |
| 11612 | { |
| 11613 | UA_TYPENAME("AlphabeticCode") /* .memberName */ |
| 11614 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11615 | offsetof(UA_CurrencyUnitType, alphabeticCode) - offsetof(UA_CurrencyUnitType, exponent) - sizeof(UA_SByte), /* .padding */ |
| 11616 | false, /* .isArray */ |
| 11617 | false /* .isOptional */ |
| 11618 | }, |
| 11619 | { |
| 11620 | UA_TYPENAME("Currency") /* .memberName */ |
| 11621 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 11622 | offsetof(UA_CurrencyUnitType, currency) - offsetof(UA_CurrencyUnitType, alphabeticCode) - sizeof(UA_String), /* .padding */ |
| 11623 | false, /* .isArray */ |
| 11624 | false /* .isOptional */ |
| 11625 | },}; |
| 11626 | |
| 11627 | /* TrustListMasks */ |
| 11628 | #define TrustListMasks_members NULL |
| 11629 | |
| 11630 | /* TrustListDataType */ |
| 11631 | static UA_DataTypeMember TrustListDataType_members[5] = { |
| 11632 | { |
| 11633 | UA_TYPENAME("SpecifiedLists") /* .memberName */ |
| 11634 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 11635 | 0, /* .padding */ |
| 11636 | false, /* .isArray */ |
| 11637 | false /* .isOptional */ |
| 11638 | }, |
| 11639 | { |
| 11640 | UA_TYPENAME("TrustedCertificates") /* .memberName */ |
| 11641 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 11642 | offsetof(UA_TrustListDataType, trustedCertificatesSize) - offsetof(UA_TrustListDataType, specifiedLists) - sizeof(UA_UInt32), /* .padding */ |
| 11643 | true, /* .isArray */ |
| 11644 | false /* .isOptional */ |
| 11645 | }, |
| 11646 | { |
| 11647 | UA_TYPENAME("TrustedCrls") /* .memberName */ |
| 11648 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 11649 | offsetof(UA_TrustListDataType, trustedCrlsSize) - offsetof(UA_TrustListDataType, trustedCertificates) - sizeof(void *), /* .padding */ |
| 11650 | true, /* .isArray */ |
| 11651 | false /* .isOptional */ |
| 11652 | }, |
| 11653 | { |
| 11654 | UA_TYPENAME("IssuerCertificates") /* .memberName */ |
| 11655 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 11656 | offsetof(UA_TrustListDataType, issuerCertificatesSize) - offsetof(UA_TrustListDataType, trustedCrls) - sizeof(void *), /* .padding */ |
| 11657 | true, /* .isArray */ |
| 11658 | false /* .isOptional */ |
| 11659 | }, |
| 11660 | { |
| 11661 | UA_TYPENAME("IssuerCrls") /* .memberName */ |
| 11662 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 11663 | offsetof(UA_TrustListDataType, issuerCrlsSize) - offsetof(UA_TrustListDataType, issuerCertificates) - sizeof(void *), /* .padding */ |
| 11664 | true, /* .isArray */ |
| 11665 | false /* .isOptional */ |
| 11666 | },}; |
| 11667 | |
| 11668 | /* DecimalDataType */ |
| 11669 | static UA_DataTypeMember DecimalDataType_members[2] = { |
| 11670 | { |
| 11671 | UA_TYPENAME("Scale") /* .memberName */ |
| 11672 | &UA_TYPES[UA_TYPES_INT16], /* .memberType */ |
| 11673 | 0, /* .padding */ |
| 11674 | false, /* .isArray */ |
| 11675 | false /* .isOptional */ |
| 11676 | }, |
| 11677 | { |
| 11678 | UA_TYPENAME("Value") /* .memberName */ |
| 11679 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 11680 | offsetof(UA_DecimalDataType, value) - offsetof(UA_DecimalDataType, scale) - sizeof(UA_Int16), /* .padding */ |
| 11681 | false, /* .isArray */ |
| 11682 | false /* .isOptional */ |
| 11683 | },}; |
| 11684 | |
| 11685 | /* DataTypeDescription */ |
| 11686 | static UA_DataTypeMember DataTypeDescription_members[2] = { |
| 11687 | { |
| 11688 | UA_TYPENAME("DataTypeId") /* .memberName */ |
| 11689 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 11690 | 0, /* .padding */ |
| 11691 | false, /* .isArray */ |
| 11692 | false /* .isOptional */ |
| 11693 | }, |
| 11694 | { |
| 11695 | UA_TYPENAME("Name") /* .memberName */ |
| 11696 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 11697 | offsetof(UA_DataTypeDescription, name) - offsetof(UA_DataTypeDescription, dataTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 11698 | false, /* .isArray */ |
| 11699 | false /* .isOptional */ |
| 11700 | },}; |
| 11701 | |
| 11702 | /* SimpleTypeDescription */ |
| 11703 | static UA_DataTypeMember SimpleTypeDescription_members[4] = { |
| 11704 | { |
| 11705 | UA_TYPENAME("DataTypeId") /* .memberName */ |
| 11706 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 11707 | 0, /* .padding */ |
| 11708 | false, /* .isArray */ |
| 11709 | false /* .isOptional */ |
| 11710 | }, |
| 11711 | { |
| 11712 | UA_TYPENAME("Name") /* .memberName */ |
| 11713 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 11714 | offsetof(UA_SimpleTypeDescription, name) - offsetof(UA_SimpleTypeDescription, dataTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 11715 | false, /* .isArray */ |
| 11716 | false /* .isOptional */ |
| 11717 | }, |
| 11718 | { |
| 11719 | UA_TYPENAME("BaseDataType") /* .memberName */ |
| 11720 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 11721 | offsetof(UA_SimpleTypeDescription, baseDataType) - offsetof(UA_SimpleTypeDescription, name) - sizeof(UA_QualifiedName), /* .padding */ |
| 11722 | false, /* .isArray */ |
| 11723 | false /* .isOptional */ |
| 11724 | }, |
| 11725 | { |
| 11726 | UA_TYPENAME("BuiltInType") /* .memberName */ |
| 11727 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 11728 | offsetof(UA_SimpleTypeDescription, builtInType) - offsetof(UA_SimpleTypeDescription, baseDataType) - sizeof(UA_NodeId), /* .padding */ |
| 11729 | false, /* .isArray */ |
| 11730 | false /* .isOptional */ |
| 11731 | },}; |
| 11732 | |
| 11733 | /* PortableQualifiedName */ |
| 11734 | static UA_DataTypeMember PortableQualifiedName_members[2] = { |
| 11735 | { |
| 11736 | UA_TYPENAME("NamespaceUri") /* .memberName */ |
| 11737 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11738 | 0, /* .padding */ |
| 11739 | false, /* .isArray */ |
| 11740 | false /* .isOptional */ |
| 11741 | }, |
| 11742 | { |
| 11743 | UA_TYPENAME("Name") /* .memberName */ |
| 11744 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11745 | offsetof(UA_PortableQualifiedName, name) - offsetof(UA_PortableQualifiedName, namespaceUri) - sizeof(UA_String), /* .padding */ |
| 11746 | false, /* .isArray */ |
| 11747 | false /* .isOptional */ |
| 11748 | },}; |
| 11749 | |
| 11750 | /* PortableNodeId */ |
| 11751 | static UA_DataTypeMember PortableNodeId_members[2] = { |
| 11752 | { |
| 11753 | UA_TYPENAME("NamespaceUri") /* .memberName */ |
| 11754 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11755 | 0, /* .padding */ |
| 11756 | false, /* .isArray */ |
| 11757 | false /* .isOptional */ |
| 11758 | }, |
| 11759 | { |
| 11760 | UA_TYPENAME("Identifier") /* .memberName */ |
| 11761 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 11762 | offsetof(UA_PortableNodeId, identifier) - offsetof(UA_PortableNodeId, namespaceUri) - sizeof(UA_String), /* .padding */ |
| 11763 | false, /* .isArray */ |
| 11764 | false /* .isOptional */ |
| 11765 | },}; |
| 11766 | |
| 11767 | /* UnsignedRationalNumber */ |
| 11768 | static UA_DataTypeMember UnsignedRationalNumber_members[2] = { |
| 11769 | { |
| 11770 | UA_TYPENAME("Numerator") /* .memberName */ |
| 11771 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 11772 | 0, /* .padding */ |
| 11773 | false, /* .isArray */ |
| 11774 | false /* .isOptional */ |
| 11775 | }, |
| 11776 | { |
| 11777 | UA_TYPENAME("Denominator") /* .memberName */ |
| 11778 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 11779 | offsetof(UA_UnsignedRationalNumber, denominator) - offsetof(UA_UnsignedRationalNumber, numerator) - sizeof(UA_UInt32), /* .padding */ |
| 11780 | false, /* .isArray */ |
| 11781 | false /* .isOptional */ |
| 11782 | },}; |
| 11783 | |
| 11784 | /* PubSubState */ |
| 11785 | #define PubSubState_members NULL |
| 11786 | |
| 11787 | /* DataSetFieldFlags */ |
| 11788 | #define DataSetFieldFlags_members NULL |
| 11789 | |
| 11790 | /* ConfigurationVersionDataType */ |
| 11791 | static UA_DataTypeMember ConfigurationVersionDataType_members[2] = { |
| 11792 | { |
| 11793 | UA_TYPENAME("MajorVersion") /* .memberName */ |
| 11794 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 11795 | 0, /* .padding */ |
| 11796 | false, /* .isArray */ |
| 11797 | false /* .isOptional */ |
| 11798 | }, |
| 11799 | { |
| 11800 | UA_TYPENAME("MinorVersion") /* .memberName */ |
| 11801 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 11802 | offsetof(UA_ConfigurationVersionDataType, minorVersion) - offsetof(UA_ConfigurationVersionDataType, majorVersion) - sizeof(UA_UInt32), /* .padding */ |
| 11803 | false, /* .isArray */ |
| 11804 | false /* .isOptional */ |
| 11805 | },}; |
| 11806 | |
| 11807 | /* PublishedVariableDataType */ |
| 11808 | static UA_DataTypeMember PublishedVariableDataType_members[8] = { |
| 11809 | { |
| 11810 | UA_TYPENAME("PublishedVariable") /* .memberName */ |
| 11811 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 11812 | 0, /* .padding */ |
| 11813 | false, /* .isArray */ |
| 11814 | false /* .isOptional */ |
| 11815 | }, |
| 11816 | { |
| 11817 | UA_TYPENAME("AttributeId") /* .memberName */ |
| 11818 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 11819 | offsetof(UA_PublishedVariableDataType, attributeId) - offsetof(UA_PublishedVariableDataType, publishedVariable) - sizeof(UA_NodeId), /* .padding */ |
| 11820 | false, /* .isArray */ |
| 11821 | false /* .isOptional */ |
| 11822 | }, |
| 11823 | { |
| 11824 | UA_TYPENAME("SamplingIntervalHint") /* .memberName */ |
| 11825 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11826 | offsetof(UA_PublishedVariableDataType, samplingIntervalHint) - offsetof(UA_PublishedVariableDataType, attributeId) - sizeof(UA_UInt32), /* .padding */ |
| 11827 | false, /* .isArray */ |
| 11828 | false /* .isOptional */ |
| 11829 | }, |
| 11830 | { |
| 11831 | UA_TYPENAME("DeadbandType") /* .memberName */ |
| 11832 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 11833 | offsetof(UA_PublishedVariableDataType, deadbandType) - offsetof(UA_PublishedVariableDataType, samplingIntervalHint) - sizeof(UA_Double), /* .padding */ |
| 11834 | false, /* .isArray */ |
| 11835 | false /* .isOptional */ |
| 11836 | }, |
| 11837 | { |
| 11838 | UA_TYPENAME("DeadbandValue") /* .memberName */ |
| 11839 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 11840 | offsetof(UA_PublishedVariableDataType, deadbandValue) - offsetof(UA_PublishedVariableDataType, deadbandType) - sizeof(UA_UInt32), /* .padding */ |
| 11841 | false, /* .isArray */ |
| 11842 | false /* .isOptional */ |
| 11843 | }, |
| 11844 | { |
| 11845 | UA_TYPENAME("IndexRange") /* .memberName */ |
| 11846 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11847 | offsetof(UA_PublishedVariableDataType, indexRange) - offsetof(UA_PublishedVariableDataType, deadbandValue) - sizeof(UA_Double), /* .padding */ |
| 11848 | false, /* .isArray */ |
| 11849 | false /* .isOptional */ |
| 11850 | }, |
| 11851 | { |
| 11852 | UA_TYPENAME("SubstituteValue") /* .memberName */ |
| 11853 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 11854 | offsetof(UA_PublishedVariableDataType, substituteValue) - offsetof(UA_PublishedVariableDataType, indexRange) - sizeof(UA_String), /* .padding */ |
| 11855 | false, /* .isArray */ |
| 11856 | false /* .isOptional */ |
| 11857 | }, |
| 11858 | { |
| 11859 | UA_TYPENAME("MetaDataProperties") /* .memberName */ |
| 11860 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 11861 | offsetof(UA_PublishedVariableDataType, metaDataPropertiesSize) - offsetof(UA_PublishedVariableDataType, substituteValue) - sizeof(UA_Variant), /* .padding */ |
| 11862 | true, /* .isArray */ |
| 11863 | false /* .isOptional */ |
| 11864 | },}; |
| 11865 | |
| 11866 | /* PublishedDataItemsDataType */ |
| 11867 | static UA_DataTypeMember PublishedDataItemsDataType_members[1] = { |
| 11868 | { |
| 11869 | UA_TYPENAME("PublishedData") /* .memberName */ |
| 11870 | &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE], /* .memberType */ |
| 11871 | 0, /* .padding */ |
| 11872 | true, /* .isArray */ |
| 11873 | false /* .isOptional */ |
| 11874 | },}; |
| 11875 | |
| 11876 | /* PublishedDataSetCustomSourceDataType */ |
| 11877 | static UA_DataTypeMember PublishedDataSetCustomSourceDataType_members[1] = { |
| 11878 | { |
| 11879 | UA_TYPENAME("CyclicDataSet") /* .memberName */ |
| 11880 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 11881 | 0, /* .padding */ |
| 11882 | false, /* .isArray */ |
| 11883 | false /* .isOptional */ |
| 11884 | },}; |
| 11885 | |
| 11886 | /* DataSetFieldContentMask */ |
| 11887 | #define DataSetFieldContentMask_members NULL |
| 11888 | |
| 11889 | /* DataSetWriterDataType */ |
| 11890 | static UA_DataTypeMember DataSetWriterDataType_members[9] = { |
| 11891 | { |
| 11892 | UA_TYPENAME("Name") /* .memberName */ |
| 11893 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11894 | 0, /* .padding */ |
| 11895 | false, /* .isArray */ |
| 11896 | false /* .isOptional */ |
| 11897 | }, |
| 11898 | { |
| 11899 | UA_TYPENAME("Enabled") /* .memberName */ |
| 11900 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 11901 | offsetof(UA_DataSetWriterDataType, enabled) - offsetof(UA_DataSetWriterDataType, name) - sizeof(UA_String), /* .padding */ |
| 11902 | false, /* .isArray */ |
| 11903 | false /* .isOptional */ |
| 11904 | }, |
| 11905 | { |
| 11906 | UA_TYPENAME("DataSetWriterId") /* .memberName */ |
| 11907 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 11908 | offsetof(UA_DataSetWriterDataType, dataSetWriterId) - offsetof(UA_DataSetWriterDataType, enabled) - sizeof(UA_Boolean), /* .padding */ |
| 11909 | false, /* .isArray */ |
| 11910 | false /* .isOptional */ |
| 11911 | }, |
| 11912 | { |
| 11913 | UA_TYPENAME("DataSetFieldContentMask") /* .memberName */ |
| 11914 | &UA_TYPES[UA_TYPES_DATASETFIELDCONTENTMASK], /* .memberType */ |
| 11915 | offsetof(UA_DataSetWriterDataType, dataSetFieldContentMask) - offsetof(UA_DataSetWriterDataType, dataSetWriterId) - sizeof(UA_UInt16), /* .padding */ |
| 11916 | false, /* .isArray */ |
| 11917 | false /* .isOptional */ |
| 11918 | }, |
| 11919 | { |
| 11920 | UA_TYPENAME("KeyFrameCount") /* .memberName */ |
| 11921 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 11922 | offsetof(UA_DataSetWriterDataType, keyFrameCount) - offsetof(UA_DataSetWriterDataType, dataSetFieldContentMask) - sizeof(UA_DataSetFieldContentMask), /* .padding */ |
| 11923 | false, /* .isArray */ |
| 11924 | false /* .isOptional */ |
| 11925 | }, |
| 11926 | { |
| 11927 | UA_TYPENAME("DataSetName") /* .memberName */ |
| 11928 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11929 | offsetof(UA_DataSetWriterDataType, dataSetName) - offsetof(UA_DataSetWriterDataType, keyFrameCount) - sizeof(UA_UInt32), /* .padding */ |
| 11930 | false, /* .isArray */ |
| 11931 | false /* .isOptional */ |
| 11932 | }, |
| 11933 | { |
| 11934 | UA_TYPENAME("DataSetWriterProperties") /* .memberName */ |
| 11935 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 11936 | offsetof(UA_DataSetWriterDataType, dataSetWriterPropertiesSize) - offsetof(UA_DataSetWriterDataType, dataSetName) - sizeof(UA_String), /* .padding */ |
| 11937 | true, /* .isArray */ |
| 11938 | false /* .isOptional */ |
| 11939 | }, |
| 11940 | { |
| 11941 | UA_TYPENAME("TransportSettings") /* .memberName */ |
| 11942 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 11943 | offsetof(UA_DataSetWriterDataType, transportSettings) - offsetof(UA_DataSetWriterDataType, dataSetWriterProperties) - sizeof(void *), /* .padding */ |
| 11944 | false, /* .isArray */ |
| 11945 | false /* .isOptional */ |
| 11946 | }, |
| 11947 | { |
| 11948 | UA_TYPENAME("MessageSettings") /* .memberName */ |
| 11949 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 11950 | offsetof(UA_DataSetWriterDataType, messageSettings) - offsetof(UA_DataSetWriterDataType, transportSettings) - sizeof(UA_ExtensionObject), /* .padding */ |
| 11951 | false, /* .isArray */ |
| 11952 | false /* .isOptional */ |
| 11953 | },}; |
| 11954 | |
| 11955 | /* NetworkAddressDataType */ |
| 11956 | static UA_DataTypeMember NetworkAddressDataType_members[1] = { |
| 11957 | { |
| 11958 | UA_TYPENAME("NetworkInterface") /* .memberName */ |
| 11959 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11960 | 0, /* .padding */ |
| 11961 | false, /* .isArray */ |
| 11962 | false /* .isOptional */ |
| 11963 | },}; |
| 11964 | |
| 11965 | /* NetworkAddressUrlDataType */ |
| 11966 | static UA_DataTypeMember NetworkAddressUrlDataType_members[2] = { |
| 11967 | { |
| 11968 | UA_TYPENAME("NetworkInterface") /* .memberName */ |
| 11969 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11970 | 0, /* .padding */ |
| 11971 | false, /* .isArray */ |
| 11972 | false /* .isOptional */ |
| 11973 | }, |
| 11974 | { |
| 11975 | UA_TYPENAME("Url") /* .memberName */ |
| 11976 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11977 | offsetof(UA_NetworkAddressUrlDataType, url) - offsetof(UA_NetworkAddressUrlDataType, networkInterface) - sizeof(UA_String), /* .padding */ |
| 11978 | false, /* .isArray */ |
| 11979 | false /* .isOptional */ |
| 11980 | },}; |
| 11981 | |
| 11982 | /* OverrideValueHandling */ |
| 11983 | #define OverrideValueHandling_members NULL |
| 11984 | |
| 11985 | /* StandaloneSubscribedDataSetRefDataType */ |
| 11986 | static UA_DataTypeMember StandaloneSubscribedDataSetRefDataType_members[1] = { |
| 11987 | { |
| 11988 | UA_TYPENAME("DataSetName") /* .memberName */ |
| 11989 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 11990 | 0, /* .padding */ |
| 11991 | false, /* .isArray */ |
| 11992 | false /* .isOptional */ |
| 11993 | },}; |
| 11994 | |
| 11995 | /* DataSetOrderingType */ |
| 11996 | #define DataSetOrderingType_members NULL |
| 11997 | |
| 11998 | /* UadpNetworkMessageContentMask */ |
| 11999 | #define UadpNetworkMessageContentMask_members NULL |
| 12000 | |
| 12001 | /* UadpWriterGroupMessageDataType */ |
| 12002 | static UA_DataTypeMember UadpWriterGroupMessageDataType_members[5] = { |
| 12003 | { |
| 12004 | UA_TYPENAME("GroupVersion") /* .memberName */ |
| 12005 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 12006 | 0, /* .padding */ |
| 12007 | false, /* .isArray */ |
| 12008 | false /* .isOptional */ |
| 12009 | }, |
| 12010 | { |
| 12011 | UA_TYPENAME("DataSetOrdering") /* .memberName */ |
| 12012 | &UA_TYPES[UA_TYPES_DATASETORDERINGTYPE], /* .memberType */ |
| 12013 | offsetof(UA_UadpWriterGroupMessageDataType, dataSetOrdering) - offsetof(UA_UadpWriterGroupMessageDataType, groupVersion) - sizeof(UA_UInt32), /* .padding */ |
| 12014 | false, /* .isArray */ |
| 12015 | false /* .isOptional */ |
| 12016 | }, |
| 12017 | { |
| 12018 | UA_TYPENAME("NetworkMessageContentMask") /* .memberName */ |
| 12019 | &UA_TYPES[UA_TYPES_UADPNETWORKMESSAGECONTENTMASK], /* .memberType */ |
| 12020 | offsetof(UA_UadpWriterGroupMessageDataType, networkMessageContentMask) - offsetof(UA_UadpWriterGroupMessageDataType, dataSetOrdering) - sizeof(UA_DataSetOrderingType), /* .padding */ |
| 12021 | false, /* .isArray */ |
| 12022 | false /* .isOptional */ |
| 12023 | }, |
| 12024 | { |
| 12025 | UA_TYPENAME("SamplingOffset") /* .memberName */ |
| 12026 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 12027 | offsetof(UA_UadpWriterGroupMessageDataType, samplingOffset) - offsetof(UA_UadpWriterGroupMessageDataType, networkMessageContentMask) - sizeof(UA_UadpNetworkMessageContentMask), /* .padding */ |
| 12028 | false, /* .isArray */ |
| 12029 | false /* .isOptional */ |
| 12030 | }, |
| 12031 | { |
| 12032 | UA_TYPENAME("PublishingOffset") /* .memberName */ |
| 12033 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 12034 | offsetof(UA_UadpWriterGroupMessageDataType, publishingOffsetSize) - offsetof(UA_UadpWriterGroupMessageDataType, samplingOffset) - sizeof(UA_Double), /* .padding */ |
| 12035 | true, /* .isArray */ |
| 12036 | false /* .isOptional */ |
| 12037 | },}; |
| 12038 | |
| 12039 | /* UadpDataSetMessageContentMask */ |
| 12040 | #define UadpDataSetMessageContentMask_members NULL |
| 12041 | |
| 12042 | /* UadpDataSetWriterMessageDataType */ |
| 12043 | static UA_DataTypeMember UadpDataSetWriterMessageDataType_members[4] = { |
| 12044 | { |
| 12045 | UA_TYPENAME("DataSetMessageContentMask") /* .memberName */ |
| 12046 | &UA_TYPES[UA_TYPES_UADPDATASETMESSAGECONTENTMASK], /* .memberType */ |
| 12047 | 0, /* .padding */ |
| 12048 | false, /* .isArray */ |
| 12049 | false /* .isOptional */ |
| 12050 | }, |
| 12051 | { |
| 12052 | UA_TYPENAME("ConfiguredSize") /* .memberName */ |
| 12053 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 12054 | offsetof(UA_UadpDataSetWriterMessageDataType, configuredSize) - offsetof(UA_UadpDataSetWriterMessageDataType, dataSetMessageContentMask) - sizeof(UA_UadpDataSetMessageContentMask), /* .padding */ |
| 12055 | false, /* .isArray */ |
| 12056 | false /* .isOptional */ |
| 12057 | }, |
| 12058 | { |
| 12059 | UA_TYPENAME("NetworkMessageNumber") /* .memberName */ |
| 12060 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 12061 | offsetof(UA_UadpDataSetWriterMessageDataType, networkMessageNumber) - offsetof(UA_UadpDataSetWriterMessageDataType, configuredSize) - sizeof(UA_UInt16), /* .padding */ |
| 12062 | false, /* .isArray */ |
| 12063 | false /* .isOptional */ |
| 12064 | }, |
| 12065 | { |
| 12066 | UA_TYPENAME("DataSetOffset") /* .memberName */ |
| 12067 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 12068 | offsetof(UA_UadpDataSetWriterMessageDataType, dataSetOffset) - offsetof(UA_UadpDataSetWriterMessageDataType, networkMessageNumber) - sizeof(UA_UInt16), /* .padding */ |
| 12069 | false, /* .isArray */ |
| 12070 | false /* .isOptional */ |
| 12071 | },}; |
| 12072 | |
| 12073 | /* UadpDataSetReaderMessageDataType */ |
| 12074 | static UA_DataTypeMember UadpDataSetReaderMessageDataType_members[9] = { |
| 12075 | { |
| 12076 | UA_TYPENAME("GroupVersion") /* .memberName */ |
| 12077 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 12078 | 0, /* .padding */ |
| 12079 | false, /* .isArray */ |
| 12080 | false /* .isOptional */ |
| 12081 | }, |
| 12082 | { |
| 12083 | UA_TYPENAME("NetworkMessageNumber") /* .memberName */ |
| 12084 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 12085 | offsetof(UA_UadpDataSetReaderMessageDataType, networkMessageNumber) - offsetof(UA_UadpDataSetReaderMessageDataType, groupVersion) - sizeof(UA_UInt32), /* .padding */ |
| 12086 | false, /* .isArray */ |
| 12087 | false /* .isOptional */ |
| 12088 | }, |
| 12089 | { |
| 12090 | UA_TYPENAME("DataSetOffset") /* .memberName */ |
| 12091 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 12092 | offsetof(UA_UadpDataSetReaderMessageDataType, dataSetOffset) - offsetof(UA_UadpDataSetReaderMessageDataType, networkMessageNumber) - sizeof(UA_UInt16), /* .padding */ |
| 12093 | false, /* .isArray */ |
| 12094 | false /* .isOptional */ |
| 12095 | }, |
| 12096 | { |
| 12097 | UA_TYPENAME("DataSetClassId") /* .memberName */ |
| 12098 | &UA_TYPES[UA_TYPES_GUID], /* .memberType */ |
| 12099 | offsetof(UA_UadpDataSetReaderMessageDataType, dataSetClassId) - offsetof(UA_UadpDataSetReaderMessageDataType, dataSetOffset) - sizeof(UA_UInt16), /* .padding */ |
| 12100 | false, /* .isArray */ |
| 12101 | false /* .isOptional */ |
| 12102 | }, |
| 12103 | { |
| 12104 | UA_TYPENAME("NetworkMessageContentMask") /* .memberName */ |
| 12105 | &UA_TYPES[UA_TYPES_UADPNETWORKMESSAGECONTENTMASK], /* .memberType */ |
| 12106 | offsetof(UA_UadpDataSetReaderMessageDataType, networkMessageContentMask) - offsetof(UA_UadpDataSetReaderMessageDataType, dataSetClassId) - sizeof(UA_Guid), /* .padding */ |
| 12107 | false, /* .isArray */ |
| 12108 | false /* .isOptional */ |
| 12109 | }, |
| 12110 | { |
| 12111 | UA_TYPENAME("DataSetMessageContentMask") /* .memberName */ |
| 12112 | &UA_TYPES[UA_TYPES_UADPDATASETMESSAGECONTENTMASK], /* .memberType */ |
| 12113 | offsetof(UA_UadpDataSetReaderMessageDataType, dataSetMessageContentMask) - offsetof(UA_UadpDataSetReaderMessageDataType, networkMessageContentMask) - sizeof(UA_UadpNetworkMessageContentMask), /* .padding */ |
| 12114 | false, /* .isArray */ |
| 12115 | false /* .isOptional */ |
| 12116 | }, |
| 12117 | { |
| 12118 | UA_TYPENAME("PublishingInterval") /* .memberName */ |
| 12119 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 12120 | offsetof(UA_UadpDataSetReaderMessageDataType, publishingInterval) - offsetof(UA_UadpDataSetReaderMessageDataType, dataSetMessageContentMask) - sizeof(UA_UadpDataSetMessageContentMask), /* .padding */ |
| 12121 | false, /* .isArray */ |
| 12122 | false /* .isOptional */ |
| 12123 | }, |
| 12124 | { |
| 12125 | UA_TYPENAME("ReceiveOffset") /* .memberName */ |
| 12126 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 12127 | offsetof(UA_UadpDataSetReaderMessageDataType, receiveOffset) - offsetof(UA_UadpDataSetReaderMessageDataType, publishingInterval) - sizeof(UA_Double), /* .padding */ |
| 12128 | false, /* .isArray */ |
| 12129 | false /* .isOptional */ |
| 12130 | }, |
| 12131 | { |
| 12132 | UA_TYPENAME("ProcessingOffset") /* .memberName */ |
| 12133 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 12134 | offsetof(UA_UadpDataSetReaderMessageDataType, processingOffset) - offsetof(UA_UadpDataSetReaderMessageDataType, receiveOffset) - sizeof(UA_Double), /* .padding */ |
| 12135 | false, /* .isArray */ |
| 12136 | false /* .isOptional */ |
| 12137 | },}; |
| 12138 | |
| 12139 | /* JsonNetworkMessageContentMask */ |
| 12140 | #define JsonNetworkMessageContentMask_members NULL |
| 12141 | |
| 12142 | /* JsonWriterGroupMessageDataType */ |
| 12143 | static UA_DataTypeMember JsonWriterGroupMessageDataType_members[1] = { |
| 12144 | { |
| 12145 | UA_TYPENAME("NetworkMessageContentMask") /* .memberName */ |
| 12146 | &UA_TYPES[UA_TYPES_JSONNETWORKMESSAGECONTENTMASK], /* .memberType */ |
| 12147 | 0, /* .padding */ |
| 12148 | false, /* .isArray */ |
| 12149 | false /* .isOptional */ |
| 12150 | },}; |
| 12151 | |
| 12152 | /* JsonDataSetMessageContentMask */ |
| 12153 | #define JsonDataSetMessageContentMask_members NULL |
| 12154 | |
| 12155 | /* JsonDataSetWriterMessageDataType */ |
| 12156 | static UA_DataTypeMember JsonDataSetWriterMessageDataType_members[1] = { |
| 12157 | { |
| 12158 | UA_TYPENAME("DataSetMessageContentMask") /* .memberName */ |
| 12159 | &UA_TYPES[UA_TYPES_JSONDATASETMESSAGECONTENTMASK], /* .memberType */ |
| 12160 | 0, /* .padding */ |
| 12161 | false, /* .isArray */ |
| 12162 | false /* .isOptional */ |
| 12163 | },}; |
| 12164 | |
| 12165 | /* JsonDataSetReaderMessageDataType */ |
| 12166 | static UA_DataTypeMember JsonDataSetReaderMessageDataType_members[2] = { |
| 12167 | { |
| 12168 | UA_TYPENAME("NetworkMessageContentMask") /* .memberName */ |
| 12169 | &UA_TYPES[UA_TYPES_JSONNETWORKMESSAGECONTENTMASK], /* .memberType */ |
| 12170 | 0, /* .padding */ |
| 12171 | false, /* .isArray */ |
| 12172 | false /* .isOptional */ |
| 12173 | }, |
| 12174 | { |
| 12175 | UA_TYPENAME("DataSetMessageContentMask") /* .memberName */ |
| 12176 | &UA_TYPES[UA_TYPES_JSONDATASETMESSAGECONTENTMASK], /* .memberType */ |
| 12177 | offsetof(UA_JsonDataSetReaderMessageDataType, dataSetMessageContentMask) - offsetof(UA_JsonDataSetReaderMessageDataType, networkMessageContentMask) - sizeof(UA_JsonNetworkMessageContentMask), /* .padding */ |
| 12178 | false, /* .isArray */ |
| 12179 | false /* .isOptional */ |
| 12180 | },}; |
| 12181 | |
| 12182 | /* TransmitQosPriorityDataType */ |
| 12183 | static UA_DataTypeMember TransmitQosPriorityDataType_members[1] = { |
| 12184 | { |
| 12185 | UA_TYPENAME("PriorityLabel") /* .memberName */ |
| 12186 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12187 | 0, /* .padding */ |
| 12188 | false, /* .isArray */ |
| 12189 | false /* .isOptional */ |
| 12190 | },}; |
| 12191 | |
| 12192 | /* ReceiveQosPriorityDataType */ |
| 12193 | static UA_DataTypeMember ReceiveQosPriorityDataType_members[1] = { |
| 12194 | { |
| 12195 | UA_TYPENAME("PriorityLabel") /* .memberName */ |
| 12196 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12197 | 0, /* .padding */ |
| 12198 | false, /* .isArray */ |
| 12199 | false /* .isOptional */ |
| 12200 | },}; |
| 12201 | |
| 12202 | /* DatagramConnectionTransportDataType */ |
| 12203 | static UA_DataTypeMember DatagramConnectionTransportDataType_members[1] = { |
| 12204 | { |
| 12205 | UA_TYPENAME("DiscoveryAddress") /* .memberName */ |
| 12206 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 12207 | 0, /* .padding */ |
| 12208 | false, /* .isArray */ |
| 12209 | false /* .isOptional */ |
| 12210 | },}; |
| 12211 | |
| 12212 | /* DatagramConnectionTransport2DataType */ |
| 12213 | static UA_DataTypeMember DatagramConnectionTransport2DataType_members[5] = { |
| 12214 | { |
| 12215 | UA_TYPENAME("DiscoveryAddress") /* .memberName */ |
| 12216 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 12217 | 0, /* .padding */ |
| 12218 | false, /* .isArray */ |
| 12219 | false /* .isOptional */ |
| 12220 | }, |
| 12221 | { |
| 12222 | UA_TYPENAME("DiscoveryAnnounceRate") /* .memberName */ |
| 12223 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 12224 | offsetof(UA_DatagramConnectionTransport2DataType, discoveryAnnounceRate) - offsetof(UA_DatagramConnectionTransport2DataType, discoveryAddress) - sizeof(UA_ExtensionObject), /* .padding */ |
| 12225 | false, /* .isArray */ |
| 12226 | false /* .isOptional */ |
| 12227 | }, |
| 12228 | { |
| 12229 | UA_TYPENAME("DiscoveryMaxMessageSize") /* .memberName */ |
| 12230 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 12231 | offsetof(UA_DatagramConnectionTransport2DataType, discoveryMaxMessageSize) - offsetof(UA_DatagramConnectionTransport2DataType, discoveryAnnounceRate) - sizeof(UA_UInt32), /* .padding */ |
| 12232 | false, /* .isArray */ |
| 12233 | false /* .isOptional */ |
| 12234 | }, |
| 12235 | { |
| 12236 | UA_TYPENAME("QosCategory") /* .memberName */ |
| 12237 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12238 | offsetof(UA_DatagramConnectionTransport2DataType, qosCategory) - offsetof(UA_DatagramConnectionTransport2DataType, discoveryMaxMessageSize) - sizeof(UA_UInt32), /* .padding */ |
| 12239 | false, /* .isArray */ |
| 12240 | false /* .isOptional */ |
| 12241 | }, |
| 12242 | { |
| 12243 | UA_TYPENAME("DatagramQos") /* .memberName */ |
| 12244 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 12245 | offsetof(UA_DatagramConnectionTransport2DataType, datagramQosSize) - offsetof(UA_DatagramConnectionTransport2DataType, qosCategory) - sizeof(UA_String), /* .padding */ |
| 12246 | true, /* .isArray */ |
| 12247 | false /* .isOptional */ |
| 12248 | },}; |
| 12249 | |
| 12250 | /* DatagramWriterGroupTransportDataType */ |
| 12251 | static UA_DataTypeMember DatagramWriterGroupTransportDataType_members[2] = { |
| 12252 | { |
| 12253 | UA_TYPENAME("MessageRepeatCount") /* .memberName */ |
| 12254 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 12255 | 0, /* .padding */ |
| 12256 | false, /* .isArray */ |
| 12257 | false /* .isOptional */ |
| 12258 | }, |
| 12259 | { |
| 12260 | UA_TYPENAME("MessageRepeatDelay") /* .memberName */ |
| 12261 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 12262 | offsetof(UA_DatagramWriterGroupTransportDataType, messageRepeatDelay) - offsetof(UA_DatagramWriterGroupTransportDataType, messageRepeatCount) - sizeof(UA_Byte), /* .padding */ |
| 12263 | false, /* .isArray */ |
| 12264 | false /* .isOptional */ |
| 12265 | },}; |
| 12266 | |
| 12267 | /* DatagramWriterGroupTransport2DataType */ |
| 12268 | static UA_DataTypeMember DatagramWriterGroupTransport2DataType_members[7] = { |
| 12269 | { |
| 12270 | UA_TYPENAME("MessageRepeatCount") /* .memberName */ |
| 12271 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 12272 | 0, /* .padding */ |
| 12273 | false, /* .isArray */ |
| 12274 | false /* .isOptional */ |
| 12275 | }, |
| 12276 | { |
| 12277 | UA_TYPENAME("MessageRepeatDelay") /* .memberName */ |
| 12278 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 12279 | offsetof(UA_DatagramWriterGroupTransport2DataType, messageRepeatDelay) - offsetof(UA_DatagramWriterGroupTransport2DataType, messageRepeatCount) - sizeof(UA_Byte), /* .padding */ |
| 12280 | false, /* .isArray */ |
| 12281 | false /* .isOptional */ |
| 12282 | }, |
| 12283 | { |
| 12284 | UA_TYPENAME("Address") /* .memberName */ |
| 12285 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 12286 | offsetof(UA_DatagramWriterGroupTransport2DataType, address) - offsetof(UA_DatagramWriterGroupTransport2DataType, messageRepeatDelay) - sizeof(UA_Double), /* .padding */ |
| 12287 | false, /* .isArray */ |
| 12288 | false /* .isOptional */ |
| 12289 | }, |
| 12290 | { |
| 12291 | UA_TYPENAME("QosCategory") /* .memberName */ |
| 12292 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12293 | offsetof(UA_DatagramWriterGroupTransport2DataType, qosCategory) - offsetof(UA_DatagramWriterGroupTransport2DataType, address) - sizeof(UA_ExtensionObject), /* .padding */ |
| 12294 | false, /* .isArray */ |
| 12295 | false /* .isOptional */ |
| 12296 | }, |
| 12297 | { |
| 12298 | UA_TYPENAME("DatagramQos") /* .memberName */ |
| 12299 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 12300 | offsetof(UA_DatagramWriterGroupTransport2DataType, datagramQosSize) - offsetof(UA_DatagramWriterGroupTransport2DataType, qosCategory) - sizeof(UA_String), /* .padding */ |
| 12301 | true, /* .isArray */ |
| 12302 | false /* .isOptional */ |
| 12303 | }, |
| 12304 | { |
| 12305 | UA_TYPENAME("DiscoveryAnnounceRate") /* .memberName */ |
| 12306 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 12307 | offsetof(UA_DatagramWriterGroupTransport2DataType, discoveryAnnounceRate) - offsetof(UA_DatagramWriterGroupTransport2DataType, datagramQos) - sizeof(void *), /* .padding */ |
| 12308 | false, /* .isArray */ |
| 12309 | false /* .isOptional */ |
| 12310 | }, |
| 12311 | { |
| 12312 | UA_TYPENAME("Topic") /* .memberName */ |
| 12313 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12314 | offsetof(UA_DatagramWriterGroupTransport2DataType, topic) - offsetof(UA_DatagramWriterGroupTransport2DataType, discoveryAnnounceRate) - sizeof(UA_UInt32), /* .padding */ |
| 12315 | false, /* .isArray */ |
| 12316 | false /* .isOptional */ |
| 12317 | },}; |
| 12318 | |
| 12319 | /* DatagramDataSetReaderTransportDataType */ |
| 12320 | static UA_DataTypeMember DatagramDataSetReaderTransportDataType_members[4] = { |
| 12321 | { |
| 12322 | UA_TYPENAME("Address") /* .memberName */ |
| 12323 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 12324 | 0, /* .padding */ |
| 12325 | false, /* .isArray */ |
| 12326 | false /* .isOptional */ |
| 12327 | }, |
| 12328 | { |
| 12329 | UA_TYPENAME("QosCategory") /* .memberName */ |
| 12330 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12331 | offsetof(UA_DatagramDataSetReaderTransportDataType, qosCategory) - offsetof(UA_DatagramDataSetReaderTransportDataType, address) - sizeof(UA_ExtensionObject), /* .padding */ |
| 12332 | false, /* .isArray */ |
| 12333 | false /* .isOptional */ |
| 12334 | }, |
| 12335 | { |
| 12336 | UA_TYPENAME("DatagramQos") /* .memberName */ |
| 12337 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 12338 | offsetof(UA_DatagramDataSetReaderTransportDataType, datagramQosSize) - offsetof(UA_DatagramDataSetReaderTransportDataType, qosCategory) - sizeof(UA_String), /* .padding */ |
| 12339 | true, /* .isArray */ |
| 12340 | false /* .isOptional */ |
| 12341 | }, |
| 12342 | { |
| 12343 | UA_TYPENAME("Topic") /* .memberName */ |
| 12344 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12345 | offsetof(UA_DatagramDataSetReaderTransportDataType, topic) - offsetof(UA_DatagramDataSetReaderTransportDataType, datagramQos) - sizeof(void *), /* .padding */ |
| 12346 | false, /* .isArray */ |
| 12347 | false /* .isOptional */ |
| 12348 | },}; |
| 12349 | |
| 12350 | /* BrokerConnectionTransportDataType */ |
| 12351 | static UA_DataTypeMember BrokerConnectionTransportDataType_members[2] = { |
| 12352 | { |
| 12353 | UA_TYPENAME("ResourceUri") /* .memberName */ |
| 12354 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12355 | 0, /* .padding */ |
| 12356 | false, /* .isArray */ |
| 12357 | false /* .isOptional */ |
| 12358 | }, |
| 12359 | { |
| 12360 | UA_TYPENAME("AuthenticationProfileUri") /* .memberName */ |
| 12361 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12362 | offsetof(UA_BrokerConnectionTransportDataType, authenticationProfileUri) - offsetof(UA_BrokerConnectionTransportDataType, resourceUri) - sizeof(UA_String), /* .padding */ |
| 12363 | false, /* .isArray */ |
| 12364 | false /* .isOptional */ |
| 12365 | },}; |
| 12366 | |
| 12367 | /* BrokerTransportQualityOfService */ |
| 12368 | #define BrokerTransportQualityOfService_members NULL |
| 12369 | |
| 12370 | /* BrokerWriterGroupTransportDataType */ |
| 12371 | static UA_DataTypeMember BrokerWriterGroupTransportDataType_members[4] = { |
| 12372 | { |
| 12373 | UA_TYPENAME("QueueName") /* .memberName */ |
| 12374 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12375 | 0, /* .padding */ |
| 12376 | false, /* .isArray */ |
| 12377 | false /* .isOptional */ |
| 12378 | }, |
| 12379 | { |
| 12380 | UA_TYPENAME("ResourceUri") /* .memberName */ |
| 12381 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12382 | offsetof(UA_BrokerWriterGroupTransportDataType, resourceUri) - offsetof(UA_BrokerWriterGroupTransportDataType, queueName) - sizeof(UA_String), /* .padding */ |
| 12383 | false, /* .isArray */ |
| 12384 | false /* .isOptional */ |
| 12385 | }, |
| 12386 | { |
| 12387 | UA_TYPENAME("AuthenticationProfileUri") /* .memberName */ |
| 12388 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12389 | offsetof(UA_BrokerWriterGroupTransportDataType, authenticationProfileUri) - offsetof(UA_BrokerWriterGroupTransportDataType, resourceUri) - sizeof(UA_String), /* .padding */ |
| 12390 | false, /* .isArray */ |
| 12391 | false /* .isOptional */ |
| 12392 | }, |
| 12393 | { |
| 12394 | UA_TYPENAME("RequestedDeliveryGuarantee") /* .memberName */ |
| 12395 | &UA_TYPES[UA_TYPES_BROKERTRANSPORTQUALITYOFSERVICE], /* .memberType */ |
| 12396 | offsetof(UA_BrokerWriterGroupTransportDataType, requestedDeliveryGuarantee) - offsetof(UA_BrokerWriterGroupTransportDataType, authenticationProfileUri) - sizeof(UA_String), /* .padding */ |
| 12397 | false, /* .isArray */ |
| 12398 | false /* .isOptional */ |
| 12399 | },}; |
| 12400 | |
| 12401 | /* BrokerDataSetWriterTransportDataType */ |
| 12402 | static UA_DataTypeMember BrokerDataSetWriterTransportDataType_members[6] = { |
| 12403 | { |
| 12404 | UA_TYPENAME("QueueName") /* .memberName */ |
| 12405 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12406 | 0, /* .padding */ |
| 12407 | false, /* .isArray */ |
| 12408 | false /* .isOptional */ |
| 12409 | }, |
| 12410 | { |
| 12411 | UA_TYPENAME("ResourceUri") /* .memberName */ |
| 12412 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12413 | offsetof(UA_BrokerDataSetWriterTransportDataType, resourceUri) - offsetof(UA_BrokerDataSetWriterTransportDataType, queueName) - sizeof(UA_String), /* .padding */ |
| 12414 | false, /* .isArray */ |
| 12415 | false /* .isOptional */ |
| 12416 | }, |
| 12417 | { |
| 12418 | UA_TYPENAME("AuthenticationProfileUri") /* .memberName */ |
| 12419 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12420 | offsetof(UA_BrokerDataSetWriterTransportDataType, authenticationProfileUri) - offsetof(UA_BrokerDataSetWriterTransportDataType, resourceUri) - sizeof(UA_String), /* .padding */ |
| 12421 | false, /* .isArray */ |
| 12422 | false /* .isOptional */ |
| 12423 | }, |
| 12424 | { |
| 12425 | UA_TYPENAME("RequestedDeliveryGuarantee") /* .memberName */ |
| 12426 | &UA_TYPES[UA_TYPES_BROKERTRANSPORTQUALITYOFSERVICE], /* .memberType */ |
| 12427 | offsetof(UA_BrokerDataSetWriterTransportDataType, requestedDeliveryGuarantee) - offsetof(UA_BrokerDataSetWriterTransportDataType, authenticationProfileUri) - sizeof(UA_String), /* .padding */ |
| 12428 | false, /* .isArray */ |
| 12429 | false /* .isOptional */ |
| 12430 | }, |
| 12431 | { |
| 12432 | UA_TYPENAME("MetaDataQueueName") /* .memberName */ |
| 12433 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12434 | offsetof(UA_BrokerDataSetWriterTransportDataType, metaDataQueueName) - offsetof(UA_BrokerDataSetWriterTransportDataType, requestedDeliveryGuarantee) - sizeof(UA_BrokerTransportQualityOfService), /* .padding */ |
| 12435 | false, /* .isArray */ |
| 12436 | false /* .isOptional */ |
| 12437 | }, |
| 12438 | { |
| 12439 | UA_TYPENAME("MetaDataUpdateTime") /* .memberName */ |
| 12440 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 12441 | offsetof(UA_BrokerDataSetWriterTransportDataType, metaDataUpdateTime) - offsetof(UA_BrokerDataSetWriterTransportDataType, metaDataQueueName) - sizeof(UA_String), /* .padding */ |
| 12442 | false, /* .isArray */ |
| 12443 | false /* .isOptional */ |
| 12444 | },}; |
| 12445 | |
| 12446 | /* BrokerDataSetReaderTransportDataType */ |
| 12447 | static UA_DataTypeMember BrokerDataSetReaderTransportDataType_members[5] = { |
| 12448 | { |
| 12449 | UA_TYPENAME("QueueName") /* .memberName */ |
| 12450 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12451 | 0, /* .padding */ |
| 12452 | false, /* .isArray */ |
| 12453 | false /* .isOptional */ |
| 12454 | }, |
| 12455 | { |
| 12456 | UA_TYPENAME("ResourceUri") /* .memberName */ |
| 12457 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12458 | offsetof(UA_BrokerDataSetReaderTransportDataType, resourceUri) - offsetof(UA_BrokerDataSetReaderTransportDataType, queueName) - sizeof(UA_String), /* .padding */ |
| 12459 | false, /* .isArray */ |
| 12460 | false /* .isOptional */ |
| 12461 | }, |
| 12462 | { |
| 12463 | UA_TYPENAME("AuthenticationProfileUri") /* .memberName */ |
| 12464 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12465 | offsetof(UA_BrokerDataSetReaderTransportDataType, authenticationProfileUri) - offsetof(UA_BrokerDataSetReaderTransportDataType, resourceUri) - sizeof(UA_String), /* .padding */ |
| 12466 | false, /* .isArray */ |
| 12467 | false /* .isOptional */ |
| 12468 | }, |
| 12469 | { |
| 12470 | UA_TYPENAME("RequestedDeliveryGuarantee") /* .memberName */ |
| 12471 | &UA_TYPES[UA_TYPES_BROKERTRANSPORTQUALITYOFSERVICE], /* .memberType */ |
| 12472 | offsetof(UA_BrokerDataSetReaderTransportDataType, requestedDeliveryGuarantee) - offsetof(UA_BrokerDataSetReaderTransportDataType, authenticationProfileUri) - sizeof(UA_String), /* .padding */ |
| 12473 | false, /* .isArray */ |
| 12474 | false /* .isOptional */ |
| 12475 | }, |
| 12476 | { |
| 12477 | UA_TYPENAME("MetaDataQueueName") /* .memberName */ |
| 12478 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12479 | offsetof(UA_BrokerDataSetReaderTransportDataType, metaDataQueueName) - offsetof(UA_BrokerDataSetReaderTransportDataType, requestedDeliveryGuarantee) - sizeof(UA_BrokerTransportQualityOfService), /* .padding */ |
| 12480 | false, /* .isArray */ |
| 12481 | false /* .isOptional */ |
| 12482 | },}; |
| 12483 | |
| 12484 | /* PubSubConfigurationRefMask */ |
| 12485 | #define PubSubConfigurationRefMask_members NULL |
| 12486 | |
| 12487 | /* PubSubConfigurationRefDataType */ |
| 12488 | static UA_DataTypeMember PubSubConfigurationRefDataType_members[4] = { |
| 12489 | { |
| 12490 | UA_TYPENAME("ConfigurationMask") /* .memberName */ |
| 12491 | &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONREFMASK], /* .memberType */ |
| 12492 | 0, /* .padding */ |
| 12493 | false, /* .isArray */ |
| 12494 | false /* .isOptional */ |
| 12495 | }, |
| 12496 | { |
| 12497 | UA_TYPENAME("ElementIndex") /* .memberName */ |
| 12498 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 12499 | offsetof(UA_PubSubConfigurationRefDataType, elementIndex) - offsetof(UA_PubSubConfigurationRefDataType, configurationMask) - sizeof(UA_PubSubConfigurationRefMask), /* .padding */ |
| 12500 | false, /* .isArray */ |
| 12501 | false /* .isOptional */ |
| 12502 | }, |
| 12503 | { |
| 12504 | UA_TYPENAME("ConnectionIndex") /* .memberName */ |
| 12505 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 12506 | offsetof(UA_PubSubConfigurationRefDataType, connectionIndex) - offsetof(UA_PubSubConfigurationRefDataType, elementIndex) - sizeof(UA_UInt16), /* .padding */ |
| 12507 | false, /* .isArray */ |
| 12508 | false /* .isOptional */ |
| 12509 | }, |
| 12510 | { |
| 12511 | UA_TYPENAME("GroupIndex") /* .memberName */ |
| 12512 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 12513 | offsetof(UA_PubSubConfigurationRefDataType, groupIndex) - offsetof(UA_PubSubConfigurationRefDataType, connectionIndex) - sizeof(UA_UInt16), /* .padding */ |
| 12514 | false, /* .isArray */ |
| 12515 | false /* .isOptional */ |
| 12516 | },}; |
| 12517 | |
| 12518 | /* PubSubConfigurationValueDataType */ |
| 12519 | static UA_DataTypeMember PubSubConfigurationValueDataType_members[3] = { |
| 12520 | { |
| 12521 | UA_TYPENAME("ConfigurationElement") /* .memberName */ |
| 12522 | &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONREFDATATYPE], /* .memberType */ |
| 12523 | 0, /* .padding */ |
| 12524 | false, /* .isArray */ |
| 12525 | false /* .isOptional */ |
| 12526 | }, |
| 12527 | { |
| 12528 | UA_TYPENAME("Name") /* .memberName */ |
| 12529 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12530 | offsetof(UA_PubSubConfigurationValueDataType, name) - offsetof(UA_PubSubConfigurationValueDataType, configurationElement) - sizeof(UA_PubSubConfigurationRefDataType), /* .padding */ |
| 12531 | false, /* .isArray */ |
| 12532 | false /* .isOptional */ |
| 12533 | }, |
| 12534 | { |
| 12535 | UA_TYPENAME("Identifier") /* .memberName */ |
| 12536 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 12537 | offsetof(UA_PubSubConfigurationValueDataType, identifier) - offsetof(UA_PubSubConfigurationValueDataType, name) - sizeof(UA_String), /* .padding */ |
| 12538 | false, /* .isArray */ |
| 12539 | false /* .isOptional */ |
| 12540 | },}; |
| 12541 | |
| 12542 | /* DiagnosticsLevel */ |
| 12543 | #define DiagnosticsLevel_members NULL |
| 12544 | |
| 12545 | /* PubSubDiagnosticsCounterClassification */ |
| 12546 | #define PubSubDiagnosticsCounterClassification_members NULL |
| 12547 | |
| 12548 | /* AliasNameDataType */ |
| 12549 | static UA_DataTypeMember AliasNameDataType_members[2] = { |
| 12550 | { |
| 12551 | UA_TYPENAME("AliasName") /* .memberName */ |
| 12552 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 12553 | 0, /* .padding */ |
| 12554 | false, /* .isArray */ |
| 12555 | false /* .isOptional */ |
| 12556 | }, |
| 12557 | { |
| 12558 | UA_TYPENAME("ReferencedNodes") /* .memberName */ |
| 12559 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 12560 | offsetof(UA_AliasNameDataType, referencedNodesSize) - offsetof(UA_AliasNameDataType, aliasName) - sizeof(UA_QualifiedName), /* .padding */ |
| 12561 | true, /* .isArray */ |
| 12562 | false /* .isOptional */ |
| 12563 | },}; |
| 12564 | |
| 12565 | /* PasswordOptionsMask */ |
| 12566 | #define PasswordOptionsMask_members NULL |
| 12567 | |
| 12568 | /* UserConfigurationMask */ |
| 12569 | #define UserConfigurationMask_members NULL |
| 12570 | |
| 12571 | /* UserManagementDataType */ |
| 12572 | static UA_DataTypeMember UserManagementDataType_members[3] = { |
| 12573 | { |
| 12574 | UA_TYPENAME("UserName") /* .memberName */ |
| 12575 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12576 | 0, /* .padding */ |
| 12577 | false, /* .isArray */ |
| 12578 | false /* .isOptional */ |
| 12579 | }, |
| 12580 | { |
| 12581 | UA_TYPENAME("UserConfiguration") /* .memberName */ |
| 12582 | &UA_TYPES[UA_TYPES_USERCONFIGURATIONMASK], /* .memberType */ |
| 12583 | offsetof(UA_UserManagementDataType, userConfiguration) - offsetof(UA_UserManagementDataType, userName) - sizeof(UA_String), /* .padding */ |
| 12584 | false, /* .isArray */ |
| 12585 | false /* .isOptional */ |
| 12586 | }, |
| 12587 | { |
| 12588 | UA_TYPENAME("Description") /* .memberName */ |
| 12589 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12590 | offsetof(UA_UserManagementDataType, description) - offsetof(UA_UserManagementDataType, userConfiguration) - sizeof(UA_UserConfigurationMask), /* .padding */ |
| 12591 | false, /* .isArray */ |
| 12592 | false /* .isOptional */ |
| 12593 | },}; |
| 12594 | |
| 12595 | /* Duplex */ |
| 12596 | #define Duplex_members NULL |
| 12597 | |
| 12598 | /* InterfaceAdminStatus */ |
| 12599 | #define InterfaceAdminStatus_members NULL |
| 12600 | |
| 12601 | /* InterfaceOperStatus */ |
| 12602 | #define InterfaceOperStatus_members NULL |
| 12603 | |
| 12604 | /* NegotiationStatus */ |
| 12605 | #define NegotiationStatus_members NULL |
| 12606 | |
| 12607 | /* TsnFailureCode */ |
| 12608 | #define TsnFailureCode_members NULL |
| 12609 | |
| 12610 | /* TsnStreamState */ |
| 12611 | #define TsnStreamState_members NULL |
| 12612 | |
| 12613 | /* TsnTalkerStatus */ |
| 12614 | #define TsnTalkerStatus_members NULL |
| 12615 | |
| 12616 | /* TsnListenerStatus */ |
| 12617 | #define TsnListenerStatus_members NULL |
| 12618 | |
| 12619 | /* PriorityMappingEntryType */ |
| 12620 | static UA_DataTypeMember PriorityMappingEntryType_members[4] = { |
| 12621 | { |
| 12622 | UA_TYPENAME("MappingUri") /* .memberName */ |
| 12623 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12624 | 0, /* .padding */ |
| 12625 | false, /* .isArray */ |
| 12626 | false /* .isOptional */ |
| 12627 | }, |
| 12628 | { |
| 12629 | UA_TYPENAME("PriorityLabel") /* .memberName */ |
| 12630 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12631 | offsetof(UA_PriorityMappingEntryType, priorityLabel) - offsetof(UA_PriorityMappingEntryType, mappingUri) - sizeof(UA_String), /* .padding */ |
| 12632 | false, /* .isArray */ |
| 12633 | false /* .isOptional */ |
| 12634 | }, |
| 12635 | { |
| 12636 | UA_TYPENAME("PriorityValue_PCP") /* .memberName */ |
| 12637 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 12638 | offsetof(UA_PriorityMappingEntryType, priorityValue_PCP) - offsetof(UA_PriorityMappingEntryType, priorityLabel) - sizeof(UA_String), /* .padding */ |
| 12639 | false, /* .isArray */ |
| 12640 | false /* .isOptional */ |
| 12641 | }, |
| 12642 | { |
| 12643 | UA_TYPENAME("PriorityValue_DSCP") /* .memberName */ |
| 12644 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 12645 | offsetof(UA_PriorityMappingEntryType, priorityValue_DSCP) - offsetof(UA_PriorityMappingEntryType, priorityValue_PCP) - sizeof(UA_Byte), /* .padding */ |
| 12646 | false, /* .isArray */ |
| 12647 | false /* .isOptional */ |
| 12648 | },}; |
| 12649 | |
| 12650 | /* IdType */ |
| 12651 | #define IdType_members NULL |
| 12652 | |
| 12653 | /* NodeClass */ |
| 12654 | #define NodeClass_members NULL |
| 12655 | |
| 12656 | /* PermissionType */ |
| 12657 | #define PermissionType_members NULL |
| 12658 | |
| 12659 | /* AccessLevelType */ |
| 12660 | #define AccessLevelType_members NULL |
| 12661 | |
| 12662 | /* AccessLevelExType */ |
| 12663 | #define AccessLevelExType_members NULL |
| 12664 | |
| 12665 | /* EventNotifierType */ |
| 12666 | #define EventNotifierType_members NULL |
| 12667 | |
| 12668 | /* AccessRestrictionType */ |
| 12669 | #define AccessRestrictionType_members NULL |
| 12670 | |
| 12671 | /* RolePermissionType */ |
| 12672 | static UA_DataTypeMember RolePermissionType_members[2] = { |
| 12673 | { |
| 12674 | UA_TYPENAME("RoleId") /* .memberName */ |
| 12675 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 12676 | 0, /* .padding */ |
| 12677 | false, /* .isArray */ |
| 12678 | false /* .isOptional */ |
| 12679 | }, |
| 12680 | { |
| 12681 | UA_TYPENAME("Permissions") /* .memberName */ |
| 12682 | &UA_TYPES[UA_TYPES_PERMISSIONTYPE], /* .memberType */ |
| 12683 | offsetof(UA_RolePermissionType, permissions) - offsetof(UA_RolePermissionType, roleId) - sizeof(UA_NodeId), /* .padding */ |
| 12684 | false, /* .isArray */ |
| 12685 | false /* .isOptional */ |
| 12686 | },}; |
| 12687 | |
| 12688 | /* StructureType */ |
| 12689 | #define StructureType_members NULL |
| 12690 | |
| 12691 | /* StructureField */ |
| 12692 | static UA_DataTypeMember StructureField_members[7] = { |
| 12693 | { |
| 12694 | UA_TYPENAME("Name") /* .memberName */ |
| 12695 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12696 | 0, /* .padding */ |
| 12697 | false, /* .isArray */ |
| 12698 | false /* .isOptional */ |
| 12699 | }, |
| 12700 | { |
| 12701 | UA_TYPENAME("Description") /* .memberName */ |
| 12702 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 12703 | offsetof(UA_StructureField, description) - offsetof(UA_StructureField, name) - sizeof(UA_String), /* .padding */ |
| 12704 | false, /* .isArray */ |
| 12705 | false /* .isOptional */ |
| 12706 | }, |
| 12707 | { |
| 12708 | UA_TYPENAME("DataType") /* .memberName */ |
| 12709 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 12710 | offsetof(UA_StructureField, dataType) - offsetof(UA_StructureField, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 12711 | false, /* .isArray */ |
| 12712 | false /* .isOptional */ |
| 12713 | }, |
| 12714 | { |
| 12715 | UA_TYPENAME("ValueRank") /* .memberName */ |
| 12716 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 12717 | offsetof(UA_StructureField, valueRank) - offsetof(UA_StructureField, dataType) - sizeof(UA_NodeId), /* .padding */ |
| 12718 | false, /* .isArray */ |
| 12719 | false /* .isOptional */ |
| 12720 | }, |
| 12721 | { |
| 12722 | UA_TYPENAME("ArrayDimensions") /* .memberName */ |
| 12723 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 12724 | offsetof(UA_StructureField, arrayDimensionsSize) - offsetof(UA_StructureField, valueRank) - sizeof(UA_Int32), /* .padding */ |
| 12725 | true, /* .isArray */ |
| 12726 | false /* .isOptional */ |
| 12727 | }, |
| 12728 | { |
| 12729 | UA_TYPENAME("MaxStringLength") /* .memberName */ |
| 12730 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 12731 | offsetof(UA_StructureField, maxStringLength) - offsetof(UA_StructureField, arrayDimensions) - sizeof(void *), /* .padding */ |
| 12732 | false, /* .isArray */ |
| 12733 | false /* .isOptional */ |
| 12734 | }, |
| 12735 | { |
| 12736 | UA_TYPENAME("IsOptional") /* .memberName */ |
| 12737 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 12738 | offsetof(UA_StructureField, isOptional) - offsetof(UA_StructureField, maxStringLength) - sizeof(UA_UInt32), /* .padding */ |
| 12739 | false, /* .isArray */ |
| 12740 | false /* .isOptional */ |
| 12741 | },}; |
| 12742 | |
| 12743 | /* StructureDefinition */ |
| 12744 | static UA_DataTypeMember StructureDefinition_members[4] = { |
| 12745 | { |
| 12746 | UA_TYPENAME("DefaultEncodingId") /* .memberName */ |
| 12747 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 12748 | 0, /* .padding */ |
| 12749 | false, /* .isArray */ |
| 12750 | false /* .isOptional */ |
| 12751 | }, |
| 12752 | { |
| 12753 | UA_TYPENAME("BaseDataType") /* .memberName */ |
| 12754 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 12755 | offsetof(UA_StructureDefinition, baseDataType) - offsetof(UA_StructureDefinition, defaultEncodingId) - sizeof(UA_NodeId), /* .padding */ |
| 12756 | false, /* .isArray */ |
| 12757 | false /* .isOptional */ |
| 12758 | }, |
| 12759 | { |
| 12760 | UA_TYPENAME("StructureType") /* .memberName */ |
| 12761 | &UA_TYPES[UA_TYPES_STRUCTURETYPE], /* .memberType */ |
| 12762 | offsetof(UA_StructureDefinition, structureType) - offsetof(UA_StructureDefinition, baseDataType) - sizeof(UA_NodeId), /* .padding */ |
| 12763 | false, /* .isArray */ |
| 12764 | false /* .isOptional */ |
| 12765 | }, |
| 12766 | { |
| 12767 | UA_TYPENAME("Fields") /* .memberName */ |
| 12768 | &UA_TYPES[UA_TYPES_STRUCTUREFIELD], /* .memberType */ |
| 12769 | offsetof(UA_StructureDefinition, fieldsSize) - offsetof(UA_StructureDefinition, structureType) - sizeof(UA_StructureType), /* .padding */ |
| 12770 | true, /* .isArray */ |
| 12771 | false /* .isOptional */ |
| 12772 | },}; |
| 12773 | |
| 12774 | /* ReferenceNode */ |
| 12775 | static UA_DataTypeMember ReferenceNode_members[3] = { |
| 12776 | { |
| 12777 | UA_TYPENAME("ReferenceTypeId") /* .memberName */ |
| 12778 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 12779 | 0, /* .padding */ |
| 12780 | false, /* .isArray */ |
| 12781 | false /* .isOptional */ |
| 12782 | }, |
| 12783 | { |
| 12784 | UA_TYPENAME("IsInverse") /* .memberName */ |
| 12785 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 12786 | offsetof(UA_ReferenceNode, isInverse) - offsetof(UA_ReferenceNode, referenceTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 12787 | false, /* .isArray */ |
| 12788 | false /* .isOptional */ |
| 12789 | }, |
| 12790 | { |
| 12791 | UA_TYPENAME("TargetId") /* .memberName */ |
| 12792 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 12793 | offsetof(UA_ReferenceNode, targetId) - offsetof(UA_ReferenceNode, isInverse) - sizeof(UA_Boolean), /* .padding */ |
| 12794 | false, /* .isArray */ |
| 12795 | false /* .isOptional */ |
| 12796 | },}; |
| 12797 | |
| 12798 | /* Argument */ |
| 12799 | static UA_DataTypeMember Argument_members[5] = { |
| 12800 | { |
| 12801 | UA_TYPENAME("Name") /* .memberName */ |
| 12802 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12803 | 0, /* .padding */ |
| 12804 | false, /* .isArray */ |
| 12805 | false /* .isOptional */ |
| 12806 | }, |
| 12807 | { |
| 12808 | UA_TYPENAME("DataType") /* .memberName */ |
| 12809 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 12810 | offsetof(UA_Argument, dataType) - offsetof(UA_Argument, name) - sizeof(UA_String), /* .padding */ |
| 12811 | false, /* .isArray */ |
| 12812 | false /* .isOptional */ |
| 12813 | }, |
| 12814 | { |
| 12815 | UA_TYPENAME("ValueRank") /* .memberName */ |
| 12816 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 12817 | offsetof(UA_Argument, valueRank) - offsetof(UA_Argument, dataType) - sizeof(UA_NodeId), /* .padding */ |
| 12818 | false, /* .isArray */ |
| 12819 | false /* .isOptional */ |
| 12820 | }, |
| 12821 | { |
| 12822 | UA_TYPENAME("ArrayDimensions") /* .memberName */ |
| 12823 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 12824 | offsetof(UA_Argument, arrayDimensionsSize) - offsetof(UA_Argument, valueRank) - sizeof(UA_Int32), /* .padding */ |
| 12825 | true, /* .isArray */ |
| 12826 | false /* .isOptional */ |
| 12827 | }, |
| 12828 | { |
| 12829 | UA_TYPENAME("Description") /* .memberName */ |
| 12830 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 12831 | offsetof(UA_Argument, description) - offsetof(UA_Argument, arrayDimensions) - sizeof(void *), /* .padding */ |
| 12832 | false, /* .isArray */ |
| 12833 | false /* .isOptional */ |
| 12834 | },}; |
| 12835 | |
| 12836 | /* EnumValueType */ |
| 12837 | static UA_DataTypeMember EnumValueType_members[3] = { |
| 12838 | { |
| 12839 | UA_TYPENAME("Value") /* .memberName */ |
| 12840 | &UA_TYPES[UA_TYPES_INT64], /* .memberType */ |
| 12841 | 0, /* .padding */ |
| 12842 | false, /* .isArray */ |
| 12843 | false /* .isOptional */ |
| 12844 | }, |
| 12845 | { |
| 12846 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 12847 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 12848 | offsetof(UA_EnumValueType, displayName) - offsetof(UA_EnumValueType, value) - sizeof(UA_Int64), /* .padding */ |
| 12849 | false, /* .isArray */ |
| 12850 | false /* .isOptional */ |
| 12851 | }, |
| 12852 | { |
| 12853 | UA_TYPENAME("Description") /* .memberName */ |
| 12854 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 12855 | offsetof(UA_EnumValueType, description) - offsetof(UA_EnumValueType, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 12856 | false, /* .isArray */ |
| 12857 | false /* .isOptional */ |
| 12858 | },}; |
| 12859 | |
| 12860 | /* EnumField */ |
| 12861 | static UA_DataTypeMember EnumField_members[4] = { |
| 12862 | { |
| 12863 | UA_TYPENAME("Value") /* .memberName */ |
| 12864 | &UA_TYPES[UA_TYPES_INT64], /* .memberType */ |
| 12865 | 0, /* .padding */ |
| 12866 | false, /* .isArray */ |
| 12867 | false /* .isOptional */ |
| 12868 | }, |
| 12869 | { |
| 12870 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 12871 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 12872 | offsetof(UA_EnumField, displayName) - offsetof(UA_EnumField, value) - sizeof(UA_Int64), /* .padding */ |
| 12873 | false, /* .isArray */ |
| 12874 | false /* .isOptional */ |
| 12875 | }, |
| 12876 | { |
| 12877 | UA_TYPENAME("Description") /* .memberName */ |
| 12878 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 12879 | offsetof(UA_EnumField, description) - offsetof(UA_EnumField, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 12880 | false, /* .isArray */ |
| 12881 | false /* .isOptional */ |
| 12882 | }, |
| 12883 | { |
| 12884 | UA_TYPENAME("Name") /* .memberName */ |
| 12885 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12886 | offsetof(UA_EnumField, name) - offsetof(UA_EnumField, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 12887 | false, /* .isArray */ |
| 12888 | false /* .isOptional */ |
| 12889 | },}; |
| 12890 | |
| 12891 | /* OptionSet */ |
| 12892 | static UA_DataTypeMember OptionSet_members[2] = { |
| 12893 | { |
| 12894 | UA_TYPENAME("Value") /* .memberName */ |
| 12895 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 12896 | 0, /* .padding */ |
| 12897 | false, /* .isArray */ |
| 12898 | false /* .isOptional */ |
| 12899 | }, |
| 12900 | { |
| 12901 | UA_TYPENAME("ValidBits") /* .memberName */ |
| 12902 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 12903 | offsetof(UA_OptionSet, validBits) - offsetof(UA_OptionSet, value) - sizeof(UA_ByteString), /* .padding */ |
| 12904 | false, /* .isArray */ |
| 12905 | false /* .isOptional */ |
| 12906 | },}; |
| 12907 | |
| 12908 | /* NormalizedString */ |
| 12909 | #define NormalizedString_members NULL |
| 12910 | |
| 12911 | /* DecimalString */ |
| 12912 | #define DecimalString_members NULL |
| 12913 | |
| 12914 | /* DurationString */ |
| 12915 | #define DurationString_members NULL |
| 12916 | |
| 12917 | /* TimeString */ |
| 12918 | #define TimeString_members NULL |
| 12919 | |
| 12920 | /* DateString */ |
| 12921 | #define DateString_members NULL |
| 12922 | |
| 12923 | /* Duration */ |
| 12924 | #define Duration_members NULL |
| 12925 | |
| 12926 | /* UtcTime */ |
| 12927 | #define UtcTime_members NULL |
| 12928 | |
| 12929 | /* LocaleId */ |
| 12930 | #define LocaleId_members NULL |
| 12931 | |
| 12932 | /* TimeZoneDataType */ |
| 12933 | static UA_DataTypeMember TimeZoneDataType_members[2] = { |
| 12934 | { |
| 12935 | UA_TYPENAME("Offset") /* .memberName */ |
| 12936 | &UA_TYPES[UA_TYPES_INT16], /* .memberType */ |
| 12937 | 0, /* .padding */ |
| 12938 | false, /* .isArray */ |
| 12939 | false /* .isOptional */ |
| 12940 | }, |
| 12941 | { |
| 12942 | UA_TYPENAME("DaylightSavingInOffset") /* .memberName */ |
| 12943 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 12944 | offsetof(UA_TimeZoneDataType, daylightSavingInOffset) - offsetof(UA_TimeZoneDataType, offset) - sizeof(UA_Int16), /* .padding */ |
| 12945 | false, /* .isArray */ |
| 12946 | false /* .isOptional */ |
| 12947 | },}; |
| 12948 | |
| 12949 | /* Index */ |
| 12950 | #define Index_members NULL |
| 12951 | |
| 12952 | /* IntegerId */ |
| 12953 | #define IntegerId_members NULL |
| 12954 | |
| 12955 | /* ApplicationType */ |
| 12956 | #define ApplicationType_members NULL |
| 12957 | |
| 12958 | /* ApplicationDescription */ |
| 12959 | static UA_DataTypeMember ApplicationDescription_members[7] = { |
| 12960 | { |
| 12961 | UA_TYPENAME("ApplicationUri") /* .memberName */ |
| 12962 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12963 | 0, /* .padding */ |
| 12964 | false, /* .isArray */ |
| 12965 | false /* .isOptional */ |
| 12966 | }, |
| 12967 | { |
| 12968 | UA_TYPENAME("ProductUri") /* .memberName */ |
| 12969 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12970 | offsetof(UA_ApplicationDescription, productUri) - offsetof(UA_ApplicationDescription, applicationUri) - sizeof(UA_String), /* .padding */ |
| 12971 | false, /* .isArray */ |
| 12972 | false /* .isOptional */ |
| 12973 | }, |
| 12974 | { |
| 12975 | UA_TYPENAME("ApplicationName") /* .memberName */ |
| 12976 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 12977 | offsetof(UA_ApplicationDescription, applicationName) - offsetof(UA_ApplicationDescription, productUri) - sizeof(UA_String), /* .padding */ |
| 12978 | false, /* .isArray */ |
| 12979 | false /* .isOptional */ |
| 12980 | }, |
| 12981 | { |
| 12982 | UA_TYPENAME("ApplicationType") /* .memberName */ |
| 12983 | &UA_TYPES[UA_TYPES_APPLICATIONTYPE], /* .memberType */ |
| 12984 | offsetof(UA_ApplicationDescription, applicationType) - offsetof(UA_ApplicationDescription, applicationName) - sizeof(UA_LocalizedText), /* .padding */ |
| 12985 | false, /* .isArray */ |
| 12986 | false /* .isOptional */ |
| 12987 | }, |
| 12988 | { |
| 12989 | UA_TYPENAME("GatewayServerUri") /* .memberName */ |
| 12990 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12991 | offsetof(UA_ApplicationDescription, gatewayServerUri) - offsetof(UA_ApplicationDescription, applicationType) - sizeof(UA_ApplicationType), /* .padding */ |
| 12992 | false, /* .isArray */ |
| 12993 | false /* .isOptional */ |
| 12994 | }, |
| 12995 | { |
| 12996 | UA_TYPENAME("DiscoveryProfileUri") /* .memberName */ |
| 12997 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 12998 | offsetof(UA_ApplicationDescription, discoveryProfileUri) - offsetof(UA_ApplicationDescription, gatewayServerUri) - sizeof(UA_String), /* .padding */ |
| 12999 | false, /* .isArray */ |
| 13000 | false /* .isOptional */ |
| 13001 | }, |
| 13002 | { |
| 13003 | UA_TYPENAME("DiscoveryUrls") /* .memberName */ |
| 13004 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13005 | offsetof(UA_ApplicationDescription, discoveryUrlsSize) - offsetof(UA_ApplicationDescription, discoveryProfileUri) - sizeof(UA_String), /* .padding */ |
| 13006 | true, /* .isArray */ |
| 13007 | false /* .isOptional */ |
| 13008 | },}; |
| 13009 | |
| 13010 | /* RequestHeader */ |
| 13011 | static UA_DataTypeMember RequestHeader_members[7] = { |
| 13012 | { |
| 13013 | UA_TYPENAME("AuthenticationToken") /* .memberName */ |
| 13014 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 13015 | 0, /* .padding */ |
| 13016 | false, /* .isArray */ |
| 13017 | false /* .isOptional */ |
| 13018 | }, |
| 13019 | { |
| 13020 | UA_TYPENAME("Timestamp") /* .memberName */ |
| 13021 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 13022 | offsetof(UA_RequestHeader, timestamp) - offsetof(UA_RequestHeader, authenticationToken) - sizeof(UA_NodeId), /* .padding */ |
| 13023 | false, /* .isArray */ |
| 13024 | false /* .isOptional */ |
| 13025 | }, |
| 13026 | { |
| 13027 | UA_TYPENAME("RequestHandle") /* .memberName */ |
| 13028 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13029 | offsetof(UA_RequestHeader, requestHandle) - offsetof(UA_RequestHeader, timestamp) - sizeof(UA_DateTime), /* .padding */ |
| 13030 | false, /* .isArray */ |
| 13031 | false /* .isOptional */ |
| 13032 | }, |
| 13033 | { |
| 13034 | UA_TYPENAME("ReturnDiagnostics") /* .memberName */ |
| 13035 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13036 | offsetof(UA_RequestHeader, returnDiagnostics) - offsetof(UA_RequestHeader, requestHandle) - sizeof(UA_UInt32), /* .padding */ |
| 13037 | false, /* .isArray */ |
| 13038 | false /* .isOptional */ |
| 13039 | }, |
| 13040 | { |
| 13041 | UA_TYPENAME("AuditEntryId") /* .memberName */ |
| 13042 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13043 | offsetof(UA_RequestHeader, auditEntryId) - offsetof(UA_RequestHeader, returnDiagnostics) - sizeof(UA_UInt32), /* .padding */ |
| 13044 | false, /* .isArray */ |
| 13045 | false /* .isOptional */ |
| 13046 | }, |
| 13047 | { |
| 13048 | UA_TYPENAME("TimeoutHint") /* .memberName */ |
| 13049 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13050 | offsetof(UA_RequestHeader, timeoutHint) - offsetof(UA_RequestHeader, auditEntryId) - sizeof(UA_String), /* .padding */ |
| 13051 | false, /* .isArray */ |
| 13052 | false /* .isOptional */ |
| 13053 | }, |
| 13054 | { |
| 13055 | UA_TYPENAME("AdditionalHeader") /* .memberName */ |
| 13056 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 13057 | offsetof(UA_RequestHeader, additionalHeader) - offsetof(UA_RequestHeader, timeoutHint) - sizeof(UA_UInt32), /* .padding */ |
| 13058 | false, /* .isArray */ |
| 13059 | false /* .isOptional */ |
| 13060 | },}; |
| 13061 | |
| 13062 | /* ResponseHeader */ |
| 13063 | static UA_DataTypeMember ResponseHeader_members[6] = { |
| 13064 | { |
| 13065 | UA_TYPENAME("Timestamp") /* .memberName */ |
| 13066 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 13067 | 0, /* .padding */ |
| 13068 | false, /* .isArray */ |
| 13069 | false /* .isOptional */ |
| 13070 | }, |
| 13071 | { |
| 13072 | UA_TYPENAME("RequestHandle") /* .memberName */ |
| 13073 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13074 | offsetof(UA_ResponseHeader, requestHandle) - offsetof(UA_ResponseHeader, timestamp) - sizeof(UA_DateTime), /* .padding */ |
| 13075 | false, /* .isArray */ |
| 13076 | false /* .isOptional */ |
| 13077 | }, |
| 13078 | { |
| 13079 | UA_TYPENAME("ServiceResult") /* .memberName */ |
| 13080 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 13081 | offsetof(UA_ResponseHeader, serviceResult) - offsetof(UA_ResponseHeader, requestHandle) - sizeof(UA_UInt32), /* .padding */ |
| 13082 | false, /* .isArray */ |
| 13083 | false /* .isOptional */ |
| 13084 | }, |
| 13085 | { |
| 13086 | UA_TYPENAME("ServiceDiagnostics") /* .memberName */ |
| 13087 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 13088 | offsetof(UA_ResponseHeader, serviceDiagnostics) - offsetof(UA_ResponseHeader, serviceResult) - sizeof(UA_StatusCode), /* .padding */ |
| 13089 | false, /* .isArray */ |
| 13090 | false /* .isOptional */ |
| 13091 | }, |
| 13092 | { |
| 13093 | UA_TYPENAME("StringTable") /* .memberName */ |
| 13094 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13095 | offsetof(UA_ResponseHeader, stringTableSize) - offsetof(UA_ResponseHeader, serviceDiagnostics) - sizeof(UA_DiagnosticInfo), /* .padding */ |
| 13096 | true, /* .isArray */ |
| 13097 | false /* .isOptional */ |
| 13098 | }, |
| 13099 | { |
| 13100 | UA_TYPENAME("AdditionalHeader") /* .memberName */ |
| 13101 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 13102 | offsetof(UA_ResponseHeader, additionalHeader) - offsetof(UA_ResponseHeader, stringTable) - sizeof(void *), /* .padding */ |
| 13103 | false, /* .isArray */ |
| 13104 | false /* .isOptional */ |
| 13105 | },}; |
| 13106 | |
| 13107 | /* VersionTime */ |
| 13108 | #define VersionTime_members NULL |
| 13109 | |
| 13110 | /* ServiceFault */ |
| 13111 | static UA_DataTypeMember ServiceFault_members[1] = { |
| 13112 | { |
| 13113 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 13114 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 13115 | 0, /* .padding */ |
| 13116 | false, /* .isArray */ |
| 13117 | false /* .isOptional */ |
| 13118 | },}; |
| 13119 | |
| 13120 | /* SessionlessInvokeRequestType */ |
| 13121 | static UA_DataTypeMember SessionlessInvokeRequestType_members[5] = { |
| 13122 | { |
| 13123 | UA_TYPENAME("UrisVersion") /* .memberName */ |
| 13124 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13125 | 0, /* .padding */ |
| 13126 | false, /* .isArray */ |
| 13127 | false /* .isOptional */ |
| 13128 | }, |
| 13129 | { |
| 13130 | UA_TYPENAME("NamespaceUris") /* .memberName */ |
| 13131 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13132 | offsetof(UA_SessionlessInvokeRequestType, namespaceUrisSize) - offsetof(UA_SessionlessInvokeRequestType, urisVersion) - sizeof(UA_UInt32), /* .padding */ |
| 13133 | true, /* .isArray */ |
| 13134 | false /* .isOptional */ |
| 13135 | }, |
| 13136 | { |
| 13137 | UA_TYPENAME("ServerUris") /* .memberName */ |
| 13138 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13139 | offsetof(UA_SessionlessInvokeRequestType, serverUrisSize) - offsetof(UA_SessionlessInvokeRequestType, namespaceUris) - sizeof(void *), /* .padding */ |
| 13140 | true, /* .isArray */ |
| 13141 | false /* .isOptional */ |
| 13142 | }, |
| 13143 | { |
| 13144 | UA_TYPENAME("LocaleIds") /* .memberName */ |
| 13145 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13146 | offsetof(UA_SessionlessInvokeRequestType, localeIdsSize) - offsetof(UA_SessionlessInvokeRequestType, serverUris) - sizeof(void *), /* .padding */ |
| 13147 | true, /* .isArray */ |
| 13148 | false /* .isOptional */ |
| 13149 | }, |
| 13150 | { |
| 13151 | UA_TYPENAME("ServiceId") /* .memberName */ |
| 13152 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13153 | offsetof(UA_SessionlessInvokeRequestType, serviceId) - offsetof(UA_SessionlessInvokeRequestType, localeIds) - sizeof(void *), /* .padding */ |
| 13154 | false, /* .isArray */ |
| 13155 | false /* .isOptional */ |
| 13156 | },}; |
| 13157 | |
| 13158 | /* SessionlessInvokeResponseType */ |
| 13159 | static UA_DataTypeMember SessionlessInvokeResponseType_members[3] = { |
| 13160 | { |
| 13161 | UA_TYPENAME("NamespaceUris") /* .memberName */ |
| 13162 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13163 | 0, /* .padding */ |
| 13164 | true, /* .isArray */ |
| 13165 | false /* .isOptional */ |
| 13166 | }, |
| 13167 | { |
| 13168 | UA_TYPENAME("ServerUris") /* .memberName */ |
| 13169 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13170 | offsetof(UA_SessionlessInvokeResponseType, serverUrisSize) - offsetof(UA_SessionlessInvokeResponseType, namespaceUris) - sizeof(void *), /* .padding */ |
| 13171 | true, /* .isArray */ |
| 13172 | false /* .isOptional */ |
| 13173 | }, |
| 13174 | { |
| 13175 | UA_TYPENAME("ServiceId") /* .memberName */ |
| 13176 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13177 | offsetof(UA_SessionlessInvokeResponseType, serviceId) - offsetof(UA_SessionlessInvokeResponseType, serverUris) - sizeof(void *), /* .padding */ |
| 13178 | false, /* .isArray */ |
| 13179 | false /* .isOptional */ |
| 13180 | },}; |
| 13181 | |
| 13182 | /* FindServersRequest */ |
| 13183 | static UA_DataTypeMember FindServersRequest_members[4] = { |
| 13184 | { |
| 13185 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 13186 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 13187 | 0, /* .padding */ |
| 13188 | false, /* .isArray */ |
| 13189 | false /* .isOptional */ |
| 13190 | }, |
| 13191 | { |
| 13192 | UA_TYPENAME("EndpointUrl") /* .memberName */ |
| 13193 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13194 | offsetof(UA_FindServersRequest, endpointUrl) - offsetof(UA_FindServersRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 13195 | false, /* .isArray */ |
| 13196 | false /* .isOptional */ |
| 13197 | }, |
| 13198 | { |
| 13199 | UA_TYPENAME("LocaleIds") /* .memberName */ |
| 13200 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13201 | offsetof(UA_FindServersRequest, localeIdsSize) - offsetof(UA_FindServersRequest, endpointUrl) - sizeof(UA_String), /* .padding */ |
| 13202 | true, /* .isArray */ |
| 13203 | false /* .isOptional */ |
| 13204 | }, |
| 13205 | { |
| 13206 | UA_TYPENAME("ServerUris") /* .memberName */ |
| 13207 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13208 | offsetof(UA_FindServersRequest, serverUrisSize) - offsetof(UA_FindServersRequest, localeIds) - sizeof(void *), /* .padding */ |
| 13209 | true, /* .isArray */ |
| 13210 | false /* .isOptional */ |
| 13211 | },}; |
| 13212 | |
| 13213 | /* FindServersResponse */ |
| 13214 | static UA_DataTypeMember FindServersResponse_members[2] = { |
| 13215 | { |
| 13216 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 13217 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 13218 | 0, /* .padding */ |
| 13219 | false, /* .isArray */ |
| 13220 | false /* .isOptional */ |
| 13221 | }, |
| 13222 | { |
| 13223 | UA_TYPENAME("Servers") /* .memberName */ |
| 13224 | &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */ |
| 13225 | offsetof(UA_FindServersResponse, serversSize) - offsetof(UA_FindServersResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 13226 | true, /* .isArray */ |
| 13227 | false /* .isOptional */ |
| 13228 | },}; |
| 13229 | |
| 13230 | /* ServerOnNetwork */ |
| 13231 | static UA_DataTypeMember ServerOnNetwork_members[4] = { |
| 13232 | { |
| 13233 | UA_TYPENAME("RecordId") /* .memberName */ |
| 13234 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13235 | 0, /* .padding */ |
| 13236 | false, /* .isArray */ |
| 13237 | false /* .isOptional */ |
| 13238 | }, |
| 13239 | { |
| 13240 | UA_TYPENAME("ServerName") /* .memberName */ |
| 13241 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13242 | offsetof(UA_ServerOnNetwork, serverName) - offsetof(UA_ServerOnNetwork, recordId) - sizeof(UA_UInt32), /* .padding */ |
| 13243 | false, /* .isArray */ |
| 13244 | false /* .isOptional */ |
| 13245 | }, |
| 13246 | { |
| 13247 | UA_TYPENAME("DiscoveryUrl") /* .memberName */ |
| 13248 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13249 | offsetof(UA_ServerOnNetwork, discoveryUrl) - offsetof(UA_ServerOnNetwork, serverName) - sizeof(UA_String), /* .padding */ |
| 13250 | false, /* .isArray */ |
| 13251 | false /* .isOptional */ |
| 13252 | }, |
| 13253 | { |
| 13254 | UA_TYPENAME("ServerCapabilities") /* .memberName */ |
| 13255 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13256 | offsetof(UA_ServerOnNetwork, serverCapabilitiesSize) - offsetof(UA_ServerOnNetwork, discoveryUrl) - sizeof(UA_String), /* .padding */ |
| 13257 | true, /* .isArray */ |
| 13258 | false /* .isOptional */ |
| 13259 | },}; |
| 13260 | |
| 13261 | /* FindServersOnNetworkRequest */ |
| 13262 | static UA_DataTypeMember FindServersOnNetworkRequest_members[4] = { |
| 13263 | { |
| 13264 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 13265 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 13266 | 0, /* .padding */ |
| 13267 | false, /* .isArray */ |
| 13268 | false /* .isOptional */ |
| 13269 | }, |
| 13270 | { |
| 13271 | UA_TYPENAME("StartingRecordId") /* .memberName */ |
| 13272 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13273 | offsetof(UA_FindServersOnNetworkRequest, startingRecordId) - offsetof(UA_FindServersOnNetworkRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 13274 | false, /* .isArray */ |
| 13275 | false /* .isOptional */ |
| 13276 | }, |
| 13277 | { |
| 13278 | UA_TYPENAME("MaxRecordsToReturn") /* .memberName */ |
| 13279 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13280 | offsetof(UA_FindServersOnNetworkRequest, maxRecordsToReturn) - offsetof(UA_FindServersOnNetworkRequest, startingRecordId) - sizeof(UA_UInt32), /* .padding */ |
| 13281 | false, /* .isArray */ |
| 13282 | false /* .isOptional */ |
| 13283 | }, |
| 13284 | { |
| 13285 | UA_TYPENAME("ServerCapabilityFilter") /* .memberName */ |
| 13286 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13287 | offsetof(UA_FindServersOnNetworkRequest, serverCapabilityFilterSize) - offsetof(UA_FindServersOnNetworkRequest, maxRecordsToReturn) - sizeof(UA_UInt32), /* .padding */ |
| 13288 | true, /* .isArray */ |
| 13289 | false /* .isOptional */ |
| 13290 | },}; |
| 13291 | |
| 13292 | /* FindServersOnNetworkResponse */ |
| 13293 | static UA_DataTypeMember FindServersOnNetworkResponse_members[3] = { |
| 13294 | { |
| 13295 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 13296 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 13297 | 0, /* .padding */ |
| 13298 | false, /* .isArray */ |
| 13299 | false /* .isOptional */ |
| 13300 | }, |
| 13301 | { |
| 13302 | UA_TYPENAME("LastCounterResetTime") /* .memberName */ |
| 13303 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 13304 | offsetof(UA_FindServersOnNetworkResponse, lastCounterResetTime) - offsetof(UA_FindServersOnNetworkResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 13305 | false, /* .isArray */ |
| 13306 | false /* .isOptional */ |
| 13307 | }, |
| 13308 | { |
| 13309 | UA_TYPENAME("Servers") /* .memberName */ |
| 13310 | &UA_TYPES[UA_TYPES_SERVERONNETWORK], /* .memberType */ |
| 13311 | offsetof(UA_FindServersOnNetworkResponse, serversSize) - offsetof(UA_FindServersOnNetworkResponse, lastCounterResetTime) - sizeof(UA_DateTime), /* .padding */ |
| 13312 | true, /* .isArray */ |
| 13313 | false /* .isOptional */ |
| 13314 | },}; |
| 13315 | |
| 13316 | /* ApplicationInstanceCertificate */ |
| 13317 | #define ApplicationInstanceCertificate_members NULL |
| 13318 | |
| 13319 | /* MessageSecurityMode */ |
| 13320 | #define MessageSecurityMode_members NULL |
| 13321 | |
| 13322 | /* UserTokenType */ |
| 13323 | #define UserTokenType_members NULL |
| 13324 | |
| 13325 | /* UserTokenPolicy */ |
| 13326 | static UA_DataTypeMember UserTokenPolicy_members[5] = { |
| 13327 | { |
| 13328 | UA_TYPENAME("PolicyId") /* .memberName */ |
| 13329 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13330 | 0, /* .padding */ |
| 13331 | false, /* .isArray */ |
| 13332 | false /* .isOptional */ |
| 13333 | }, |
| 13334 | { |
| 13335 | UA_TYPENAME("TokenType") /* .memberName */ |
| 13336 | &UA_TYPES[UA_TYPES_USERTOKENTYPE], /* .memberType */ |
| 13337 | offsetof(UA_UserTokenPolicy, tokenType) - offsetof(UA_UserTokenPolicy, policyId) - sizeof(UA_String), /* .padding */ |
| 13338 | false, /* .isArray */ |
| 13339 | false /* .isOptional */ |
| 13340 | }, |
| 13341 | { |
| 13342 | UA_TYPENAME("IssuedTokenType") /* .memberName */ |
| 13343 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13344 | offsetof(UA_UserTokenPolicy, issuedTokenType) - offsetof(UA_UserTokenPolicy, tokenType) - sizeof(UA_UserTokenType), /* .padding */ |
| 13345 | false, /* .isArray */ |
| 13346 | false /* .isOptional */ |
| 13347 | }, |
| 13348 | { |
| 13349 | UA_TYPENAME("IssuerEndpointUrl") /* .memberName */ |
| 13350 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13351 | offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - offsetof(UA_UserTokenPolicy, issuedTokenType) - sizeof(UA_String), /* .padding */ |
| 13352 | false, /* .isArray */ |
| 13353 | false /* .isOptional */ |
| 13354 | }, |
| 13355 | { |
| 13356 | UA_TYPENAME("SecurityPolicyUri") /* .memberName */ |
| 13357 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13358 | offsetof(UA_UserTokenPolicy, securityPolicyUri) - offsetof(UA_UserTokenPolicy, issuerEndpointUrl) - sizeof(UA_String), /* .padding */ |
| 13359 | false, /* .isArray */ |
| 13360 | false /* .isOptional */ |
| 13361 | },}; |
| 13362 | |
| 13363 | /* EndpointDescription */ |
| 13364 | static UA_DataTypeMember EndpointDescription_members[8] = { |
| 13365 | { |
| 13366 | UA_TYPENAME("EndpointUrl") /* .memberName */ |
| 13367 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13368 | 0, /* .padding */ |
| 13369 | false, /* .isArray */ |
| 13370 | false /* .isOptional */ |
| 13371 | }, |
| 13372 | { |
| 13373 | UA_TYPENAME("Server") /* .memberName */ |
| 13374 | &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */ |
| 13375 | offsetof(UA_EndpointDescription, server) - offsetof(UA_EndpointDescription, endpointUrl) - sizeof(UA_String), /* .padding */ |
| 13376 | false, /* .isArray */ |
| 13377 | false /* .isOptional */ |
| 13378 | }, |
| 13379 | { |
| 13380 | UA_TYPENAME("ServerCertificate") /* .memberName */ |
| 13381 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13382 | offsetof(UA_EndpointDescription, serverCertificate) - offsetof(UA_EndpointDescription, server) - sizeof(UA_ApplicationDescription), /* .padding */ |
| 13383 | false, /* .isArray */ |
| 13384 | false /* .isOptional */ |
| 13385 | }, |
| 13386 | { |
| 13387 | UA_TYPENAME("SecurityMode") /* .memberName */ |
| 13388 | &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */ |
| 13389 | offsetof(UA_EndpointDescription, securityMode) - offsetof(UA_EndpointDescription, serverCertificate) - sizeof(UA_ByteString), /* .padding */ |
| 13390 | false, /* .isArray */ |
| 13391 | false /* .isOptional */ |
| 13392 | }, |
| 13393 | { |
| 13394 | UA_TYPENAME("SecurityPolicyUri") /* .memberName */ |
| 13395 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13396 | offsetof(UA_EndpointDescription, securityPolicyUri) - offsetof(UA_EndpointDescription, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */ |
| 13397 | false, /* .isArray */ |
| 13398 | false /* .isOptional */ |
| 13399 | }, |
| 13400 | { |
| 13401 | UA_TYPENAME("UserIdentityTokens") /* .memberName */ |
| 13402 | &UA_TYPES[UA_TYPES_USERTOKENPOLICY], /* .memberType */ |
| 13403 | offsetof(UA_EndpointDescription, userIdentityTokensSize) - offsetof(UA_EndpointDescription, securityPolicyUri) - sizeof(UA_String), /* .padding */ |
| 13404 | true, /* .isArray */ |
| 13405 | false /* .isOptional */ |
| 13406 | }, |
| 13407 | { |
| 13408 | UA_TYPENAME("TransportProfileUri") /* .memberName */ |
| 13409 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13410 | offsetof(UA_EndpointDescription, transportProfileUri) - offsetof(UA_EndpointDescription, userIdentityTokens) - sizeof(void *), /* .padding */ |
| 13411 | false, /* .isArray */ |
| 13412 | false /* .isOptional */ |
| 13413 | }, |
| 13414 | { |
| 13415 | UA_TYPENAME("SecurityLevel") /* .memberName */ |
| 13416 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 13417 | offsetof(UA_EndpointDescription, securityLevel) - offsetof(UA_EndpointDescription, transportProfileUri) - sizeof(UA_String), /* .padding */ |
| 13418 | false, /* .isArray */ |
| 13419 | false /* .isOptional */ |
| 13420 | },}; |
| 13421 | |
| 13422 | /* GetEndpointsRequest */ |
| 13423 | static UA_DataTypeMember GetEndpointsRequest_members[4] = { |
| 13424 | { |
| 13425 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 13426 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 13427 | 0, /* .padding */ |
| 13428 | false, /* .isArray */ |
| 13429 | false /* .isOptional */ |
| 13430 | }, |
| 13431 | { |
| 13432 | UA_TYPENAME("EndpointUrl") /* .memberName */ |
| 13433 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13434 | offsetof(UA_GetEndpointsRequest, endpointUrl) - offsetof(UA_GetEndpointsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 13435 | false, /* .isArray */ |
| 13436 | false /* .isOptional */ |
| 13437 | }, |
| 13438 | { |
| 13439 | UA_TYPENAME("LocaleIds") /* .memberName */ |
| 13440 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13441 | offsetof(UA_GetEndpointsRequest, localeIdsSize) - offsetof(UA_GetEndpointsRequest, endpointUrl) - sizeof(UA_String), /* .padding */ |
| 13442 | true, /* .isArray */ |
| 13443 | false /* .isOptional */ |
| 13444 | }, |
| 13445 | { |
| 13446 | UA_TYPENAME("ProfileUris") /* .memberName */ |
| 13447 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13448 | offsetof(UA_GetEndpointsRequest, profileUrisSize) - offsetof(UA_GetEndpointsRequest, localeIds) - sizeof(void *), /* .padding */ |
| 13449 | true, /* .isArray */ |
| 13450 | false /* .isOptional */ |
| 13451 | },}; |
| 13452 | |
| 13453 | /* GetEndpointsResponse */ |
| 13454 | static UA_DataTypeMember GetEndpointsResponse_members[2] = { |
| 13455 | { |
| 13456 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 13457 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 13458 | 0, /* .padding */ |
| 13459 | false, /* .isArray */ |
| 13460 | false /* .isOptional */ |
| 13461 | }, |
| 13462 | { |
| 13463 | UA_TYPENAME("Endpoints") /* .memberName */ |
| 13464 | &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */ |
| 13465 | offsetof(UA_GetEndpointsResponse, endpointsSize) - offsetof(UA_GetEndpointsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 13466 | true, /* .isArray */ |
| 13467 | false /* .isOptional */ |
| 13468 | },}; |
| 13469 | |
| 13470 | /* RegisteredServer */ |
| 13471 | static UA_DataTypeMember RegisteredServer_members[8] = { |
| 13472 | { |
| 13473 | UA_TYPENAME("ServerUri") /* .memberName */ |
| 13474 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13475 | 0, /* .padding */ |
| 13476 | false, /* .isArray */ |
| 13477 | false /* .isOptional */ |
| 13478 | }, |
| 13479 | { |
| 13480 | UA_TYPENAME("ProductUri") /* .memberName */ |
| 13481 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13482 | offsetof(UA_RegisteredServer, productUri) - offsetof(UA_RegisteredServer, serverUri) - sizeof(UA_String), /* .padding */ |
| 13483 | false, /* .isArray */ |
| 13484 | false /* .isOptional */ |
| 13485 | }, |
| 13486 | { |
| 13487 | UA_TYPENAME("ServerNames") /* .memberName */ |
| 13488 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 13489 | offsetof(UA_RegisteredServer, serverNamesSize) - offsetof(UA_RegisteredServer, productUri) - sizeof(UA_String), /* .padding */ |
| 13490 | true, /* .isArray */ |
| 13491 | false /* .isOptional */ |
| 13492 | }, |
| 13493 | { |
| 13494 | UA_TYPENAME("ServerType") /* .memberName */ |
| 13495 | &UA_TYPES[UA_TYPES_APPLICATIONTYPE], /* .memberType */ |
| 13496 | offsetof(UA_RegisteredServer, serverType) - offsetof(UA_RegisteredServer, serverNames) - sizeof(void *), /* .padding */ |
| 13497 | false, /* .isArray */ |
| 13498 | false /* .isOptional */ |
| 13499 | }, |
| 13500 | { |
| 13501 | UA_TYPENAME("GatewayServerUri") /* .memberName */ |
| 13502 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13503 | offsetof(UA_RegisteredServer, gatewayServerUri) - offsetof(UA_RegisteredServer, serverType) - sizeof(UA_ApplicationType), /* .padding */ |
| 13504 | false, /* .isArray */ |
| 13505 | false /* .isOptional */ |
| 13506 | }, |
| 13507 | { |
| 13508 | UA_TYPENAME("DiscoveryUrls") /* .memberName */ |
| 13509 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13510 | offsetof(UA_RegisteredServer, discoveryUrlsSize) - offsetof(UA_RegisteredServer, gatewayServerUri) - sizeof(UA_String), /* .padding */ |
| 13511 | true, /* .isArray */ |
| 13512 | false /* .isOptional */ |
| 13513 | }, |
| 13514 | { |
| 13515 | UA_TYPENAME("SemaphoreFilePath") /* .memberName */ |
| 13516 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13517 | offsetof(UA_RegisteredServer, semaphoreFilePath) - offsetof(UA_RegisteredServer, discoveryUrls) - sizeof(void *), /* .padding */ |
| 13518 | false, /* .isArray */ |
| 13519 | false /* .isOptional */ |
| 13520 | }, |
| 13521 | { |
| 13522 | UA_TYPENAME("IsOnline") /* .memberName */ |
| 13523 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 13524 | offsetof(UA_RegisteredServer, isOnline) - offsetof(UA_RegisteredServer, semaphoreFilePath) - sizeof(UA_String), /* .padding */ |
| 13525 | false, /* .isArray */ |
| 13526 | false /* .isOptional */ |
| 13527 | },}; |
| 13528 | |
| 13529 | /* RegisterServerRequest */ |
| 13530 | static UA_DataTypeMember RegisterServerRequest_members[2] = { |
| 13531 | { |
| 13532 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 13533 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 13534 | 0, /* .padding */ |
| 13535 | false, /* .isArray */ |
| 13536 | false /* .isOptional */ |
| 13537 | }, |
| 13538 | { |
| 13539 | UA_TYPENAME("Server") /* .memberName */ |
| 13540 | &UA_TYPES[UA_TYPES_REGISTEREDSERVER], /* .memberType */ |
| 13541 | offsetof(UA_RegisterServerRequest, server) - offsetof(UA_RegisterServerRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 13542 | false, /* .isArray */ |
| 13543 | false /* .isOptional */ |
| 13544 | },}; |
| 13545 | |
| 13546 | /* RegisterServerResponse */ |
| 13547 | static UA_DataTypeMember RegisterServerResponse_members[1] = { |
| 13548 | { |
| 13549 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 13550 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 13551 | 0, /* .padding */ |
| 13552 | false, /* .isArray */ |
| 13553 | false /* .isOptional */ |
| 13554 | },}; |
| 13555 | |
| 13556 | /* MdnsDiscoveryConfiguration */ |
| 13557 | static UA_DataTypeMember MdnsDiscoveryConfiguration_members[2] = { |
| 13558 | { |
| 13559 | UA_TYPENAME("MdnsServerName") /* .memberName */ |
| 13560 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13561 | 0, /* .padding */ |
| 13562 | false, /* .isArray */ |
| 13563 | false /* .isOptional */ |
| 13564 | }, |
| 13565 | { |
| 13566 | UA_TYPENAME("ServerCapabilities") /* .memberName */ |
| 13567 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13568 | offsetof(UA_MdnsDiscoveryConfiguration, serverCapabilitiesSize) - offsetof(UA_MdnsDiscoveryConfiguration, mdnsServerName) - sizeof(UA_String), /* .padding */ |
| 13569 | true, /* .isArray */ |
| 13570 | false /* .isOptional */ |
| 13571 | },}; |
| 13572 | |
| 13573 | /* RegisterServer2Request */ |
| 13574 | static UA_DataTypeMember RegisterServer2Request_members[3] = { |
| 13575 | { |
| 13576 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 13577 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 13578 | 0, /* .padding */ |
| 13579 | false, /* .isArray */ |
| 13580 | false /* .isOptional */ |
| 13581 | }, |
| 13582 | { |
| 13583 | UA_TYPENAME("Server") /* .memberName */ |
| 13584 | &UA_TYPES[UA_TYPES_REGISTEREDSERVER], /* .memberType */ |
| 13585 | offsetof(UA_RegisterServer2Request, server) - offsetof(UA_RegisterServer2Request, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 13586 | false, /* .isArray */ |
| 13587 | false /* .isOptional */ |
| 13588 | }, |
| 13589 | { |
| 13590 | UA_TYPENAME("DiscoveryConfiguration") /* .memberName */ |
| 13591 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 13592 | offsetof(UA_RegisterServer2Request, discoveryConfigurationSize) - offsetof(UA_RegisterServer2Request, server) - sizeof(UA_RegisteredServer), /* .padding */ |
| 13593 | true, /* .isArray */ |
| 13594 | false /* .isOptional */ |
| 13595 | },}; |
| 13596 | |
| 13597 | /* RegisterServer2Response */ |
| 13598 | static UA_DataTypeMember RegisterServer2Response_members[3] = { |
| 13599 | { |
| 13600 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 13601 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 13602 | 0, /* .padding */ |
| 13603 | false, /* .isArray */ |
| 13604 | false /* .isOptional */ |
| 13605 | }, |
| 13606 | { |
| 13607 | UA_TYPENAME("ConfigurationResults") /* .memberName */ |
| 13608 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 13609 | offsetof(UA_RegisterServer2Response, configurationResultsSize) - offsetof(UA_RegisterServer2Response, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 13610 | true, /* .isArray */ |
| 13611 | false /* .isOptional */ |
| 13612 | }, |
| 13613 | { |
| 13614 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 13615 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 13616 | offsetof(UA_RegisterServer2Response, diagnosticInfosSize) - offsetof(UA_RegisterServer2Response, configurationResults) - sizeof(void *), /* .padding */ |
| 13617 | true, /* .isArray */ |
| 13618 | false /* .isOptional */ |
| 13619 | },}; |
| 13620 | |
| 13621 | /* SecurityTokenRequestType */ |
| 13622 | #define SecurityTokenRequestType_members NULL |
| 13623 | |
| 13624 | /* ChannelSecurityToken */ |
| 13625 | static UA_DataTypeMember ChannelSecurityToken_members[4] = { |
| 13626 | { |
| 13627 | UA_TYPENAME("ChannelId") /* .memberName */ |
| 13628 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13629 | 0, /* .padding */ |
| 13630 | false, /* .isArray */ |
| 13631 | false /* .isOptional */ |
| 13632 | }, |
| 13633 | { |
| 13634 | UA_TYPENAME("TokenId") /* .memberName */ |
| 13635 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13636 | offsetof(UA_ChannelSecurityToken, tokenId) - offsetof(UA_ChannelSecurityToken, channelId) - sizeof(UA_UInt32), /* .padding */ |
| 13637 | false, /* .isArray */ |
| 13638 | false /* .isOptional */ |
| 13639 | }, |
| 13640 | { |
| 13641 | UA_TYPENAME("CreatedAt") /* .memberName */ |
| 13642 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 13643 | offsetof(UA_ChannelSecurityToken, createdAt) - offsetof(UA_ChannelSecurityToken, tokenId) - sizeof(UA_UInt32), /* .padding */ |
| 13644 | false, /* .isArray */ |
| 13645 | false /* .isOptional */ |
| 13646 | }, |
| 13647 | { |
| 13648 | UA_TYPENAME("RevisedLifetime") /* .memberName */ |
| 13649 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13650 | offsetof(UA_ChannelSecurityToken, revisedLifetime) - offsetof(UA_ChannelSecurityToken, createdAt) - sizeof(UA_DateTime), /* .padding */ |
| 13651 | false, /* .isArray */ |
| 13652 | false /* .isOptional */ |
| 13653 | },}; |
| 13654 | |
| 13655 | /* OpenSecureChannelRequest */ |
| 13656 | static UA_DataTypeMember OpenSecureChannelRequest_members[6] = { |
| 13657 | { |
| 13658 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 13659 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 13660 | 0, /* .padding */ |
| 13661 | false, /* .isArray */ |
| 13662 | false /* .isOptional */ |
| 13663 | }, |
| 13664 | { |
| 13665 | UA_TYPENAME("ClientProtocolVersion") /* .memberName */ |
| 13666 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13667 | offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - offsetof(UA_OpenSecureChannelRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 13668 | false, /* .isArray */ |
| 13669 | false /* .isOptional */ |
| 13670 | }, |
| 13671 | { |
| 13672 | UA_TYPENAME("RequestType") /* .memberName */ |
| 13673 | &UA_TYPES[UA_TYPES_SECURITYTOKENREQUESTTYPE], /* .memberType */ |
| 13674 | offsetof(UA_OpenSecureChannelRequest, requestType) - offsetof(UA_OpenSecureChannelRequest, clientProtocolVersion) - sizeof(UA_UInt32), /* .padding */ |
| 13675 | false, /* .isArray */ |
| 13676 | false /* .isOptional */ |
| 13677 | }, |
| 13678 | { |
| 13679 | UA_TYPENAME("SecurityMode") /* .memberName */ |
| 13680 | &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */ |
| 13681 | offsetof(UA_OpenSecureChannelRequest, securityMode) - offsetof(UA_OpenSecureChannelRequest, requestType) - sizeof(UA_SecurityTokenRequestType), /* .padding */ |
| 13682 | false, /* .isArray */ |
| 13683 | false /* .isOptional */ |
| 13684 | }, |
| 13685 | { |
| 13686 | UA_TYPENAME("ClientNonce") /* .memberName */ |
| 13687 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13688 | offsetof(UA_OpenSecureChannelRequest, clientNonce) - offsetof(UA_OpenSecureChannelRequest, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */ |
| 13689 | false, /* .isArray */ |
| 13690 | false /* .isOptional */ |
| 13691 | }, |
| 13692 | { |
| 13693 | UA_TYPENAME("RequestedLifetime") /* .memberName */ |
| 13694 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13695 | offsetof(UA_OpenSecureChannelRequest, requestedLifetime) - offsetof(UA_OpenSecureChannelRequest, clientNonce) - sizeof(UA_ByteString), /* .padding */ |
| 13696 | false, /* .isArray */ |
| 13697 | false /* .isOptional */ |
| 13698 | },}; |
| 13699 | |
| 13700 | /* OpenSecureChannelResponse */ |
| 13701 | static UA_DataTypeMember OpenSecureChannelResponse_members[4] = { |
| 13702 | { |
| 13703 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 13704 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 13705 | 0, /* .padding */ |
| 13706 | false, /* .isArray */ |
| 13707 | false /* .isOptional */ |
| 13708 | }, |
| 13709 | { |
| 13710 | UA_TYPENAME("ServerProtocolVersion") /* .memberName */ |
| 13711 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13712 | offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - offsetof(UA_OpenSecureChannelResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 13713 | false, /* .isArray */ |
| 13714 | false /* .isOptional */ |
| 13715 | }, |
| 13716 | { |
| 13717 | UA_TYPENAME("SecurityToken") /* .memberName */ |
| 13718 | &UA_TYPES[UA_TYPES_CHANNELSECURITYTOKEN], /* .memberType */ |
| 13719 | offsetof(UA_OpenSecureChannelResponse, securityToken) - offsetof(UA_OpenSecureChannelResponse, serverProtocolVersion) - sizeof(UA_UInt32), /* .padding */ |
| 13720 | false, /* .isArray */ |
| 13721 | false /* .isOptional */ |
| 13722 | }, |
| 13723 | { |
| 13724 | UA_TYPENAME("ServerNonce") /* .memberName */ |
| 13725 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13726 | offsetof(UA_OpenSecureChannelResponse, serverNonce) - offsetof(UA_OpenSecureChannelResponse, securityToken) - sizeof(UA_ChannelSecurityToken), /* .padding */ |
| 13727 | false, /* .isArray */ |
| 13728 | false /* .isOptional */ |
| 13729 | },}; |
| 13730 | |
| 13731 | /* CloseSecureChannelRequest */ |
| 13732 | static UA_DataTypeMember CloseSecureChannelRequest_members[1] = { |
| 13733 | { |
| 13734 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 13735 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 13736 | 0, /* .padding */ |
| 13737 | false, /* .isArray */ |
| 13738 | false /* .isOptional */ |
| 13739 | },}; |
| 13740 | |
| 13741 | /* CloseSecureChannelResponse */ |
| 13742 | static UA_DataTypeMember CloseSecureChannelResponse_members[1] = { |
| 13743 | { |
| 13744 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 13745 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 13746 | 0, /* .padding */ |
| 13747 | false, /* .isArray */ |
| 13748 | false /* .isOptional */ |
| 13749 | },}; |
| 13750 | |
| 13751 | /* SignedSoftwareCertificate */ |
| 13752 | static UA_DataTypeMember SignedSoftwareCertificate_members[2] = { |
| 13753 | { |
| 13754 | UA_TYPENAME("CertificateData") /* .memberName */ |
| 13755 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13756 | 0, /* .padding */ |
| 13757 | false, /* .isArray */ |
| 13758 | false /* .isOptional */ |
| 13759 | }, |
| 13760 | { |
| 13761 | UA_TYPENAME("Signature") /* .memberName */ |
| 13762 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13763 | offsetof(UA_SignedSoftwareCertificate, signature) - offsetof(UA_SignedSoftwareCertificate, certificateData) - sizeof(UA_ByteString), /* .padding */ |
| 13764 | false, /* .isArray */ |
| 13765 | false /* .isOptional */ |
| 13766 | },}; |
| 13767 | |
| 13768 | /* SessionAuthenticationToken */ |
| 13769 | #define SessionAuthenticationToken_members NULL |
| 13770 | |
| 13771 | /* SignatureData */ |
| 13772 | static UA_DataTypeMember SignatureData_members[2] = { |
| 13773 | { |
| 13774 | UA_TYPENAME("Algorithm") /* .memberName */ |
| 13775 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13776 | 0, /* .padding */ |
| 13777 | false, /* .isArray */ |
| 13778 | false /* .isOptional */ |
| 13779 | }, |
| 13780 | { |
| 13781 | UA_TYPENAME("Signature") /* .memberName */ |
| 13782 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13783 | offsetof(UA_SignatureData, signature) - offsetof(UA_SignatureData, algorithm) - sizeof(UA_String), /* .padding */ |
| 13784 | false, /* .isArray */ |
| 13785 | false /* .isOptional */ |
| 13786 | },}; |
| 13787 | |
| 13788 | /* CreateSessionRequest */ |
| 13789 | static UA_DataTypeMember CreateSessionRequest_members[9] = { |
| 13790 | { |
| 13791 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 13792 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 13793 | 0, /* .padding */ |
| 13794 | false, /* .isArray */ |
| 13795 | false /* .isOptional */ |
| 13796 | }, |
| 13797 | { |
| 13798 | UA_TYPENAME("ClientDescription") /* .memberName */ |
| 13799 | &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */ |
| 13800 | offsetof(UA_CreateSessionRequest, clientDescription) - offsetof(UA_CreateSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 13801 | false, /* .isArray */ |
| 13802 | false /* .isOptional */ |
| 13803 | }, |
| 13804 | { |
| 13805 | UA_TYPENAME("ServerUri") /* .memberName */ |
| 13806 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13807 | offsetof(UA_CreateSessionRequest, serverUri) - offsetof(UA_CreateSessionRequest, clientDescription) - sizeof(UA_ApplicationDescription), /* .padding */ |
| 13808 | false, /* .isArray */ |
| 13809 | false /* .isOptional */ |
| 13810 | }, |
| 13811 | { |
| 13812 | UA_TYPENAME("EndpointUrl") /* .memberName */ |
| 13813 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13814 | offsetof(UA_CreateSessionRequest, endpointUrl) - offsetof(UA_CreateSessionRequest, serverUri) - sizeof(UA_String), /* .padding */ |
| 13815 | false, /* .isArray */ |
| 13816 | false /* .isOptional */ |
| 13817 | }, |
| 13818 | { |
| 13819 | UA_TYPENAME("SessionName") /* .memberName */ |
| 13820 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13821 | offsetof(UA_CreateSessionRequest, sessionName) - offsetof(UA_CreateSessionRequest, endpointUrl) - sizeof(UA_String), /* .padding */ |
| 13822 | false, /* .isArray */ |
| 13823 | false /* .isOptional */ |
| 13824 | }, |
| 13825 | { |
| 13826 | UA_TYPENAME("ClientNonce") /* .memberName */ |
| 13827 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13828 | offsetof(UA_CreateSessionRequest, clientNonce) - offsetof(UA_CreateSessionRequest, sessionName) - sizeof(UA_String), /* .padding */ |
| 13829 | false, /* .isArray */ |
| 13830 | false /* .isOptional */ |
| 13831 | }, |
| 13832 | { |
| 13833 | UA_TYPENAME("ClientCertificate") /* .memberName */ |
| 13834 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13835 | offsetof(UA_CreateSessionRequest, clientCertificate) - offsetof(UA_CreateSessionRequest, clientNonce) - sizeof(UA_ByteString), /* .padding */ |
| 13836 | false, /* .isArray */ |
| 13837 | false /* .isOptional */ |
| 13838 | }, |
| 13839 | { |
| 13840 | UA_TYPENAME("RequestedSessionTimeout") /* .memberName */ |
| 13841 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 13842 | offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - offsetof(UA_CreateSessionRequest, clientCertificate) - sizeof(UA_ByteString), /* .padding */ |
| 13843 | false, /* .isArray */ |
| 13844 | false /* .isOptional */ |
| 13845 | }, |
| 13846 | { |
| 13847 | UA_TYPENAME("MaxResponseMessageSize") /* .memberName */ |
| 13848 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13849 | offsetof(UA_CreateSessionRequest, maxResponseMessageSize) - offsetof(UA_CreateSessionRequest, requestedSessionTimeout) - sizeof(UA_Double), /* .padding */ |
| 13850 | false, /* .isArray */ |
| 13851 | false /* .isOptional */ |
| 13852 | },}; |
| 13853 | |
| 13854 | /* CreateSessionResponse */ |
| 13855 | static UA_DataTypeMember CreateSessionResponse_members[10] = { |
| 13856 | { |
| 13857 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 13858 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 13859 | 0, /* .padding */ |
| 13860 | false, /* .isArray */ |
| 13861 | false /* .isOptional */ |
| 13862 | }, |
| 13863 | { |
| 13864 | UA_TYPENAME("SessionId") /* .memberName */ |
| 13865 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 13866 | offsetof(UA_CreateSessionResponse, sessionId) - offsetof(UA_CreateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 13867 | false, /* .isArray */ |
| 13868 | false /* .isOptional */ |
| 13869 | }, |
| 13870 | { |
| 13871 | UA_TYPENAME("AuthenticationToken") /* .memberName */ |
| 13872 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 13873 | offsetof(UA_CreateSessionResponse, authenticationToken) - offsetof(UA_CreateSessionResponse, sessionId) - sizeof(UA_NodeId), /* .padding */ |
| 13874 | false, /* .isArray */ |
| 13875 | false /* .isOptional */ |
| 13876 | }, |
| 13877 | { |
| 13878 | UA_TYPENAME("RevisedSessionTimeout") /* .memberName */ |
| 13879 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 13880 | offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - offsetof(UA_CreateSessionResponse, authenticationToken) - sizeof(UA_NodeId), /* .padding */ |
| 13881 | false, /* .isArray */ |
| 13882 | false /* .isOptional */ |
| 13883 | }, |
| 13884 | { |
| 13885 | UA_TYPENAME("ServerNonce") /* .memberName */ |
| 13886 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13887 | offsetof(UA_CreateSessionResponse, serverNonce) - offsetof(UA_CreateSessionResponse, revisedSessionTimeout) - sizeof(UA_Double), /* .padding */ |
| 13888 | false, /* .isArray */ |
| 13889 | false /* .isOptional */ |
| 13890 | }, |
| 13891 | { |
| 13892 | UA_TYPENAME("ServerCertificate") /* .memberName */ |
| 13893 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13894 | offsetof(UA_CreateSessionResponse, serverCertificate) - offsetof(UA_CreateSessionResponse, serverNonce) - sizeof(UA_ByteString), /* .padding */ |
| 13895 | false, /* .isArray */ |
| 13896 | false /* .isOptional */ |
| 13897 | }, |
| 13898 | { |
| 13899 | UA_TYPENAME("ServerEndpoints") /* .memberName */ |
| 13900 | &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */ |
| 13901 | offsetof(UA_CreateSessionResponse, serverEndpointsSize) - offsetof(UA_CreateSessionResponse, serverCertificate) - sizeof(UA_ByteString), /* .padding */ |
| 13902 | true, /* .isArray */ |
| 13903 | false /* .isOptional */ |
| 13904 | }, |
| 13905 | { |
| 13906 | UA_TYPENAME("ServerSoftwareCertificates") /* .memberName */ |
| 13907 | &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], /* .memberType */ |
| 13908 | offsetof(UA_CreateSessionResponse, serverSoftwareCertificatesSize) - offsetof(UA_CreateSessionResponse, serverEndpoints) - sizeof(void *), /* .padding */ |
| 13909 | true, /* .isArray */ |
| 13910 | false /* .isOptional */ |
| 13911 | }, |
| 13912 | { |
| 13913 | UA_TYPENAME("ServerSignature") /* .memberName */ |
| 13914 | &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */ |
| 13915 | offsetof(UA_CreateSessionResponse, serverSignature) - offsetof(UA_CreateSessionResponse, serverSoftwareCertificates) - sizeof(void *), /* .padding */ |
| 13916 | false, /* .isArray */ |
| 13917 | false /* .isOptional */ |
| 13918 | }, |
| 13919 | { |
| 13920 | UA_TYPENAME("MaxRequestMessageSize") /* .memberName */ |
| 13921 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 13922 | offsetof(UA_CreateSessionResponse, maxRequestMessageSize) - offsetof(UA_CreateSessionResponse, serverSignature) - sizeof(UA_SignatureData), /* .padding */ |
| 13923 | false, /* .isArray */ |
| 13924 | false /* .isOptional */ |
| 13925 | },}; |
| 13926 | |
| 13927 | /* UserIdentityToken */ |
| 13928 | static UA_DataTypeMember UserIdentityToken_members[1] = { |
| 13929 | { |
| 13930 | UA_TYPENAME("PolicyId") /* .memberName */ |
| 13931 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13932 | 0, /* .padding */ |
| 13933 | false, /* .isArray */ |
| 13934 | false /* .isOptional */ |
| 13935 | },}; |
| 13936 | |
| 13937 | /* AnonymousIdentityToken */ |
| 13938 | static UA_DataTypeMember AnonymousIdentityToken_members[1] = { |
| 13939 | { |
| 13940 | UA_TYPENAME("PolicyId") /* .memberName */ |
| 13941 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13942 | 0, /* .padding */ |
| 13943 | false, /* .isArray */ |
| 13944 | false /* .isOptional */ |
| 13945 | },}; |
| 13946 | |
| 13947 | /* UserNameIdentityToken */ |
| 13948 | static UA_DataTypeMember UserNameIdentityToken_members[4] = { |
| 13949 | { |
| 13950 | UA_TYPENAME("PolicyId") /* .memberName */ |
| 13951 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13952 | 0, /* .padding */ |
| 13953 | false, /* .isArray */ |
| 13954 | false /* .isOptional */ |
| 13955 | }, |
| 13956 | { |
| 13957 | UA_TYPENAME("UserName") /* .memberName */ |
| 13958 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13959 | offsetof(UA_UserNameIdentityToken, userName) - offsetof(UA_UserNameIdentityToken, policyId) - sizeof(UA_String), /* .padding */ |
| 13960 | false, /* .isArray */ |
| 13961 | false /* .isOptional */ |
| 13962 | }, |
| 13963 | { |
| 13964 | UA_TYPENAME("Password") /* .memberName */ |
| 13965 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13966 | offsetof(UA_UserNameIdentityToken, password) - offsetof(UA_UserNameIdentityToken, userName) - sizeof(UA_String), /* .padding */ |
| 13967 | false, /* .isArray */ |
| 13968 | false /* .isOptional */ |
| 13969 | }, |
| 13970 | { |
| 13971 | UA_TYPENAME("EncryptionAlgorithm") /* .memberName */ |
| 13972 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13973 | offsetof(UA_UserNameIdentityToken, encryptionAlgorithm) - offsetof(UA_UserNameIdentityToken, password) - sizeof(UA_ByteString), /* .padding */ |
| 13974 | false, /* .isArray */ |
| 13975 | false /* .isOptional */ |
| 13976 | },}; |
| 13977 | |
| 13978 | /* X509IdentityToken */ |
| 13979 | static UA_DataTypeMember X509IdentityToken_members[2] = { |
| 13980 | { |
| 13981 | UA_TYPENAME("PolicyId") /* .memberName */ |
| 13982 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 13983 | 0, /* .padding */ |
| 13984 | false, /* .isArray */ |
| 13985 | false /* .isOptional */ |
| 13986 | }, |
| 13987 | { |
| 13988 | UA_TYPENAME("CertificateData") /* .memberName */ |
| 13989 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 13990 | offsetof(UA_X509IdentityToken, certificateData) - offsetof(UA_X509IdentityToken, policyId) - sizeof(UA_String), /* .padding */ |
| 13991 | false, /* .isArray */ |
| 13992 | false /* .isOptional */ |
| 13993 | },}; |
| 13994 | |
| 13995 | /* IssuedIdentityToken */ |
| 13996 | static UA_DataTypeMember IssuedIdentityToken_members[3] = { |
| 13997 | { |
| 13998 | UA_TYPENAME("PolicyId") /* .memberName */ |
| 13999 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 14000 | 0, /* .padding */ |
| 14001 | false, /* .isArray */ |
| 14002 | false /* .isOptional */ |
| 14003 | }, |
| 14004 | { |
| 14005 | UA_TYPENAME("TokenData") /* .memberName */ |
| 14006 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 14007 | offsetof(UA_IssuedIdentityToken, tokenData) - offsetof(UA_IssuedIdentityToken, policyId) - sizeof(UA_String), /* .padding */ |
| 14008 | false, /* .isArray */ |
| 14009 | false /* .isOptional */ |
| 14010 | }, |
| 14011 | { |
| 14012 | UA_TYPENAME("EncryptionAlgorithm") /* .memberName */ |
| 14013 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 14014 | offsetof(UA_IssuedIdentityToken, encryptionAlgorithm) - offsetof(UA_IssuedIdentityToken, tokenData) - sizeof(UA_ByteString), /* .padding */ |
| 14015 | false, /* .isArray */ |
| 14016 | false /* .isOptional */ |
| 14017 | },}; |
| 14018 | |
| 14019 | /* RsaEncryptedSecret */ |
| 14020 | #define RsaEncryptedSecret_members NULL |
| 14021 | |
| 14022 | /* EccEncryptedSecret */ |
| 14023 | #define EccEncryptedSecret_members NULL |
| 14024 | |
| 14025 | /* ActivateSessionRequest */ |
| 14026 | static UA_DataTypeMember ActivateSessionRequest_members[6] = { |
| 14027 | { |
| 14028 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 14029 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 14030 | 0, /* .padding */ |
| 14031 | false, /* .isArray */ |
| 14032 | false /* .isOptional */ |
| 14033 | }, |
| 14034 | { |
| 14035 | UA_TYPENAME("ClientSignature") /* .memberName */ |
| 14036 | &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */ |
| 14037 | offsetof(UA_ActivateSessionRequest, clientSignature) - offsetof(UA_ActivateSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 14038 | false, /* .isArray */ |
| 14039 | false /* .isOptional */ |
| 14040 | }, |
| 14041 | { |
| 14042 | UA_TYPENAME("ClientSoftwareCertificates") /* .memberName */ |
| 14043 | &UA_TYPES[UA_TYPES_SIGNEDSOFTWARECERTIFICATE], /* .memberType */ |
| 14044 | offsetof(UA_ActivateSessionRequest, clientSoftwareCertificatesSize) - offsetof(UA_ActivateSessionRequest, clientSignature) - sizeof(UA_SignatureData), /* .padding */ |
| 14045 | true, /* .isArray */ |
| 14046 | false /* .isOptional */ |
| 14047 | }, |
| 14048 | { |
| 14049 | UA_TYPENAME("LocaleIds") /* .memberName */ |
| 14050 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 14051 | offsetof(UA_ActivateSessionRequest, localeIdsSize) - offsetof(UA_ActivateSessionRequest, clientSoftwareCertificates) - sizeof(void *), /* .padding */ |
| 14052 | true, /* .isArray */ |
| 14053 | false /* .isOptional */ |
| 14054 | }, |
| 14055 | { |
| 14056 | UA_TYPENAME("UserIdentityToken") /* .memberName */ |
| 14057 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 14058 | offsetof(UA_ActivateSessionRequest, userIdentityToken) - offsetof(UA_ActivateSessionRequest, localeIds) - sizeof(void *), /* .padding */ |
| 14059 | false, /* .isArray */ |
| 14060 | false /* .isOptional */ |
| 14061 | }, |
| 14062 | { |
| 14063 | UA_TYPENAME("UserTokenSignature") /* .memberName */ |
| 14064 | &UA_TYPES[UA_TYPES_SIGNATUREDATA], /* .memberType */ |
| 14065 | offsetof(UA_ActivateSessionRequest, userTokenSignature) - offsetof(UA_ActivateSessionRequest, userIdentityToken) - sizeof(UA_ExtensionObject), /* .padding */ |
| 14066 | false, /* .isArray */ |
| 14067 | false /* .isOptional */ |
| 14068 | },}; |
| 14069 | |
| 14070 | /* ActivateSessionResponse */ |
| 14071 | static UA_DataTypeMember ActivateSessionResponse_members[4] = { |
| 14072 | { |
| 14073 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 14074 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 14075 | 0, /* .padding */ |
| 14076 | false, /* .isArray */ |
| 14077 | false /* .isOptional */ |
| 14078 | }, |
| 14079 | { |
| 14080 | UA_TYPENAME("ServerNonce") /* .memberName */ |
| 14081 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 14082 | offsetof(UA_ActivateSessionResponse, serverNonce) - offsetof(UA_ActivateSessionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 14083 | false, /* .isArray */ |
| 14084 | false /* .isOptional */ |
| 14085 | }, |
| 14086 | { |
| 14087 | UA_TYPENAME("Results") /* .memberName */ |
| 14088 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 14089 | offsetof(UA_ActivateSessionResponse, resultsSize) - offsetof(UA_ActivateSessionResponse, serverNonce) - sizeof(UA_ByteString), /* .padding */ |
| 14090 | true, /* .isArray */ |
| 14091 | false /* .isOptional */ |
| 14092 | }, |
| 14093 | { |
| 14094 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 14095 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 14096 | offsetof(UA_ActivateSessionResponse, diagnosticInfosSize) - offsetof(UA_ActivateSessionResponse, results) - sizeof(void *), /* .padding */ |
| 14097 | true, /* .isArray */ |
| 14098 | false /* .isOptional */ |
| 14099 | },}; |
| 14100 | |
| 14101 | /* CloseSessionRequest */ |
| 14102 | static UA_DataTypeMember CloseSessionRequest_members[2] = { |
| 14103 | { |
| 14104 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 14105 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 14106 | 0, /* .padding */ |
| 14107 | false, /* .isArray */ |
| 14108 | false /* .isOptional */ |
| 14109 | }, |
| 14110 | { |
| 14111 | UA_TYPENAME("DeleteSubscriptions") /* .memberName */ |
| 14112 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14113 | offsetof(UA_CloseSessionRequest, deleteSubscriptions) - offsetof(UA_CloseSessionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 14114 | false, /* .isArray */ |
| 14115 | false /* .isOptional */ |
| 14116 | },}; |
| 14117 | |
| 14118 | /* CloseSessionResponse */ |
| 14119 | static UA_DataTypeMember CloseSessionResponse_members[1] = { |
| 14120 | { |
| 14121 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 14122 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 14123 | 0, /* .padding */ |
| 14124 | false, /* .isArray */ |
| 14125 | false /* .isOptional */ |
| 14126 | },}; |
| 14127 | |
| 14128 | /* CancelRequest */ |
| 14129 | static UA_DataTypeMember CancelRequest_members[2] = { |
| 14130 | { |
| 14131 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 14132 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 14133 | 0, /* .padding */ |
| 14134 | false, /* .isArray */ |
| 14135 | false /* .isOptional */ |
| 14136 | }, |
| 14137 | { |
| 14138 | UA_TYPENAME("RequestHandle") /* .memberName */ |
| 14139 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14140 | offsetof(UA_CancelRequest, requestHandle) - offsetof(UA_CancelRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 14141 | false, /* .isArray */ |
| 14142 | false /* .isOptional */ |
| 14143 | },}; |
| 14144 | |
| 14145 | /* CancelResponse */ |
| 14146 | static UA_DataTypeMember CancelResponse_members[2] = { |
| 14147 | { |
| 14148 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 14149 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 14150 | 0, /* .padding */ |
| 14151 | false, /* .isArray */ |
| 14152 | false /* .isOptional */ |
| 14153 | }, |
| 14154 | { |
| 14155 | UA_TYPENAME("CancelCount") /* .memberName */ |
| 14156 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14157 | offsetof(UA_CancelResponse, cancelCount) - offsetof(UA_CancelResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 14158 | false, /* .isArray */ |
| 14159 | false /* .isOptional */ |
| 14160 | },}; |
| 14161 | |
| 14162 | /* NodeAttributesMask */ |
| 14163 | #define NodeAttributesMask_members NULL |
| 14164 | |
| 14165 | /* NodeAttributes */ |
| 14166 | static UA_DataTypeMember NodeAttributes_members[5] = { |
| 14167 | { |
| 14168 | UA_TYPENAME("SpecifiedAttributes") /* .memberName */ |
| 14169 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14170 | 0, /* .padding */ |
| 14171 | false, /* .isArray */ |
| 14172 | false /* .isOptional */ |
| 14173 | }, |
| 14174 | { |
| 14175 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 14176 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14177 | offsetof(UA_NodeAttributes, displayName) - offsetof(UA_NodeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */ |
| 14178 | false, /* .isArray */ |
| 14179 | false /* .isOptional */ |
| 14180 | }, |
| 14181 | { |
| 14182 | UA_TYPENAME("Description") /* .memberName */ |
| 14183 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14184 | offsetof(UA_NodeAttributes, description) - offsetof(UA_NodeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 14185 | false, /* .isArray */ |
| 14186 | false /* .isOptional */ |
| 14187 | }, |
| 14188 | { |
| 14189 | UA_TYPENAME("WriteMask") /* .memberName */ |
| 14190 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14191 | offsetof(UA_NodeAttributes, writeMask) - offsetof(UA_NodeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 14192 | false, /* .isArray */ |
| 14193 | false /* .isOptional */ |
| 14194 | }, |
| 14195 | { |
| 14196 | UA_TYPENAME("UserWriteMask") /* .memberName */ |
| 14197 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14198 | offsetof(UA_NodeAttributes, userWriteMask) - offsetof(UA_NodeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */ |
| 14199 | false, /* .isArray */ |
| 14200 | false /* .isOptional */ |
| 14201 | },}; |
| 14202 | |
| 14203 | /* ObjectAttributes */ |
| 14204 | static UA_DataTypeMember ObjectAttributes_members[6] = { |
| 14205 | { |
| 14206 | UA_TYPENAME("SpecifiedAttributes") /* .memberName */ |
| 14207 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14208 | 0, /* .padding */ |
| 14209 | false, /* .isArray */ |
| 14210 | false /* .isOptional */ |
| 14211 | }, |
| 14212 | { |
| 14213 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 14214 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14215 | offsetof(UA_ObjectAttributes, displayName) - offsetof(UA_ObjectAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */ |
| 14216 | false, /* .isArray */ |
| 14217 | false /* .isOptional */ |
| 14218 | }, |
| 14219 | { |
| 14220 | UA_TYPENAME("Description") /* .memberName */ |
| 14221 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14222 | offsetof(UA_ObjectAttributes, description) - offsetof(UA_ObjectAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 14223 | false, /* .isArray */ |
| 14224 | false /* .isOptional */ |
| 14225 | }, |
| 14226 | { |
| 14227 | UA_TYPENAME("WriteMask") /* .memberName */ |
| 14228 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14229 | offsetof(UA_ObjectAttributes, writeMask) - offsetof(UA_ObjectAttributes, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 14230 | false, /* .isArray */ |
| 14231 | false /* .isOptional */ |
| 14232 | }, |
| 14233 | { |
| 14234 | UA_TYPENAME("UserWriteMask") /* .memberName */ |
| 14235 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14236 | offsetof(UA_ObjectAttributes, userWriteMask) - offsetof(UA_ObjectAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */ |
| 14237 | false, /* .isArray */ |
| 14238 | false /* .isOptional */ |
| 14239 | }, |
| 14240 | { |
| 14241 | UA_TYPENAME("EventNotifier") /* .memberName */ |
| 14242 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 14243 | offsetof(UA_ObjectAttributes, eventNotifier) - offsetof(UA_ObjectAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */ |
| 14244 | false, /* .isArray */ |
| 14245 | false /* .isOptional */ |
| 14246 | },}; |
| 14247 | |
| 14248 | /* VariableAttributes */ |
| 14249 | static UA_DataTypeMember VariableAttributes_members[13] = { |
| 14250 | { |
| 14251 | UA_TYPENAME("SpecifiedAttributes") /* .memberName */ |
| 14252 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14253 | 0, /* .padding */ |
| 14254 | false, /* .isArray */ |
| 14255 | false /* .isOptional */ |
| 14256 | }, |
| 14257 | { |
| 14258 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 14259 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14260 | offsetof(UA_VariableAttributes, displayName) - offsetof(UA_VariableAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */ |
| 14261 | false, /* .isArray */ |
| 14262 | false /* .isOptional */ |
| 14263 | }, |
| 14264 | { |
| 14265 | UA_TYPENAME("Description") /* .memberName */ |
| 14266 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14267 | offsetof(UA_VariableAttributes, description) - offsetof(UA_VariableAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 14268 | false, /* .isArray */ |
| 14269 | false /* .isOptional */ |
| 14270 | }, |
| 14271 | { |
| 14272 | UA_TYPENAME("WriteMask") /* .memberName */ |
| 14273 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14274 | offsetof(UA_VariableAttributes, writeMask) - offsetof(UA_VariableAttributes, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 14275 | false, /* .isArray */ |
| 14276 | false /* .isOptional */ |
| 14277 | }, |
| 14278 | { |
| 14279 | UA_TYPENAME("UserWriteMask") /* .memberName */ |
| 14280 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14281 | offsetof(UA_VariableAttributes, userWriteMask) - offsetof(UA_VariableAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */ |
| 14282 | false, /* .isArray */ |
| 14283 | false /* .isOptional */ |
| 14284 | }, |
| 14285 | { |
| 14286 | UA_TYPENAME("Value") /* .memberName */ |
| 14287 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 14288 | offsetof(UA_VariableAttributes, value) - offsetof(UA_VariableAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */ |
| 14289 | false, /* .isArray */ |
| 14290 | false /* .isOptional */ |
| 14291 | }, |
| 14292 | { |
| 14293 | UA_TYPENAME("DataType") /* .memberName */ |
| 14294 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 14295 | offsetof(UA_VariableAttributes, dataType) - offsetof(UA_VariableAttributes, value) - sizeof(UA_Variant), /* .padding */ |
| 14296 | false, /* .isArray */ |
| 14297 | false /* .isOptional */ |
| 14298 | }, |
| 14299 | { |
| 14300 | UA_TYPENAME("ValueRank") /* .memberName */ |
| 14301 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 14302 | offsetof(UA_VariableAttributes, valueRank) - offsetof(UA_VariableAttributes, dataType) - sizeof(UA_NodeId), /* .padding */ |
| 14303 | false, /* .isArray */ |
| 14304 | false /* .isOptional */ |
| 14305 | }, |
| 14306 | { |
| 14307 | UA_TYPENAME("ArrayDimensions") /* .memberName */ |
| 14308 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14309 | offsetof(UA_VariableAttributes, arrayDimensionsSize) - offsetof(UA_VariableAttributes, valueRank) - sizeof(UA_Int32), /* .padding */ |
| 14310 | true, /* .isArray */ |
| 14311 | false /* .isOptional */ |
| 14312 | }, |
| 14313 | { |
| 14314 | UA_TYPENAME("AccessLevel") /* .memberName */ |
| 14315 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 14316 | offsetof(UA_VariableAttributes, accessLevel) - offsetof(UA_VariableAttributes, arrayDimensions) - sizeof(void *), /* .padding */ |
| 14317 | false, /* .isArray */ |
| 14318 | false /* .isOptional */ |
| 14319 | }, |
| 14320 | { |
| 14321 | UA_TYPENAME("UserAccessLevel") /* .memberName */ |
| 14322 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 14323 | offsetof(UA_VariableAttributes, userAccessLevel) - offsetof(UA_VariableAttributes, accessLevel) - sizeof(UA_Byte), /* .padding */ |
| 14324 | false, /* .isArray */ |
| 14325 | false /* .isOptional */ |
| 14326 | }, |
| 14327 | { |
| 14328 | UA_TYPENAME("MinimumSamplingInterval") /* .memberName */ |
| 14329 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 14330 | offsetof(UA_VariableAttributes, minimumSamplingInterval) - offsetof(UA_VariableAttributes, userAccessLevel) - sizeof(UA_Byte), /* .padding */ |
| 14331 | false, /* .isArray */ |
| 14332 | false /* .isOptional */ |
| 14333 | }, |
| 14334 | { |
| 14335 | UA_TYPENAME("Historizing") /* .memberName */ |
| 14336 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14337 | offsetof(UA_VariableAttributes, historizing) - offsetof(UA_VariableAttributes, minimumSamplingInterval) - sizeof(UA_Double), /* .padding */ |
| 14338 | false, /* .isArray */ |
| 14339 | false /* .isOptional */ |
| 14340 | },}; |
| 14341 | |
| 14342 | /* MethodAttributes */ |
| 14343 | static UA_DataTypeMember MethodAttributes_members[7] = { |
| 14344 | { |
| 14345 | UA_TYPENAME("SpecifiedAttributes") /* .memberName */ |
| 14346 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14347 | 0, /* .padding */ |
| 14348 | false, /* .isArray */ |
| 14349 | false /* .isOptional */ |
| 14350 | }, |
| 14351 | { |
| 14352 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 14353 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14354 | offsetof(UA_MethodAttributes, displayName) - offsetof(UA_MethodAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */ |
| 14355 | false, /* .isArray */ |
| 14356 | false /* .isOptional */ |
| 14357 | }, |
| 14358 | { |
| 14359 | UA_TYPENAME("Description") /* .memberName */ |
| 14360 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14361 | offsetof(UA_MethodAttributes, description) - offsetof(UA_MethodAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 14362 | false, /* .isArray */ |
| 14363 | false /* .isOptional */ |
| 14364 | }, |
| 14365 | { |
| 14366 | UA_TYPENAME("WriteMask") /* .memberName */ |
| 14367 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14368 | offsetof(UA_MethodAttributes, writeMask) - offsetof(UA_MethodAttributes, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 14369 | false, /* .isArray */ |
| 14370 | false /* .isOptional */ |
| 14371 | }, |
| 14372 | { |
| 14373 | UA_TYPENAME("UserWriteMask") /* .memberName */ |
| 14374 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14375 | offsetof(UA_MethodAttributes, userWriteMask) - offsetof(UA_MethodAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */ |
| 14376 | false, /* .isArray */ |
| 14377 | false /* .isOptional */ |
| 14378 | }, |
| 14379 | { |
| 14380 | UA_TYPENAME("Executable") /* .memberName */ |
| 14381 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14382 | offsetof(UA_MethodAttributes, executable) - offsetof(UA_MethodAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */ |
| 14383 | false, /* .isArray */ |
| 14384 | false /* .isOptional */ |
| 14385 | }, |
| 14386 | { |
| 14387 | UA_TYPENAME("UserExecutable") /* .memberName */ |
| 14388 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14389 | offsetof(UA_MethodAttributes, userExecutable) - offsetof(UA_MethodAttributes, executable) - sizeof(UA_Boolean), /* .padding */ |
| 14390 | false, /* .isArray */ |
| 14391 | false /* .isOptional */ |
| 14392 | },}; |
| 14393 | |
| 14394 | /* ObjectTypeAttributes */ |
| 14395 | static UA_DataTypeMember ObjectTypeAttributes_members[6] = { |
| 14396 | { |
| 14397 | UA_TYPENAME("SpecifiedAttributes") /* .memberName */ |
| 14398 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14399 | 0, /* .padding */ |
| 14400 | false, /* .isArray */ |
| 14401 | false /* .isOptional */ |
| 14402 | }, |
| 14403 | { |
| 14404 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 14405 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14406 | offsetof(UA_ObjectTypeAttributes, displayName) - offsetof(UA_ObjectTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */ |
| 14407 | false, /* .isArray */ |
| 14408 | false /* .isOptional */ |
| 14409 | }, |
| 14410 | { |
| 14411 | UA_TYPENAME("Description") /* .memberName */ |
| 14412 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14413 | offsetof(UA_ObjectTypeAttributes, description) - offsetof(UA_ObjectTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 14414 | false, /* .isArray */ |
| 14415 | false /* .isOptional */ |
| 14416 | }, |
| 14417 | { |
| 14418 | UA_TYPENAME("WriteMask") /* .memberName */ |
| 14419 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14420 | offsetof(UA_ObjectTypeAttributes, writeMask) - offsetof(UA_ObjectTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 14421 | false, /* .isArray */ |
| 14422 | false /* .isOptional */ |
| 14423 | }, |
| 14424 | { |
| 14425 | UA_TYPENAME("UserWriteMask") /* .memberName */ |
| 14426 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14427 | offsetof(UA_ObjectTypeAttributes, userWriteMask) - offsetof(UA_ObjectTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */ |
| 14428 | false, /* .isArray */ |
| 14429 | false /* .isOptional */ |
| 14430 | }, |
| 14431 | { |
| 14432 | UA_TYPENAME("IsAbstract") /* .memberName */ |
| 14433 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14434 | offsetof(UA_ObjectTypeAttributes, isAbstract) - offsetof(UA_ObjectTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */ |
| 14435 | false, /* .isArray */ |
| 14436 | false /* .isOptional */ |
| 14437 | },}; |
| 14438 | |
| 14439 | /* VariableTypeAttributes */ |
| 14440 | static UA_DataTypeMember VariableTypeAttributes_members[10] = { |
| 14441 | { |
| 14442 | UA_TYPENAME("SpecifiedAttributes") /* .memberName */ |
| 14443 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14444 | 0, /* .padding */ |
| 14445 | false, /* .isArray */ |
| 14446 | false /* .isOptional */ |
| 14447 | }, |
| 14448 | { |
| 14449 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 14450 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14451 | offsetof(UA_VariableTypeAttributes, displayName) - offsetof(UA_VariableTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */ |
| 14452 | false, /* .isArray */ |
| 14453 | false /* .isOptional */ |
| 14454 | }, |
| 14455 | { |
| 14456 | UA_TYPENAME("Description") /* .memberName */ |
| 14457 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14458 | offsetof(UA_VariableTypeAttributes, description) - offsetof(UA_VariableTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 14459 | false, /* .isArray */ |
| 14460 | false /* .isOptional */ |
| 14461 | }, |
| 14462 | { |
| 14463 | UA_TYPENAME("WriteMask") /* .memberName */ |
| 14464 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14465 | offsetof(UA_VariableTypeAttributes, writeMask) - offsetof(UA_VariableTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 14466 | false, /* .isArray */ |
| 14467 | false /* .isOptional */ |
| 14468 | }, |
| 14469 | { |
| 14470 | UA_TYPENAME("UserWriteMask") /* .memberName */ |
| 14471 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14472 | offsetof(UA_VariableTypeAttributes, userWriteMask) - offsetof(UA_VariableTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */ |
| 14473 | false, /* .isArray */ |
| 14474 | false /* .isOptional */ |
| 14475 | }, |
| 14476 | { |
| 14477 | UA_TYPENAME("Value") /* .memberName */ |
| 14478 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 14479 | offsetof(UA_VariableTypeAttributes, value) - offsetof(UA_VariableTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */ |
| 14480 | false, /* .isArray */ |
| 14481 | false /* .isOptional */ |
| 14482 | }, |
| 14483 | { |
| 14484 | UA_TYPENAME("DataType") /* .memberName */ |
| 14485 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 14486 | offsetof(UA_VariableTypeAttributes, dataType) - offsetof(UA_VariableTypeAttributes, value) - sizeof(UA_Variant), /* .padding */ |
| 14487 | false, /* .isArray */ |
| 14488 | false /* .isOptional */ |
| 14489 | }, |
| 14490 | { |
| 14491 | UA_TYPENAME("ValueRank") /* .memberName */ |
| 14492 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 14493 | offsetof(UA_VariableTypeAttributes, valueRank) - offsetof(UA_VariableTypeAttributes, dataType) - sizeof(UA_NodeId), /* .padding */ |
| 14494 | false, /* .isArray */ |
| 14495 | false /* .isOptional */ |
| 14496 | }, |
| 14497 | { |
| 14498 | UA_TYPENAME("ArrayDimensions") /* .memberName */ |
| 14499 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14500 | offsetof(UA_VariableTypeAttributes, arrayDimensionsSize) - offsetof(UA_VariableTypeAttributes, valueRank) - sizeof(UA_Int32), /* .padding */ |
| 14501 | true, /* .isArray */ |
| 14502 | false /* .isOptional */ |
| 14503 | }, |
| 14504 | { |
| 14505 | UA_TYPENAME("IsAbstract") /* .memberName */ |
| 14506 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14507 | offsetof(UA_VariableTypeAttributes, isAbstract) - offsetof(UA_VariableTypeAttributes, arrayDimensions) - sizeof(void *), /* .padding */ |
| 14508 | false, /* .isArray */ |
| 14509 | false /* .isOptional */ |
| 14510 | },}; |
| 14511 | |
| 14512 | /* ReferenceTypeAttributes */ |
| 14513 | static UA_DataTypeMember ReferenceTypeAttributes_members[8] = { |
| 14514 | { |
| 14515 | UA_TYPENAME("SpecifiedAttributes") /* .memberName */ |
| 14516 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14517 | 0, /* .padding */ |
| 14518 | false, /* .isArray */ |
| 14519 | false /* .isOptional */ |
| 14520 | }, |
| 14521 | { |
| 14522 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 14523 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14524 | offsetof(UA_ReferenceTypeAttributes, displayName) - offsetof(UA_ReferenceTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */ |
| 14525 | false, /* .isArray */ |
| 14526 | false /* .isOptional */ |
| 14527 | }, |
| 14528 | { |
| 14529 | UA_TYPENAME("Description") /* .memberName */ |
| 14530 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14531 | offsetof(UA_ReferenceTypeAttributes, description) - offsetof(UA_ReferenceTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 14532 | false, /* .isArray */ |
| 14533 | false /* .isOptional */ |
| 14534 | }, |
| 14535 | { |
| 14536 | UA_TYPENAME("WriteMask") /* .memberName */ |
| 14537 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14538 | offsetof(UA_ReferenceTypeAttributes, writeMask) - offsetof(UA_ReferenceTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 14539 | false, /* .isArray */ |
| 14540 | false /* .isOptional */ |
| 14541 | }, |
| 14542 | { |
| 14543 | UA_TYPENAME("UserWriteMask") /* .memberName */ |
| 14544 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14545 | offsetof(UA_ReferenceTypeAttributes, userWriteMask) - offsetof(UA_ReferenceTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */ |
| 14546 | false, /* .isArray */ |
| 14547 | false /* .isOptional */ |
| 14548 | }, |
| 14549 | { |
| 14550 | UA_TYPENAME("IsAbstract") /* .memberName */ |
| 14551 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14552 | offsetof(UA_ReferenceTypeAttributes, isAbstract) - offsetof(UA_ReferenceTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */ |
| 14553 | false, /* .isArray */ |
| 14554 | false /* .isOptional */ |
| 14555 | }, |
| 14556 | { |
| 14557 | UA_TYPENAME("Symmetric") /* .memberName */ |
| 14558 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14559 | offsetof(UA_ReferenceTypeAttributes, symmetric) - offsetof(UA_ReferenceTypeAttributes, isAbstract) - sizeof(UA_Boolean), /* .padding */ |
| 14560 | false, /* .isArray */ |
| 14561 | false /* .isOptional */ |
| 14562 | }, |
| 14563 | { |
| 14564 | UA_TYPENAME("InverseName") /* .memberName */ |
| 14565 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14566 | offsetof(UA_ReferenceTypeAttributes, inverseName) - offsetof(UA_ReferenceTypeAttributes, symmetric) - sizeof(UA_Boolean), /* .padding */ |
| 14567 | false, /* .isArray */ |
| 14568 | false /* .isOptional */ |
| 14569 | },}; |
| 14570 | |
| 14571 | /* DataTypeAttributes */ |
| 14572 | static UA_DataTypeMember DataTypeAttributes_members[6] = { |
| 14573 | { |
| 14574 | UA_TYPENAME("SpecifiedAttributes") /* .memberName */ |
| 14575 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14576 | 0, /* .padding */ |
| 14577 | false, /* .isArray */ |
| 14578 | false /* .isOptional */ |
| 14579 | }, |
| 14580 | { |
| 14581 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 14582 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14583 | offsetof(UA_DataTypeAttributes, displayName) - offsetof(UA_DataTypeAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */ |
| 14584 | false, /* .isArray */ |
| 14585 | false /* .isOptional */ |
| 14586 | }, |
| 14587 | { |
| 14588 | UA_TYPENAME("Description") /* .memberName */ |
| 14589 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14590 | offsetof(UA_DataTypeAttributes, description) - offsetof(UA_DataTypeAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 14591 | false, /* .isArray */ |
| 14592 | false /* .isOptional */ |
| 14593 | }, |
| 14594 | { |
| 14595 | UA_TYPENAME("WriteMask") /* .memberName */ |
| 14596 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14597 | offsetof(UA_DataTypeAttributes, writeMask) - offsetof(UA_DataTypeAttributes, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 14598 | false, /* .isArray */ |
| 14599 | false /* .isOptional */ |
| 14600 | }, |
| 14601 | { |
| 14602 | UA_TYPENAME("UserWriteMask") /* .memberName */ |
| 14603 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14604 | offsetof(UA_DataTypeAttributes, userWriteMask) - offsetof(UA_DataTypeAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */ |
| 14605 | false, /* .isArray */ |
| 14606 | false /* .isOptional */ |
| 14607 | }, |
| 14608 | { |
| 14609 | UA_TYPENAME("IsAbstract") /* .memberName */ |
| 14610 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14611 | offsetof(UA_DataTypeAttributes, isAbstract) - offsetof(UA_DataTypeAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */ |
| 14612 | false, /* .isArray */ |
| 14613 | false /* .isOptional */ |
| 14614 | },}; |
| 14615 | |
| 14616 | /* ViewAttributes */ |
| 14617 | static UA_DataTypeMember ViewAttributes_members[7] = { |
| 14618 | { |
| 14619 | UA_TYPENAME("SpecifiedAttributes") /* .memberName */ |
| 14620 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14621 | 0, /* .padding */ |
| 14622 | false, /* .isArray */ |
| 14623 | false /* .isOptional */ |
| 14624 | }, |
| 14625 | { |
| 14626 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 14627 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14628 | offsetof(UA_ViewAttributes, displayName) - offsetof(UA_ViewAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */ |
| 14629 | false, /* .isArray */ |
| 14630 | false /* .isOptional */ |
| 14631 | }, |
| 14632 | { |
| 14633 | UA_TYPENAME("Description") /* .memberName */ |
| 14634 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14635 | offsetof(UA_ViewAttributes, description) - offsetof(UA_ViewAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 14636 | false, /* .isArray */ |
| 14637 | false /* .isOptional */ |
| 14638 | }, |
| 14639 | { |
| 14640 | UA_TYPENAME("WriteMask") /* .memberName */ |
| 14641 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14642 | offsetof(UA_ViewAttributes, writeMask) - offsetof(UA_ViewAttributes, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 14643 | false, /* .isArray */ |
| 14644 | false /* .isOptional */ |
| 14645 | }, |
| 14646 | { |
| 14647 | UA_TYPENAME("UserWriteMask") /* .memberName */ |
| 14648 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14649 | offsetof(UA_ViewAttributes, userWriteMask) - offsetof(UA_ViewAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */ |
| 14650 | false, /* .isArray */ |
| 14651 | false /* .isOptional */ |
| 14652 | }, |
| 14653 | { |
| 14654 | UA_TYPENAME("ContainsNoLoops") /* .memberName */ |
| 14655 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14656 | offsetof(UA_ViewAttributes, containsNoLoops) - offsetof(UA_ViewAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */ |
| 14657 | false, /* .isArray */ |
| 14658 | false /* .isOptional */ |
| 14659 | }, |
| 14660 | { |
| 14661 | UA_TYPENAME("EventNotifier") /* .memberName */ |
| 14662 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 14663 | offsetof(UA_ViewAttributes, eventNotifier) - offsetof(UA_ViewAttributes, containsNoLoops) - sizeof(UA_Boolean), /* .padding */ |
| 14664 | false, /* .isArray */ |
| 14665 | false /* .isOptional */ |
| 14666 | },}; |
| 14667 | |
| 14668 | /* GenericAttributeValue */ |
| 14669 | static UA_DataTypeMember GenericAttributeValue_members[2] = { |
| 14670 | { |
| 14671 | UA_TYPENAME("AttributeId") /* .memberName */ |
| 14672 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14673 | 0, /* .padding */ |
| 14674 | false, /* .isArray */ |
| 14675 | false /* .isOptional */ |
| 14676 | }, |
| 14677 | { |
| 14678 | UA_TYPENAME("Value") /* .memberName */ |
| 14679 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 14680 | offsetof(UA_GenericAttributeValue, value) - offsetof(UA_GenericAttributeValue, attributeId) - sizeof(UA_UInt32), /* .padding */ |
| 14681 | false, /* .isArray */ |
| 14682 | false /* .isOptional */ |
| 14683 | },}; |
| 14684 | |
| 14685 | /* GenericAttributes */ |
| 14686 | static UA_DataTypeMember GenericAttributes_members[6] = { |
| 14687 | { |
| 14688 | UA_TYPENAME("SpecifiedAttributes") /* .memberName */ |
| 14689 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14690 | 0, /* .padding */ |
| 14691 | false, /* .isArray */ |
| 14692 | false /* .isOptional */ |
| 14693 | }, |
| 14694 | { |
| 14695 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 14696 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14697 | offsetof(UA_GenericAttributes, displayName) - offsetof(UA_GenericAttributes, specifiedAttributes) - sizeof(UA_UInt32), /* .padding */ |
| 14698 | false, /* .isArray */ |
| 14699 | false /* .isOptional */ |
| 14700 | }, |
| 14701 | { |
| 14702 | UA_TYPENAME("Description") /* .memberName */ |
| 14703 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 14704 | offsetof(UA_GenericAttributes, description) - offsetof(UA_GenericAttributes, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 14705 | false, /* .isArray */ |
| 14706 | false /* .isOptional */ |
| 14707 | }, |
| 14708 | { |
| 14709 | UA_TYPENAME("WriteMask") /* .memberName */ |
| 14710 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14711 | offsetof(UA_GenericAttributes, writeMask) - offsetof(UA_GenericAttributes, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 14712 | false, /* .isArray */ |
| 14713 | false /* .isOptional */ |
| 14714 | }, |
| 14715 | { |
| 14716 | UA_TYPENAME("UserWriteMask") /* .memberName */ |
| 14717 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 14718 | offsetof(UA_GenericAttributes, userWriteMask) - offsetof(UA_GenericAttributes, writeMask) - sizeof(UA_UInt32), /* .padding */ |
| 14719 | false, /* .isArray */ |
| 14720 | false /* .isOptional */ |
| 14721 | }, |
| 14722 | { |
| 14723 | UA_TYPENAME("AttributeValues") /* .memberName */ |
| 14724 | &UA_TYPES[UA_TYPES_GENERICATTRIBUTEVALUE], /* .memberType */ |
| 14725 | offsetof(UA_GenericAttributes, attributeValuesSize) - offsetof(UA_GenericAttributes, userWriteMask) - sizeof(UA_UInt32), /* .padding */ |
| 14726 | true, /* .isArray */ |
| 14727 | false /* .isOptional */ |
| 14728 | },}; |
| 14729 | |
| 14730 | /* AddNodesItem */ |
| 14731 | static UA_DataTypeMember AddNodesItem_members[7] = { |
| 14732 | { |
| 14733 | UA_TYPENAME("ParentNodeId") /* .memberName */ |
| 14734 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 14735 | 0, /* .padding */ |
| 14736 | false, /* .isArray */ |
| 14737 | false /* .isOptional */ |
| 14738 | }, |
| 14739 | { |
| 14740 | UA_TYPENAME("ReferenceTypeId") /* .memberName */ |
| 14741 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 14742 | offsetof(UA_AddNodesItem, referenceTypeId) - offsetof(UA_AddNodesItem, parentNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */ |
| 14743 | false, /* .isArray */ |
| 14744 | false /* .isOptional */ |
| 14745 | }, |
| 14746 | { |
| 14747 | UA_TYPENAME("RequestedNewNodeId") /* .memberName */ |
| 14748 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 14749 | offsetof(UA_AddNodesItem, requestedNewNodeId) - offsetof(UA_AddNodesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 14750 | false, /* .isArray */ |
| 14751 | false /* .isOptional */ |
| 14752 | }, |
| 14753 | { |
| 14754 | UA_TYPENAME("BrowseName") /* .memberName */ |
| 14755 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 14756 | offsetof(UA_AddNodesItem, browseName) - offsetof(UA_AddNodesItem, requestedNewNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */ |
| 14757 | false, /* .isArray */ |
| 14758 | false /* .isOptional */ |
| 14759 | }, |
| 14760 | { |
| 14761 | UA_TYPENAME("NodeClass") /* .memberName */ |
| 14762 | &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */ |
| 14763 | offsetof(UA_AddNodesItem, nodeClass) - offsetof(UA_AddNodesItem, browseName) - sizeof(UA_QualifiedName), /* .padding */ |
| 14764 | false, /* .isArray */ |
| 14765 | false /* .isOptional */ |
| 14766 | }, |
| 14767 | { |
| 14768 | UA_TYPENAME("NodeAttributes") /* .memberName */ |
| 14769 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 14770 | offsetof(UA_AddNodesItem, nodeAttributes) - offsetof(UA_AddNodesItem, nodeClass) - sizeof(UA_NodeClass), /* .padding */ |
| 14771 | false, /* .isArray */ |
| 14772 | false /* .isOptional */ |
| 14773 | }, |
| 14774 | { |
| 14775 | UA_TYPENAME("TypeDefinition") /* .memberName */ |
| 14776 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 14777 | offsetof(UA_AddNodesItem, typeDefinition) - offsetof(UA_AddNodesItem, nodeAttributes) - sizeof(UA_ExtensionObject), /* .padding */ |
| 14778 | false, /* .isArray */ |
| 14779 | false /* .isOptional */ |
| 14780 | },}; |
| 14781 | |
| 14782 | /* AddNodesResult */ |
| 14783 | static UA_DataTypeMember AddNodesResult_members[2] = { |
| 14784 | { |
| 14785 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 14786 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 14787 | 0, /* .padding */ |
| 14788 | false, /* .isArray */ |
| 14789 | false /* .isOptional */ |
| 14790 | }, |
| 14791 | { |
| 14792 | UA_TYPENAME("AddedNodeId") /* .memberName */ |
| 14793 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 14794 | offsetof(UA_AddNodesResult, addedNodeId) - offsetof(UA_AddNodesResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 14795 | false, /* .isArray */ |
| 14796 | false /* .isOptional */ |
| 14797 | },}; |
| 14798 | |
| 14799 | /* AddNodesRequest */ |
| 14800 | static UA_DataTypeMember AddNodesRequest_members[2] = { |
| 14801 | { |
| 14802 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 14803 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 14804 | 0, /* .padding */ |
| 14805 | false, /* .isArray */ |
| 14806 | false /* .isOptional */ |
| 14807 | }, |
| 14808 | { |
| 14809 | UA_TYPENAME("NodesToAdd") /* .memberName */ |
| 14810 | &UA_TYPES[UA_TYPES_ADDNODESITEM], /* .memberType */ |
| 14811 | offsetof(UA_AddNodesRequest, nodesToAddSize) - offsetof(UA_AddNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 14812 | true, /* .isArray */ |
| 14813 | false /* .isOptional */ |
| 14814 | },}; |
| 14815 | |
| 14816 | /* AddNodesResponse */ |
| 14817 | static UA_DataTypeMember AddNodesResponse_members[3] = { |
| 14818 | { |
| 14819 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 14820 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 14821 | 0, /* .padding */ |
| 14822 | false, /* .isArray */ |
| 14823 | false /* .isOptional */ |
| 14824 | }, |
| 14825 | { |
| 14826 | UA_TYPENAME("Results") /* .memberName */ |
| 14827 | &UA_TYPES[UA_TYPES_ADDNODESRESULT], /* .memberType */ |
| 14828 | offsetof(UA_AddNodesResponse, resultsSize) - offsetof(UA_AddNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 14829 | true, /* .isArray */ |
| 14830 | false /* .isOptional */ |
| 14831 | }, |
| 14832 | { |
| 14833 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 14834 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 14835 | offsetof(UA_AddNodesResponse, diagnosticInfosSize) - offsetof(UA_AddNodesResponse, results) - sizeof(void *), /* .padding */ |
| 14836 | true, /* .isArray */ |
| 14837 | false /* .isOptional */ |
| 14838 | },}; |
| 14839 | |
| 14840 | /* AddReferencesItem */ |
| 14841 | static UA_DataTypeMember AddReferencesItem_members[6] = { |
| 14842 | { |
| 14843 | UA_TYPENAME("SourceNodeId") /* .memberName */ |
| 14844 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 14845 | 0, /* .padding */ |
| 14846 | false, /* .isArray */ |
| 14847 | false /* .isOptional */ |
| 14848 | }, |
| 14849 | { |
| 14850 | UA_TYPENAME("ReferenceTypeId") /* .memberName */ |
| 14851 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 14852 | offsetof(UA_AddReferencesItem, referenceTypeId) - offsetof(UA_AddReferencesItem, sourceNodeId) - sizeof(UA_NodeId), /* .padding */ |
| 14853 | false, /* .isArray */ |
| 14854 | false /* .isOptional */ |
| 14855 | }, |
| 14856 | { |
| 14857 | UA_TYPENAME("IsForward") /* .memberName */ |
| 14858 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14859 | offsetof(UA_AddReferencesItem, isForward) - offsetof(UA_AddReferencesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 14860 | false, /* .isArray */ |
| 14861 | false /* .isOptional */ |
| 14862 | }, |
| 14863 | { |
| 14864 | UA_TYPENAME("TargetServerUri") /* .memberName */ |
| 14865 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 14866 | offsetof(UA_AddReferencesItem, targetServerUri) - offsetof(UA_AddReferencesItem, isForward) - sizeof(UA_Boolean), /* .padding */ |
| 14867 | false, /* .isArray */ |
| 14868 | false /* .isOptional */ |
| 14869 | }, |
| 14870 | { |
| 14871 | UA_TYPENAME("TargetNodeId") /* .memberName */ |
| 14872 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 14873 | offsetof(UA_AddReferencesItem, targetNodeId) - offsetof(UA_AddReferencesItem, targetServerUri) - sizeof(UA_String), /* .padding */ |
| 14874 | false, /* .isArray */ |
| 14875 | false /* .isOptional */ |
| 14876 | }, |
| 14877 | { |
| 14878 | UA_TYPENAME("TargetNodeClass") /* .memberName */ |
| 14879 | &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */ |
| 14880 | offsetof(UA_AddReferencesItem, targetNodeClass) - offsetof(UA_AddReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */ |
| 14881 | false, /* .isArray */ |
| 14882 | false /* .isOptional */ |
| 14883 | },}; |
| 14884 | |
| 14885 | /* AddReferencesRequest */ |
| 14886 | static UA_DataTypeMember AddReferencesRequest_members[2] = { |
| 14887 | { |
| 14888 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 14889 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 14890 | 0, /* .padding */ |
| 14891 | false, /* .isArray */ |
| 14892 | false /* .isOptional */ |
| 14893 | }, |
| 14894 | { |
| 14895 | UA_TYPENAME("ReferencesToAdd") /* .memberName */ |
| 14896 | &UA_TYPES[UA_TYPES_ADDREFERENCESITEM], /* .memberType */ |
| 14897 | offsetof(UA_AddReferencesRequest, referencesToAddSize) - offsetof(UA_AddReferencesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 14898 | true, /* .isArray */ |
| 14899 | false /* .isOptional */ |
| 14900 | },}; |
| 14901 | |
| 14902 | /* AddReferencesResponse */ |
| 14903 | static UA_DataTypeMember AddReferencesResponse_members[3] = { |
| 14904 | { |
| 14905 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 14906 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 14907 | 0, /* .padding */ |
| 14908 | false, /* .isArray */ |
| 14909 | false /* .isOptional */ |
| 14910 | }, |
| 14911 | { |
| 14912 | UA_TYPENAME("Results") /* .memberName */ |
| 14913 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 14914 | offsetof(UA_AddReferencesResponse, resultsSize) - offsetof(UA_AddReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 14915 | true, /* .isArray */ |
| 14916 | false /* .isOptional */ |
| 14917 | }, |
| 14918 | { |
| 14919 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 14920 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 14921 | offsetof(UA_AddReferencesResponse, diagnosticInfosSize) - offsetof(UA_AddReferencesResponse, results) - sizeof(void *), /* .padding */ |
| 14922 | true, /* .isArray */ |
| 14923 | false /* .isOptional */ |
| 14924 | },}; |
| 14925 | |
| 14926 | /* DeleteNodesItem */ |
| 14927 | static UA_DataTypeMember DeleteNodesItem_members[2] = { |
| 14928 | { |
| 14929 | UA_TYPENAME("NodeId") /* .memberName */ |
| 14930 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 14931 | 0, /* .padding */ |
| 14932 | false, /* .isArray */ |
| 14933 | false /* .isOptional */ |
| 14934 | }, |
| 14935 | { |
| 14936 | UA_TYPENAME("DeleteTargetReferences") /* .memberName */ |
| 14937 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 14938 | offsetof(UA_DeleteNodesItem, deleteTargetReferences) - offsetof(UA_DeleteNodesItem, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 14939 | false, /* .isArray */ |
| 14940 | false /* .isOptional */ |
| 14941 | },}; |
| 14942 | |
| 14943 | /* DeleteNodesRequest */ |
| 14944 | static UA_DataTypeMember DeleteNodesRequest_members[2] = { |
| 14945 | { |
| 14946 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 14947 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 14948 | 0, /* .padding */ |
| 14949 | false, /* .isArray */ |
| 14950 | false /* .isOptional */ |
| 14951 | }, |
| 14952 | { |
| 14953 | UA_TYPENAME("NodesToDelete") /* .memberName */ |
| 14954 | &UA_TYPES[UA_TYPES_DELETENODESITEM], /* .memberType */ |
| 14955 | offsetof(UA_DeleteNodesRequest, nodesToDeleteSize) - offsetof(UA_DeleteNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 14956 | true, /* .isArray */ |
| 14957 | false /* .isOptional */ |
| 14958 | },}; |
| 14959 | |
| 14960 | /* DeleteNodesResponse */ |
| 14961 | static UA_DataTypeMember DeleteNodesResponse_members[3] = { |
| 14962 | { |
| 14963 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 14964 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 14965 | 0, /* .padding */ |
| 14966 | false, /* .isArray */ |
| 14967 | false /* .isOptional */ |
| 14968 | }, |
| 14969 | { |
| 14970 | UA_TYPENAME("Results") /* .memberName */ |
| 14971 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 14972 | offsetof(UA_DeleteNodesResponse, resultsSize) - offsetof(UA_DeleteNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 14973 | true, /* .isArray */ |
| 14974 | false /* .isOptional */ |
| 14975 | }, |
| 14976 | { |
| 14977 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 14978 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 14979 | offsetof(UA_DeleteNodesResponse, diagnosticInfosSize) - offsetof(UA_DeleteNodesResponse, results) - sizeof(void *), /* .padding */ |
| 14980 | true, /* .isArray */ |
| 14981 | false /* .isOptional */ |
| 14982 | },}; |
| 14983 | |
| 14984 | /* DeleteReferencesItem */ |
| 14985 | static UA_DataTypeMember DeleteReferencesItem_members[5] = { |
| 14986 | { |
| 14987 | UA_TYPENAME("SourceNodeId") /* .memberName */ |
| 14988 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 14989 | 0, /* .padding */ |
| 14990 | false, /* .isArray */ |
| 14991 | false /* .isOptional */ |
| 14992 | }, |
| 14993 | { |
| 14994 | UA_TYPENAME("ReferenceTypeId") /* .memberName */ |
| 14995 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 14996 | offsetof(UA_DeleteReferencesItem, referenceTypeId) - offsetof(UA_DeleteReferencesItem, sourceNodeId) - sizeof(UA_NodeId), /* .padding */ |
| 14997 | false, /* .isArray */ |
| 14998 | false /* .isOptional */ |
| 14999 | }, |
| 15000 | { |
| 15001 | UA_TYPENAME("IsForward") /* .memberName */ |
| 15002 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15003 | offsetof(UA_DeleteReferencesItem, isForward) - offsetof(UA_DeleteReferencesItem, referenceTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 15004 | false, /* .isArray */ |
| 15005 | false /* .isOptional */ |
| 15006 | }, |
| 15007 | { |
| 15008 | UA_TYPENAME("TargetNodeId") /* .memberName */ |
| 15009 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 15010 | offsetof(UA_DeleteReferencesItem, targetNodeId) - offsetof(UA_DeleteReferencesItem, isForward) - sizeof(UA_Boolean), /* .padding */ |
| 15011 | false, /* .isArray */ |
| 15012 | false /* .isOptional */ |
| 15013 | }, |
| 15014 | { |
| 15015 | UA_TYPENAME("DeleteBidirectional") /* .memberName */ |
| 15016 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15017 | offsetof(UA_DeleteReferencesItem, deleteBidirectional) - offsetof(UA_DeleteReferencesItem, targetNodeId) - sizeof(UA_ExpandedNodeId), /* .padding */ |
| 15018 | false, /* .isArray */ |
| 15019 | false /* .isOptional */ |
| 15020 | },}; |
| 15021 | |
| 15022 | /* DeleteReferencesRequest */ |
| 15023 | static UA_DataTypeMember DeleteReferencesRequest_members[2] = { |
| 15024 | { |
| 15025 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 15026 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 15027 | 0, /* .padding */ |
| 15028 | false, /* .isArray */ |
| 15029 | false /* .isOptional */ |
| 15030 | }, |
| 15031 | { |
| 15032 | UA_TYPENAME("ReferencesToDelete") /* .memberName */ |
| 15033 | &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM], /* .memberType */ |
| 15034 | offsetof(UA_DeleteReferencesRequest, referencesToDeleteSize) - offsetof(UA_DeleteReferencesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 15035 | true, /* .isArray */ |
| 15036 | false /* .isOptional */ |
| 15037 | },}; |
| 15038 | |
| 15039 | /* DeleteReferencesResponse */ |
| 15040 | static UA_DataTypeMember DeleteReferencesResponse_members[3] = { |
| 15041 | { |
| 15042 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 15043 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 15044 | 0, /* .padding */ |
| 15045 | false, /* .isArray */ |
| 15046 | false /* .isOptional */ |
| 15047 | }, |
| 15048 | { |
| 15049 | UA_TYPENAME("Results") /* .memberName */ |
| 15050 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 15051 | offsetof(UA_DeleteReferencesResponse, resultsSize) - offsetof(UA_DeleteReferencesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 15052 | true, /* .isArray */ |
| 15053 | false /* .isOptional */ |
| 15054 | }, |
| 15055 | { |
| 15056 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 15057 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 15058 | offsetof(UA_DeleteReferencesResponse, diagnosticInfosSize) - offsetof(UA_DeleteReferencesResponse, results) - sizeof(void *), /* .padding */ |
| 15059 | true, /* .isArray */ |
| 15060 | false /* .isOptional */ |
| 15061 | },}; |
| 15062 | |
| 15063 | /* AttributeWriteMask */ |
| 15064 | #define AttributeWriteMask_members NULL |
| 15065 | |
| 15066 | /* BrowseDirection */ |
| 15067 | #define BrowseDirection_members NULL |
| 15068 | |
| 15069 | /* ViewDescription */ |
| 15070 | static UA_DataTypeMember ViewDescription_members[3] = { |
| 15071 | { |
| 15072 | UA_TYPENAME("ViewId") /* .memberName */ |
| 15073 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15074 | 0, /* .padding */ |
| 15075 | false, /* .isArray */ |
| 15076 | false /* .isOptional */ |
| 15077 | }, |
| 15078 | { |
| 15079 | UA_TYPENAME("Timestamp") /* .memberName */ |
| 15080 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 15081 | offsetof(UA_ViewDescription, timestamp) - offsetof(UA_ViewDescription, viewId) - sizeof(UA_NodeId), /* .padding */ |
| 15082 | false, /* .isArray */ |
| 15083 | false /* .isOptional */ |
| 15084 | }, |
| 15085 | { |
| 15086 | UA_TYPENAME("ViewVersion") /* .memberName */ |
| 15087 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15088 | offsetof(UA_ViewDescription, viewVersion) - offsetof(UA_ViewDescription, timestamp) - sizeof(UA_DateTime), /* .padding */ |
| 15089 | false, /* .isArray */ |
| 15090 | false /* .isOptional */ |
| 15091 | },}; |
| 15092 | |
| 15093 | /* BrowseDescription */ |
| 15094 | static UA_DataTypeMember BrowseDescription_members[6] = { |
| 15095 | { |
| 15096 | UA_TYPENAME("NodeId") /* .memberName */ |
| 15097 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15098 | 0, /* .padding */ |
| 15099 | false, /* .isArray */ |
| 15100 | false /* .isOptional */ |
| 15101 | }, |
| 15102 | { |
| 15103 | UA_TYPENAME("BrowseDirection") /* .memberName */ |
| 15104 | &UA_TYPES[UA_TYPES_BROWSEDIRECTION], /* .memberType */ |
| 15105 | offsetof(UA_BrowseDescription, browseDirection) - offsetof(UA_BrowseDescription, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 15106 | false, /* .isArray */ |
| 15107 | false /* .isOptional */ |
| 15108 | }, |
| 15109 | { |
| 15110 | UA_TYPENAME("ReferenceTypeId") /* .memberName */ |
| 15111 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15112 | offsetof(UA_BrowseDescription, referenceTypeId) - offsetof(UA_BrowseDescription, browseDirection) - sizeof(UA_BrowseDirection), /* .padding */ |
| 15113 | false, /* .isArray */ |
| 15114 | false /* .isOptional */ |
| 15115 | }, |
| 15116 | { |
| 15117 | UA_TYPENAME("IncludeSubtypes") /* .memberName */ |
| 15118 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15119 | offsetof(UA_BrowseDescription, includeSubtypes) - offsetof(UA_BrowseDescription, referenceTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 15120 | false, /* .isArray */ |
| 15121 | false /* .isOptional */ |
| 15122 | }, |
| 15123 | { |
| 15124 | UA_TYPENAME("NodeClassMask") /* .memberName */ |
| 15125 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15126 | offsetof(UA_BrowseDescription, nodeClassMask) - offsetof(UA_BrowseDescription, includeSubtypes) - sizeof(UA_Boolean), /* .padding */ |
| 15127 | false, /* .isArray */ |
| 15128 | false /* .isOptional */ |
| 15129 | }, |
| 15130 | { |
| 15131 | UA_TYPENAME("ResultMask") /* .memberName */ |
| 15132 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15133 | offsetof(UA_BrowseDescription, resultMask) - offsetof(UA_BrowseDescription, nodeClassMask) - sizeof(UA_UInt32), /* .padding */ |
| 15134 | false, /* .isArray */ |
| 15135 | false /* .isOptional */ |
| 15136 | },}; |
| 15137 | |
| 15138 | /* BrowseResultMask */ |
| 15139 | #define BrowseResultMask_members NULL |
| 15140 | |
| 15141 | /* ReferenceDescription */ |
| 15142 | static UA_DataTypeMember ReferenceDescription_members[7] = { |
| 15143 | { |
| 15144 | UA_TYPENAME("ReferenceTypeId") /* .memberName */ |
| 15145 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15146 | 0, /* .padding */ |
| 15147 | false, /* .isArray */ |
| 15148 | false /* .isOptional */ |
| 15149 | }, |
| 15150 | { |
| 15151 | UA_TYPENAME("IsForward") /* .memberName */ |
| 15152 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15153 | offsetof(UA_ReferenceDescription, isForward) - offsetof(UA_ReferenceDescription, referenceTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 15154 | false, /* .isArray */ |
| 15155 | false /* .isOptional */ |
| 15156 | }, |
| 15157 | { |
| 15158 | UA_TYPENAME("NodeId") /* .memberName */ |
| 15159 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 15160 | offsetof(UA_ReferenceDescription, nodeId) - offsetof(UA_ReferenceDescription, isForward) - sizeof(UA_Boolean), /* .padding */ |
| 15161 | false, /* .isArray */ |
| 15162 | false /* .isOptional */ |
| 15163 | }, |
| 15164 | { |
| 15165 | UA_TYPENAME("BrowseName") /* .memberName */ |
| 15166 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 15167 | offsetof(UA_ReferenceDescription, browseName) - offsetof(UA_ReferenceDescription, nodeId) - sizeof(UA_ExpandedNodeId), /* .padding */ |
| 15168 | false, /* .isArray */ |
| 15169 | false /* .isOptional */ |
| 15170 | }, |
| 15171 | { |
| 15172 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 15173 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 15174 | offsetof(UA_ReferenceDescription, displayName) - offsetof(UA_ReferenceDescription, browseName) - sizeof(UA_QualifiedName), /* .padding */ |
| 15175 | false, /* .isArray */ |
| 15176 | false /* .isOptional */ |
| 15177 | }, |
| 15178 | { |
| 15179 | UA_TYPENAME("NodeClass") /* .memberName */ |
| 15180 | &UA_TYPES[UA_TYPES_NODECLASS], /* .memberType */ |
| 15181 | offsetof(UA_ReferenceDescription, nodeClass) - offsetof(UA_ReferenceDescription, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 15182 | false, /* .isArray */ |
| 15183 | false /* .isOptional */ |
| 15184 | }, |
| 15185 | { |
| 15186 | UA_TYPENAME("TypeDefinition") /* .memberName */ |
| 15187 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 15188 | offsetof(UA_ReferenceDescription, typeDefinition) - offsetof(UA_ReferenceDescription, nodeClass) - sizeof(UA_NodeClass), /* .padding */ |
| 15189 | false, /* .isArray */ |
| 15190 | false /* .isOptional */ |
| 15191 | },}; |
| 15192 | |
| 15193 | /* ContinuationPoint */ |
| 15194 | #define ContinuationPoint_members NULL |
| 15195 | |
| 15196 | /* BrowseResult */ |
| 15197 | static UA_DataTypeMember BrowseResult_members[3] = { |
| 15198 | { |
| 15199 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 15200 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 15201 | 0, /* .padding */ |
| 15202 | false, /* .isArray */ |
| 15203 | false /* .isOptional */ |
| 15204 | }, |
| 15205 | { |
| 15206 | UA_TYPENAME("ContinuationPoint") /* .memberName */ |
| 15207 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 15208 | offsetof(UA_BrowseResult, continuationPoint) - offsetof(UA_BrowseResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 15209 | false, /* .isArray */ |
| 15210 | false /* .isOptional */ |
| 15211 | }, |
| 15212 | { |
| 15213 | UA_TYPENAME("References") /* .memberName */ |
| 15214 | &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION], /* .memberType */ |
| 15215 | offsetof(UA_BrowseResult, referencesSize) - offsetof(UA_BrowseResult, continuationPoint) - sizeof(UA_ByteString), /* .padding */ |
| 15216 | true, /* .isArray */ |
| 15217 | false /* .isOptional */ |
| 15218 | },}; |
| 15219 | |
| 15220 | /* BrowseRequest */ |
| 15221 | static UA_DataTypeMember BrowseRequest_members[4] = { |
| 15222 | { |
| 15223 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 15224 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 15225 | 0, /* .padding */ |
| 15226 | false, /* .isArray */ |
| 15227 | false /* .isOptional */ |
| 15228 | }, |
| 15229 | { |
| 15230 | UA_TYPENAME("View") /* .memberName */ |
| 15231 | &UA_TYPES[UA_TYPES_VIEWDESCRIPTION], /* .memberType */ |
| 15232 | offsetof(UA_BrowseRequest, view) - offsetof(UA_BrowseRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 15233 | false, /* .isArray */ |
| 15234 | false /* .isOptional */ |
| 15235 | }, |
| 15236 | { |
| 15237 | UA_TYPENAME("RequestedMaxReferencesPerNode") /* .memberName */ |
| 15238 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15239 | offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - offsetof(UA_BrowseRequest, view) - sizeof(UA_ViewDescription), /* .padding */ |
| 15240 | false, /* .isArray */ |
| 15241 | false /* .isOptional */ |
| 15242 | }, |
| 15243 | { |
| 15244 | UA_TYPENAME("NodesToBrowse") /* .memberName */ |
| 15245 | &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION], /* .memberType */ |
| 15246 | offsetof(UA_BrowseRequest, nodesToBrowseSize) - offsetof(UA_BrowseRequest, requestedMaxReferencesPerNode) - sizeof(UA_UInt32), /* .padding */ |
| 15247 | true, /* .isArray */ |
| 15248 | false /* .isOptional */ |
| 15249 | },}; |
| 15250 | |
| 15251 | /* BrowseResponse */ |
| 15252 | static UA_DataTypeMember BrowseResponse_members[3] = { |
| 15253 | { |
| 15254 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 15255 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 15256 | 0, /* .padding */ |
| 15257 | false, /* .isArray */ |
| 15258 | false /* .isOptional */ |
| 15259 | }, |
| 15260 | { |
| 15261 | UA_TYPENAME("Results") /* .memberName */ |
| 15262 | &UA_TYPES[UA_TYPES_BROWSERESULT], /* .memberType */ |
| 15263 | offsetof(UA_BrowseResponse, resultsSize) - offsetof(UA_BrowseResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 15264 | true, /* .isArray */ |
| 15265 | false /* .isOptional */ |
| 15266 | }, |
| 15267 | { |
| 15268 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 15269 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 15270 | offsetof(UA_BrowseResponse, diagnosticInfosSize) - offsetof(UA_BrowseResponse, results) - sizeof(void *), /* .padding */ |
| 15271 | true, /* .isArray */ |
| 15272 | false /* .isOptional */ |
| 15273 | },}; |
| 15274 | |
| 15275 | /* BrowseNextRequest */ |
| 15276 | static UA_DataTypeMember BrowseNextRequest_members[3] = { |
| 15277 | { |
| 15278 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 15279 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 15280 | 0, /* .padding */ |
| 15281 | false, /* .isArray */ |
| 15282 | false /* .isOptional */ |
| 15283 | }, |
| 15284 | { |
| 15285 | UA_TYPENAME("ReleaseContinuationPoints") /* .memberName */ |
| 15286 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15287 | offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - offsetof(UA_BrowseNextRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 15288 | false, /* .isArray */ |
| 15289 | false /* .isOptional */ |
| 15290 | }, |
| 15291 | { |
| 15292 | UA_TYPENAME("ContinuationPoints") /* .memberName */ |
| 15293 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 15294 | offsetof(UA_BrowseNextRequest, continuationPointsSize) - offsetof(UA_BrowseNextRequest, releaseContinuationPoints) - sizeof(UA_Boolean), /* .padding */ |
| 15295 | true, /* .isArray */ |
| 15296 | false /* .isOptional */ |
| 15297 | },}; |
| 15298 | |
| 15299 | /* BrowseNextResponse */ |
| 15300 | static UA_DataTypeMember BrowseNextResponse_members[3] = { |
| 15301 | { |
| 15302 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 15303 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 15304 | 0, /* .padding */ |
| 15305 | false, /* .isArray */ |
| 15306 | false /* .isOptional */ |
| 15307 | }, |
| 15308 | { |
| 15309 | UA_TYPENAME("Results") /* .memberName */ |
| 15310 | &UA_TYPES[UA_TYPES_BROWSERESULT], /* .memberType */ |
| 15311 | offsetof(UA_BrowseNextResponse, resultsSize) - offsetof(UA_BrowseNextResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 15312 | true, /* .isArray */ |
| 15313 | false /* .isOptional */ |
| 15314 | }, |
| 15315 | { |
| 15316 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 15317 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 15318 | offsetof(UA_BrowseNextResponse, diagnosticInfosSize) - offsetof(UA_BrowseNextResponse, results) - sizeof(void *), /* .padding */ |
| 15319 | true, /* .isArray */ |
| 15320 | false /* .isOptional */ |
| 15321 | },}; |
| 15322 | |
| 15323 | /* RelativePathElement */ |
| 15324 | static UA_DataTypeMember RelativePathElement_members[4] = { |
| 15325 | { |
| 15326 | UA_TYPENAME("ReferenceTypeId") /* .memberName */ |
| 15327 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15328 | 0, /* .padding */ |
| 15329 | false, /* .isArray */ |
| 15330 | false /* .isOptional */ |
| 15331 | }, |
| 15332 | { |
| 15333 | UA_TYPENAME("IsInverse") /* .memberName */ |
| 15334 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15335 | offsetof(UA_RelativePathElement, isInverse) - offsetof(UA_RelativePathElement, referenceTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 15336 | false, /* .isArray */ |
| 15337 | false /* .isOptional */ |
| 15338 | }, |
| 15339 | { |
| 15340 | UA_TYPENAME("IncludeSubtypes") /* .memberName */ |
| 15341 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15342 | offsetof(UA_RelativePathElement, includeSubtypes) - offsetof(UA_RelativePathElement, isInverse) - sizeof(UA_Boolean), /* .padding */ |
| 15343 | false, /* .isArray */ |
| 15344 | false /* .isOptional */ |
| 15345 | }, |
| 15346 | { |
| 15347 | UA_TYPENAME("TargetName") /* .memberName */ |
| 15348 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 15349 | offsetof(UA_RelativePathElement, targetName) - offsetof(UA_RelativePathElement, includeSubtypes) - sizeof(UA_Boolean), /* .padding */ |
| 15350 | false, /* .isArray */ |
| 15351 | false /* .isOptional */ |
| 15352 | },}; |
| 15353 | |
| 15354 | /* RelativePath */ |
| 15355 | static UA_DataTypeMember RelativePath_members[1] = { |
| 15356 | { |
| 15357 | UA_TYPENAME("Elements") /* .memberName */ |
| 15358 | &UA_TYPES[UA_TYPES_RELATIVEPATHELEMENT], /* .memberType */ |
| 15359 | 0, /* .padding */ |
| 15360 | true, /* .isArray */ |
| 15361 | false /* .isOptional */ |
| 15362 | },}; |
| 15363 | |
| 15364 | /* BrowsePath */ |
| 15365 | static UA_DataTypeMember BrowsePath_members[2] = { |
| 15366 | { |
| 15367 | UA_TYPENAME("StartingNode") /* .memberName */ |
| 15368 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15369 | 0, /* .padding */ |
| 15370 | false, /* .isArray */ |
| 15371 | false /* .isOptional */ |
| 15372 | }, |
| 15373 | { |
| 15374 | UA_TYPENAME("RelativePath") /* .memberName */ |
| 15375 | &UA_TYPES[UA_TYPES_RELATIVEPATH], /* .memberType */ |
| 15376 | offsetof(UA_BrowsePath, relativePath) - offsetof(UA_BrowsePath, startingNode) - sizeof(UA_NodeId), /* .padding */ |
| 15377 | false, /* .isArray */ |
| 15378 | false /* .isOptional */ |
| 15379 | },}; |
| 15380 | |
| 15381 | /* BrowsePathTarget */ |
| 15382 | static UA_DataTypeMember BrowsePathTarget_members[2] = { |
| 15383 | { |
| 15384 | UA_TYPENAME("TargetId") /* .memberName */ |
| 15385 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 15386 | 0, /* .padding */ |
| 15387 | false, /* .isArray */ |
| 15388 | false /* .isOptional */ |
| 15389 | }, |
| 15390 | { |
| 15391 | UA_TYPENAME("RemainingPathIndex") /* .memberName */ |
| 15392 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15393 | offsetof(UA_BrowsePathTarget, remainingPathIndex) - offsetof(UA_BrowsePathTarget, targetId) - sizeof(UA_ExpandedNodeId), /* .padding */ |
| 15394 | false, /* .isArray */ |
| 15395 | false /* .isOptional */ |
| 15396 | },}; |
| 15397 | |
| 15398 | /* BrowsePathResult */ |
| 15399 | static UA_DataTypeMember BrowsePathResult_members[2] = { |
| 15400 | { |
| 15401 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 15402 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 15403 | 0, /* .padding */ |
| 15404 | false, /* .isArray */ |
| 15405 | false /* .isOptional */ |
| 15406 | }, |
| 15407 | { |
| 15408 | UA_TYPENAME("Targets") /* .memberName */ |
| 15409 | &UA_TYPES[UA_TYPES_BROWSEPATHTARGET], /* .memberType */ |
| 15410 | offsetof(UA_BrowsePathResult, targetsSize) - offsetof(UA_BrowsePathResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 15411 | true, /* .isArray */ |
| 15412 | false /* .isOptional */ |
| 15413 | },}; |
| 15414 | |
| 15415 | /* TranslateBrowsePathsToNodeIdsRequest */ |
| 15416 | static UA_DataTypeMember TranslateBrowsePathsToNodeIdsRequest_members[2] = { |
| 15417 | { |
| 15418 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 15419 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 15420 | 0, /* .padding */ |
| 15421 | false, /* .isArray */ |
| 15422 | false /* .isOptional */ |
| 15423 | }, |
| 15424 | { |
| 15425 | UA_TYPENAME("BrowsePaths") /* .memberName */ |
| 15426 | &UA_TYPES[UA_TYPES_BROWSEPATH], /* .memberType */ |
| 15427 | offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, browsePathsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 15428 | true, /* .isArray */ |
| 15429 | false /* .isOptional */ |
| 15430 | },}; |
| 15431 | |
| 15432 | /* TranslateBrowsePathsToNodeIdsResponse */ |
| 15433 | static UA_DataTypeMember TranslateBrowsePathsToNodeIdsResponse_members[3] = { |
| 15434 | { |
| 15435 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 15436 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 15437 | 0, /* .padding */ |
| 15438 | false, /* .isArray */ |
| 15439 | false /* .isOptional */ |
| 15440 | }, |
| 15441 | { |
| 15442 | UA_TYPENAME("Results") /* .memberName */ |
| 15443 | &UA_TYPES[UA_TYPES_BROWSEPATHRESULT], /* .memberType */ |
| 15444 | offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, resultsSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 15445 | true, /* .isArray */ |
| 15446 | false /* .isOptional */ |
| 15447 | }, |
| 15448 | { |
| 15449 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 15450 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 15451 | offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, diagnosticInfosSize) - offsetof(UA_TranslateBrowsePathsToNodeIdsResponse, results) - sizeof(void *), /* .padding */ |
| 15452 | true, /* .isArray */ |
| 15453 | false /* .isOptional */ |
| 15454 | },}; |
| 15455 | |
| 15456 | /* RegisterNodesRequest */ |
| 15457 | static UA_DataTypeMember RegisterNodesRequest_members[2] = { |
| 15458 | { |
| 15459 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 15460 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 15461 | 0, /* .padding */ |
| 15462 | false, /* .isArray */ |
| 15463 | false /* .isOptional */ |
| 15464 | }, |
| 15465 | { |
| 15466 | UA_TYPENAME("NodesToRegister") /* .memberName */ |
| 15467 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15468 | offsetof(UA_RegisterNodesRequest, nodesToRegisterSize) - offsetof(UA_RegisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 15469 | true, /* .isArray */ |
| 15470 | false /* .isOptional */ |
| 15471 | },}; |
| 15472 | |
| 15473 | /* RegisterNodesResponse */ |
| 15474 | static UA_DataTypeMember RegisterNodesResponse_members[2] = { |
| 15475 | { |
| 15476 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 15477 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 15478 | 0, /* .padding */ |
| 15479 | false, /* .isArray */ |
| 15480 | false /* .isOptional */ |
| 15481 | }, |
| 15482 | { |
| 15483 | UA_TYPENAME("RegisteredNodeIds") /* .memberName */ |
| 15484 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15485 | offsetof(UA_RegisterNodesResponse, registeredNodeIdsSize) - offsetof(UA_RegisterNodesResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 15486 | true, /* .isArray */ |
| 15487 | false /* .isOptional */ |
| 15488 | },}; |
| 15489 | |
| 15490 | /* UnregisterNodesRequest */ |
| 15491 | static UA_DataTypeMember UnregisterNodesRequest_members[2] = { |
| 15492 | { |
| 15493 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 15494 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 15495 | 0, /* .padding */ |
| 15496 | false, /* .isArray */ |
| 15497 | false /* .isOptional */ |
| 15498 | }, |
| 15499 | { |
| 15500 | UA_TYPENAME("NodesToUnregister") /* .memberName */ |
| 15501 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15502 | offsetof(UA_UnregisterNodesRequest, nodesToUnregisterSize) - offsetof(UA_UnregisterNodesRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 15503 | true, /* .isArray */ |
| 15504 | false /* .isOptional */ |
| 15505 | },}; |
| 15506 | |
| 15507 | /* UnregisterNodesResponse */ |
| 15508 | static UA_DataTypeMember UnregisterNodesResponse_members[1] = { |
| 15509 | { |
| 15510 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 15511 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 15512 | 0, /* .padding */ |
| 15513 | false, /* .isArray */ |
| 15514 | false /* .isOptional */ |
| 15515 | },}; |
| 15516 | |
| 15517 | /* Counter */ |
| 15518 | #define Counter_members NULL |
| 15519 | |
| 15520 | /* OpaqueNumericRange */ |
| 15521 | #define OpaqueNumericRange_members NULL |
| 15522 | |
| 15523 | /* EndpointConfiguration */ |
| 15524 | static UA_DataTypeMember EndpointConfiguration_members[9] = { |
| 15525 | { |
| 15526 | UA_TYPENAME("OperationTimeout") /* .memberName */ |
| 15527 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 15528 | 0, /* .padding */ |
| 15529 | false, /* .isArray */ |
| 15530 | false /* .isOptional */ |
| 15531 | }, |
| 15532 | { |
| 15533 | UA_TYPENAME("UseBinaryEncoding") /* .memberName */ |
| 15534 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15535 | offsetof(UA_EndpointConfiguration, useBinaryEncoding) - offsetof(UA_EndpointConfiguration, operationTimeout) - sizeof(UA_Int32), /* .padding */ |
| 15536 | false, /* .isArray */ |
| 15537 | false /* .isOptional */ |
| 15538 | }, |
| 15539 | { |
| 15540 | UA_TYPENAME("MaxStringLength") /* .memberName */ |
| 15541 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 15542 | offsetof(UA_EndpointConfiguration, maxStringLength) - offsetof(UA_EndpointConfiguration, useBinaryEncoding) - sizeof(UA_Boolean), /* .padding */ |
| 15543 | false, /* .isArray */ |
| 15544 | false /* .isOptional */ |
| 15545 | }, |
| 15546 | { |
| 15547 | UA_TYPENAME("MaxByteStringLength") /* .memberName */ |
| 15548 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 15549 | offsetof(UA_EndpointConfiguration, maxByteStringLength) - offsetof(UA_EndpointConfiguration, maxStringLength) - sizeof(UA_Int32), /* .padding */ |
| 15550 | false, /* .isArray */ |
| 15551 | false /* .isOptional */ |
| 15552 | }, |
| 15553 | { |
| 15554 | UA_TYPENAME("MaxArrayLength") /* .memberName */ |
| 15555 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 15556 | offsetof(UA_EndpointConfiguration, maxArrayLength) - offsetof(UA_EndpointConfiguration, maxByteStringLength) - sizeof(UA_Int32), /* .padding */ |
| 15557 | false, /* .isArray */ |
| 15558 | false /* .isOptional */ |
| 15559 | }, |
| 15560 | { |
| 15561 | UA_TYPENAME("MaxMessageSize") /* .memberName */ |
| 15562 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 15563 | offsetof(UA_EndpointConfiguration, maxMessageSize) - offsetof(UA_EndpointConfiguration, maxArrayLength) - sizeof(UA_Int32), /* .padding */ |
| 15564 | false, /* .isArray */ |
| 15565 | false /* .isOptional */ |
| 15566 | }, |
| 15567 | { |
| 15568 | UA_TYPENAME("MaxBufferSize") /* .memberName */ |
| 15569 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 15570 | offsetof(UA_EndpointConfiguration, maxBufferSize) - offsetof(UA_EndpointConfiguration, maxMessageSize) - sizeof(UA_Int32), /* .padding */ |
| 15571 | false, /* .isArray */ |
| 15572 | false /* .isOptional */ |
| 15573 | }, |
| 15574 | { |
| 15575 | UA_TYPENAME("ChannelLifetime") /* .memberName */ |
| 15576 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 15577 | offsetof(UA_EndpointConfiguration, channelLifetime) - offsetof(UA_EndpointConfiguration, maxBufferSize) - sizeof(UA_Int32), /* .padding */ |
| 15578 | false, /* .isArray */ |
| 15579 | false /* .isOptional */ |
| 15580 | }, |
| 15581 | { |
| 15582 | UA_TYPENAME("SecurityTokenLifetime") /* .memberName */ |
| 15583 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 15584 | offsetof(UA_EndpointConfiguration, securityTokenLifetime) - offsetof(UA_EndpointConfiguration, channelLifetime) - sizeof(UA_Int32), /* .padding */ |
| 15585 | false, /* .isArray */ |
| 15586 | false /* .isOptional */ |
| 15587 | },}; |
| 15588 | |
| 15589 | /* QueryDataDescription */ |
| 15590 | static UA_DataTypeMember QueryDataDescription_members[3] = { |
| 15591 | { |
| 15592 | UA_TYPENAME("RelativePath") /* .memberName */ |
| 15593 | &UA_TYPES[UA_TYPES_RELATIVEPATH], /* .memberType */ |
| 15594 | 0, /* .padding */ |
| 15595 | false, /* .isArray */ |
| 15596 | false /* .isOptional */ |
| 15597 | }, |
| 15598 | { |
| 15599 | UA_TYPENAME("AttributeId") /* .memberName */ |
| 15600 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15601 | offsetof(UA_QueryDataDescription, attributeId) - offsetof(UA_QueryDataDescription, relativePath) - sizeof(UA_RelativePath), /* .padding */ |
| 15602 | false, /* .isArray */ |
| 15603 | false /* .isOptional */ |
| 15604 | }, |
| 15605 | { |
| 15606 | UA_TYPENAME("IndexRange") /* .memberName */ |
| 15607 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 15608 | offsetof(UA_QueryDataDescription, indexRange) - offsetof(UA_QueryDataDescription, attributeId) - sizeof(UA_UInt32), /* .padding */ |
| 15609 | false, /* .isArray */ |
| 15610 | false /* .isOptional */ |
| 15611 | },}; |
| 15612 | |
| 15613 | /* NodeTypeDescription */ |
| 15614 | static UA_DataTypeMember NodeTypeDescription_members[3] = { |
| 15615 | { |
| 15616 | UA_TYPENAME("TypeDefinitionNode") /* .memberName */ |
| 15617 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 15618 | 0, /* .padding */ |
| 15619 | false, /* .isArray */ |
| 15620 | false /* .isOptional */ |
| 15621 | }, |
| 15622 | { |
| 15623 | UA_TYPENAME("IncludeSubTypes") /* .memberName */ |
| 15624 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15625 | offsetof(UA_NodeTypeDescription, includeSubTypes) - offsetof(UA_NodeTypeDescription, typeDefinitionNode) - sizeof(UA_ExpandedNodeId), /* .padding */ |
| 15626 | false, /* .isArray */ |
| 15627 | false /* .isOptional */ |
| 15628 | }, |
| 15629 | { |
| 15630 | UA_TYPENAME("DataToReturn") /* .memberName */ |
| 15631 | &UA_TYPES[UA_TYPES_QUERYDATADESCRIPTION], /* .memberType */ |
| 15632 | offsetof(UA_NodeTypeDescription, dataToReturnSize) - offsetof(UA_NodeTypeDescription, includeSubTypes) - sizeof(UA_Boolean), /* .padding */ |
| 15633 | true, /* .isArray */ |
| 15634 | false /* .isOptional */ |
| 15635 | },}; |
| 15636 | |
| 15637 | /* FilterOperator */ |
| 15638 | #define FilterOperator_members NULL |
| 15639 | |
| 15640 | /* QueryDataSet */ |
| 15641 | static UA_DataTypeMember QueryDataSet_members[3] = { |
| 15642 | { |
| 15643 | UA_TYPENAME("NodeId") /* .memberName */ |
| 15644 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 15645 | 0, /* .padding */ |
| 15646 | false, /* .isArray */ |
| 15647 | false /* .isOptional */ |
| 15648 | }, |
| 15649 | { |
| 15650 | UA_TYPENAME("TypeDefinitionNode") /* .memberName */ |
| 15651 | &UA_TYPES[UA_TYPES_EXPANDEDNODEID], /* .memberType */ |
| 15652 | offsetof(UA_QueryDataSet, typeDefinitionNode) - offsetof(UA_QueryDataSet, nodeId) - sizeof(UA_ExpandedNodeId), /* .padding */ |
| 15653 | false, /* .isArray */ |
| 15654 | false /* .isOptional */ |
| 15655 | }, |
| 15656 | { |
| 15657 | UA_TYPENAME("Values") /* .memberName */ |
| 15658 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 15659 | offsetof(UA_QueryDataSet, valuesSize) - offsetof(UA_QueryDataSet, typeDefinitionNode) - sizeof(UA_ExpandedNodeId), /* .padding */ |
| 15660 | true, /* .isArray */ |
| 15661 | false /* .isOptional */ |
| 15662 | },}; |
| 15663 | |
| 15664 | /* NodeReference */ |
| 15665 | static UA_DataTypeMember NodeReference_members[4] = { |
| 15666 | { |
| 15667 | UA_TYPENAME("NodeId") /* .memberName */ |
| 15668 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15669 | 0, /* .padding */ |
| 15670 | false, /* .isArray */ |
| 15671 | false /* .isOptional */ |
| 15672 | }, |
| 15673 | { |
| 15674 | UA_TYPENAME("ReferenceTypeId") /* .memberName */ |
| 15675 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15676 | offsetof(UA_NodeReference, referenceTypeId) - offsetof(UA_NodeReference, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 15677 | false, /* .isArray */ |
| 15678 | false /* .isOptional */ |
| 15679 | }, |
| 15680 | { |
| 15681 | UA_TYPENAME("IsForward") /* .memberName */ |
| 15682 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15683 | offsetof(UA_NodeReference, isForward) - offsetof(UA_NodeReference, referenceTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 15684 | false, /* .isArray */ |
| 15685 | false /* .isOptional */ |
| 15686 | }, |
| 15687 | { |
| 15688 | UA_TYPENAME("ReferencedNodeIds") /* .memberName */ |
| 15689 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15690 | offsetof(UA_NodeReference, referencedNodeIdsSize) - offsetof(UA_NodeReference, isForward) - sizeof(UA_Boolean), /* .padding */ |
| 15691 | true, /* .isArray */ |
| 15692 | false /* .isOptional */ |
| 15693 | },}; |
| 15694 | |
| 15695 | /* ContentFilterElement */ |
| 15696 | static UA_DataTypeMember ContentFilterElement_members[2] = { |
| 15697 | { |
| 15698 | UA_TYPENAME("FilterOperator") /* .memberName */ |
| 15699 | &UA_TYPES[UA_TYPES_FILTEROPERATOR], /* .memberType */ |
| 15700 | 0, /* .padding */ |
| 15701 | false, /* .isArray */ |
| 15702 | false /* .isOptional */ |
| 15703 | }, |
| 15704 | { |
| 15705 | UA_TYPENAME("FilterOperands") /* .memberName */ |
| 15706 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 15707 | offsetof(UA_ContentFilterElement, filterOperandsSize) - offsetof(UA_ContentFilterElement, filterOperator) - sizeof(UA_FilterOperator), /* .padding */ |
| 15708 | true, /* .isArray */ |
| 15709 | false /* .isOptional */ |
| 15710 | },}; |
| 15711 | |
| 15712 | /* ContentFilter */ |
| 15713 | static UA_DataTypeMember ContentFilter_members[1] = { |
| 15714 | { |
| 15715 | UA_TYPENAME("Elements") /* .memberName */ |
| 15716 | &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENT], /* .memberType */ |
| 15717 | 0, /* .padding */ |
| 15718 | true, /* .isArray */ |
| 15719 | false /* .isOptional */ |
| 15720 | },}; |
| 15721 | |
| 15722 | /* ElementOperand */ |
| 15723 | static UA_DataTypeMember ElementOperand_members[1] = { |
| 15724 | { |
| 15725 | UA_TYPENAME("Index") /* .memberName */ |
| 15726 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15727 | 0, /* .padding */ |
| 15728 | false, /* .isArray */ |
| 15729 | false /* .isOptional */ |
| 15730 | },}; |
| 15731 | |
| 15732 | /* LiteralOperand */ |
| 15733 | static UA_DataTypeMember LiteralOperand_members[1] = { |
| 15734 | { |
| 15735 | UA_TYPENAME("Value") /* .memberName */ |
| 15736 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 15737 | 0, /* .padding */ |
| 15738 | false, /* .isArray */ |
| 15739 | false /* .isOptional */ |
| 15740 | },}; |
| 15741 | |
| 15742 | /* AttributeOperand */ |
| 15743 | static UA_DataTypeMember AttributeOperand_members[5] = { |
| 15744 | { |
| 15745 | UA_TYPENAME("NodeId") /* .memberName */ |
| 15746 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15747 | 0, /* .padding */ |
| 15748 | false, /* .isArray */ |
| 15749 | false /* .isOptional */ |
| 15750 | }, |
| 15751 | { |
| 15752 | UA_TYPENAME("Alias") /* .memberName */ |
| 15753 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 15754 | offsetof(UA_AttributeOperand, alias) - offsetof(UA_AttributeOperand, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 15755 | false, /* .isArray */ |
| 15756 | false /* .isOptional */ |
| 15757 | }, |
| 15758 | { |
| 15759 | UA_TYPENAME("BrowsePath") /* .memberName */ |
| 15760 | &UA_TYPES[UA_TYPES_RELATIVEPATH], /* .memberType */ |
| 15761 | offsetof(UA_AttributeOperand, browsePath) - offsetof(UA_AttributeOperand, alias) - sizeof(UA_String), /* .padding */ |
| 15762 | false, /* .isArray */ |
| 15763 | false /* .isOptional */ |
| 15764 | }, |
| 15765 | { |
| 15766 | UA_TYPENAME("AttributeId") /* .memberName */ |
| 15767 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15768 | offsetof(UA_AttributeOperand, attributeId) - offsetof(UA_AttributeOperand, browsePath) - sizeof(UA_RelativePath), /* .padding */ |
| 15769 | false, /* .isArray */ |
| 15770 | false /* .isOptional */ |
| 15771 | }, |
| 15772 | { |
| 15773 | UA_TYPENAME("IndexRange") /* .memberName */ |
| 15774 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 15775 | offsetof(UA_AttributeOperand, indexRange) - offsetof(UA_AttributeOperand, attributeId) - sizeof(UA_UInt32), /* .padding */ |
| 15776 | false, /* .isArray */ |
| 15777 | false /* .isOptional */ |
| 15778 | },}; |
| 15779 | |
| 15780 | /* SimpleAttributeOperand */ |
| 15781 | static UA_DataTypeMember SimpleAttributeOperand_members[4] = { |
| 15782 | { |
| 15783 | UA_TYPENAME("TypeDefinitionId") /* .memberName */ |
| 15784 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 15785 | 0, /* .padding */ |
| 15786 | false, /* .isArray */ |
| 15787 | false /* .isOptional */ |
| 15788 | }, |
| 15789 | { |
| 15790 | UA_TYPENAME("BrowsePath") /* .memberName */ |
| 15791 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 15792 | offsetof(UA_SimpleAttributeOperand, browsePathSize) - offsetof(UA_SimpleAttributeOperand, typeDefinitionId) - sizeof(UA_NodeId), /* .padding */ |
| 15793 | true, /* .isArray */ |
| 15794 | false /* .isOptional */ |
| 15795 | }, |
| 15796 | { |
| 15797 | UA_TYPENAME("AttributeId") /* .memberName */ |
| 15798 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15799 | offsetof(UA_SimpleAttributeOperand, attributeId) - offsetof(UA_SimpleAttributeOperand, browsePath) - sizeof(void *), /* .padding */ |
| 15800 | false, /* .isArray */ |
| 15801 | false /* .isOptional */ |
| 15802 | }, |
| 15803 | { |
| 15804 | UA_TYPENAME("IndexRange") /* .memberName */ |
| 15805 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 15806 | offsetof(UA_SimpleAttributeOperand, indexRange) - offsetof(UA_SimpleAttributeOperand, attributeId) - sizeof(UA_UInt32), /* .padding */ |
| 15807 | false, /* .isArray */ |
| 15808 | false /* .isOptional */ |
| 15809 | },}; |
| 15810 | |
| 15811 | /* ContentFilterElementResult */ |
| 15812 | static UA_DataTypeMember ContentFilterElementResult_members[3] = { |
| 15813 | { |
| 15814 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 15815 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 15816 | 0, /* .padding */ |
| 15817 | false, /* .isArray */ |
| 15818 | false /* .isOptional */ |
| 15819 | }, |
| 15820 | { |
| 15821 | UA_TYPENAME("OperandStatusCodes") /* .memberName */ |
| 15822 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 15823 | offsetof(UA_ContentFilterElementResult, operandStatusCodesSize) - offsetof(UA_ContentFilterElementResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 15824 | true, /* .isArray */ |
| 15825 | false /* .isOptional */ |
| 15826 | }, |
| 15827 | { |
| 15828 | UA_TYPENAME("OperandDiagnosticInfos") /* .memberName */ |
| 15829 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 15830 | offsetof(UA_ContentFilterElementResult, operandDiagnosticInfosSize) - offsetof(UA_ContentFilterElementResult, operandStatusCodes) - sizeof(void *), /* .padding */ |
| 15831 | true, /* .isArray */ |
| 15832 | false /* .isOptional */ |
| 15833 | },}; |
| 15834 | |
| 15835 | /* ContentFilterResult */ |
| 15836 | static UA_DataTypeMember ContentFilterResult_members[2] = { |
| 15837 | { |
| 15838 | UA_TYPENAME("ElementResults") /* .memberName */ |
| 15839 | &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT], /* .memberType */ |
| 15840 | 0, /* .padding */ |
| 15841 | true, /* .isArray */ |
| 15842 | false /* .isOptional */ |
| 15843 | }, |
| 15844 | { |
| 15845 | UA_TYPENAME("ElementDiagnosticInfos") /* .memberName */ |
| 15846 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 15847 | offsetof(UA_ContentFilterResult, elementDiagnosticInfosSize) - offsetof(UA_ContentFilterResult, elementResults) - sizeof(void *), /* .padding */ |
| 15848 | true, /* .isArray */ |
| 15849 | false /* .isOptional */ |
| 15850 | },}; |
| 15851 | |
| 15852 | /* ParsingResult */ |
| 15853 | static UA_DataTypeMember ParsingResult_members[3] = { |
| 15854 | { |
| 15855 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 15856 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 15857 | 0, /* .padding */ |
| 15858 | false, /* .isArray */ |
| 15859 | false /* .isOptional */ |
| 15860 | }, |
| 15861 | { |
| 15862 | UA_TYPENAME("DataStatusCodes") /* .memberName */ |
| 15863 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 15864 | offsetof(UA_ParsingResult, dataStatusCodesSize) - offsetof(UA_ParsingResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 15865 | true, /* .isArray */ |
| 15866 | false /* .isOptional */ |
| 15867 | }, |
| 15868 | { |
| 15869 | UA_TYPENAME("DataDiagnosticInfos") /* .memberName */ |
| 15870 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 15871 | offsetof(UA_ParsingResult, dataDiagnosticInfosSize) - offsetof(UA_ParsingResult, dataStatusCodes) - sizeof(void *), /* .padding */ |
| 15872 | true, /* .isArray */ |
| 15873 | false /* .isOptional */ |
| 15874 | },}; |
| 15875 | |
| 15876 | /* QueryFirstRequest */ |
| 15877 | static UA_DataTypeMember QueryFirstRequest_members[6] = { |
| 15878 | { |
| 15879 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 15880 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 15881 | 0, /* .padding */ |
| 15882 | false, /* .isArray */ |
| 15883 | false /* .isOptional */ |
| 15884 | }, |
| 15885 | { |
| 15886 | UA_TYPENAME("View") /* .memberName */ |
| 15887 | &UA_TYPES[UA_TYPES_VIEWDESCRIPTION], /* .memberType */ |
| 15888 | offsetof(UA_QueryFirstRequest, view) - offsetof(UA_QueryFirstRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 15889 | false, /* .isArray */ |
| 15890 | false /* .isOptional */ |
| 15891 | }, |
| 15892 | { |
| 15893 | UA_TYPENAME("NodeTypes") /* .memberName */ |
| 15894 | &UA_TYPES[UA_TYPES_NODETYPEDESCRIPTION], /* .memberType */ |
| 15895 | offsetof(UA_QueryFirstRequest, nodeTypesSize) - offsetof(UA_QueryFirstRequest, view) - sizeof(UA_ViewDescription), /* .padding */ |
| 15896 | true, /* .isArray */ |
| 15897 | false /* .isOptional */ |
| 15898 | }, |
| 15899 | { |
| 15900 | UA_TYPENAME("Filter") /* .memberName */ |
| 15901 | &UA_TYPES[UA_TYPES_CONTENTFILTER], /* .memberType */ |
| 15902 | offsetof(UA_QueryFirstRequest, filter) - offsetof(UA_QueryFirstRequest, nodeTypes) - sizeof(void *), /* .padding */ |
| 15903 | false, /* .isArray */ |
| 15904 | false /* .isOptional */ |
| 15905 | }, |
| 15906 | { |
| 15907 | UA_TYPENAME("MaxDataSetsToReturn") /* .memberName */ |
| 15908 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15909 | offsetof(UA_QueryFirstRequest, maxDataSetsToReturn) - offsetof(UA_QueryFirstRequest, filter) - sizeof(UA_ContentFilter), /* .padding */ |
| 15910 | false, /* .isArray */ |
| 15911 | false /* .isOptional */ |
| 15912 | }, |
| 15913 | { |
| 15914 | UA_TYPENAME("MaxReferencesToReturn") /* .memberName */ |
| 15915 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 15916 | offsetof(UA_QueryFirstRequest, maxReferencesToReturn) - offsetof(UA_QueryFirstRequest, maxDataSetsToReturn) - sizeof(UA_UInt32), /* .padding */ |
| 15917 | false, /* .isArray */ |
| 15918 | false /* .isOptional */ |
| 15919 | },}; |
| 15920 | |
| 15921 | /* QueryFirstResponse */ |
| 15922 | static UA_DataTypeMember QueryFirstResponse_members[6] = { |
| 15923 | { |
| 15924 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 15925 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 15926 | 0, /* .padding */ |
| 15927 | false, /* .isArray */ |
| 15928 | false /* .isOptional */ |
| 15929 | }, |
| 15930 | { |
| 15931 | UA_TYPENAME("QueryDataSets") /* .memberName */ |
| 15932 | &UA_TYPES[UA_TYPES_QUERYDATASET], /* .memberType */ |
| 15933 | offsetof(UA_QueryFirstResponse, queryDataSetsSize) - offsetof(UA_QueryFirstResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 15934 | true, /* .isArray */ |
| 15935 | false /* .isOptional */ |
| 15936 | }, |
| 15937 | { |
| 15938 | UA_TYPENAME("ContinuationPoint") /* .memberName */ |
| 15939 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 15940 | offsetof(UA_QueryFirstResponse, continuationPoint) - offsetof(UA_QueryFirstResponse, queryDataSets) - sizeof(void *), /* .padding */ |
| 15941 | false, /* .isArray */ |
| 15942 | false /* .isOptional */ |
| 15943 | }, |
| 15944 | { |
| 15945 | UA_TYPENAME("ParsingResults") /* .memberName */ |
| 15946 | &UA_TYPES[UA_TYPES_PARSINGRESULT], /* .memberType */ |
| 15947 | offsetof(UA_QueryFirstResponse, parsingResultsSize) - offsetof(UA_QueryFirstResponse, continuationPoint) - sizeof(UA_ByteString), /* .padding */ |
| 15948 | true, /* .isArray */ |
| 15949 | false /* .isOptional */ |
| 15950 | }, |
| 15951 | { |
| 15952 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 15953 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 15954 | offsetof(UA_QueryFirstResponse, diagnosticInfosSize) - offsetof(UA_QueryFirstResponse, parsingResults) - sizeof(void *), /* .padding */ |
| 15955 | true, /* .isArray */ |
| 15956 | false /* .isOptional */ |
| 15957 | }, |
| 15958 | { |
| 15959 | UA_TYPENAME("FilterResult") /* .memberName */ |
| 15960 | &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT], /* .memberType */ |
| 15961 | offsetof(UA_QueryFirstResponse, filterResult) - offsetof(UA_QueryFirstResponse, diagnosticInfos) - sizeof(void *), /* .padding */ |
| 15962 | false, /* .isArray */ |
| 15963 | false /* .isOptional */ |
| 15964 | },}; |
| 15965 | |
| 15966 | /* QueryNextRequest */ |
| 15967 | static UA_DataTypeMember QueryNextRequest_members[3] = { |
| 15968 | { |
| 15969 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 15970 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 15971 | 0, /* .padding */ |
| 15972 | false, /* .isArray */ |
| 15973 | false /* .isOptional */ |
| 15974 | }, |
| 15975 | { |
| 15976 | UA_TYPENAME("ReleaseContinuationPoint") /* .memberName */ |
| 15977 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 15978 | offsetof(UA_QueryNextRequest, releaseContinuationPoint) - offsetof(UA_QueryNextRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 15979 | false, /* .isArray */ |
| 15980 | false /* .isOptional */ |
| 15981 | }, |
| 15982 | { |
| 15983 | UA_TYPENAME("ContinuationPoint") /* .memberName */ |
| 15984 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 15985 | offsetof(UA_QueryNextRequest, continuationPoint) - offsetof(UA_QueryNextRequest, releaseContinuationPoint) - sizeof(UA_Boolean), /* .padding */ |
| 15986 | false, /* .isArray */ |
| 15987 | false /* .isOptional */ |
| 15988 | },}; |
| 15989 | |
| 15990 | /* QueryNextResponse */ |
| 15991 | static UA_DataTypeMember QueryNextResponse_members[3] = { |
| 15992 | { |
| 15993 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 15994 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 15995 | 0, /* .padding */ |
| 15996 | false, /* .isArray */ |
| 15997 | false /* .isOptional */ |
| 15998 | }, |
| 15999 | { |
| 16000 | UA_TYPENAME("QueryDataSets") /* .memberName */ |
| 16001 | &UA_TYPES[UA_TYPES_QUERYDATASET], /* .memberType */ |
| 16002 | offsetof(UA_QueryNextResponse, queryDataSetsSize) - offsetof(UA_QueryNextResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 16003 | true, /* .isArray */ |
| 16004 | false /* .isOptional */ |
| 16005 | }, |
| 16006 | { |
| 16007 | UA_TYPENAME("RevisedContinuationPoint") /* .memberName */ |
| 16008 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 16009 | offsetof(UA_QueryNextResponse, revisedContinuationPoint) - offsetof(UA_QueryNextResponse, queryDataSets) - sizeof(void *), /* .padding */ |
| 16010 | false, /* .isArray */ |
| 16011 | false /* .isOptional */ |
| 16012 | },}; |
| 16013 | |
| 16014 | /* TimestampsToReturn */ |
| 16015 | #define TimestampsToReturn_members NULL |
| 16016 | |
| 16017 | /* ReadValueId */ |
| 16018 | static UA_DataTypeMember ReadValueId_members[4] = { |
| 16019 | { |
| 16020 | UA_TYPENAME("NodeId") /* .memberName */ |
| 16021 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16022 | 0, /* .padding */ |
| 16023 | false, /* .isArray */ |
| 16024 | false /* .isOptional */ |
| 16025 | }, |
| 16026 | { |
| 16027 | UA_TYPENAME("AttributeId") /* .memberName */ |
| 16028 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 16029 | offsetof(UA_ReadValueId, attributeId) - offsetof(UA_ReadValueId, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 16030 | false, /* .isArray */ |
| 16031 | false /* .isOptional */ |
| 16032 | }, |
| 16033 | { |
| 16034 | UA_TYPENAME("IndexRange") /* .memberName */ |
| 16035 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 16036 | offsetof(UA_ReadValueId, indexRange) - offsetof(UA_ReadValueId, attributeId) - sizeof(UA_UInt32), /* .padding */ |
| 16037 | false, /* .isArray */ |
| 16038 | false /* .isOptional */ |
| 16039 | }, |
| 16040 | { |
| 16041 | UA_TYPENAME("DataEncoding") /* .memberName */ |
| 16042 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 16043 | offsetof(UA_ReadValueId, dataEncoding) - offsetof(UA_ReadValueId, indexRange) - sizeof(UA_String), /* .padding */ |
| 16044 | false, /* .isArray */ |
| 16045 | false /* .isOptional */ |
| 16046 | },}; |
| 16047 | |
| 16048 | /* ReadRequest */ |
| 16049 | static UA_DataTypeMember ReadRequest_members[4] = { |
| 16050 | { |
| 16051 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 16052 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 16053 | 0, /* .padding */ |
| 16054 | false, /* .isArray */ |
| 16055 | false /* .isOptional */ |
| 16056 | }, |
| 16057 | { |
| 16058 | UA_TYPENAME("MaxAge") /* .memberName */ |
| 16059 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 16060 | offsetof(UA_ReadRequest, maxAge) - offsetof(UA_ReadRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 16061 | false, /* .isArray */ |
| 16062 | false /* .isOptional */ |
| 16063 | }, |
| 16064 | { |
| 16065 | UA_TYPENAME("TimestampsToReturn") /* .memberName */ |
| 16066 | &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */ |
| 16067 | offsetof(UA_ReadRequest, timestampsToReturn) - offsetof(UA_ReadRequest, maxAge) - sizeof(UA_Double), /* .padding */ |
| 16068 | false, /* .isArray */ |
| 16069 | false /* .isOptional */ |
| 16070 | }, |
| 16071 | { |
| 16072 | UA_TYPENAME("NodesToRead") /* .memberName */ |
| 16073 | &UA_TYPES[UA_TYPES_READVALUEID], /* .memberType */ |
| 16074 | offsetof(UA_ReadRequest, nodesToReadSize) - offsetof(UA_ReadRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */ |
| 16075 | true, /* .isArray */ |
| 16076 | false /* .isOptional */ |
| 16077 | },}; |
| 16078 | |
| 16079 | /* ReadResponse */ |
| 16080 | static UA_DataTypeMember ReadResponse_members[3] = { |
| 16081 | { |
| 16082 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 16083 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 16084 | 0, /* .padding */ |
| 16085 | false, /* .isArray */ |
| 16086 | false /* .isOptional */ |
| 16087 | }, |
| 16088 | { |
| 16089 | UA_TYPENAME("Results") /* .memberName */ |
| 16090 | &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */ |
| 16091 | offsetof(UA_ReadResponse, resultsSize) - offsetof(UA_ReadResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 16092 | true, /* .isArray */ |
| 16093 | false /* .isOptional */ |
| 16094 | }, |
| 16095 | { |
| 16096 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 16097 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 16098 | offsetof(UA_ReadResponse, diagnosticInfosSize) - offsetof(UA_ReadResponse, results) - sizeof(void *), /* .padding */ |
| 16099 | true, /* .isArray */ |
| 16100 | false /* .isOptional */ |
| 16101 | },}; |
| 16102 | |
| 16103 | /* HistoryReadValueId */ |
| 16104 | static UA_DataTypeMember HistoryReadValueId_members[4] = { |
| 16105 | { |
| 16106 | UA_TYPENAME("NodeId") /* .memberName */ |
| 16107 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16108 | 0, /* .padding */ |
| 16109 | false, /* .isArray */ |
| 16110 | false /* .isOptional */ |
| 16111 | }, |
| 16112 | { |
| 16113 | UA_TYPENAME("IndexRange") /* .memberName */ |
| 16114 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 16115 | offsetof(UA_HistoryReadValueId, indexRange) - offsetof(UA_HistoryReadValueId, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 16116 | false, /* .isArray */ |
| 16117 | false /* .isOptional */ |
| 16118 | }, |
| 16119 | { |
| 16120 | UA_TYPENAME("DataEncoding") /* .memberName */ |
| 16121 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 16122 | offsetof(UA_HistoryReadValueId, dataEncoding) - offsetof(UA_HistoryReadValueId, indexRange) - sizeof(UA_String), /* .padding */ |
| 16123 | false, /* .isArray */ |
| 16124 | false /* .isOptional */ |
| 16125 | }, |
| 16126 | { |
| 16127 | UA_TYPENAME("ContinuationPoint") /* .memberName */ |
| 16128 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 16129 | offsetof(UA_HistoryReadValueId, continuationPoint) - offsetof(UA_HistoryReadValueId, dataEncoding) - sizeof(UA_QualifiedName), /* .padding */ |
| 16130 | false, /* .isArray */ |
| 16131 | false /* .isOptional */ |
| 16132 | },}; |
| 16133 | |
| 16134 | /* HistoryReadResult */ |
| 16135 | static UA_DataTypeMember HistoryReadResult_members[3] = { |
| 16136 | { |
| 16137 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 16138 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 16139 | 0, /* .padding */ |
| 16140 | false, /* .isArray */ |
| 16141 | false /* .isOptional */ |
| 16142 | }, |
| 16143 | { |
| 16144 | UA_TYPENAME("ContinuationPoint") /* .memberName */ |
| 16145 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 16146 | offsetof(UA_HistoryReadResult, continuationPoint) - offsetof(UA_HistoryReadResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 16147 | false, /* .isArray */ |
| 16148 | false /* .isOptional */ |
| 16149 | }, |
| 16150 | { |
| 16151 | UA_TYPENAME("HistoryData") /* .memberName */ |
| 16152 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 16153 | offsetof(UA_HistoryReadResult, historyData) - offsetof(UA_HistoryReadResult, continuationPoint) - sizeof(UA_ByteString), /* .padding */ |
| 16154 | false, /* .isArray */ |
| 16155 | false /* .isOptional */ |
| 16156 | },}; |
| 16157 | |
| 16158 | /* ReadRawModifiedDetails */ |
| 16159 | static UA_DataTypeMember ReadRawModifiedDetails_members[5] = { |
| 16160 | { |
| 16161 | UA_TYPENAME("IsReadModified") /* .memberName */ |
| 16162 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 16163 | 0, /* .padding */ |
| 16164 | false, /* .isArray */ |
| 16165 | false /* .isOptional */ |
| 16166 | }, |
| 16167 | { |
| 16168 | UA_TYPENAME("StartTime") /* .memberName */ |
| 16169 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 16170 | offsetof(UA_ReadRawModifiedDetails, startTime) - offsetof(UA_ReadRawModifiedDetails, isReadModified) - sizeof(UA_Boolean), /* .padding */ |
| 16171 | false, /* .isArray */ |
| 16172 | false /* .isOptional */ |
| 16173 | }, |
| 16174 | { |
| 16175 | UA_TYPENAME("EndTime") /* .memberName */ |
| 16176 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 16177 | offsetof(UA_ReadRawModifiedDetails, endTime) - offsetof(UA_ReadRawModifiedDetails, startTime) - sizeof(UA_DateTime), /* .padding */ |
| 16178 | false, /* .isArray */ |
| 16179 | false /* .isOptional */ |
| 16180 | }, |
| 16181 | { |
| 16182 | UA_TYPENAME("NumValuesPerNode") /* .memberName */ |
| 16183 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 16184 | offsetof(UA_ReadRawModifiedDetails, numValuesPerNode) - offsetof(UA_ReadRawModifiedDetails, endTime) - sizeof(UA_DateTime), /* .padding */ |
| 16185 | false, /* .isArray */ |
| 16186 | false /* .isOptional */ |
| 16187 | }, |
| 16188 | { |
| 16189 | UA_TYPENAME("ReturnBounds") /* .memberName */ |
| 16190 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 16191 | offsetof(UA_ReadRawModifiedDetails, returnBounds) - offsetof(UA_ReadRawModifiedDetails, numValuesPerNode) - sizeof(UA_UInt32), /* .padding */ |
| 16192 | false, /* .isArray */ |
| 16193 | false /* .isOptional */ |
| 16194 | },}; |
| 16195 | |
| 16196 | /* ReadAtTimeDetails */ |
| 16197 | static UA_DataTypeMember ReadAtTimeDetails_members[2] = { |
| 16198 | { |
| 16199 | UA_TYPENAME("ReqTimes") /* .memberName */ |
| 16200 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 16201 | 0, /* .padding */ |
| 16202 | true, /* .isArray */ |
| 16203 | false /* .isOptional */ |
| 16204 | }, |
| 16205 | { |
| 16206 | UA_TYPENAME("UseSimpleBounds") /* .memberName */ |
| 16207 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 16208 | offsetof(UA_ReadAtTimeDetails, useSimpleBounds) - offsetof(UA_ReadAtTimeDetails, reqTimes) - sizeof(void *), /* .padding */ |
| 16209 | false, /* .isArray */ |
| 16210 | false /* .isOptional */ |
| 16211 | },}; |
| 16212 | |
| 16213 | /* ReadAnnotationDataDetails */ |
| 16214 | static UA_DataTypeMember ReadAnnotationDataDetails_members[1] = { |
| 16215 | { |
| 16216 | UA_TYPENAME("ReqTimes") /* .memberName */ |
| 16217 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 16218 | 0, /* .padding */ |
| 16219 | true, /* .isArray */ |
| 16220 | false /* .isOptional */ |
| 16221 | },}; |
| 16222 | |
| 16223 | /* HistoryData */ |
| 16224 | static UA_DataTypeMember HistoryData_members[1] = { |
| 16225 | { |
| 16226 | UA_TYPENAME("DataValues") /* .memberName */ |
| 16227 | &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */ |
| 16228 | 0, /* .padding */ |
| 16229 | true, /* .isArray */ |
| 16230 | false /* .isOptional */ |
| 16231 | },}; |
| 16232 | |
| 16233 | /* HistoryReadRequest */ |
| 16234 | static UA_DataTypeMember HistoryReadRequest_members[5] = { |
| 16235 | { |
| 16236 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 16237 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 16238 | 0, /* .padding */ |
| 16239 | false, /* .isArray */ |
| 16240 | false /* .isOptional */ |
| 16241 | }, |
| 16242 | { |
| 16243 | UA_TYPENAME("HistoryReadDetails") /* .memberName */ |
| 16244 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 16245 | offsetof(UA_HistoryReadRequest, historyReadDetails) - offsetof(UA_HistoryReadRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 16246 | false, /* .isArray */ |
| 16247 | false /* .isOptional */ |
| 16248 | }, |
| 16249 | { |
| 16250 | UA_TYPENAME("TimestampsToReturn") /* .memberName */ |
| 16251 | &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */ |
| 16252 | offsetof(UA_HistoryReadRequest, timestampsToReturn) - offsetof(UA_HistoryReadRequest, historyReadDetails) - sizeof(UA_ExtensionObject), /* .padding */ |
| 16253 | false, /* .isArray */ |
| 16254 | false /* .isOptional */ |
| 16255 | }, |
| 16256 | { |
| 16257 | UA_TYPENAME("ReleaseContinuationPoints") /* .memberName */ |
| 16258 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 16259 | offsetof(UA_HistoryReadRequest, releaseContinuationPoints) - offsetof(UA_HistoryReadRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */ |
| 16260 | false, /* .isArray */ |
| 16261 | false /* .isOptional */ |
| 16262 | }, |
| 16263 | { |
| 16264 | UA_TYPENAME("NodesToRead") /* .memberName */ |
| 16265 | &UA_TYPES[UA_TYPES_HISTORYREADVALUEID], /* .memberType */ |
| 16266 | offsetof(UA_HistoryReadRequest, nodesToReadSize) - offsetof(UA_HistoryReadRequest, releaseContinuationPoints) - sizeof(UA_Boolean), /* .padding */ |
| 16267 | true, /* .isArray */ |
| 16268 | false /* .isOptional */ |
| 16269 | },}; |
| 16270 | |
| 16271 | /* HistoryReadResponse */ |
| 16272 | static UA_DataTypeMember HistoryReadResponse_members[3] = { |
| 16273 | { |
| 16274 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 16275 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 16276 | 0, /* .padding */ |
| 16277 | false, /* .isArray */ |
| 16278 | false /* .isOptional */ |
| 16279 | }, |
| 16280 | { |
| 16281 | UA_TYPENAME("Results") /* .memberName */ |
| 16282 | &UA_TYPES[UA_TYPES_HISTORYREADRESULT], /* .memberType */ |
| 16283 | offsetof(UA_HistoryReadResponse, resultsSize) - offsetof(UA_HistoryReadResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 16284 | true, /* .isArray */ |
| 16285 | false /* .isOptional */ |
| 16286 | }, |
| 16287 | { |
| 16288 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 16289 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 16290 | offsetof(UA_HistoryReadResponse, diagnosticInfosSize) - offsetof(UA_HistoryReadResponse, results) - sizeof(void *), /* .padding */ |
| 16291 | true, /* .isArray */ |
| 16292 | false /* .isOptional */ |
| 16293 | },}; |
| 16294 | |
| 16295 | /* WriteValue */ |
| 16296 | static UA_DataTypeMember WriteValue_members[4] = { |
| 16297 | { |
| 16298 | UA_TYPENAME("NodeId") /* .memberName */ |
| 16299 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16300 | 0, /* .padding */ |
| 16301 | false, /* .isArray */ |
| 16302 | false /* .isOptional */ |
| 16303 | }, |
| 16304 | { |
| 16305 | UA_TYPENAME("AttributeId") /* .memberName */ |
| 16306 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 16307 | offsetof(UA_WriteValue, attributeId) - offsetof(UA_WriteValue, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 16308 | false, /* .isArray */ |
| 16309 | false /* .isOptional */ |
| 16310 | }, |
| 16311 | { |
| 16312 | UA_TYPENAME("IndexRange") /* .memberName */ |
| 16313 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 16314 | offsetof(UA_WriteValue, indexRange) - offsetof(UA_WriteValue, attributeId) - sizeof(UA_UInt32), /* .padding */ |
| 16315 | false, /* .isArray */ |
| 16316 | false /* .isOptional */ |
| 16317 | }, |
| 16318 | { |
| 16319 | UA_TYPENAME("Value") /* .memberName */ |
| 16320 | &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */ |
| 16321 | offsetof(UA_WriteValue, value) - offsetof(UA_WriteValue, indexRange) - sizeof(UA_String), /* .padding */ |
| 16322 | false, /* .isArray */ |
| 16323 | false /* .isOptional */ |
| 16324 | },}; |
| 16325 | |
| 16326 | /* WriteRequest */ |
| 16327 | static UA_DataTypeMember WriteRequest_members[2] = { |
| 16328 | { |
| 16329 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 16330 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 16331 | 0, /* .padding */ |
| 16332 | false, /* .isArray */ |
| 16333 | false /* .isOptional */ |
| 16334 | }, |
| 16335 | { |
| 16336 | UA_TYPENAME("NodesToWrite") /* .memberName */ |
| 16337 | &UA_TYPES[UA_TYPES_WRITEVALUE], /* .memberType */ |
| 16338 | offsetof(UA_WriteRequest, nodesToWriteSize) - offsetof(UA_WriteRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 16339 | true, /* .isArray */ |
| 16340 | false /* .isOptional */ |
| 16341 | },}; |
| 16342 | |
| 16343 | /* WriteResponse */ |
| 16344 | static UA_DataTypeMember WriteResponse_members[3] = { |
| 16345 | { |
| 16346 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 16347 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 16348 | 0, /* .padding */ |
| 16349 | false, /* .isArray */ |
| 16350 | false /* .isOptional */ |
| 16351 | }, |
| 16352 | { |
| 16353 | UA_TYPENAME("Results") /* .memberName */ |
| 16354 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 16355 | offsetof(UA_WriteResponse, resultsSize) - offsetof(UA_WriteResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 16356 | true, /* .isArray */ |
| 16357 | false /* .isOptional */ |
| 16358 | }, |
| 16359 | { |
| 16360 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 16361 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 16362 | offsetof(UA_WriteResponse, diagnosticInfosSize) - offsetof(UA_WriteResponse, results) - sizeof(void *), /* .padding */ |
| 16363 | true, /* .isArray */ |
| 16364 | false /* .isOptional */ |
| 16365 | },}; |
| 16366 | |
| 16367 | /* HistoryUpdateDetails */ |
| 16368 | static UA_DataTypeMember HistoryUpdateDetails_members[1] = { |
| 16369 | { |
| 16370 | UA_TYPENAME("NodeId") /* .memberName */ |
| 16371 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16372 | 0, /* .padding */ |
| 16373 | false, /* .isArray */ |
| 16374 | false /* .isOptional */ |
| 16375 | },}; |
| 16376 | |
| 16377 | /* HistoryUpdateType */ |
| 16378 | #define HistoryUpdateType_members NULL |
| 16379 | |
| 16380 | /* PerformUpdateType */ |
| 16381 | #define PerformUpdateType_members NULL |
| 16382 | |
| 16383 | /* UpdateDataDetails */ |
| 16384 | static UA_DataTypeMember UpdateDataDetails_members[3] = { |
| 16385 | { |
| 16386 | UA_TYPENAME("NodeId") /* .memberName */ |
| 16387 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16388 | 0, /* .padding */ |
| 16389 | false, /* .isArray */ |
| 16390 | false /* .isOptional */ |
| 16391 | }, |
| 16392 | { |
| 16393 | UA_TYPENAME("PerformInsertReplace") /* .memberName */ |
| 16394 | &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE], /* .memberType */ |
| 16395 | offsetof(UA_UpdateDataDetails, performInsertReplace) - offsetof(UA_UpdateDataDetails, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 16396 | false, /* .isArray */ |
| 16397 | false /* .isOptional */ |
| 16398 | }, |
| 16399 | { |
| 16400 | UA_TYPENAME("UpdateValues") /* .memberName */ |
| 16401 | &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */ |
| 16402 | offsetof(UA_UpdateDataDetails, updateValuesSize) - offsetof(UA_UpdateDataDetails, performInsertReplace) - sizeof(UA_PerformUpdateType), /* .padding */ |
| 16403 | true, /* .isArray */ |
| 16404 | false /* .isOptional */ |
| 16405 | },}; |
| 16406 | |
| 16407 | /* UpdateStructureDataDetails */ |
| 16408 | static UA_DataTypeMember UpdateStructureDataDetails_members[3] = { |
| 16409 | { |
| 16410 | UA_TYPENAME("NodeId") /* .memberName */ |
| 16411 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16412 | 0, /* .padding */ |
| 16413 | false, /* .isArray */ |
| 16414 | false /* .isOptional */ |
| 16415 | }, |
| 16416 | { |
| 16417 | UA_TYPENAME("PerformInsertReplace") /* .memberName */ |
| 16418 | &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE], /* .memberType */ |
| 16419 | offsetof(UA_UpdateStructureDataDetails, performInsertReplace) - offsetof(UA_UpdateStructureDataDetails, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 16420 | false, /* .isArray */ |
| 16421 | false /* .isOptional */ |
| 16422 | }, |
| 16423 | { |
| 16424 | UA_TYPENAME("UpdateValues") /* .memberName */ |
| 16425 | &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */ |
| 16426 | offsetof(UA_UpdateStructureDataDetails, updateValuesSize) - offsetof(UA_UpdateStructureDataDetails, performInsertReplace) - sizeof(UA_PerformUpdateType), /* .padding */ |
| 16427 | true, /* .isArray */ |
| 16428 | false /* .isOptional */ |
| 16429 | },}; |
| 16430 | |
| 16431 | /* DeleteRawModifiedDetails */ |
| 16432 | static UA_DataTypeMember DeleteRawModifiedDetails_members[4] = { |
| 16433 | { |
| 16434 | UA_TYPENAME("NodeId") /* .memberName */ |
| 16435 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16436 | 0, /* .padding */ |
| 16437 | false, /* .isArray */ |
| 16438 | false /* .isOptional */ |
| 16439 | }, |
| 16440 | { |
| 16441 | UA_TYPENAME("IsDeleteModified") /* .memberName */ |
| 16442 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 16443 | offsetof(UA_DeleteRawModifiedDetails, isDeleteModified) - offsetof(UA_DeleteRawModifiedDetails, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 16444 | false, /* .isArray */ |
| 16445 | false /* .isOptional */ |
| 16446 | }, |
| 16447 | { |
| 16448 | UA_TYPENAME("StartTime") /* .memberName */ |
| 16449 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 16450 | offsetof(UA_DeleteRawModifiedDetails, startTime) - offsetof(UA_DeleteRawModifiedDetails, isDeleteModified) - sizeof(UA_Boolean), /* .padding */ |
| 16451 | false, /* .isArray */ |
| 16452 | false /* .isOptional */ |
| 16453 | }, |
| 16454 | { |
| 16455 | UA_TYPENAME("EndTime") /* .memberName */ |
| 16456 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 16457 | offsetof(UA_DeleteRawModifiedDetails, endTime) - offsetof(UA_DeleteRawModifiedDetails, startTime) - sizeof(UA_DateTime), /* .padding */ |
| 16458 | false, /* .isArray */ |
| 16459 | false /* .isOptional */ |
| 16460 | },}; |
| 16461 | |
| 16462 | /* DeleteAtTimeDetails */ |
| 16463 | static UA_DataTypeMember DeleteAtTimeDetails_members[2] = { |
| 16464 | { |
| 16465 | UA_TYPENAME("NodeId") /* .memberName */ |
| 16466 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16467 | 0, /* .padding */ |
| 16468 | false, /* .isArray */ |
| 16469 | false /* .isOptional */ |
| 16470 | }, |
| 16471 | { |
| 16472 | UA_TYPENAME("ReqTimes") /* .memberName */ |
| 16473 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 16474 | offsetof(UA_DeleteAtTimeDetails, reqTimesSize) - offsetof(UA_DeleteAtTimeDetails, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 16475 | true, /* .isArray */ |
| 16476 | false /* .isOptional */ |
| 16477 | },}; |
| 16478 | |
| 16479 | /* DeleteEventDetails */ |
| 16480 | static UA_DataTypeMember DeleteEventDetails_members[2] = { |
| 16481 | { |
| 16482 | UA_TYPENAME("NodeId") /* .memberName */ |
| 16483 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16484 | 0, /* .padding */ |
| 16485 | false, /* .isArray */ |
| 16486 | false /* .isOptional */ |
| 16487 | }, |
| 16488 | { |
| 16489 | UA_TYPENAME("EventIds") /* .memberName */ |
| 16490 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 16491 | offsetof(UA_DeleteEventDetails, eventIdsSize) - offsetof(UA_DeleteEventDetails, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 16492 | true, /* .isArray */ |
| 16493 | false /* .isOptional */ |
| 16494 | },}; |
| 16495 | |
| 16496 | /* HistoryUpdateResult */ |
| 16497 | static UA_DataTypeMember HistoryUpdateResult_members[3] = { |
| 16498 | { |
| 16499 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 16500 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 16501 | 0, /* .padding */ |
| 16502 | false, /* .isArray */ |
| 16503 | false /* .isOptional */ |
| 16504 | }, |
| 16505 | { |
| 16506 | UA_TYPENAME("OperationResults") /* .memberName */ |
| 16507 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 16508 | offsetof(UA_HistoryUpdateResult, operationResultsSize) - offsetof(UA_HistoryUpdateResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 16509 | true, /* .isArray */ |
| 16510 | false /* .isOptional */ |
| 16511 | }, |
| 16512 | { |
| 16513 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 16514 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 16515 | offsetof(UA_HistoryUpdateResult, diagnosticInfosSize) - offsetof(UA_HistoryUpdateResult, operationResults) - sizeof(void *), /* .padding */ |
| 16516 | true, /* .isArray */ |
| 16517 | false /* .isOptional */ |
| 16518 | },}; |
| 16519 | |
| 16520 | /* HistoryUpdateRequest */ |
| 16521 | static UA_DataTypeMember HistoryUpdateRequest_members[2] = { |
| 16522 | { |
| 16523 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 16524 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 16525 | 0, /* .padding */ |
| 16526 | false, /* .isArray */ |
| 16527 | false /* .isOptional */ |
| 16528 | }, |
| 16529 | { |
| 16530 | UA_TYPENAME("HistoryUpdateDetails") /* .memberName */ |
| 16531 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 16532 | offsetof(UA_HistoryUpdateRequest, historyUpdateDetailsSize) - offsetof(UA_HistoryUpdateRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 16533 | true, /* .isArray */ |
| 16534 | false /* .isOptional */ |
| 16535 | },}; |
| 16536 | |
| 16537 | /* HistoryUpdateResponse */ |
| 16538 | static UA_DataTypeMember HistoryUpdateResponse_members[3] = { |
| 16539 | { |
| 16540 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 16541 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 16542 | 0, /* .padding */ |
| 16543 | false, /* .isArray */ |
| 16544 | false /* .isOptional */ |
| 16545 | }, |
| 16546 | { |
| 16547 | UA_TYPENAME("Results") /* .memberName */ |
| 16548 | &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT], /* .memberType */ |
| 16549 | offsetof(UA_HistoryUpdateResponse, resultsSize) - offsetof(UA_HistoryUpdateResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 16550 | true, /* .isArray */ |
| 16551 | false /* .isOptional */ |
| 16552 | }, |
| 16553 | { |
| 16554 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 16555 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 16556 | offsetof(UA_HistoryUpdateResponse, diagnosticInfosSize) - offsetof(UA_HistoryUpdateResponse, results) - sizeof(void *), /* .padding */ |
| 16557 | true, /* .isArray */ |
| 16558 | false /* .isOptional */ |
| 16559 | },}; |
| 16560 | |
| 16561 | /* CallMethodRequest */ |
| 16562 | static UA_DataTypeMember CallMethodRequest_members[3] = { |
| 16563 | { |
| 16564 | UA_TYPENAME("ObjectId") /* .memberName */ |
| 16565 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16566 | 0, /* .padding */ |
| 16567 | false, /* .isArray */ |
| 16568 | false /* .isOptional */ |
| 16569 | }, |
| 16570 | { |
| 16571 | UA_TYPENAME("MethodId") /* .memberName */ |
| 16572 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16573 | offsetof(UA_CallMethodRequest, methodId) - offsetof(UA_CallMethodRequest, objectId) - sizeof(UA_NodeId), /* .padding */ |
| 16574 | false, /* .isArray */ |
| 16575 | false /* .isOptional */ |
| 16576 | }, |
| 16577 | { |
| 16578 | UA_TYPENAME("InputArguments") /* .memberName */ |
| 16579 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 16580 | offsetof(UA_CallMethodRequest, inputArgumentsSize) - offsetof(UA_CallMethodRequest, methodId) - sizeof(UA_NodeId), /* .padding */ |
| 16581 | true, /* .isArray */ |
| 16582 | false /* .isOptional */ |
| 16583 | },}; |
| 16584 | |
| 16585 | /* CallMethodResult */ |
| 16586 | static UA_DataTypeMember CallMethodResult_members[4] = { |
| 16587 | { |
| 16588 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 16589 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 16590 | 0, /* .padding */ |
| 16591 | false, /* .isArray */ |
| 16592 | false /* .isOptional */ |
| 16593 | }, |
| 16594 | { |
| 16595 | UA_TYPENAME("InputArgumentResults") /* .memberName */ |
| 16596 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 16597 | offsetof(UA_CallMethodResult, inputArgumentResultsSize) - offsetof(UA_CallMethodResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 16598 | true, /* .isArray */ |
| 16599 | false /* .isOptional */ |
| 16600 | }, |
| 16601 | { |
| 16602 | UA_TYPENAME("InputArgumentDiagnosticInfos") /* .memberName */ |
| 16603 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 16604 | offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfosSize) - offsetof(UA_CallMethodResult, inputArgumentResults) - sizeof(void *), /* .padding */ |
| 16605 | true, /* .isArray */ |
| 16606 | false /* .isOptional */ |
| 16607 | }, |
| 16608 | { |
| 16609 | UA_TYPENAME("OutputArguments") /* .memberName */ |
| 16610 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 16611 | offsetof(UA_CallMethodResult, outputArgumentsSize) - offsetof(UA_CallMethodResult, inputArgumentDiagnosticInfos) - sizeof(void *), /* .padding */ |
| 16612 | true, /* .isArray */ |
| 16613 | false /* .isOptional */ |
| 16614 | },}; |
| 16615 | |
| 16616 | /* CallRequest */ |
| 16617 | static UA_DataTypeMember CallRequest_members[2] = { |
| 16618 | { |
| 16619 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 16620 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 16621 | 0, /* .padding */ |
| 16622 | false, /* .isArray */ |
| 16623 | false /* .isOptional */ |
| 16624 | }, |
| 16625 | { |
| 16626 | UA_TYPENAME("MethodsToCall") /* .memberName */ |
| 16627 | &UA_TYPES[UA_TYPES_CALLMETHODREQUEST], /* .memberType */ |
| 16628 | offsetof(UA_CallRequest, methodsToCallSize) - offsetof(UA_CallRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 16629 | true, /* .isArray */ |
| 16630 | false /* .isOptional */ |
| 16631 | },}; |
| 16632 | |
| 16633 | /* CallResponse */ |
| 16634 | static UA_DataTypeMember CallResponse_members[3] = { |
| 16635 | { |
| 16636 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 16637 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 16638 | 0, /* .padding */ |
| 16639 | false, /* .isArray */ |
| 16640 | false /* .isOptional */ |
| 16641 | }, |
| 16642 | { |
| 16643 | UA_TYPENAME("Results") /* .memberName */ |
| 16644 | &UA_TYPES[UA_TYPES_CALLMETHODRESULT], /* .memberType */ |
| 16645 | offsetof(UA_CallResponse, resultsSize) - offsetof(UA_CallResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 16646 | true, /* .isArray */ |
| 16647 | false /* .isOptional */ |
| 16648 | }, |
| 16649 | { |
| 16650 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 16651 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 16652 | offsetof(UA_CallResponse, diagnosticInfosSize) - offsetof(UA_CallResponse, results) - sizeof(void *), /* .padding */ |
| 16653 | true, /* .isArray */ |
| 16654 | false /* .isOptional */ |
| 16655 | },}; |
| 16656 | |
| 16657 | /* MonitoringMode */ |
| 16658 | #define MonitoringMode_members NULL |
| 16659 | |
| 16660 | /* DataChangeTrigger */ |
| 16661 | #define DataChangeTrigger_members NULL |
| 16662 | |
| 16663 | /* DeadbandType */ |
| 16664 | #define DeadbandType_members NULL |
| 16665 | |
| 16666 | /* DataChangeFilter */ |
| 16667 | static UA_DataTypeMember DataChangeFilter_members[3] = { |
| 16668 | { |
| 16669 | UA_TYPENAME("Trigger") /* .memberName */ |
| 16670 | &UA_TYPES[UA_TYPES_DATACHANGETRIGGER], /* .memberType */ |
| 16671 | 0, /* .padding */ |
| 16672 | false, /* .isArray */ |
| 16673 | false /* .isOptional */ |
| 16674 | }, |
| 16675 | { |
| 16676 | UA_TYPENAME("DeadbandType") /* .memberName */ |
| 16677 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 16678 | offsetof(UA_DataChangeFilter, deadbandType) - offsetof(UA_DataChangeFilter, trigger) - sizeof(UA_DataChangeTrigger), /* .padding */ |
| 16679 | false, /* .isArray */ |
| 16680 | false /* .isOptional */ |
| 16681 | }, |
| 16682 | { |
| 16683 | UA_TYPENAME("DeadbandValue") /* .memberName */ |
| 16684 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 16685 | offsetof(UA_DataChangeFilter, deadbandValue) - offsetof(UA_DataChangeFilter, deadbandType) - sizeof(UA_UInt32), /* .padding */ |
| 16686 | false, /* .isArray */ |
| 16687 | false /* .isOptional */ |
| 16688 | },}; |
| 16689 | |
| 16690 | /* EventFilter */ |
| 16691 | static UA_DataTypeMember EventFilter_members[2] = { |
| 16692 | { |
| 16693 | UA_TYPENAME("SelectClauses") /* .memberName */ |
| 16694 | &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND], /* .memberType */ |
| 16695 | 0, /* .padding */ |
| 16696 | true, /* .isArray */ |
| 16697 | false /* .isOptional */ |
| 16698 | }, |
| 16699 | { |
| 16700 | UA_TYPENAME("WhereClause") /* .memberName */ |
| 16701 | &UA_TYPES[UA_TYPES_CONTENTFILTER], /* .memberType */ |
| 16702 | offsetof(UA_EventFilter, whereClause) - offsetof(UA_EventFilter, selectClauses) - sizeof(void *), /* .padding */ |
| 16703 | false, /* .isArray */ |
| 16704 | false /* .isOptional */ |
| 16705 | },}; |
| 16706 | |
| 16707 | /* AggregateConfiguration */ |
| 16708 | static UA_DataTypeMember AggregateConfiguration_members[5] = { |
| 16709 | { |
| 16710 | UA_TYPENAME("UseServerCapabilitiesDefaults") /* .memberName */ |
| 16711 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 16712 | 0, /* .padding */ |
| 16713 | false, /* .isArray */ |
| 16714 | false /* .isOptional */ |
| 16715 | }, |
| 16716 | { |
| 16717 | UA_TYPENAME("TreatUncertainAsBad") /* .memberName */ |
| 16718 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 16719 | offsetof(UA_AggregateConfiguration, treatUncertainAsBad) - offsetof(UA_AggregateConfiguration, useServerCapabilitiesDefaults) - sizeof(UA_Boolean), /* .padding */ |
| 16720 | false, /* .isArray */ |
| 16721 | false /* .isOptional */ |
| 16722 | }, |
| 16723 | { |
| 16724 | UA_TYPENAME("PercentDataBad") /* .memberName */ |
| 16725 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 16726 | offsetof(UA_AggregateConfiguration, percentDataBad) - offsetof(UA_AggregateConfiguration, treatUncertainAsBad) - sizeof(UA_Boolean), /* .padding */ |
| 16727 | false, /* .isArray */ |
| 16728 | false /* .isOptional */ |
| 16729 | }, |
| 16730 | { |
| 16731 | UA_TYPENAME("PercentDataGood") /* .memberName */ |
| 16732 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 16733 | offsetof(UA_AggregateConfiguration, percentDataGood) - offsetof(UA_AggregateConfiguration, percentDataBad) - sizeof(UA_Byte), /* .padding */ |
| 16734 | false, /* .isArray */ |
| 16735 | false /* .isOptional */ |
| 16736 | }, |
| 16737 | { |
| 16738 | UA_TYPENAME("UseSlopedExtrapolation") /* .memberName */ |
| 16739 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 16740 | offsetof(UA_AggregateConfiguration, useSlopedExtrapolation) - offsetof(UA_AggregateConfiguration, percentDataGood) - sizeof(UA_Byte), /* .padding */ |
| 16741 | false, /* .isArray */ |
| 16742 | false /* .isOptional */ |
| 16743 | },}; |
| 16744 | |
| 16745 | /* AggregateFilter */ |
| 16746 | static UA_DataTypeMember AggregateFilter_members[4] = { |
| 16747 | { |
| 16748 | UA_TYPENAME("StartTime") /* .memberName */ |
| 16749 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 16750 | 0, /* .padding */ |
| 16751 | false, /* .isArray */ |
| 16752 | false /* .isOptional */ |
| 16753 | }, |
| 16754 | { |
| 16755 | UA_TYPENAME("AggregateType") /* .memberName */ |
| 16756 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 16757 | offsetof(UA_AggregateFilter, aggregateType) - offsetof(UA_AggregateFilter, startTime) - sizeof(UA_DateTime), /* .padding */ |
| 16758 | false, /* .isArray */ |
| 16759 | false /* .isOptional */ |
| 16760 | }, |
| 16761 | { |
| 16762 | UA_TYPENAME("ProcessingInterval") /* .memberName */ |
| 16763 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 16764 | offsetof(UA_AggregateFilter, processingInterval) - offsetof(UA_AggregateFilter, aggregateType) - sizeof(UA_NodeId), /* .padding */ |
| 16765 | false, /* .isArray */ |
| 16766 | false /* .isOptional */ |
| 16767 | }, |
| 16768 | { |
| 16769 | UA_TYPENAME("AggregateConfiguration") /* .memberName */ |
| 16770 | &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], /* .memberType */ |
| 16771 | offsetof(UA_AggregateFilter, aggregateConfiguration) - offsetof(UA_AggregateFilter, processingInterval) - sizeof(UA_Double), /* .padding */ |
| 16772 | false, /* .isArray */ |
| 16773 | false /* .isOptional */ |
| 16774 | },}; |
| 16775 | |
| 16776 | /* EventFilterResult */ |
| 16777 | static UA_DataTypeMember EventFilterResult_members[3] = { |
| 16778 | { |
| 16779 | UA_TYPENAME("SelectClauseResults") /* .memberName */ |
| 16780 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 16781 | 0, /* .padding */ |
| 16782 | true, /* .isArray */ |
| 16783 | false /* .isOptional */ |
| 16784 | }, |
| 16785 | { |
| 16786 | UA_TYPENAME("SelectClauseDiagnosticInfos") /* .memberName */ |
| 16787 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 16788 | offsetof(UA_EventFilterResult, selectClauseDiagnosticInfosSize) - offsetof(UA_EventFilterResult, selectClauseResults) - sizeof(void *), /* .padding */ |
| 16789 | true, /* .isArray */ |
| 16790 | false /* .isOptional */ |
| 16791 | }, |
| 16792 | { |
| 16793 | UA_TYPENAME("WhereClauseResult") /* .memberName */ |
| 16794 | &UA_TYPES[UA_TYPES_CONTENTFILTERRESULT], /* .memberType */ |
| 16795 | offsetof(UA_EventFilterResult, whereClauseResult) - offsetof(UA_EventFilterResult, selectClauseDiagnosticInfos) - sizeof(void *), /* .padding */ |
| 16796 | false, /* .isArray */ |
| 16797 | false /* .isOptional */ |
| 16798 | },}; |
| 16799 | |
| 16800 | /* AggregateFilterResult */ |
| 16801 | static UA_DataTypeMember AggregateFilterResult_members[3] = { |
| 16802 | { |
| 16803 | UA_TYPENAME("RevisedStartTime") /* .memberName */ |
| 16804 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 16805 | 0, /* .padding */ |
| 16806 | false, /* .isArray */ |
| 16807 | false /* .isOptional */ |
| 16808 | }, |
| 16809 | { |
| 16810 | UA_TYPENAME("RevisedProcessingInterval") /* .memberName */ |
| 16811 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 16812 | offsetof(UA_AggregateFilterResult, revisedProcessingInterval) - offsetof(UA_AggregateFilterResult, revisedStartTime) - sizeof(UA_DateTime), /* .padding */ |
| 16813 | false, /* .isArray */ |
| 16814 | false /* .isOptional */ |
| 16815 | }, |
| 16816 | { |
| 16817 | UA_TYPENAME("RevisedAggregateConfiguration") /* .memberName */ |
| 16818 | &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], /* .memberType */ |
| 16819 | offsetof(UA_AggregateFilterResult, revisedAggregateConfiguration) - offsetof(UA_AggregateFilterResult, revisedProcessingInterval) - sizeof(UA_Double), /* .padding */ |
| 16820 | false, /* .isArray */ |
| 16821 | false /* .isOptional */ |
| 16822 | },}; |
| 16823 | |
| 16824 | /* MonitoringParameters */ |
| 16825 | static UA_DataTypeMember MonitoringParameters_members[5] = { |
| 16826 | { |
| 16827 | UA_TYPENAME("ClientHandle") /* .memberName */ |
| 16828 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 16829 | 0, /* .padding */ |
| 16830 | false, /* .isArray */ |
| 16831 | false /* .isOptional */ |
| 16832 | }, |
| 16833 | { |
| 16834 | UA_TYPENAME("SamplingInterval") /* .memberName */ |
| 16835 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 16836 | offsetof(UA_MonitoringParameters, samplingInterval) - offsetof(UA_MonitoringParameters, clientHandle) - sizeof(UA_UInt32), /* .padding */ |
| 16837 | false, /* .isArray */ |
| 16838 | false /* .isOptional */ |
| 16839 | }, |
| 16840 | { |
| 16841 | UA_TYPENAME("Filter") /* .memberName */ |
| 16842 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 16843 | offsetof(UA_MonitoringParameters, filter) - offsetof(UA_MonitoringParameters, samplingInterval) - sizeof(UA_Double), /* .padding */ |
| 16844 | false, /* .isArray */ |
| 16845 | false /* .isOptional */ |
| 16846 | }, |
| 16847 | { |
| 16848 | UA_TYPENAME("QueueSize") /* .memberName */ |
| 16849 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 16850 | offsetof(UA_MonitoringParameters, queueSize) - offsetof(UA_MonitoringParameters, filter) - sizeof(UA_ExtensionObject), /* .padding */ |
| 16851 | false, /* .isArray */ |
| 16852 | false /* .isOptional */ |
| 16853 | }, |
| 16854 | { |
| 16855 | UA_TYPENAME("DiscardOldest") /* .memberName */ |
| 16856 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 16857 | offsetof(UA_MonitoringParameters, discardOldest) - offsetof(UA_MonitoringParameters, queueSize) - sizeof(UA_UInt32), /* .padding */ |
| 16858 | false, /* .isArray */ |
| 16859 | false /* .isOptional */ |
| 16860 | },}; |
| 16861 | |
| 16862 | /* MonitoredItemCreateRequest */ |
| 16863 | static UA_DataTypeMember MonitoredItemCreateRequest_members[3] = { |
| 16864 | { |
| 16865 | UA_TYPENAME("ItemToMonitor") /* .memberName */ |
| 16866 | &UA_TYPES[UA_TYPES_READVALUEID], /* .memberType */ |
| 16867 | 0, /* .padding */ |
| 16868 | false, /* .isArray */ |
| 16869 | false /* .isOptional */ |
| 16870 | }, |
| 16871 | { |
| 16872 | UA_TYPENAME("MonitoringMode") /* .memberName */ |
| 16873 | &UA_TYPES[UA_TYPES_MONITORINGMODE], /* .memberType */ |
| 16874 | offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - offsetof(UA_MonitoredItemCreateRequest, itemToMonitor) - sizeof(UA_ReadValueId), /* .padding */ |
| 16875 | false, /* .isArray */ |
| 16876 | false /* .isOptional */ |
| 16877 | }, |
| 16878 | { |
| 16879 | UA_TYPENAME("RequestedParameters") /* .memberName */ |
| 16880 | &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], /* .memberType */ |
| 16881 | offsetof(UA_MonitoredItemCreateRequest, requestedParameters) - offsetof(UA_MonitoredItemCreateRequest, monitoringMode) - sizeof(UA_MonitoringMode), /* .padding */ |
| 16882 | false, /* .isArray */ |
| 16883 | false /* .isOptional */ |
| 16884 | },}; |
| 16885 | |
| 16886 | /* MonitoredItemCreateResult */ |
| 16887 | static UA_DataTypeMember MonitoredItemCreateResult_members[5] = { |
| 16888 | { |
| 16889 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 16890 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 16891 | 0, /* .padding */ |
| 16892 | false, /* .isArray */ |
| 16893 | false /* .isOptional */ |
| 16894 | }, |
| 16895 | { |
| 16896 | UA_TYPENAME("MonitoredItemId") /* .memberName */ |
| 16897 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 16898 | offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - offsetof(UA_MonitoredItemCreateResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 16899 | false, /* .isArray */ |
| 16900 | false /* .isOptional */ |
| 16901 | }, |
| 16902 | { |
| 16903 | UA_TYPENAME("RevisedSamplingInterval") /* .memberName */ |
| 16904 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 16905 | offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemCreateResult, monitoredItemId) - sizeof(UA_UInt32), /* .padding */ |
| 16906 | false, /* .isArray */ |
| 16907 | false /* .isOptional */ |
| 16908 | }, |
| 16909 | { |
| 16910 | UA_TYPENAME("RevisedQueueSize") /* .memberName */ |
| 16911 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 16912 | offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - offsetof(UA_MonitoredItemCreateResult, revisedSamplingInterval) - sizeof(UA_Double), /* .padding */ |
| 16913 | false, /* .isArray */ |
| 16914 | false /* .isOptional */ |
| 16915 | }, |
| 16916 | { |
| 16917 | UA_TYPENAME("FilterResult") /* .memberName */ |
| 16918 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 16919 | offsetof(UA_MonitoredItemCreateResult, filterResult) - offsetof(UA_MonitoredItemCreateResult, revisedQueueSize) - sizeof(UA_UInt32), /* .padding */ |
| 16920 | false, /* .isArray */ |
| 16921 | false /* .isOptional */ |
| 16922 | },}; |
| 16923 | |
| 16924 | /* CreateMonitoredItemsRequest */ |
| 16925 | static UA_DataTypeMember CreateMonitoredItemsRequest_members[4] = { |
| 16926 | { |
| 16927 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 16928 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 16929 | 0, /* .padding */ |
| 16930 | false, /* .isArray */ |
| 16931 | false /* .isOptional */ |
| 16932 | }, |
| 16933 | { |
| 16934 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 16935 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 16936 | offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - offsetof(UA_CreateMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 16937 | false, /* .isArray */ |
| 16938 | false /* .isOptional */ |
| 16939 | }, |
| 16940 | { |
| 16941 | UA_TYPENAME("TimestampsToReturn") /* .memberName */ |
| 16942 | &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */ |
| 16943 | offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_CreateMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 16944 | false, /* .isArray */ |
| 16945 | false /* .isOptional */ |
| 16946 | }, |
| 16947 | { |
| 16948 | UA_TYPENAME("ItemsToCreate") /* .memberName */ |
| 16949 | &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST], /* .memberType */ |
| 16950 | offsetof(UA_CreateMonitoredItemsRequest, itemsToCreateSize) - offsetof(UA_CreateMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */ |
| 16951 | true, /* .isArray */ |
| 16952 | false /* .isOptional */ |
| 16953 | },}; |
| 16954 | |
| 16955 | /* CreateMonitoredItemsResponse */ |
| 16956 | static UA_DataTypeMember CreateMonitoredItemsResponse_members[3] = { |
| 16957 | { |
| 16958 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 16959 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 16960 | 0, /* .padding */ |
| 16961 | false, /* .isArray */ |
| 16962 | false /* .isOptional */ |
| 16963 | }, |
| 16964 | { |
| 16965 | UA_TYPENAME("Results") /* .memberName */ |
| 16966 | &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT], /* .memberType */ |
| 16967 | offsetof(UA_CreateMonitoredItemsResponse, resultsSize) - offsetof(UA_CreateMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 16968 | true, /* .isArray */ |
| 16969 | false /* .isOptional */ |
| 16970 | }, |
| 16971 | { |
| 16972 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 16973 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 16974 | offsetof(UA_CreateMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_CreateMonitoredItemsResponse, results) - sizeof(void *), /* .padding */ |
| 16975 | true, /* .isArray */ |
| 16976 | false /* .isOptional */ |
| 16977 | },}; |
| 16978 | |
| 16979 | /* MonitoredItemModifyRequest */ |
| 16980 | static UA_DataTypeMember MonitoredItemModifyRequest_members[2] = { |
| 16981 | { |
| 16982 | UA_TYPENAME("MonitoredItemId") /* .memberName */ |
| 16983 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 16984 | 0, /* .padding */ |
| 16985 | false, /* .isArray */ |
| 16986 | false /* .isOptional */ |
| 16987 | }, |
| 16988 | { |
| 16989 | UA_TYPENAME("RequestedParameters") /* .memberName */ |
| 16990 | &UA_TYPES[UA_TYPES_MONITORINGPARAMETERS], /* .memberType */ |
| 16991 | offsetof(UA_MonitoredItemModifyRequest, requestedParameters) - offsetof(UA_MonitoredItemModifyRequest, monitoredItemId) - sizeof(UA_UInt32), /* .padding */ |
| 16992 | false, /* .isArray */ |
| 16993 | false /* .isOptional */ |
| 16994 | },}; |
| 16995 | |
| 16996 | /* MonitoredItemModifyResult */ |
| 16997 | static UA_DataTypeMember MonitoredItemModifyResult_members[4] = { |
| 16998 | { |
| 16999 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 17000 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 17001 | 0, /* .padding */ |
| 17002 | false, /* .isArray */ |
| 17003 | false /* .isOptional */ |
| 17004 | }, |
| 17005 | { |
| 17006 | UA_TYPENAME("RevisedSamplingInterval") /* .memberName */ |
| 17007 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 17008 | offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - offsetof(UA_MonitoredItemModifyResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 17009 | false, /* .isArray */ |
| 17010 | false /* .isOptional */ |
| 17011 | }, |
| 17012 | { |
| 17013 | UA_TYPENAME("RevisedQueueSize") /* .memberName */ |
| 17014 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17015 | offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - offsetof(UA_MonitoredItemModifyResult, revisedSamplingInterval) - sizeof(UA_Double), /* .padding */ |
| 17016 | false, /* .isArray */ |
| 17017 | false /* .isOptional */ |
| 17018 | }, |
| 17019 | { |
| 17020 | UA_TYPENAME("FilterResult") /* .memberName */ |
| 17021 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 17022 | offsetof(UA_MonitoredItemModifyResult, filterResult) - offsetof(UA_MonitoredItemModifyResult, revisedQueueSize) - sizeof(UA_UInt32), /* .padding */ |
| 17023 | false, /* .isArray */ |
| 17024 | false /* .isOptional */ |
| 17025 | },}; |
| 17026 | |
| 17027 | /* ModifyMonitoredItemsRequest */ |
| 17028 | static UA_DataTypeMember ModifyMonitoredItemsRequest_members[4] = { |
| 17029 | { |
| 17030 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17031 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17032 | 0, /* .padding */ |
| 17033 | false, /* .isArray */ |
| 17034 | false /* .isOptional */ |
| 17035 | }, |
| 17036 | { |
| 17037 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 17038 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17039 | offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - offsetof(UA_ModifyMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17040 | false, /* .isArray */ |
| 17041 | false /* .isOptional */ |
| 17042 | }, |
| 17043 | { |
| 17044 | UA_TYPENAME("TimestampsToReturn") /* .memberName */ |
| 17045 | &UA_TYPES[UA_TYPES_TIMESTAMPSTORETURN], /* .memberType */ |
| 17046 | offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - offsetof(UA_ModifyMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 17047 | false, /* .isArray */ |
| 17048 | false /* .isOptional */ |
| 17049 | }, |
| 17050 | { |
| 17051 | UA_TYPENAME("ItemsToModify") /* .memberName */ |
| 17052 | &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST], /* .memberType */ |
| 17053 | offsetof(UA_ModifyMonitoredItemsRequest, itemsToModifySize) - offsetof(UA_ModifyMonitoredItemsRequest, timestampsToReturn) - sizeof(UA_TimestampsToReturn), /* .padding */ |
| 17054 | true, /* .isArray */ |
| 17055 | false /* .isOptional */ |
| 17056 | },}; |
| 17057 | |
| 17058 | /* ModifyMonitoredItemsResponse */ |
| 17059 | static UA_DataTypeMember ModifyMonitoredItemsResponse_members[3] = { |
| 17060 | { |
| 17061 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17062 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17063 | 0, /* .padding */ |
| 17064 | false, /* .isArray */ |
| 17065 | false /* .isOptional */ |
| 17066 | }, |
| 17067 | { |
| 17068 | UA_TYPENAME("Results") /* .memberName */ |
| 17069 | &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT], /* .memberType */ |
| 17070 | offsetof(UA_ModifyMonitoredItemsResponse, resultsSize) - offsetof(UA_ModifyMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17071 | true, /* .isArray */ |
| 17072 | false /* .isOptional */ |
| 17073 | }, |
| 17074 | { |
| 17075 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 17076 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 17077 | offsetof(UA_ModifyMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_ModifyMonitoredItemsResponse, results) - sizeof(void *), /* .padding */ |
| 17078 | true, /* .isArray */ |
| 17079 | false /* .isOptional */ |
| 17080 | },}; |
| 17081 | |
| 17082 | /* SetMonitoringModeRequest */ |
| 17083 | static UA_DataTypeMember SetMonitoringModeRequest_members[4] = { |
| 17084 | { |
| 17085 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17086 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17087 | 0, /* .padding */ |
| 17088 | false, /* .isArray */ |
| 17089 | false /* .isOptional */ |
| 17090 | }, |
| 17091 | { |
| 17092 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 17093 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17094 | offsetof(UA_SetMonitoringModeRequest, subscriptionId) - offsetof(UA_SetMonitoringModeRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17095 | false, /* .isArray */ |
| 17096 | false /* .isOptional */ |
| 17097 | }, |
| 17098 | { |
| 17099 | UA_TYPENAME("MonitoringMode") /* .memberName */ |
| 17100 | &UA_TYPES[UA_TYPES_MONITORINGMODE], /* .memberType */ |
| 17101 | offsetof(UA_SetMonitoringModeRequest, monitoringMode) - offsetof(UA_SetMonitoringModeRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 17102 | false, /* .isArray */ |
| 17103 | false /* .isOptional */ |
| 17104 | }, |
| 17105 | { |
| 17106 | UA_TYPENAME("MonitoredItemIds") /* .memberName */ |
| 17107 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17108 | offsetof(UA_SetMonitoringModeRequest, monitoredItemIdsSize) - offsetof(UA_SetMonitoringModeRequest, monitoringMode) - sizeof(UA_MonitoringMode), /* .padding */ |
| 17109 | true, /* .isArray */ |
| 17110 | false /* .isOptional */ |
| 17111 | },}; |
| 17112 | |
| 17113 | /* SetMonitoringModeResponse */ |
| 17114 | static UA_DataTypeMember SetMonitoringModeResponse_members[3] = { |
| 17115 | { |
| 17116 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17117 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17118 | 0, /* .padding */ |
| 17119 | false, /* .isArray */ |
| 17120 | false /* .isOptional */ |
| 17121 | }, |
| 17122 | { |
| 17123 | UA_TYPENAME("Results") /* .memberName */ |
| 17124 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 17125 | offsetof(UA_SetMonitoringModeResponse, resultsSize) - offsetof(UA_SetMonitoringModeResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17126 | true, /* .isArray */ |
| 17127 | false /* .isOptional */ |
| 17128 | }, |
| 17129 | { |
| 17130 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 17131 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 17132 | offsetof(UA_SetMonitoringModeResponse, diagnosticInfosSize) - offsetof(UA_SetMonitoringModeResponse, results) - sizeof(void *), /* .padding */ |
| 17133 | true, /* .isArray */ |
| 17134 | false /* .isOptional */ |
| 17135 | },}; |
| 17136 | |
| 17137 | /* SetTriggeringRequest */ |
| 17138 | static UA_DataTypeMember SetTriggeringRequest_members[5] = { |
| 17139 | { |
| 17140 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17141 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17142 | 0, /* .padding */ |
| 17143 | false, /* .isArray */ |
| 17144 | false /* .isOptional */ |
| 17145 | }, |
| 17146 | { |
| 17147 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 17148 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17149 | offsetof(UA_SetTriggeringRequest, subscriptionId) - offsetof(UA_SetTriggeringRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17150 | false, /* .isArray */ |
| 17151 | false /* .isOptional */ |
| 17152 | }, |
| 17153 | { |
| 17154 | UA_TYPENAME("TriggeringItemId") /* .memberName */ |
| 17155 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17156 | offsetof(UA_SetTriggeringRequest, triggeringItemId) - offsetof(UA_SetTriggeringRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 17157 | false, /* .isArray */ |
| 17158 | false /* .isOptional */ |
| 17159 | }, |
| 17160 | { |
| 17161 | UA_TYPENAME("LinksToAdd") /* .memberName */ |
| 17162 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17163 | offsetof(UA_SetTriggeringRequest, linksToAddSize) - offsetof(UA_SetTriggeringRequest, triggeringItemId) - sizeof(UA_UInt32), /* .padding */ |
| 17164 | true, /* .isArray */ |
| 17165 | false /* .isOptional */ |
| 17166 | }, |
| 17167 | { |
| 17168 | UA_TYPENAME("LinksToRemove") /* .memberName */ |
| 17169 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17170 | offsetof(UA_SetTriggeringRequest, linksToRemoveSize) - offsetof(UA_SetTriggeringRequest, linksToAdd) - sizeof(void *), /* .padding */ |
| 17171 | true, /* .isArray */ |
| 17172 | false /* .isOptional */ |
| 17173 | },}; |
| 17174 | |
| 17175 | /* SetTriggeringResponse */ |
| 17176 | static UA_DataTypeMember SetTriggeringResponse_members[5] = { |
| 17177 | { |
| 17178 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17179 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17180 | 0, /* .padding */ |
| 17181 | false, /* .isArray */ |
| 17182 | false /* .isOptional */ |
| 17183 | }, |
| 17184 | { |
| 17185 | UA_TYPENAME("AddResults") /* .memberName */ |
| 17186 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 17187 | offsetof(UA_SetTriggeringResponse, addResultsSize) - offsetof(UA_SetTriggeringResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17188 | true, /* .isArray */ |
| 17189 | false /* .isOptional */ |
| 17190 | }, |
| 17191 | { |
| 17192 | UA_TYPENAME("AddDiagnosticInfos") /* .memberName */ |
| 17193 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 17194 | offsetof(UA_SetTriggeringResponse, addDiagnosticInfosSize) - offsetof(UA_SetTriggeringResponse, addResults) - sizeof(void *), /* .padding */ |
| 17195 | true, /* .isArray */ |
| 17196 | false /* .isOptional */ |
| 17197 | }, |
| 17198 | { |
| 17199 | UA_TYPENAME("RemoveResults") /* .memberName */ |
| 17200 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 17201 | offsetof(UA_SetTriggeringResponse, removeResultsSize) - offsetof(UA_SetTriggeringResponse, addDiagnosticInfos) - sizeof(void *), /* .padding */ |
| 17202 | true, /* .isArray */ |
| 17203 | false /* .isOptional */ |
| 17204 | }, |
| 17205 | { |
| 17206 | UA_TYPENAME("RemoveDiagnosticInfos") /* .memberName */ |
| 17207 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 17208 | offsetof(UA_SetTriggeringResponse, removeDiagnosticInfosSize) - offsetof(UA_SetTriggeringResponse, removeResults) - sizeof(void *), /* .padding */ |
| 17209 | true, /* .isArray */ |
| 17210 | false /* .isOptional */ |
| 17211 | },}; |
| 17212 | |
| 17213 | /* DeleteMonitoredItemsRequest */ |
| 17214 | static UA_DataTypeMember DeleteMonitoredItemsRequest_members[3] = { |
| 17215 | { |
| 17216 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17217 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17218 | 0, /* .padding */ |
| 17219 | false, /* .isArray */ |
| 17220 | false /* .isOptional */ |
| 17221 | }, |
| 17222 | { |
| 17223 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 17224 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17225 | offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - offsetof(UA_DeleteMonitoredItemsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17226 | false, /* .isArray */ |
| 17227 | false /* .isOptional */ |
| 17228 | }, |
| 17229 | { |
| 17230 | UA_TYPENAME("MonitoredItemIds") /* .memberName */ |
| 17231 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17232 | offsetof(UA_DeleteMonitoredItemsRequest, monitoredItemIdsSize) - offsetof(UA_DeleteMonitoredItemsRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 17233 | true, /* .isArray */ |
| 17234 | false /* .isOptional */ |
| 17235 | },}; |
| 17236 | |
| 17237 | /* DeleteMonitoredItemsResponse */ |
| 17238 | static UA_DataTypeMember DeleteMonitoredItemsResponse_members[3] = { |
| 17239 | { |
| 17240 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17241 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17242 | 0, /* .padding */ |
| 17243 | false, /* .isArray */ |
| 17244 | false /* .isOptional */ |
| 17245 | }, |
| 17246 | { |
| 17247 | UA_TYPENAME("Results") /* .memberName */ |
| 17248 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 17249 | offsetof(UA_DeleteMonitoredItemsResponse, resultsSize) - offsetof(UA_DeleteMonitoredItemsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17250 | true, /* .isArray */ |
| 17251 | false /* .isOptional */ |
| 17252 | }, |
| 17253 | { |
| 17254 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 17255 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 17256 | offsetof(UA_DeleteMonitoredItemsResponse, diagnosticInfosSize) - offsetof(UA_DeleteMonitoredItemsResponse, results) - sizeof(void *), /* .padding */ |
| 17257 | true, /* .isArray */ |
| 17258 | false /* .isOptional */ |
| 17259 | },}; |
| 17260 | |
| 17261 | /* CreateSubscriptionRequest */ |
| 17262 | static UA_DataTypeMember CreateSubscriptionRequest_members[7] = { |
| 17263 | { |
| 17264 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17265 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17266 | 0, /* .padding */ |
| 17267 | false, /* .isArray */ |
| 17268 | false /* .isOptional */ |
| 17269 | }, |
| 17270 | { |
| 17271 | UA_TYPENAME("RequestedPublishingInterval") /* .memberName */ |
| 17272 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 17273 | offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - offsetof(UA_CreateSubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17274 | false, /* .isArray */ |
| 17275 | false /* .isOptional */ |
| 17276 | }, |
| 17277 | { |
| 17278 | UA_TYPENAME("RequestedLifetimeCount") /* .memberName */ |
| 17279 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17280 | offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - offsetof(UA_CreateSubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double), /* .padding */ |
| 17281 | false, /* .isArray */ |
| 17282 | false /* .isOptional */ |
| 17283 | }, |
| 17284 | { |
| 17285 | UA_TYPENAME("RequestedMaxKeepAliveCount") /* .memberName */ |
| 17286 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17287 | offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32), /* .padding */ |
| 17288 | false, /* .isArray */ |
| 17289 | false /* .isOptional */ |
| 17290 | }, |
| 17291 | { |
| 17292 | UA_TYPENAME("MaxNotificationsPerPublish") /* .memberName */ |
| 17293 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17294 | offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_CreateSubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */ |
| 17295 | false, /* .isArray */ |
| 17296 | false /* .isOptional */ |
| 17297 | }, |
| 17298 | { |
| 17299 | UA_TYPENAME("PublishingEnabled") /* .memberName */ |
| 17300 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 17301 | offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - offsetof(UA_CreateSubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */ |
| 17302 | false, /* .isArray */ |
| 17303 | false /* .isOptional */ |
| 17304 | }, |
| 17305 | { |
| 17306 | UA_TYPENAME("Priority") /* .memberName */ |
| 17307 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 17308 | offsetof(UA_CreateSubscriptionRequest, priority) - offsetof(UA_CreateSubscriptionRequest, publishingEnabled) - sizeof(UA_Boolean), /* .padding */ |
| 17309 | false, /* .isArray */ |
| 17310 | false /* .isOptional */ |
| 17311 | },}; |
| 17312 | |
| 17313 | /* CreateSubscriptionResponse */ |
| 17314 | static UA_DataTypeMember CreateSubscriptionResponse_members[5] = { |
| 17315 | { |
| 17316 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17317 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17318 | 0, /* .padding */ |
| 17319 | false, /* .isArray */ |
| 17320 | false /* .isOptional */ |
| 17321 | }, |
| 17322 | { |
| 17323 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 17324 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17325 | offsetof(UA_CreateSubscriptionResponse, subscriptionId) - offsetof(UA_CreateSubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17326 | false, /* .isArray */ |
| 17327 | false /* .isOptional */ |
| 17328 | }, |
| 17329 | { |
| 17330 | UA_TYPENAME("RevisedPublishingInterval") /* .memberName */ |
| 17331 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 17332 | offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - offsetof(UA_CreateSubscriptionResponse, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 17333 | false, /* .isArray */ |
| 17334 | false /* .isOptional */ |
| 17335 | }, |
| 17336 | { |
| 17337 | UA_TYPENAME("RevisedLifetimeCount") /* .memberName */ |
| 17338 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17339 | offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - offsetof(UA_CreateSubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double), /* .padding */ |
| 17340 | false, /* .isArray */ |
| 17341 | false /* .isOptional */ |
| 17342 | }, |
| 17343 | { |
| 17344 | UA_TYPENAME("RevisedMaxKeepAliveCount") /* .memberName */ |
| 17345 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17346 | offsetof(UA_CreateSubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_CreateSubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32), /* .padding */ |
| 17347 | false, /* .isArray */ |
| 17348 | false /* .isOptional */ |
| 17349 | },}; |
| 17350 | |
| 17351 | /* ModifySubscriptionRequest */ |
| 17352 | static UA_DataTypeMember ModifySubscriptionRequest_members[7] = { |
| 17353 | { |
| 17354 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17355 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17356 | 0, /* .padding */ |
| 17357 | false, /* .isArray */ |
| 17358 | false /* .isOptional */ |
| 17359 | }, |
| 17360 | { |
| 17361 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 17362 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17363 | offsetof(UA_ModifySubscriptionRequest, subscriptionId) - offsetof(UA_ModifySubscriptionRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17364 | false, /* .isArray */ |
| 17365 | false /* .isOptional */ |
| 17366 | }, |
| 17367 | { |
| 17368 | UA_TYPENAME("RequestedPublishingInterval") /* .memberName */ |
| 17369 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 17370 | offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - offsetof(UA_ModifySubscriptionRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 17371 | false, /* .isArray */ |
| 17372 | false /* .isOptional */ |
| 17373 | }, |
| 17374 | { |
| 17375 | UA_TYPENAME("RequestedLifetimeCount") /* .memberName */ |
| 17376 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17377 | offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - offsetof(UA_ModifySubscriptionRequest, requestedPublishingInterval) - sizeof(UA_Double), /* .padding */ |
| 17378 | false, /* .isArray */ |
| 17379 | false /* .isOptional */ |
| 17380 | }, |
| 17381 | { |
| 17382 | UA_TYPENAME("RequestedMaxKeepAliveCount") /* .memberName */ |
| 17383 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17384 | offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionRequest, requestedLifetimeCount) - sizeof(UA_UInt32), /* .padding */ |
| 17385 | false, /* .isArray */ |
| 17386 | false /* .isOptional */ |
| 17387 | }, |
| 17388 | { |
| 17389 | UA_TYPENAME("MaxNotificationsPerPublish") /* .memberName */ |
| 17390 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17391 | offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - offsetof(UA_ModifySubscriptionRequest, requestedMaxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */ |
| 17392 | false, /* .isArray */ |
| 17393 | false /* .isOptional */ |
| 17394 | }, |
| 17395 | { |
| 17396 | UA_TYPENAME("Priority") /* .memberName */ |
| 17397 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 17398 | offsetof(UA_ModifySubscriptionRequest, priority) - offsetof(UA_ModifySubscriptionRequest, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */ |
| 17399 | false, /* .isArray */ |
| 17400 | false /* .isOptional */ |
| 17401 | },}; |
| 17402 | |
| 17403 | /* ModifySubscriptionResponse */ |
| 17404 | static UA_DataTypeMember ModifySubscriptionResponse_members[4] = { |
| 17405 | { |
| 17406 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17407 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17408 | 0, /* .padding */ |
| 17409 | false, /* .isArray */ |
| 17410 | false /* .isOptional */ |
| 17411 | }, |
| 17412 | { |
| 17413 | UA_TYPENAME("RevisedPublishingInterval") /* .memberName */ |
| 17414 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 17415 | offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - offsetof(UA_ModifySubscriptionResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17416 | false, /* .isArray */ |
| 17417 | false /* .isOptional */ |
| 17418 | }, |
| 17419 | { |
| 17420 | UA_TYPENAME("RevisedLifetimeCount") /* .memberName */ |
| 17421 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17422 | offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - offsetof(UA_ModifySubscriptionResponse, revisedPublishingInterval) - sizeof(UA_Double), /* .padding */ |
| 17423 | false, /* .isArray */ |
| 17424 | false /* .isOptional */ |
| 17425 | }, |
| 17426 | { |
| 17427 | UA_TYPENAME("RevisedMaxKeepAliveCount") /* .memberName */ |
| 17428 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17429 | offsetof(UA_ModifySubscriptionResponse, revisedMaxKeepAliveCount) - offsetof(UA_ModifySubscriptionResponse, revisedLifetimeCount) - sizeof(UA_UInt32), /* .padding */ |
| 17430 | false, /* .isArray */ |
| 17431 | false /* .isOptional */ |
| 17432 | },}; |
| 17433 | |
| 17434 | /* SetPublishingModeRequest */ |
| 17435 | static UA_DataTypeMember SetPublishingModeRequest_members[3] = { |
| 17436 | { |
| 17437 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17438 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17439 | 0, /* .padding */ |
| 17440 | false, /* .isArray */ |
| 17441 | false /* .isOptional */ |
| 17442 | }, |
| 17443 | { |
| 17444 | UA_TYPENAME("PublishingEnabled") /* .memberName */ |
| 17445 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 17446 | offsetof(UA_SetPublishingModeRequest, publishingEnabled) - offsetof(UA_SetPublishingModeRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17447 | false, /* .isArray */ |
| 17448 | false /* .isOptional */ |
| 17449 | }, |
| 17450 | { |
| 17451 | UA_TYPENAME("SubscriptionIds") /* .memberName */ |
| 17452 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17453 | offsetof(UA_SetPublishingModeRequest, subscriptionIdsSize) - offsetof(UA_SetPublishingModeRequest, publishingEnabled) - sizeof(UA_Boolean), /* .padding */ |
| 17454 | true, /* .isArray */ |
| 17455 | false /* .isOptional */ |
| 17456 | },}; |
| 17457 | |
| 17458 | /* SetPublishingModeResponse */ |
| 17459 | static UA_DataTypeMember SetPublishingModeResponse_members[3] = { |
| 17460 | { |
| 17461 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17462 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17463 | 0, /* .padding */ |
| 17464 | false, /* .isArray */ |
| 17465 | false /* .isOptional */ |
| 17466 | }, |
| 17467 | { |
| 17468 | UA_TYPENAME("Results") /* .memberName */ |
| 17469 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 17470 | offsetof(UA_SetPublishingModeResponse, resultsSize) - offsetof(UA_SetPublishingModeResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17471 | true, /* .isArray */ |
| 17472 | false /* .isOptional */ |
| 17473 | }, |
| 17474 | { |
| 17475 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 17476 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 17477 | offsetof(UA_SetPublishingModeResponse, diagnosticInfosSize) - offsetof(UA_SetPublishingModeResponse, results) - sizeof(void *), /* .padding */ |
| 17478 | true, /* .isArray */ |
| 17479 | false /* .isOptional */ |
| 17480 | },}; |
| 17481 | |
| 17482 | /* NotificationMessage */ |
| 17483 | static UA_DataTypeMember NotificationMessage_members[3] = { |
| 17484 | { |
| 17485 | UA_TYPENAME("SequenceNumber") /* .memberName */ |
| 17486 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17487 | 0, /* .padding */ |
| 17488 | false, /* .isArray */ |
| 17489 | false /* .isOptional */ |
| 17490 | }, |
| 17491 | { |
| 17492 | UA_TYPENAME("PublishTime") /* .memberName */ |
| 17493 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 17494 | offsetof(UA_NotificationMessage, publishTime) - offsetof(UA_NotificationMessage, sequenceNumber) - sizeof(UA_UInt32), /* .padding */ |
| 17495 | false, /* .isArray */ |
| 17496 | false /* .isOptional */ |
| 17497 | }, |
| 17498 | { |
| 17499 | UA_TYPENAME("NotificationData") /* .memberName */ |
| 17500 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 17501 | offsetof(UA_NotificationMessage, notificationDataSize) - offsetof(UA_NotificationMessage, publishTime) - sizeof(UA_DateTime), /* .padding */ |
| 17502 | true, /* .isArray */ |
| 17503 | false /* .isOptional */ |
| 17504 | },}; |
| 17505 | |
| 17506 | /* MonitoredItemNotification */ |
| 17507 | static UA_DataTypeMember MonitoredItemNotification_members[2] = { |
| 17508 | { |
| 17509 | UA_TYPENAME("ClientHandle") /* .memberName */ |
| 17510 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17511 | 0, /* .padding */ |
| 17512 | false, /* .isArray */ |
| 17513 | false /* .isOptional */ |
| 17514 | }, |
| 17515 | { |
| 17516 | UA_TYPENAME("Value") /* .memberName */ |
| 17517 | &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */ |
| 17518 | offsetof(UA_MonitoredItemNotification, value) - offsetof(UA_MonitoredItemNotification, clientHandle) - sizeof(UA_UInt32), /* .padding */ |
| 17519 | false, /* .isArray */ |
| 17520 | false /* .isOptional */ |
| 17521 | },}; |
| 17522 | |
| 17523 | /* EventFieldList */ |
| 17524 | static UA_DataTypeMember EventFieldList_members[2] = { |
| 17525 | { |
| 17526 | UA_TYPENAME("ClientHandle") /* .memberName */ |
| 17527 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17528 | 0, /* .padding */ |
| 17529 | false, /* .isArray */ |
| 17530 | false /* .isOptional */ |
| 17531 | }, |
| 17532 | { |
| 17533 | UA_TYPENAME("EventFields") /* .memberName */ |
| 17534 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 17535 | offsetof(UA_EventFieldList, eventFieldsSize) - offsetof(UA_EventFieldList, clientHandle) - sizeof(UA_UInt32), /* .padding */ |
| 17536 | true, /* .isArray */ |
| 17537 | false /* .isOptional */ |
| 17538 | },}; |
| 17539 | |
| 17540 | /* HistoryEventFieldList */ |
| 17541 | static UA_DataTypeMember HistoryEventFieldList_members[1] = { |
| 17542 | { |
| 17543 | UA_TYPENAME("EventFields") /* .memberName */ |
| 17544 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 17545 | 0, /* .padding */ |
| 17546 | true, /* .isArray */ |
| 17547 | false /* .isOptional */ |
| 17548 | },}; |
| 17549 | |
| 17550 | /* StatusChangeNotification */ |
| 17551 | static UA_DataTypeMember StatusChangeNotification_members[2] = { |
| 17552 | { |
| 17553 | UA_TYPENAME("Status") /* .memberName */ |
| 17554 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 17555 | 0, /* .padding */ |
| 17556 | false, /* .isArray */ |
| 17557 | false /* .isOptional */ |
| 17558 | }, |
| 17559 | { |
| 17560 | UA_TYPENAME("DiagnosticInfo") /* .memberName */ |
| 17561 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 17562 | offsetof(UA_StatusChangeNotification, diagnosticInfo) - offsetof(UA_StatusChangeNotification, status) - sizeof(UA_StatusCode), /* .padding */ |
| 17563 | false, /* .isArray */ |
| 17564 | false /* .isOptional */ |
| 17565 | },}; |
| 17566 | |
| 17567 | /* SubscriptionAcknowledgement */ |
| 17568 | static UA_DataTypeMember SubscriptionAcknowledgement_members[2] = { |
| 17569 | { |
| 17570 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 17571 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17572 | 0, /* .padding */ |
| 17573 | false, /* .isArray */ |
| 17574 | false /* .isOptional */ |
| 17575 | }, |
| 17576 | { |
| 17577 | UA_TYPENAME("SequenceNumber") /* .memberName */ |
| 17578 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17579 | offsetof(UA_SubscriptionAcknowledgement, sequenceNumber) - offsetof(UA_SubscriptionAcknowledgement, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 17580 | false, /* .isArray */ |
| 17581 | false /* .isOptional */ |
| 17582 | },}; |
| 17583 | |
| 17584 | /* PublishRequest */ |
| 17585 | static UA_DataTypeMember PublishRequest_members[2] = { |
| 17586 | { |
| 17587 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17588 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17589 | 0, /* .padding */ |
| 17590 | false, /* .isArray */ |
| 17591 | false /* .isOptional */ |
| 17592 | }, |
| 17593 | { |
| 17594 | UA_TYPENAME("SubscriptionAcknowledgements") /* .memberName */ |
| 17595 | &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT], /* .memberType */ |
| 17596 | offsetof(UA_PublishRequest, subscriptionAcknowledgementsSize) - offsetof(UA_PublishRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17597 | true, /* .isArray */ |
| 17598 | false /* .isOptional */ |
| 17599 | },}; |
| 17600 | |
| 17601 | /* PublishResponse */ |
| 17602 | static UA_DataTypeMember PublishResponse_members[7] = { |
| 17603 | { |
| 17604 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17605 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17606 | 0, /* .padding */ |
| 17607 | false, /* .isArray */ |
| 17608 | false /* .isOptional */ |
| 17609 | }, |
| 17610 | { |
| 17611 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 17612 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17613 | offsetof(UA_PublishResponse, subscriptionId) - offsetof(UA_PublishResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17614 | false, /* .isArray */ |
| 17615 | false /* .isOptional */ |
| 17616 | }, |
| 17617 | { |
| 17618 | UA_TYPENAME("AvailableSequenceNumbers") /* .memberName */ |
| 17619 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17620 | offsetof(UA_PublishResponse, availableSequenceNumbersSize) - offsetof(UA_PublishResponse, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 17621 | true, /* .isArray */ |
| 17622 | false /* .isOptional */ |
| 17623 | }, |
| 17624 | { |
| 17625 | UA_TYPENAME("MoreNotifications") /* .memberName */ |
| 17626 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 17627 | offsetof(UA_PublishResponse, moreNotifications) - offsetof(UA_PublishResponse, availableSequenceNumbers) - sizeof(void *), /* .padding */ |
| 17628 | false, /* .isArray */ |
| 17629 | false /* .isOptional */ |
| 17630 | }, |
| 17631 | { |
| 17632 | UA_TYPENAME("NotificationMessage") /* .memberName */ |
| 17633 | &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], /* .memberType */ |
| 17634 | offsetof(UA_PublishResponse, notificationMessage) - offsetof(UA_PublishResponse, moreNotifications) - sizeof(UA_Boolean), /* .padding */ |
| 17635 | false, /* .isArray */ |
| 17636 | false /* .isOptional */ |
| 17637 | }, |
| 17638 | { |
| 17639 | UA_TYPENAME("Results") /* .memberName */ |
| 17640 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 17641 | offsetof(UA_PublishResponse, resultsSize) - offsetof(UA_PublishResponse, notificationMessage) - sizeof(UA_NotificationMessage), /* .padding */ |
| 17642 | true, /* .isArray */ |
| 17643 | false /* .isOptional */ |
| 17644 | }, |
| 17645 | { |
| 17646 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 17647 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 17648 | offsetof(UA_PublishResponse, diagnosticInfosSize) - offsetof(UA_PublishResponse, results) - sizeof(void *), /* .padding */ |
| 17649 | true, /* .isArray */ |
| 17650 | false /* .isOptional */ |
| 17651 | },}; |
| 17652 | |
| 17653 | /* RepublishRequest */ |
| 17654 | static UA_DataTypeMember RepublishRequest_members[3] = { |
| 17655 | { |
| 17656 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17657 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17658 | 0, /* .padding */ |
| 17659 | false, /* .isArray */ |
| 17660 | false /* .isOptional */ |
| 17661 | }, |
| 17662 | { |
| 17663 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 17664 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17665 | offsetof(UA_RepublishRequest, subscriptionId) - offsetof(UA_RepublishRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17666 | false, /* .isArray */ |
| 17667 | false /* .isOptional */ |
| 17668 | }, |
| 17669 | { |
| 17670 | UA_TYPENAME("RetransmitSequenceNumber") /* .memberName */ |
| 17671 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17672 | offsetof(UA_RepublishRequest, retransmitSequenceNumber) - offsetof(UA_RepublishRequest, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 17673 | false, /* .isArray */ |
| 17674 | false /* .isOptional */ |
| 17675 | },}; |
| 17676 | |
| 17677 | /* RepublishResponse */ |
| 17678 | static UA_DataTypeMember RepublishResponse_members[2] = { |
| 17679 | { |
| 17680 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17681 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17682 | 0, /* .padding */ |
| 17683 | false, /* .isArray */ |
| 17684 | false /* .isOptional */ |
| 17685 | }, |
| 17686 | { |
| 17687 | UA_TYPENAME("NotificationMessage") /* .memberName */ |
| 17688 | &UA_TYPES[UA_TYPES_NOTIFICATIONMESSAGE], /* .memberType */ |
| 17689 | offsetof(UA_RepublishResponse, notificationMessage) - offsetof(UA_RepublishResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17690 | false, /* .isArray */ |
| 17691 | false /* .isOptional */ |
| 17692 | },}; |
| 17693 | |
| 17694 | /* TransferResult */ |
| 17695 | static UA_DataTypeMember TransferResult_members[2] = { |
| 17696 | { |
| 17697 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 17698 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 17699 | 0, /* .padding */ |
| 17700 | false, /* .isArray */ |
| 17701 | false /* .isOptional */ |
| 17702 | }, |
| 17703 | { |
| 17704 | UA_TYPENAME("AvailableSequenceNumbers") /* .memberName */ |
| 17705 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17706 | offsetof(UA_TransferResult, availableSequenceNumbersSize) - offsetof(UA_TransferResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 17707 | true, /* .isArray */ |
| 17708 | false /* .isOptional */ |
| 17709 | },}; |
| 17710 | |
| 17711 | /* TransferSubscriptionsRequest */ |
| 17712 | static UA_DataTypeMember TransferSubscriptionsRequest_members[3] = { |
| 17713 | { |
| 17714 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17715 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17716 | 0, /* .padding */ |
| 17717 | false, /* .isArray */ |
| 17718 | false /* .isOptional */ |
| 17719 | }, |
| 17720 | { |
| 17721 | UA_TYPENAME("SubscriptionIds") /* .memberName */ |
| 17722 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17723 | offsetof(UA_TransferSubscriptionsRequest, subscriptionIdsSize) - offsetof(UA_TransferSubscriptionsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17724 | true, /* .isArray */ |
| 17725 | false /* .isOptional */ |
| 17726 | }, |
| 17727 | { |
| 17728 | UA_TYPENAME("SendInitialValues") /* .memberName */ |
| 17729 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 17730 | offsetof(UA_TransferSubscriptionsRequest, sendInitialValues) - offsetof(UA_TransferSubscriptionsRequest, subscriptionIds) - sizeof(void *), /* .padding */ |
| 17731 | false, /* .isArray */ |
| 17732 | false /* .isOptional */ |
| 17733 | },}; |
| 17734 | |
| 17735 | /* TransferSubscriptionsResponse */ |
| 17736 | static UA_DataTypeMember TransferSubscriptionsResponse_members[3] = { |
| 17737 | { |
| 17738 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17739 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17740 | 0, /* .padding */ |
| 17741 | false, /* .isArray */ |
| 17742 | false /* .isOptional */ |
| 17743 | }, |
| 17744 | { |
| 17745 | UA_TYPENAME("Results") /* .memberName */ |
| 17746 | &UA_TYPES[UA_TYPES_TRANSFERRESULT], /* .memberType */ |
| 17747 | offsetof(UA_TransferSubscriptionsResponse, resultsSize) - offsetof(UA_TransferSubscriptionsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17748 | true, /* .isArray */ |
| 17749 | false /* .isOptional */ |
| 17750 | }, |
| 17751 | { |
| 17752 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 17753 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 17754 | offsetof(UA_TransferSubscriptionsResponse, diagnosticInfosSize) - offsetof(UA_TransferSubscriptionsResponse, results) - sizeof(void *), /* .padding */ |
| 17755 | true, /* .isArray */ |
| 17756 | false /* .isOptional */ |
| 17757 | },}; |
| 17758 | |
| 17759 | /* DeleteSubscriptionsRequest */ |
| 17760 | static UA_DataTypeMember DeleteSubscriptionsRequest_members[2] = { |
| 17761 | { |
| 17762 | UA_TYPENAME("RequestHeader") /* .memberName */ |
| 17763 | &UA_TYPES[UA_TYPES_REQUESTHEADER], /* .memberType */ |
| 17764 | 0, /* .padding */ |
| 17765 | false, /* .isArray */ |
| 17766 | false /* .isOptional */ |
| 17767 | }, |
| 17768 | { |
| 17769 | UA_TYPENAME("SubscriptionIds") /* .memberName */ |
| 17770 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17771 | offsetof(UA_DeleteSubscriptionsRequest, subscriptionIdsSize) - offsetof(UA_DeleteSubscriptionsRequest, requestHeader) - sizeof(UA_RequestHeader), /* .padding */ |
| 17772 | true, /* .isArray */ |
| 17773 | false /* .isOptional */ |
| 17774 | },}; |
| 17775 | |
| 17776 | /* DeleteSubscriptionsResponse */ |
| 17777 | static UA_DataTypeMember DeleteSubscriptionsResponse_members[3] = { |
| 17778 | { |
| 17779 | UA_TYPENAME("ResponseHeader") /* .memberName */ |
| 17780 | &UA_TYPES[UA_TYPES_RESPONSEHEADER], /* .memberType */ |
| 17781 | 0, /* .padding */ |
| 17782 | false, /* .isArray */ |
| 17783 | false /* .isOptional */ |
| 17784 | }, |
| 17785 | { |
| 17786 | UA_TYPENAME("Results") /* .memberName */ |
| 17787 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 17788 | offsetof(UA_DeleteSubscriptionsResponse, resultsSize) - offsetof(UA_DeleteSubscriptionsResponse, responseHeader) - sizeof(UA_ResponseHeader), /* .padding */ |
| 17789 | true, /* .isArray */ |
| 17790 | false /* .isOptional */ |
| 17791 | }, |
| 17792 | { |
| 17793 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 17794 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 17795 | offsetof(UA_DeleteSubscriptionsResponse, diagnosticInfosSize) - offsetof(UA_DeleteSubscriptionsResponse, results) - sizeof(void *), /* .padding */ |
| 17796 | true, /* .isArray */ |
| 17797 | false /* .isOptional */ |
| 17798 | },}; |
| 17799 | |
| 17800 | /* BuildInfo */ |
| 17801 | static UA_DataTypeMember BuildInfo_members[6] = { |
| 17802 | { |
| 17803 | UA_TYPENAME("ProductUri") /* .memberName */ |
| 17804 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 17805 | 0, /* .padding */ |
| 17806 | false, /* .isArray */ |
| 17807 | false /* .isOptional */ |
| 17808 | }, |
| 17809 | { |
| 17810 | UA_TYPENAME("ManufacturerName") /* .memberName */ |
| 17811 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 17812 | offsetof(UA_BuildInfo, manufacturerName) - offsetof(UA_BuildInfo, productUri) - sizeof(UA_String), /* .padding */ |
| 17813 | false, /* .isArray */ |
| 17814 | false /* .isOptional */ |
| 17815 | }, |
| 17816 | { |
| 17817 | UA_TYPENAME("ProductName") /* .memberName */ |
| 17818 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 17819 | offsetof(UA_BuildInfo, productName) - offsetof(UA_BuildInfo, manufacturerName) - sizeof(UA_String), /* .padding */ |
| 17820 | false, /* .isArray */ |
| 17821 | false /* .isOptional */ |
| 17822 | }, |
| 17823 | { |
| 17824 | UA_TYPENAME("SoftwareVersion") /* .memberName */ |
| 17825 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 17826 | offsetof(UA_BuildInfo, softwareVersion) - offsetof(UA_BuildInfo, productName) - sizeof(UA_String), /* .padding */ |
| 17827 | false, /* .isArray */ |
| 17828 | false /* .isOptional */ |
| 17829 | }, |
| 17830 | { |
| 17831 | UA_TYPENAME("BuildNumber") /* .memberName */ |
| 17832 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 17833 | offsetof(UA_BuildInfo, buildNumber) - offsetof(UA_BuildInfo, softwareVersion) - sizeof(UA_String), /* .padding */ |
| 17834 | false, /* .isArray */ |
| 17835 | false /* .isOptional */ |
| 17836 | }, |
| 17837 | { |
| 17838 | UA_TYPENAME("BuildDate") /* .memberName */ |
| 17839 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 17840 | offsetof(UA_BuildInfo, buildDate) - offsetof(UA_BuildInfo, buildNumber) - sizeof(UA_String), /* .padding */ |
| 17841 | false, /* .isArray */ |
| 17842 | false /* .isOptional */ |
| 17843 | },}; |
| 17844 | |
| 17845 | /* RedundancySupport */ |
| 17846 | #define RedundancySupport_members NULL |
| 17847 | |
| 17848 | /* ServerState */ |
| 17849 | #define ServerState_members NULL |
| 17850 | |
| 17851 | /* RedundantServerDataType */ |
| 17852 | static UA_DataTypeMember RedundantServerDataType_members[3] = { |
| 17853 | { |
| 17854 | UA_TYPENAME("ServerId") /* .memberName */ |
| 17855 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 17856 | 0, /* .padding */ |
| 17857 | false, /* .isArray */ |
| 17858 | false /* .isOptional */ |
| 17859 | }, |
| 17860 | { |
| 17861 | UA_TYPENAME("ServiceLevel") /* .memberName */ |
| 17862 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 17863 | offsetof(UA_RedundantServerDataType, serviceLevel) - offsetof(UA_RedundantServerDataType, serverId) - sizeof(UA_String), /* .padding */ |
| 17864 | false, /* .isArray */ |
| 17865 | false /* .isOptional */ |
| 17866 | }, |
| 17867 | { |
| 17868 | UA_TYPENAME("ServerState") /* .memberName */ |
| 17869 | &UA_TYPES[UA_TYPES_SERVERSTATE], /* .memberType */ |
| 17870 | offsetof(UA_RedundantServerDataType, serverState) - offsetof(UA_RedundantServerDataType, serviceLevel) - sizeof(UA_Byte), /* .padding */ |
| 17871 | false, /* .isArray */ |
| 17872 | false /* .isOptional */ |
| 17873 | },}; |
| 17874 | |
| 17875 | /* EndpointUrlListDataType */ |
| 17876 | static UA_DataTypeMember EndpointUrlListDataType_members[1] = { |
| 17877 | { |
| 17878 | UA_TYPENAME("EndpointUrlList") /* .memberName */ |
| 17879 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 17880 | 0, /* .padding */ |
| 17881 | true, /* .isArray */ |
| 17882 | false /* .isOptional */ |
| 17883 | },}; |
| 17884 | |
| 17885 | /* NetworkGroupDataType */ |
| 17886 | static UA_DataTypeMember NetworkGroupDataType_members[2] = { |
| 17887 | { |
| 17888 | UA_TYPENAME("ServerUri") /* .memberName */ |
| 17889 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 17890 | 0, /* .padding */ |
| 17891 | false, /* .isArray */ |
| 17892 | false /* .isOptional */ |
| 17893 | }, |
| 17894 | { |
| 17895 | UA_TYPENAME("NetworkPaths") /* .memberName */ |
| 17896 | &UA_TYPES[UA_TYPES_ENDPOINTURLLISTDATATYPE], /* .memberType */ |
| 17897 | offsetof(UA_NetworkGroupDataType, networkPathsSize) - offsetof(UA_NetworkGroupDataType, serverUri) - sizeof(UA_String), /* .padding */ |
| 17898 | true, /* .isArray */ |
| 17899 | false /* .isOptional */ |
| 17900 | },}; |
| 17901 | |
| 17902 | /* SamplingIntervalDiagnosticsDataType */ |
| 17903 | static UA_DataTypeMember SamplingIntervalDiagnosticsDataType_members[4] = { |
| 17904 | { |
| 17905 | UA_TYPENAME("SamplingInterval") /* .memberName */ |
| 17906 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 17907 | 0, /* .padding */ |
| 17908 | false, /* .isArray */ |
| 17909 | false /* .isOptional */ |
| 17910 | }, |
| 17911 | { |
| 17912 | UA_TYPENAME("MonitoredItemCount") /* .memberName */ |
| 17913 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17914 | offsetof(UA_SamplingIntervalDiagnosticsDataType, monitoredItemCount) - offsetof(UA_SamplingIntervalDiagnosticsDataType, samplingInterval) - sizeof(UA_Double), /* .padding */ |
| 17915 | false, /* .isArray */ |
| 17916 | false /* .isOptional */ |
| 17917 | }, |
| 17918 | { |
| 17919 | UA_TYPENAME("MaxMonitoredItemCount") /* .memberName */ |
| 17920 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17921 | offsetof(UA_SamplingIntervalDiagnosticsDataType, maxMonitoredItemCount) - offsetof(UA_SamplingIntervalDiagnosticsDataType, monitoredItemCount) - sizeof(UA_UInt32), /* .padding */ |
| 17922 | false, /* .isArray */ |
| 17923 | false /* .isOptional */ |
| 17924 | }, |
| 17925 | { |
| 17926 | UA_TYPENAME("DisabledMonitoredItemCount") /* .memberName */ |
| 17927 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17928 | offsetof(UA_SamplingIntervalDiagnosticsDataType, disabledMonitoredItemCount) - offsetof(UA_SamplingIntervalDiagnosticsDataType, maxMonitoredItemCount) - sizeof(UA_UInt32), /* .padding */ |
| 17929 | false, /* .isArray */ |
| 17930 | false /* .isOptional */ |
| 17931 | },}; |
| 17932 | |
| 17933 | /* ServerDiagnosticsSummaryDataType */ |
| 17934 | static UA_DataTypeMember ServerDiagnosticsSummaryDataType_members[12] = { |
| 17935 | { |
| 17936 | UA_TYPENAME("ServerViewCount") /* .memberName */ |
| 17937 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17938 | 0, /* .padding */ |
| 17939 | false, /* .isArray */ |
| 17940 | false /* .isOptional */ |
| 17941 | }, |
| 17942 | { |
| 17943 | UA_TYPENAME("CurrentSessionCount") /* .memberName */ |
| 17944 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17945 | offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, serverViewCount) - sizeof(UA_UInt32), /* .padding */ |
| 17946 | false, /* .isArray */ |
| 17947 | false /* .isOptional */ |
| 17948 | }, |
| 17949 | { |
| 17950 | UA_TYPENAME("CumulatedSessionCount") /* .memberName */ |
| 17951 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17952 | offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, currentSessionCount) - sizeof(UA_UInt32), /* .padding */ |
| 17953 | false, /* .isArray */ |
| 17954 | false /* .isOptional */ |
| 17955 | }, |
| 17956 | { |
| 17957 | UA_TYPENAME("SecurityRejectedSessionCount") /* .memberName */ |
| 17958 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17959 | offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSessionCount) - sizeof(UA_UInt32), /* .padding */ |
| 17960 | false, /* .isArray */ |
| 17961 | false /* .isOptional */ |
| 17962 | }, |
| 17963 | { |
| 17964 | UA_TYPENAME("RejectedSessionCount") /* .memberName */ |
| 17965 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17966 | offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedSessionCount) - sizeof(UA_UInt32), /* .padding */ |
| 17967 | false, /* .isArray */ |
| 17968 | false /* .isOptional */ |
| 17969 | }, |
| 17970 | { |
| 17971 | UA_TYPENAME("SessionTimeoutCount") /* .memberName */ |
| 17972 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17973 | offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedSessionCount) - sizeof(UA_UInt32), /* .padding */ |
| 17974 | false, /* .isArray */ |
| 17975 | false /* .isOptional */ |
| 17976 | }, |
| 17977 | { |
| 17978 | UA_TYPENAME("SessionAbortCount") /* .memberName */ |
| 17979 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17980 | offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, sessionTimeoutCount) - sizeof(UA_UInt32), /* .padding */ |
| 17981 | false, /* .isArray */ |
| 17982 | false /* .isOptional */ |
| 17983 | }, |
| 17984 | { |
| 17985 | UA_TYPENAME("CurrentSubscriptionCount") /* .memberName */ |
| 17986 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17987 | offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, sessionAbortCount) - sizeof(UA_UInt32), /* .padding */ |
| 17988 | false, /* .isArray */ |
| 17989 | false /* .isOptional */ |
| 17990 | }, |
| 17991 | { |
| 17992 | UA_TYPENAME("CumulatedSubscriptionCount") /* .memberName */ |
| 17993 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 17994 | offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, currentSubscriptionCount) - sizeof(UA_UInt32), /* .padding */ |
| 17995 | false, /* .isArray */ |
| 17996 | false /* .isOptional */ |
| 17997 | }, |
| 17998 | { |
| 17999 | UA_TYPENAME("PublishingIntervalCount") /* .memberName */ |
| 18000 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18001 | offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, cumulatedSubscriptionCount) - sizeof(UA_UInt32), /* .padding */ |
| 18002 | false, /* .isArray */ |
| 18003 | false /* .isOptional */ |
| 18004 | }, |
| 18005 | { |
| 18006 | UA_TYPENAME("SecurityRejectedRequestsCount") /* .memberName */ |
| 18007 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18008 | offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, publishingIntervalCount) - sizeof(UA_UInt32), /* .padding */ |
| 18009 | false, /* .isArray */ |
| 18010 | false /* .isOptional */ |
| 18011 | }, |
| 18012 | { |
| 18013 | UA_TYPENAME("RejectedRequestsCount") /* .memberName */ |
| 18014 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18015 | offsetof(UA_ServerDiagnosticsSummaryDataType, rejectedRequestsCount) - offsetof(UA_ServerDiagnosticsSummaryDataType, securityRejectedRequestsCount) - sizeof(UA_UInt32), /* .padding */ |
| 18016 | false, /* .isArray */ |
| 18017 | false /* .isOptional */ |
| 18018 | },}; |
| 18019 | |
| 18020 | /* ServerStatusDataType */ |
| 18021 | static UA_DataTypeMember ServerStatusDataType_members[6] = { |
| 18022 | { |
| 18023 | UA_TYPENAME("StartTime") /* .memberName */ |
| 18024 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 18025 | 0, /* .padding */ |
| 18026 | false, /* .isArray */ |
| 18027 | false /* .isOptional */ |
| 18028 | }, |
| 18029 | { |
| 18030 | UA_TYPENAME("CurrentTime") /* .memberName */ |
| 18031 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 18032 | offsetof(UA_ServerStatusDataType, currentTime) - offsetof(UA_ServerStatusDataType, startTime) - sizeof(UA_DateTime), /* .padding */ |
| 18033 | false, /* .isArray */ |
| 18034 | false /* .isOptional */ |
| 18035 | }, |
| 18036 | { |
| 18037 | UA_TYPENAME("State") /* .memberName */ |
| 18038 | &UA_TYPES[UA_TYPES_SERVERSTATE], /* .memberType */ |
| 18039 | offsetof(UA_ServerStatusDataType, state) - offsetof(UA_ServerStatusDataType, currentTime) - sizeof(UA_DateTime), /* .padding */ |
| 18040 | false, /* .isArray */ |
| 18041 | false /* .isOptional */ |
| 18042 | }, |
| 18043 | { |
| 18044 | UA_TYPENAME("BuildInfo") /* .memberName */ |
| 18045 | &UA_TYPES[UA_TYPES_BUILDINFO], /* .memberType */ |
| 18046 | offsetof(UA_ServerStatusDataType, buildInfo) - offsetof(UA_ServerStatusDataType, state) - sizeof(UA_ServerState), /* .padding */ |
| 18047 | false, /* .isArray */ |
| 18048 | false /* .isOptional */ |
| 18049 | }, |
| 18050 | { |
| 18051 | UA_TYPENAME("SecondsTillShutdown") /* .memberName */ |
| 18052 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18053 | offsetof(UA_ServerStatusDataType, secondsTillShutdown) - offsetof(UA_ServerStatusDataType, buildInfo) - sizeof(UA_BuildInfo), /* .padding */ |
| 18054 | false, /* .isArray */ |
| 18055 | false /* .isOptional */ |
| 18056 | }, |
| 18057 | { |
| 18058 | UA_TYPENAME("ShutdownReason") /* .memberName */ |
| 18059 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 18060 | offsetof(UA_ServerStatusDataType, shutdownReason) - offsetof(UA_ServerStatusDataType, secondsTillShutdown) - sizeof(UA_UInt32), /* .padding */ |
| 18061 | false, /* .isArray */ |
| 18062 | false /* .isOptional */ |
| 18063 | },}; |
| 18064 | |
| 18065 | /* SessionSecurityDiagnosticsDataType */ |
| 18066 | static UA_DataTypeMember SessionSecurityDiagnosticsDataType_members[9] = { |
| 18067 | { |
| 18068 | UA_TYPENAME("SessionId") /* .memberName */ |
| 18069 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18070 | 0, /* .padding */ |
| 18071 | false, /* .isArray */ |
| 18072 | false /* .isOptional */ |
| 18073 | }, |
| 18074 | { |
| 18075 | UA_TYPENAME("ClientUserIdOfSession") /* .memberName */ |
| 18076 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18077 | offsetof(UA_SessionSecurityDiagnosticsDataType, clientUserIdOfSession) - offsetof(UA_SessionSecurityDiagnosticsDataType, sessionId) - sizeof(UA_NodeId), /* .padding */ |
| 18078 | false, /* .isArray */ |
| 18079 | false /* .isOptional */ |
| 18080 | }, |
| 18081 | { |
| 18082 | UA_TYPENAME("ClientUserIdHistory") /* .memberName */ |
| 18083 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18084 | offsetof(UA_SessionSecurityDiagnosticsDataType, clientUserIdHistorySize) - offsetof(UA_SessionSecurityDiagnosticsDataType, clientUserIdOfSession) - sizeof(UA_String), /* .padding */ |
| 18085 | true, /* .isArray */ |
| 18086 | false /* .isOptional */ |
| 18087 | }, |
| 18088 | { |
| 18089 | UA_TYPENAME("AuthenticationMechanism") /* .memberName */ |
| 18090 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18091 | offsetof(UA_SessionSecurityDiagnosticsDataType, authenticationMechanism) - offsetof(UA_SessionSecurityDiagnosticsDataType, clientUserIdHistory) - sizeof(void *), /* .padding */ |
| 18092 | false, /* .isArray */ |
| 18093 | false /* .isOptional */ |
| 18094 | }, |
| 18095 | { |
| 18096 | UA_TYPENAME("Encoding") /* .memberName */ |
| 18097 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18098 | offsetof(UA_SessionSecurityDiagnosticsDataType, encoding) - offsetof(UA_SessionSecurityDiagnosticsDataType, authenticationMechanism) - sizeof(UA_String), /* .padding */ |
| 18099 | false, /* .isArray */ |
| 18100 | false /* .isOptional */ |
| 18101 | }, |
| 18102 | { |
| 18103 | UA_TYPENAME("TransportProtocol") /* .memberName */ |
| 18104 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18105 | offsetof(UA_SessionSecurityDiagnosticsDataType, transportProtocol) - offsetof(UA_SessionSecurityDiagnosticsDataType, encoding) - sizeof(UA_String), /* .padding */ |
| 18106 | false, /* .isArray */ |
| 18107 | false /* .isOptional */ |
| 18108 | }, |
| 18109 | { |
| 18110 | UA_TYPENAME("SecurityMode") /* .memberName */ |
| 18111 | &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */ |
| 18112 | offsetof(UA_SessionSecurityDiagnosticsDataType, securityMode) - offsetof(UA_SessionSecurityDiagnosticsDataType, transportProtocol) - sizeof(UA_String), /* .padding */ |
| 18113 | false, /* .isArray */ |
| 18114 | false /* .isOptional */ |
| 18115 | }, |
| 18116 | { |
| 18117 | UA_TYPENAME("SecurityPolicyUri") /* .memberName */ |
| 18118 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18119 | offsetof(UA_SessionSecurityDiagnosticsDataType, securityPolicyUri) - offsetof(UA_SessionSecurityDiagnosticsDataType, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */ |
| 18120 | false, /* .isArray */ |
| 18121 | false /* .isOptional */ |
| 18122 | }, |
| 18123 | { |
| 18124 | UA_TYPENAME("ClientCertificate") /* .memberName */ |
| 18125 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 18126 | offsetof(UA_SessionSecurityDiagnosticsDataType, clientCertificate) - offsetof(UA_SessionSecurityDiagnosticsDataType, securityPolicyUri) - sizeof(UA_String), /* .padding */ |
| 18127 | false, /* .isArray */ |
| 18128 | false /* .isOptional */ |
| 18129 | },}; |
| 18130 | |
| 18131 | /* ServiceCounterDataType */ |
| 18132 | static UA_DataTypeMember ServiceCounterDataType_members[2] = { |
| 18133 | { |
| 18134 | UA_TYPENAME("TotalCount") /* .memberName */ |
| 18135 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18136 | 0, /* .padding */ |
| 18137 | false, /* .isArray */ |
| 18138 | false /* .isOptional */ |
| 18139 | }, |
| 18140 | { |
| 18141 | UA_TYPENAME("ErrorCount") /* .memberName */ |
| 18142 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18143 | offsetof(UA_ServiceCounterDataType, errorCount) - offsetof(UA_ServiceCounterDataType, totalCount) - sizeof(UA_UInt32), /* .padding */ |
| 18144 | false, /* .isArray */ |
| 18145 | false /* .isOptional */ |
| 18146 | },}; |
| 18147 | |
| 18148 | /* StatusResult */ |
| 18149 | static UA_DataTypeMember StatusResult_members[2] = { |
| 18150 | { |
| 18151 | UA_TYPENAME("StatusCode") /* .memberName */ |
| 18152 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 18153 | 0, /* .padding */ |
| 18154 | false, /* .isArray */ |
| 18155 | false /* .isOptional */ |
| 18156 | }, |
| 18157 | { |
| 18158 | UA_TYPENAME("DiagnosticInfo") /* .memberName */ |
| 18159 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 18160 | offsetof(UA_StatusResult, diagnosticInfo) - offsetof(UA_StatusResult, statusCode) - sizeof(UA_StatusCode), /* .padding */ |
| 18161 | false, /* .isArray */ |
| 18162 | false /* .isOptional */ |
| 18163 | },}; |
| 18164 | |
| 18165 | /* SubscriptionDiagnosticsDataType */ |
| 18166 | static UA_DataTypeMember SubscriptionDiagnosticsDataType_members[31] = { |
| 18167 | { |
| 18168 | UA_TYPENAME("SessionId") /* .memberName */ |
| 18169 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18170 | 0, /* .padding */ |
| 18171 | false, /* .isArray */ |
| 18172 | false /* .isOptional */ |
| 18173 | }, |
| 18174 | { |
| 18175 | UA_TYPENAME("SubscriptionId") /* .memberName */ |
| 18176 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18177 | offsetof(UA_SubscriptionDiagnosticsDataType, subscriptionId) - offsetof(UA_SubscriptionDiagnosticsDataType, sessionId) - sizeof(UA_NodeId), /* .padding */ |
| 18178 | false, /* .isArray */ |
| 18179 | false /* .isOptional */ |
| 18180 | }, |
| 18181 | { |
| 18182 | UA_TYPENAME("Priority") /* .memberName */ |
| 18183 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 18184 | offsetof(UA_SubscriptionDiagnosticsDataType, priority) - offsetof(UA_SubscriptionDiagnosticsDataType, subscriptionId) - sizeof(UA_UInt32), /* .padding */ |
| 18185 | false, /* .isArray */ |
| 18186 | false /* .isOptional */ |
| 18187 | }, |
| 18188 | { |
| 18189 | UA_TYPENAME("PublishingInterval") /* .memberName */ |
| 18190 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 18191 | offsetof(UA_SubscriptionDiagnosticsDataType, publishingInterval) - offsetof(UA_SubscriptionDiagnosticsDataType, priority) - sizeof(UA_Byte), /* .padding */ |
| 18192 | false, /* .isArray */ |
| 18193 | false /* .isOptional */ |
| 18194 | }, |
| 18195 | { |
| 18196 | UA_TYPENAME("MaxKeepAliveCount") /* .memberName */ |
| 18197 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18198 | offsetof(UA_SubscriptionDiagnosticsDataType, maxKeepAliveCount) - offsetof(UA_SubscriptionDiagnosticsDataType, publishingInterval) - sizeof(UA_Double), /* .padding */ |
| 18199 | false, /* .isArray */ |
| 18200 | false /* .isOptional */ |
| 18201 | }, |
| 18202 | { |
| 18203 | UA_TYPENAME("MaxLifetimeCount") /* .memberName */ |
| 18204 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18205 | offsetof(UA_SubscriptionDiagnosticsDataType, maxLifetimeCount) - offsetof(UA_SubscriptionDiagnosticsDataType, maxKeepAliveCount) - sizeof(UA_UInt32), /* .padding */ |
| 18206 | false, /* .isArray */ |
| 18207 | false /* .isOptional */ |
| 18208 | }, |
| 18209 | { |
| 18210 | UA_TYPENAME("MaxNotificationsPerPublish") /* .memberName */ |
| 18211 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18212 | offsetof(UA_SubscriptionDiagnosticsDataType, maxNotificationsPerPublish) - offsetof(UA_SubscriptionDiagnosticsDataType, maxLifetimeCount) - sizeof(UA_UInt32), /* .padding */ |
| 18213 | false, /* .isArray */ |
| 18214 | false /* .isOptional */ |
| 18215 | }, |
| 18216 | { |
| 18217 | UA_TYPENAME("PublishingEnabled") /* .memberName */ |
| 18218 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 18219 | offsetof(UA_SubscriptionDiagnosticsDataType, publishingEnabled) - offsetof(UA_SubscriptionDiagnosticsDataType, maxNotificationsPerPublish) - sizeof(UA_UInt32), /* .padding */ |
| 18220 | false, /* .isArray */ |
| 18221 | false /* .isOptional */ |
| 18222 | }, |
| 18223 | { |
| 18224 | UA_TYPENAME("ModifyCount") /* .memberName */ |
| 18225 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18226 | offsetof(UA_SubscriptionDiagnosticsDataType, modifyCount) - offsetof(UA_SubscriptionDiagnosticsDataType, publishingEnabled) - sizeof(UA_Boolean), /* .padding */ |
| 18227 | false, /* .isArray */ |
| 18228 | false /* .isOptional */ |
| 18229 | }, |
| 18230 | { |
| 18231 | UA_TYPENAME("EnableCount") /* .memberName */ |
| 18232 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18233 | offsetof(UA_SubscriptionDiagnosticsDataType, enableCount) - offsetof(UA_SubscriptionDiagnosticsDataType, modifyCount) - sizeof(UA_UInt32), /* .padding */ |
| 18234 | false, /* .isArray */ |
| 18235 | false /* .isOptional */ |
| 18236 | }, |
| 18237 | { |
| 18238 | UA_TYPENAME("DisableCount") /* .memberName */ |
| 18239 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18240 | offsetof(UA_SubscriptionDiagnosticsDataType, disableCount) - offsetof(UA_SubscriptionDiagnosticsDataType, enableCount) - sizeof(UA_UInt32), /* .padding */ |
| 18241 | false, /* .isArray */ |
| 18242 | false /* .isOptional */ |
| 18243 | }, |
| 18244 | { |
| 18245 | UA_TYPENAME("RepublishRequestCount") /* .memberName */ |
| 18246 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18247 | offsetof(UA_SubscriptionDiagnosticsDataType, republishRequestCount) - offsetof(UA_SubscriptionDiagnosticsDataType, disableCount) - sizeof(UA_UInt32), /* .padding */ |
| 18248 | false, /* .isArray */ |
| 18249 | false /* .isOptional */ |
| 18250 | }, |
| 18251 | { |
| 18252 | UA_TYPENAME("RepublishMessageRequestCount") /* .memberName */ |
| 18253 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18254 | offsetof(UA_SubscriptionDiagnosticsDataType, republishMessageRequestCount) - offsetof(UA_SubscriptionDiagnosticsDataType, republishRequestCount) - sizeof(UA_UInt32), /* .padding */ |
| 18255 | false, /* .isArray */ |
| 18256 | false /* .isOptional */ |
| 18257 | }, |
| 18258 | { |
| 18259 | UA_TYPENAME("RepublishMessageCount") /* .memberName */ |
| 18260 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18261 | offsetof(UA_SubscriptionDiagnosticsDataType, republishMessageCount) - offsetof(UA_SubscriptionDiagnosticsDataType, republishMessageRequestCount) - sizeof(UA_UInt32), /* .padding */ |
| 18262 | false, /* .isArray */ |
| 18263 | false /* .isOptional */ |
| 18264 | }, |
| 18265 | { |
| 18266 | UA_TYPENAME("TransferRequestCount") /* .memberName */ |
| 18267 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18268 | offsetof(UA_SubscriptionDiagnosticsDataType, transferRequestCount) - offsetof(UA_SubscriptionDiagnosticsDataType, republishMessageCount) - sizeof(UA_UInt32), /* .padding */ |
| 18269 | false, /* .isArray */ |
| 18270 | false /* .isOptional */ |
| 18271 | }, |
| 18272 | { |
| 18273 | UA_TYPENAME("TransferredToAltClientCount") /* .memberName */ |
| 18274 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18275 | offsetof(UA_SubscriptionDiagnosticsDataType, transferredToAltClientCount) - offsetof(UA_SubscriptionDiagnosticsDataType, transferRequestCount) - sizeof(UA_UInt32), /* .padding */ |
| 18276 | false, /* .isArray */ |
| 18277 | false /* .isOptional */ |
| 18278 | }, |
| 18279 | { |
| 18280 | UA_TYPENAME("TransferredToSameClientCount") /* .memberName */ |
| 18281 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18282 | offsetof(UA_SubscriptionDiagnosticsDataType, transferredToSameClientCount) - offsetof(UA_SubscriptionDiagnosticsDataType, transferredToAltClientCount) - sizeof(UA_UInt32), /* .padding */ |
| 18283 | false, /* .isArray */ |
| 18284 | false /* .isOptional */ |
| 18285 | }, |
| 18286 | { |
| 18287 | UA_TYPENAME("PublishRequestCount") /* .memberName */ |
| 18288 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18289 | offsetof(UA_SubscriptionDiagnosticsDataType, publishRequestCount) - offsetof(UA_SubscriptionDiagnosticsDataType, transferredToSameClientCount) - sizeof(UA_UInt32), /* .padding */ |
| 18290 | false, /* .isArray */ |
| 18291 | false /* .isOptional */ |
| 18292 | }, |
| 18293 | { |
| 18294 | UA_TYPENAME("DataChangeNotificationsCount") /* .memberName */ |
| 18295 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18296 | offsetof(UA_SubscriptionDiagnosticsDataType, dataChangeNotificationsCount) - offsetof(UA_SubscriptionDiagnosticsDataType, publishRequestCount) - sizeof(UA_UInt32), /* .padding */ |
| 18297 | false, /* .isArray */ |
| 18298 | false /* .isOptional */ |
| 18299 | }, |
| 18300 | { |
| 18301 | UA_TYPENAME("EventNotificationsCount") /* .memberName */ |
| 18302 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18303 | offsetof(UA_SubscriptionDiagnosticsDataType, eventNotificationsCount) - offsetof(UA_SubscriptionDiagnosticsDataType, dataChangeNotificationsCount) - sizeof(UA_UInt32), /* .padding */ |
| 18304 | false, /* .isArray */ |
| 18305 | false /* .isOptional */ |
| 18306 | }, |
| 18307 | { |
| 18308 | UA_TYPENAME("NotificationsCount") /* .memberName */ |
| 18309 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18310 | offsetof(UA_SubscriptionDiagnosticsDataType, notificationsCount) - offsetof(UA_SubscriptionDiagnosticsDataType, eventNotificationsCount) - sizeof(UA_UInt32), /* .padding */ |
| 18311 | false, /* .isArray */ |
| 18312 | false /* .isOptional */ |
| 18313 | }, |
| 18314 | { |
| 18315 | UA_TYPENAME("LatePublishRequestCount") /* .memberName */ |
| 18316 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18317 | offsetof(UA_SubscriptionDiagnosticsDataType, latePublishRequestCount) - offsetof(UA_SubscriptionDiagnosticsDataType, notificationsCount) - sizeof(UA_UInt32), /* .padding */ |
| 18318 | false, /* .isArray */ |
| 18319 | false /* .isOptional */ |
| 18320 | }, |
| 18321 | { |
| 18322 | UA_TYPENAME("CurrentKeepAliveCount") /* .memberName */ |
| 18323 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18324 | offsetof(UA_SubscriptionDiagnosticsDataType, currentKeepAliveCount) - offsetof(UA_SubscriptionDiagnosticsDataType, latePublishRequestCount) - sizeof(UA_UInt32), /* .padding */ |
| 18325 | false, /* .isArray */ |
| 18326 | false /* .isOptional */ |
| 18327 | }, |
| 18328 | { |
| 18329 | UA_TYPENAME("CurrentLifetimeCount") /* .memberName */ |
| 18330 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18331 | offsetof(UA_SubscriptionDiagnosticsDataType, currentLifetimeCount) - offsetof(UA_SubscriptionDiagnosticsDataType, currentKeepAliveCount) - sizeof(UA_UInt32), /* .padding */ |
| 18332 | false, /* .isArray */ |
| 18333 | false /* .isOptional */ |
| 18334 | }, |
| 18335 | { |
| 18336 | UA_TYPENAME("UnacknowledgedMessageCount") /* .memberName */ |
| 18337 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18338 | offsetof(UA_SubscriptionDiagnosticsDataType, unacknowledgedMessageCount) - offsetof(UA_SubscriptionDiagnosticsDataType, currentLifetimeCount) - sizeof(UA_UInt32), /* .padding */ |
| 18339 | false, /* .isArray */ |
| 18340 | false /* .isOptional */ |
| 18341 | }, |
| 18342 | { |
| 18343 | UA_TYPENAME("DiscardedMessageCount") /* .memberName */ |
| 18344 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18345 | offsetof(UA_SubscriptionDiagnosticsDataType, discardedMessageCount) - offsetof(UA_SubscriptionDiagnosticsDataType, unacknowledgedMessageCount) - sizeof(UA_UInt32), /* .padding */ |
| 18346 | false, /* .isArray */ |
| 18347 | false /* .isOptional */ |
| 18348 | }, |
| 18349 | { |
| 18350 | UA_TYPENAME("MonitoredItemCount") /* .memberName */ |
| 18351 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18352 | offsetof(UA_SubscriptionDiagnosticsDataType, monitoredItemCount) - offsetof(UA_SubscriptionDiagnosticsDataType, discardedMessageCount) - sizeof(UA_UInt32), /* .padding */ |
| 18353 | false, /* .isArray */ |
| 18354 | false /* .isOptional */ |
| 18355 | }, |
| 18356 | { |
| 18357 | UA_TYPENAME("DisabledMonitoredItemCount") /* .memberName */ |
| 18358 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18359 | offsetof(UA_SubscriptionDiagnosticsDataType, disabledMonitoredItemCount) - offsetof(UA_SubscriptionDiagnosticsDataType, monitoredItemCount) - sizeof(UA_UInt32), /* .padding */ |
| 18360 | false, /* .isArray */ |
| 18361 | false /* .isOptional */ |
| 18362 | }, |
| 18363 | { |
| 18364 | UA_TYPENAME("MonitoringQueueOverflowCount") /* .memberName */ |
| 18365 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18366 | offsetof(UA_SubscriptionDiagnosticsDataType, monitoringQueueOverflowCount) - offsetof(UA_SubscriptionDiagnosticsDataType, disabledMonitoredItemCount) - sizeof(UA_UInt32), /* .padding */ |
| 18367 | false, /* .isArray */ |
| 18368 | false /* .isOptional */ |
| 18369 | }, |
| 18370 | { |
| 18371 | UA_TYPENAME("NextSequenceNumber") /* .memberName */ |
| 18372 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18373 | offsetof(UA_SubscriptionDiagnosticsDataType, nextSequenceNumber) - offsetof(UA_SubscriptionDiagnosticsDataType, monitoringQueueOverflowCount) - sizeof(UA_UInt32), /* .padding */ |
| 18374 | false, /* .isArray */ |
| 18375 | false /* .isOptional */ |
| 18376 | }, |
| 18377 | { |
| 18378 | UA_TYPENAME("EventQueueOverFlowCount") /* .memberName */ |
| 18379 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18380 | offsetof(UA_SubscriptionDiagnosticsDataType, eventQueueOverFlowCount) - offsetof(UA_SubscriptionDiagnosticsDataType, nextSequenceNumber) - sizeof(UA_UInt32), /* .padding */ |
| 18381 | false, /* .isArray */ |
| 18382 | false /* .isOptional */ |
| 18383 | },}; |
| 18384 | |
| 18385 | /* ModelChangeStructureVerbMask */ |
| 18386 | #define ModelChangeStructureVerbMask_members NULL |
| 18387 | |
| 18388 | /* ModelChangeStructureDataType */ |
| 18389 | static UA_DataTypeMember ModelChangeStructureDataType_members[3] = { |
| 18390 | { |
| 18391 | UA_TYPENAME("Affected") /* .memberName */ |
| 18392 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18393 | 0, /* .padding */ |
| 18394 | false, /* .isArray */ |
| 18395 | false /* .isOptional */ |
| 18396 | }, |
| 18397 | { |
| 18398 | UA_TYPENAME("AffectedType") /* .memberName */ |
| 18399 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18400 | offsetof(UA_ModelChangeStructureDataType, affectedType) - offsetof(UA_ModelChangeStructureDataType, affected) - sizeof(UA_NodeId), /* .padding */ |
| 18401 | false, /* .isArray */ |
| 18402 | false /* .isOptional */ |
| 18403 | }, |
| 18404 | { |
| 18405 | UA_TYPENAME("Verb") /* .memberName */ |
| 18406 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 18407 | offsetof(UA_ModelChangeStructureDataType, verb) - offsetof(UA_ModelChangeStructureDataType, affectedType) - sizeof(UA_NodeId), /* .padding */ |
| 18408 | false, /* .isArray */ |
| 18409 | false /* .isOptional */ |
| 18410 | },}; |
| 18411 | |
| 18412 | /* SemanticChangeStructureDataType */ |
| 18413 | static UA_DataTypeMember SemanticChangeStructureDataType_members[2] = { |
| 18414 | { |
| 18415 | UA_TYPENAME("Affected") /* .memberName */ |
| 18416 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18417 | 0, /* .padding */ |
| 18418 | false, /* .isArray */ |
| 18419 | false /* .isOptional */ |
| 18420 | }, |
| 18421 | { |
| 18422 | UA_TYPENAME("AffectedType") /* .memberName */ |
| 18423 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18424 | offsetof(UA_SemanticChangeStructureDataType, affectedType) - offsetof(UA_SemanticChangeStructureDataType, affected) - sizeof(UA_NodeId), /* .padding */ |
| 18425 | false, /* .isArray */ |
| 18426 | false /* .isOptional */ |
| 18427 | },}; |
| 18428 | |
| 18429 | /* Range */ |
| 18430 | static UA_DataTypeMember Range_members[2] = { |
| 18431 | { |
| 18432 | UA_TYPENAME("Low") /* .memberName */ |
| 18433 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 18434 | 0, /* .padding */ |
| 18435 | false, /* .isArray */ |
| 18436 | false /* .isOptional */ |
| 18437 | }, |
| 18438 | { |
| 18439 | UA_TYPENAME("High") /* .memberName */ |
| 18440 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 18441 | offsetof(UA_Range, high) - offsetof(UA_Range, low) - sizeof(UA_Double), /* .padding */ |
| 18442 | false, /* .isArray */ |
| 18443 | false /* .isOptional */ |
| 18444 | },}; |
| 18445 | |
| 18446 | /* EUInformation */ |
| 18447 | static UA_DataTypeMember EUInformation_members[4] = { |
| 18448 | { |
| 18449 | UA_TYPENAME("NamespaceUri") /* .memberName */ |
| 18450 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18451 | 0, /* .padding */ |
| 18452 | false, /* .isArray */ |
| 18453 | false /* .isOptional */ |
| 18454 | }, |
| 18455 | { |
| 18456 | UA_TYPENAME("UnitId") /* .memberName */ |
| 18457 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 18458 | offsetof(UA_EUInformation, unitId) - offsetof(UA_EUInformation, namespaceUri) - sizeof(UA_String), /* .padding */ |
| 18459 | false, /* .isArray */ |
| 18460 | false /* .isOptional */ |
| 18461 | }, |
| 18462 | { |
| 18463 | UA_TYPENAME("DisplayName") /* .memberName */ |
| 18464 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 18465 | offsetof(UA_EUInformation, displayName) - offsetof(UA_EUInformation, unitId) - sizeof(UA_Int32), /* .padding */ |
| 18466 | false, /* .isArray */ |
| 18467 | false /* .isOptional */ |
| 18468 | }, |
| 18469 | { |
| 18470 | UA_TYPENAME("Description") /* .memberName */ |
| 18471 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 18472 | offsetof(UA_EUInformation, description) - offsetof(UA_EUInformation, displayName) - sizeof(UA_LocalizedText), /* .padding */ |
| 18473 | false, /* .isArray */ |
| 18474 | false /* .isOptional */ |
| 18475 | },}; |
| 18476 | |
| 18477 | /* AxisScaleEnumeration */ |
| 18478 | #define AxisScaleEnumeration_members NULL |
| 18479 | |
| 18480 | /* ComplexNumberType */ |
| 18481 | static UA_DataTypeMember ComplexNumberType_members[2] = { |
| 18482 | { |
| 18483 | UA_TYPENAME("Real") /* .memberName */ |
| 18484 | &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */ |
| 18485 | 0, /* .padding */ |
| 18486 | false, /* .isArray */ |
| 18487 | false /* .isOptional */ |
| 18488 | }, |
| 18489 | { |
| 18490 | UA_TYPENAME("Imaginary") /* .memberName */ |
| 18491 | &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */ |
| 18492 | offsetof(UA_ComplexNumberType, imaginary) - offsetof(UA_ComplexNumberType, real) - sizeof(UA_Float), /* .padding */ |
| 18493 | false, /* .isArray */ |
| 18494 | false /* .isOptional */ |
| 18495 | },}; |
| 18496 | |
| 18497 | /* DoubleComplexNumberType */ |
| 18498 | static UA_DataTypeMember DoubleComplexNumberType_members[2] = { |
| 18499 | { |
| 18500 | UA_TYPENAME("Real") /* .memberName */ |
| 18501 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 18502 | 0, /* .padding */ |
| 18503 | false, /* .isArray */ |
| 18504 | false /* .isOptional */ |
| 18505 | }, |
| 18506 | { |
| 18507 | UA_TYPENAME("Imaginary") /* .memberName */ |
| 18508 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 18509 | offsetof(UA_DoubleComplexNumberType, imaginary) - offsetof(UA_DoubleComplexNumberType, real) - sizeof(UA_Double), /* .padding */ |
| 18510 | false, /* .isArray */ |
| 18511 | false /* .isOptional */ |
| 18512 | },}; |
| 18513 | |
| 18514 | /* AxisInformation */ |
| 18515 | static UA_DataTypeMember AxisInformation_members[5] = { |
| 18516 | { |
| 18517 | UA_TYPENAME("EngineeringUnits") /* .memberName */ |
| 18518 | &UA_TYPES[UA_TYPES_EUINFORMATION], /* .memberType */ |
| 18519 | 0, /* .padding */ |
| 18520 | false, /* .isArray */ |
| 18521 | false /* .isOptional */ |
| 18522 | }, |
| 18523 | { |
| 18524 | UA_TYPENAME("EURange") /* .memberName */ |
| 18525 | &UA_TYPES[UA_TYPES_RANGE], /* .memberType */ |
| 18526 | offsetof(UA_AxisInformation, eURange) - offsetof(UA_AxisInformation, engineeringUnits) - sizeof(UA_EUInformation), /* .padding */ |
| 18527 | false, /* .isArray */ |
| 18528 | false /* .isOptional */ |
| 18529 | }, |
| 18530 | { |
| 18531 | UA_TYPENAME("Title") /* .memberName */ |
| 18532 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 18533 | offsetof(UA_AxisInformation, title) - offsetof(UA_AxisInformation, eURange) - sizeof(UA_Range), /* .padding */ |
| 18534 | false, /* .isArray */ |
| 18535 | false /* .isOptional */ |
| 18536 | }, |
| 18537 | { |
| 18538 | UA_TYPENAME("AxisScaleType") /* .memberName */ |
| 18539 | &UA_TYPES[UA_TYPES_AXISSCALEENUMERATION], /* .memberType */ |
| 18540 | offsetof(UA_AxisInformation, axisScaleType) - offsetof(UA_AxisInformation, title) - sizeof(UA_LocalizedText), /* .padding */ |
| 18541 | false, /* .isArray */ |
| 18542 | false /* .isOptional */ |
| 18543 | }, |
| 18544 | { |
| 18545 | UA_TYPENAME("AxisSteps") /* .memberName */ |
| 18546 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 18547 | offsetof(UA_AxisInformation, axisStepsSize) - offsetof(UA_AxisInformation, axisScaleType) - sizeof(UA_AxisScaleEnumeration), /* .padding */ |
| 18548 | true, /* .isArray */ |
| 18549 | false /* .isOptional */ |
| 18550 | },}; |
| 18551 | |
| 18552 | /* XVType */ |
| 18553 | static UA_DataTypeMember XVType_members[2] = { |
| 18554 | { |
| 18555 | UA_TYPENAME("X") /* .memberName */ |
| 18556 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 18557 | 0, /* .padding */ |
| 18558 | false, /* .isArray */ |
| 18559 | false /* .isOptional */ |
| 18560 | }, |
| 18561 | { |
| 18562 | UA_TYPENAME("Value") /* .memberName */ |
| 18563 | &UA_TYPES[UA_TYPES_FLOAT], /* .memberType */ |
| 18564 | offsetof(UA_XVType, value) - offsetof(UA_XVType, x) - sizeof(UA_Double), /* .padding */ |
| 18565 | false, /* .isArray */ |
| 18566 | false /* .isOptional */ |
| 18567 | },}; |
| 18568 | |
| 18569 | /* ProgramDiagnosticDataType */ |
| 18570 | static UA_DataTypeMember ProgramDiagnosticDataType_members[10] = { |
| 18571 | { |
| 18572 | UA_TYPENAME("CreateSessionId") /* .memberName */ |
| 18573 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18574 | 0, /* .padding */ |
| 18575 | false, /* .isArray */ |
| 18576 | false /* .isOptional */ |
| 18577 | }, |
| 18578 | { |
| 18579 | UA_TYPENAME("CreateClientName") /* .memberName */ |
| 18580 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18581 | offsetof(UA_ProgramDiagnosticDataType, createClientName) - offsetof(UA_ProgramDiagnosticDataType, createSessionId) - sizeof(UA_NodeId), /* .padding */ |
| 18582 | false, /* .isArray */ |
| 18583 | false /* .isOptional */ |
| 18584 | }, |
| 18585 | { |
| 18586 | UA_TYPENAME("InvocationCreationTime") /* .memberName */ |
| 18587 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 18588 | offsetof(UA_ProgramDiagnosticDataType, invocationCreationTime) - offsetof(UA_ProgramDiagnosticDataType, createClientName) - sizeof(UA_String), /* .padding */ |
| 18589 | false, /* .isArray */ |
| 18590 | false /* .isOptional */ |
| 18591 | }, |
| 18592 | { |
| 18593 | UA_TYPENAME("LastTransitionTime") /* .memberName */ |
| 18594 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 18595 | offsetof(UA_ProgramDiagnosticDataType, lastTransitionTime) - offsetof(UA_ProgramDiagnosticDataType, invocationCreationTime) - sizeof(UA_DateTime), /* .padding */ |
| 18596 | false, /* .isArray */ |
| 18597 | false /* .isOptional */ |
| 18598 | }, |
| 18599 | { |
| 18600 | UA_TYPENAME("LastMethodCall") /* .memberName */ |
| 18601 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18602 | offsetof(UA_ProgramDiagnosticDataType, lastMethodCall) - offsetof(UA_ProgramDiagnosticDataType, lastTransitionTime) - sizeof(UA_DateTime), /* .padding */ |
| 18603 | false, /* .isArray */ |
| 18604 | false /* .isOptional */ |
| 18605 | }, |
| 18606 | { |
| 18607 | UA_TYPENAME("LastMethodSessionId") /* .memberName */ |
| 18608 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18609 | offsetof(UA_ProgramDiagnosticDataType, lastMethodSessionId) - offsetof(UA_ProgramDiagnosticDataType, lastMethodCall) - sizeof(UA_String), /* .padding */ |
| 18610 | false, /* .isArray */ |
| 18611 | false /* .isOptional */ |
| 18612 | }, |
| 18613 | { |
| 18614 | UA_TYPENAME("LastMethodInputArguments") /* .memberName */ |
| 18615 | &UA_TYPES[UA_TYPES_ARGUMENT], /* .memberType */ |
| 18616 | offsetof(UA_ProgramDiagnosticDataType, lastMethodInputArgumentsSize) - offsetof(UA_ProgramDiagnosticDataType, lastMethodSessionId) - sizeof(UA_NodeId), /* .padding */ |
| 18617 | true, /* .isArray */ |
| 18618 | false /* .isOptional */ |
| 18619 | }, |
| 18620 | { |
| 18621 | UA_TYPENAME("LastMethodOutputArguments") /* .memberName */ |
| 18622 | &UA_TYPES[UA_TYPES_ARGUMENT], /* .memberType */ |
| 18623 | offsetof(UA_ProgramDiagnosticDataType, lastMethodOutputArgumentsSize) - offsetof(UA_ProgramDiagnosticDataType, lastMethodInputArguments) - sizeof(void *), /* .padding */ |
| 18624 | true, /* .isArray */ |
| 18625 | false /* .isOptional */ |
| 18626 | }, |
| 18627 | { |
| 18628 | UA_TYPENAME("LastMethodCallTime") /* .memberName */ |
| 18629 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 18630 | offsetof(UA_ProgramDiagnosticDataType, lastMethodCallTime) - offsetof(UA_ProgramDiagnosticDataType, lastMethodOutputArguments) - sizeof(void *), /* .padding */ |
| 18631 | false, /* .isArray */ |
| 18632 | false /* .isOptional */ |
| 18633 | }, |
| 18634 | { |
| 18635 | UA_TYPENAME("LastMethodReturnStatus") /* .memberName */ |
| 18636 | &UA_TYPES[UA_TYPES_STATUSRESULT], /* .memberType */ |
| 18637 | offsetof(UA_ProgramDiagnosticDataType, lastMethodReturnStatus) - offsetof(UA_ProgramDiagnosticDataType, lastMethodCallTime) - sizeof(UA_DateTime), /* .padding */ |
| 18638 | false, /* .isArray */ |
| 18639 | false /* .isOptional */ |
| 18640 | },}; |
| 18641 | |
| 18642 | /* ProgramDiagnostic2DataType */ |
| 18643 | static UA_DataTypeMember ProgramDiagnostic2DataType_members[12] = { |
| 18644 | { |
| 18645 | UA_TYPENAME("CreateSessionId") /* .memberName */ |
| 18646 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18647 | 0, /* .padding */ |
| 18648 | false, /* .isArray */ |
| 18649 | false /* .isOptional */ |
| 18650 | }, |
| 18651 | { |
| 18652 | UA_TYPENAME("CreateClientName") /* .memberName */ |
| 18653 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18654 | offsetof(UA_ProgramDiagnostic2DataType, createClientName) - offsetof(UA_ProgramDiagnostic2DataType, createSessionId) - sizeof(UA_NodeId), /* .padding */ |
| 18655 | false, /* .isArray */ |
| 18656 | false /* .isOptional */ |
| 18657 | }, |
| 18658 | { |
| 18659 | UA_TYPENAME("InvocationCreationTime") /* .memberName */ |
| 18660 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 18661 | offsetof(UA_ProgramDiagnostic2DataType, invocationCreationTime) - offsetof(UA_ProgramDiagnostic2DataType, createClientName) - sizeof(UA_String), /* .padding */ |
| 18662 | false, /* .isArray */ |
| 18663 | false /* .isOptional */ |
| 18664 | }, |
| 18665 | { |
| 18666 | UA_TYPENAME("LastTransitionTime") /* .memberName */ |
| 18667 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 18668 | offsetof(UA_ProgramDiagnostic2DataType, lastTransitionTime) - offsetof(UA_ProgramDiagnostic2DataType, invocationCreationTime) - sizeof(UA_DateTime), /* .padding */ |
| 18669 | false, /* .isArray */ |
| 18670 | false /* .isOptional */ |
| 18671 | }, |
| 18672 | { |
| 18673 | UA_TYPENAME("LastMethodCall") /* .memberName */ |
| 18674 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18675 | offsetof(UA_ProgramDiagnostic2DataType, lastMethodCall) - offsetof(UA_ProgramDiagnostic2DataType, lastTransitionTime) - sizeof(UA_DateTime), /* .padding */ |
| 18676 | false, /* .isArray */ |
| 18677 | false /* .isOptional */ |
| 18678 | }, |
| 18679 | { |
| 18680 | UA_TYPENAME("LastMethodSessionId") /* .memberName */ |
| 18681 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18682 | offsetof(UA_ProgramDiagnostic2DataType, lastMethodSessionId) - offsetof(UA_ProgramDiagnostic2DataType, lastMethodCall) - sizeof(UA_String), /* .padding */ |
| 18683 | false, /* .isArray */ |
| 18684 | false /* .isOptional */ |
| 18685 | }, |
| 18686 | { |
| 18687 | UA_TYPENAME("LastMethodInputArguments") /* .memberName */ |
| 18688 | &UA_TYPES[UA_TYPES_ARGUMENT], /* .memberType */ |
| 18689 | offsetof(UA_ProgramDiagnostic2DataType, lastMethodInputArgumentsSize) - offsetof(UA_ProgramDiagnostic2DataType, lastMethodSessionId) - sizeof(UA_NodeId), /* .padding */ |
| 18690 | true, /* .isArray */ |
| 18691 | false /* .isOptional */ |
| 18692 | }, |
| 18693 | { |
| 18694 | UA_TYPENAME("LastMethodOutputArguments") /* .memberName */ |
| 18695 | &UA_TYPES[UA_TYPES_ARGUMENT], /* .memberType */ |
| 18696 | offsetof(UA_ProgramDiagnostic2DataType, lastMethodOutputArgumentsSize) - offsetof(UA_ProgramDiagnostic2DataType, lastMethodInputArguments) - sizeof(void *), /* .padding */ |
| 18697 | true, /* .isArray */ |
| 18698 | false /* .isOptional */ |
| 18699 | }, |
| 18700 | { |
| 18701 | UA_TYPENAME("LastMethodInputValues") /* .memberName */ |
| 18702 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 18703 | offsetof(UA_ProgramDiagnostic2DataType, lastMethodInputValuesSize) - offsetof(UA_ProgramDiagnostic2DataType, lastMethodOutputArguments) - sizeof(void *), /* .padding */ |
| 18704 | true, /* .isArray */ |
| 18705 | false /* .isOptional */ |
| 18706 | }, |
| 18707 | { |
| 18708 | UA_TYPENAME("LastMethodOutputValues") /* .memberName */ |
| 18709 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 18710 | offsetof(UA_ProgramDiagnostic2DataType, lastMethodOutputValuesSize) - offsetof(UA_ProgramDiagnostic2DataType, lastMethodInputValues) - sizeof(void *), /* .padding */ |
| 18711 | true, /* .isArray */ |
| 18712 | false /* .isOptional */ |
| 18713 | }, |
| 18714 | { |
| 18715 | UA_TYPENAME("LastMethodCallTime") /* .memberName */ |
| 18716 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 18717 | offsetof(UA_ProgramDiagnostic2DataType, lastMethodCallTime) - offsetof(UA_ProgramDiagnostic2DataType, lastMethodOutputValues) - sizeof(void *), /* .padding */ |
| 18718 | false, /* .isArray */ |
| 18719 | false /* .isOptional */ |
| 18720 | }, |
| 18721 | { |
| 18722 | UA_TYPENAME("LastMethodReturnStatus") /* .memberName */ |
| 18723 | &UA_TYPES[UA_TYPES_STATUSCODE], /* .memberType */ |
| 18724 | offsetof(UA_ProgramDiagnostic2DataType, lastMethodReturnStatus) - offsetof(UA_ProgramDiagnostic2DataType, lastMethodCallTime) - sizeof(UA_DateTime), /* .padding */ |
| 18725 | false, /* .isArray */ |
| 18726 | false /* .isOptional */ |
| 18727 | },}; |
| 18728 | |
| 18729 | /* Annotation */ |
| 18730 | static UA_DataTypeMember Annotation_members[3] = { |
| 18731 | { |
| 18732 | UA_TYPENAME("Message") /* .memberName */ |
| 18733 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18734 | 0, /* .padding */ |
| 18735 | false, /* .isArray */ |
| 18736 | false /* .isOptional */ |
| 18737 | }, |
| 18738 | { |
| 18739 | UA_TYPENAME("UserName") /* .memberName */ |
| 18740 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18741 | offsetof(UA_Annotation, userName) - offsetof(UA_Annotation, message) - sizeof(UA_String), /* .padding */ |
| 18742 | false, /* .isArray */ |
| 18743 | false /* .isOptional */ |
| 18744 | }, |
| 18745 | { |
| 18746 | UA_TYPENAME("AnnotationTime") /* .memberName */ |
| 18747 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 18748 | offsetof(UA_Annotation, annotationTime) - offsetof(UA_Annotation, userName) - sizeof(UA_String), /* .padding */ |
| 18749 | false, /* .isArray */ |
| 18750 | false /* .isOptional */ |
| 18751 | },}; |
| 18752 | |
| 18753 | /* ExceptionDeviationFormat */ |
| 18754 | #define ExceptionDeviationFormat_members NULL |
| 18755 | |
| 18756 | /* EndpointType */ |
| 18757 | static UA_DataTypeMember EndpointType_members[4] = { |
| 18758 | { |
| 18759 | UA_TYPENAME("EndpointUrl") /* .memberName */ |
| 18760 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18761 | 0, /* .padding */ |
| 18762 | false, /* .isArray */ |
| 18763 | false /* .isOptional */ |
| 18764 | }, |
| 18765 | { |
| 18766 | UA_TYPENAME("SecurityMode") /* .memberName */ |
| 18767 | &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */ |
| 18768 | offsetof(UA_EndpointType, securityMode) - offsetof(UA_EndpointType, endpointUrl) - sizeof(UA_String), /* .padding */ |
| 18769 | false, /* .isArray */ |
| 18770 | false /* .isOptional */ |
| 18771 | }, |
| 18772 | { |
| 18773 | UA_TYPENAME("SecurityPolicyUri") /* .memberName */ |
| 18774 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18775 | offsetof(UA_EndpointType, securityPolicyUri) - offsetof(UA_EndpointType, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */ |
| 18776 | false, /* .isArray */ |
| 18777 | false /* .isOptional */ |
| 18778 | }, |
| 18779 | { |
| 18780 | UA_TYPENAME("TransportProfileUri") /* .memberName */ |
| 18781 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18782 | offsetof(UA_EndpointType, transportProfileUri) - offsetof(UA_EndpointType, securityPolicyUri) - sizeof(UA_String), /* .padding */ |
| 18783 | false, /* .isArray */ |
| 18784 | false /* .isOptional */ |
| 18785 | },}; |
| 18786 | |
| 18787 | /* StructureDescription */ |
| 18788 | static UA_DataTypeMember StructureDescription_members[3] = { |
| 18789 | { |
| 18790 | UA_TYPENAME("DataTypeId") /* .memberName */ |
| 18791 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18792 | 0, /* .padding */ |
| 18793 | false, /* .isArray */ |
| 18794 | false /* .isOptional */ |
| 18795 | }, |
| 18796 | { |
| 18797 | UA_TYPENAME("Name") /* .memberName */ |
| 18798 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 18799 | offsetof(UA_StructureDescription, name) - offsetof(UA_StructureDescription, dataTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 18800 | false, /* .isArray */ |
| 18801 | false /* .isOptional */ |
| 18802 | }, |
| 18803 | { |
| 18804 | UA_TYPENAME("StructureDefinition") /* .memberName */ |
| 18805 | &UA_TYPES[UA_TYPES_STRUCTUREDEFINITION], /* .memberType */ |
| 18806 | offsetof(UA_StructureDescription, structureDefinition) - offsetof(UA_StructureDescription, name) - sizeof(UA_QualifiedName), /* .padding */ |
| 18807 | false, /* .isArray */ |
| 18808 | false /* .isOptional */ |
| 18809 | },}; |
| 18810 | |
| 18811 | /* FieldMetaData */ |
| 18812 | static UA_DataTypeMember FieldMetaData_members[10] = { |
| 18813 | { |
| 18814 | UA_TYPENAME("Name") /* .memberName */ |
| 18815 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18816 | 0, /* .padding */ |
| 18817 | false, /* .isArray */ |
| 18818 | false /* .isOptional */ |
| 18819 | }, |
| 18820 | { |
| 18821 | UA_TYPENAME("Description") /* .memberName */ |
| 18822 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 18823 | offsetof(UA_FieldMetaData, description) - offsetof(UA_FieldMetaData, name) - sizeof(UA_String), /* .padding */ |
| 18824 | false, /* .isArray */ |
| 18825 | false /* .isOptional */ |
| 18826 | }, |
| 18827 | { |
| 18828 | UA_TYPENAME("FieldFlags") /* .memberName */ |
| 18829 | &UA_TYPES[UA_TYPES_DATASETFIELDFLAGS], /* .memberType */ |
| 18830 | offsetof(UA_FieldMetaData, fieldFlags) - offsetof(UA_FieldMetaData, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 18831 | false, /* .isArray */ |
| 18832 | false /* .isOptional */ |
| 18833 | }, |
| 18834 | { |
| 18835 | UA_TYPENAME("BuiltInType") /* .memberName */ |
| 18836 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 18837 | offsetof(UA_FieldMetaData, builtInType) - offsetof(UA_FieldMetaData, fieldFlags) - sizeof(UA_DataSetFieldFlags), /* .padding */ |
| 18838 | false, /* .isArray */ |
| 18839 | false /* .isOptional */ |
| 18840 | }, |
| 18841 | { |
| 18842 | UA_TYPENAME("DataType") /* .memberName */ |
| 18843 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18844 | offsetof(UA_FieldMetaData, dataType) - offsetof(UA_FieldMetaData, builtInType) - sizeof(UA_Byte), /* .padding */ |
| 18845 | false, /* .isArray */ |
| 18846 | false /* .isOptional */ |
| 18847 | }, |
| 18848 | { |
| 18849 | UA_TYPENAME("ValueRank") /* .memberName */ |
| 18850 | &UA_TYPES[UA_TYPES_INT32], /* .memberType */ |
| 18851 | offsetof(UA_FieldMetaData, valueRank) - offsetof(UA_FieldMetaData, dataType) - sizeof(UA_NodeId), /* .padding */ |
| 18852 | false, /* .isArray */ |
| 18853 | false /* .isOptional */ |
| 18854 | }, |
| 18855 | { |
| 18856 | UA_TYPENAME("ArrayDimensions") /* .memberName */ |
| 18857 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18858 | offsetof(UA_FieldMetaData, arrayDimensionsSize) - offsetof(UA_FieldMetaData, valueRank) - sizeof(UA_Int32), /* .padding */ |
| 18859 | true, /* .isArray */ |
| 18860 | false /* .isOptional */ |
| 18861 | }, |
| 18862 | { |
| 18863 | UA_TYPENAME("MaxStringLength") /* .memberName */ |
| 18864 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18865 | offsetof(UA_FieldMetaData, maxStringLength) - offsetof(UA_FieldMetaData, arrayDimensions) - sizeof(void *), /* .padding */ |
| 18866 | false, /* .isArray */ |
| 18867 | false /* .isOptional */ |
| 18868 | }, |
| 18869 | { |
| 18870 | UA_TYPENAME("DataSetFieldId") /* .memberName */ |
| 18871 | &UA_TYPES[UA_TYPES_GUID], /* .memberType */ |
| 18872 | offsetof(UA_FieldMetaData, dataSetFieldId) - offsetof(UA_FieldMetaData, maxStringLength) - sizeof(UA_UInt32), /* .padding */ |
| 18873 | false, /* .isArray */ |
| 18874 | false /* .isOptional */ |
| 18875 | }, |
| 18876 | { |
| 18877 | UA_TYPENAME("Properties") /* .memberName */ |
| 18878 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 18879 | offsetof(UA_FieldMetaData, propertiesSize) - offsetof(UA_FieldMetaData, dataSetFieldId) - sizeof(UA_Guid), /* .padding */ |
| 18880 | true, /* .isArray */ |
| 18881 | false /* .isOptional */ |
| 18882 | },}; |
| 18883 | |
| 18884 | /* PublishedEventsDataType */ |
| 18885 | static UA_DataTypeMember PublishedEventsDataType_members[3] = { |
| 18886 | { |
| 18887 | UA_TYPENAME("EventNotifier") /* .memberName */ |
| 18888 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 18889 | 0, /* .padding */ |
| 18890 | false, /* .isArray */ |
| 18891 | false /* .isOptional */ |
| 18892 | }, |
| 18893 | { |
| 18894 | UA_TYPENAME("SelectedFields") /* .memberName */ |
| 18895 | &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND], /* .memberType */ |
| 18896 | offsetof(UA_PublishedEventsDataType, selectedFieldsSize) - offsetof(UA_PublishedEventsDataType, eventNotifier) - sizeof(UA_NodeId), /* .padding */ |
| 18897 | true, /* .isArray */ |
| 18898 | false /* .isOptional */ |
| 18899 | }, |
| 18900 | { |
| 18901 | UA_TYPENAME("Filter") /* .memberName */ |
| 18902 | &UA_TYPES[UA_TYPES_CONTENTFILTER], /* .memberType */ |
| 18903 | offsetof(UA_PublishedEventsDataType, filter) - offsetof(UA_PublishedEventsDataType, selectedFields) - sizeof(void *), /* .padding */ |
| 18904 | false, /* .isArray */ |
| 18905 | false /* .isOptional */ |
| 18906 | },}; |
| 18907 | |
| 18908 | /* PubSubGroupDataType */ |
| 18909 | static UA_DataTypeMember PubSubGroupDataType_members[7] = { |
| 18910 | { |
| 18911 | UA_TYPENAME("Name") /* .memberName */ |
| 18912 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18913 | 0, /* .padding */ |
| 18914 | false, /* .isArray */ |
| 18915 | false /* .isOptional */ |
| 18916 | }, |
| 18917 | { |
| 18918 | UA_TYPENAME("Enabled") /* .memberName */ |
| 18919 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 18920 | offsetof(UA_PubSubGroupDataType, enabled) - offsetof(UA_PubSubGroupDataType, name) - sizeof(UA_String), /* .padding */ |
| 18921 | false, /* .isArray */ |
| 18922 | false /* .isOptional */ |
| 18923 | }, |
| 18924 | { |
| 18925 | UA_TYPENAME("SecurityMode") /* .memberName */ |
| 18926 | &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */ |
| 18927 | offsetof(UA_PubSubGroupDataType, securityMode) - offsetof(UA_PubSubGroupDataType, enabled) - sizeof(UA_Boolean), /* .padding */ |
| 18928 | false, /* .isArray */ |
| 18929 | false /* .isOptional */ |
| 18930 | }, |
| 18931 | { |
| 18932 | UA_TYPENAME("SecurityGroupId") /* .memberName */ |
| 18933 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18934 | offsetof(UA_PubSubGroupDataType, securityGroupId) - offsetof(UA_PubSubGroupDataType, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */ |
| 18935 | false, /* .isArray */ |
| 18936 | false /* .isOptional */ |
| 18937 | }, |
| 18938 | { |
| 18939 | UA_TYPENAME("SecurityKeyServices") /* .memberName */ |
| 18940 | &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */ |
| 18941 | offsetof(UA_PubSubGroupDataType, securityKeyServicesSize) - offsetof(UA_PubSubGroupDataType, securityGroupId) - sizeof(UA_String), /* .padding */ |
| 18942 | true, /* .isArray */ |
| 18943 | false /* .isOptional */ |
| 18944 | }, |
| 18945 | { |
| 18946 | UA_TYPENAME("MaxNetworkMessageSize") /* .memberName */ |
| 18947 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 18948 | offsetof(UA_PubSubGroupDataType, maxNetworkMessageSize) - offsetof(UA_PubSubGroupDataType, securityKeyServices) - sizeof(void *), /* .padding */ |
| 18949 | false, /* .isArray */ |
| 18950 | false /* .isOptional */ |
| 18951 | }, |
| 18952 | { |
| 18953 | UA_TYPENAME("GroupProperties") /* .memberName */ |
| 18954 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 18955 | offsetof(UA_PubSubGroupDataType, groupPropertiesSize) - offsetof(UA_PubSubGroupDataType, maxNetworkMessageSize) - sizeof(UA_UInt32), /* .padding */ |
| 18956 | true, /* .isArray */ |
| 18957 | false /* .isOptional */ |
| 18958 | },}; |
| 18959 | |
| 18960 | /* WriterGroupDataType */ |
| 18961 | static UA_DataTypeMember WriterGroupDataType_members[16] = { |
| 18962 | { |
| 18963 | UA_TYPENAME("Name") /* .memberName */ |
| 18964 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18965 | 0, /* .padding */ |
| 18966 | false, /* .isArray */ |
| 18967 | false /* .isOptional */ |
| 18968 | }, |
| 18969 | { |
| 18970 | UA_TYPENAME("Enabled") /* .memberName */ |
| 18971 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 18972 | offsetof(UA_WriterGroupDataType, enabled) - offsetof(UA_WriterGroupDataType, name) - sizeof(UA_String), /* .padding */ |
| 18973 | false, /* .isArray */ |
| 18974 | false /* .isOptional */ |
| 18975 | }, |
| 18976 | { |
| 18977 | UA_TYPENAME("SecurityMode") /* .memberName */ |
| 18978 | &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */ |
| 18979 | offsetof(UA_WriterGroupDataType, securityMode) - offsetof(UA_WriterGroupDataType, enabled) - sizeof(UA_Boolean), /* .padding */ |
| 18980 | false, /* .isArray */ |
| 18981 | false /* .isOptional */ |
| 18982 | }, |
| 18983 | { |
| 18984 | UA_TYPENAME("SecurityGroupId") /* .memberName */ |
| 18985 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 18986 | offsetof(UA_WriterGroupDataType, securityGroupId) - offsetof(UA_WriterGroupDataType, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */ |
| 18987 | false, /* .isArray */ |
| 18988 | false /* .isOptional */ |
| 18989 | }, |
| 18990 | { |
| 18991 | UA_TYPENAME("SecurityKeyServices") /* .memberName */ |
| 18992 | &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */ |
| 18993 | offsetof(UA_WriterGroupDataType, securityKeyServicesSize) - offsetof(UA_WriterGroupDataType, securityGroupId) - sizeof(UA_String), /* .padding */ |
| 18994 | true, /* .isArray */ |
| 18995 | false /* .isOptional */ |
| 18996 | }, |
| 18997 | { |
| 18998 | UA_TYPENAME("MaxNetworkMessageSize") /* .memberName */ |
| 18999 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 19000 | offsetof(UA_WriterGroupDataType, maxNetworkMessageSize) - offsetof(UA_WriterGroupDataType, securityKeyServices) - sizeof(void *), /* .padding */ |
| 19001 | false, /* .isArray */ |
| 19002 | false /* .isOptional */ |
| 19003 | }, |
| 19004 | { |
| 19005 | UA_TYPENAME("GroupProperties") /* .memberName */ |
| 19006 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 19007 | offsetof(UA_WriterGroupDataType, groupPropertiesSize) - offsetof(UA_WriterGroupDataType, maxNetworkMessageSize) - sizeof(UA_UInt32), /* .padding */ |
| 19008 | true, /* .isArray */ |
| 19009 | false /* .isOptional */ |
| 19010 | }, |
| 19011 | { |
| 19012 | UA_TYPENAME("WriterGroupId") /* .memberName */ |
| 19013 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 19014 | offsetof(UA_WriterGroupDataType, writerGroupId) - offsetof(UA_WriterGroupDataType, groupProperties) - sizeof(void *), /* .padding */ |
| 19015 | false, /* .isArray */ |
| 19016 | false /* .isOptional */ |
| 19017 | }, |
| 19018 | { |
| 19019 | UA_TYPENAME("PublishingInterval") /* .memberName */ |
| 19020 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 19021 | offsetof(UA_WriterGroupDataType, publishingInterval) - offsetof(UA_WriterGroupDataType, writerGroupId) - sizeof(UA_UInt16), /* .padding */ |
| 19022 | false, /* .isArray */ |
| 19023 | false /* .isOptional */ |
| 19024 | }, |
| 19025 | { |
| 19026 | UA_TYPENAME("KeepAliveTime") /* .memberName */ |
| 19027 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 19028 | offsetof(UA_WriterGroupDataType, keepAliveTime) - offsetof(UA_WriterGroupDataType, publishingInterval) - sizeof(UA_Double), /* .padding */ |
| 19029 | false, /* .isArray */ |
| 19030 | false /* .isOptional */ |
| 19031 | }, |
| 19032 | { |
| 19033 | UA_TYPENAME("Priority") /* .memberName */ |
| 19034 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 19035 | offsetof(UA_WriterGroupDataType, priority) - offsetof(UA_WriterGroupDataType, keepAliveTime) - sizeof(UA_Double), /* .padding */ |
| 19036 | false, /* .isArray */ |
| 19037 | false /* .isOptional */ |
| 19038 | }, |
| 19039 | { |
| 19040 | UA_TYPENAME("LocaleIds") /* .memberName */ |
| 19041 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19042 | offsetof(UA_WriterGroupDataType, localeIdsSize) - offsetof(UA_WriterGroupDataType, priority) - sizeof(UA_Byte), /* .padding */ |
| 19043 | true, /* .isArray */ |
| 19044 | false /* .isOptional */ |
| 19045 | }, |
| 19046 | { |
| 19047 | UA_TYPENAME("HeaderLayoutUri") /* .memberName */ |
| 19048 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19049 | offsetof(UA_WriterGroupDataType, headerLayoutUri) - offsetof(UA_WriterGroupDataType, localeIds) - sizeof(void *), /* .padding */ |
| 19050 | false, /* .isArray */ |
| 19051 | false /* .isOptional */ |
| 19052 | }, |
| 19053 | { |
| 19054 | UA_TYPENAME("TransportSettings") /* .memberName */ |
| 19055 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 19056 | offsetof(UA_WriterGroupDataType, transportSettings) - offsetof(UA_WriterGroupDataType, headerLayoutUri) - sizeof(UA_String), /* .padding */ |
| 19057 | false, /* .isArray */ |
| 19058 | false /* .isOptional */ |
| 19059 | }, |
| 19060 | { |
| 19061 | UA_TYPENAME("MessageSettings") /* .memberName */ |
| 19062 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 19063 | offsetof(UA_WriterGroupDataType, messageSettings) - offsetof(UA_WriterGroupDataType, transportSettings) - sizeof(UA_ExtensionObject), /* .padding */ |
| 19064 | false, /* .isArray */ |
| 19065 | false /* .isOptional */ |
| 19066 | }, |
| 19067 | { |
| 19068 | UA_TYPENAME("DataSetWriters") /* .memberName */ |
| 19069 | &UA_TYPES[UA_TYPES_DATASETWRITERDATATYPE], /* .memberType */ |
| 19070 | offsetof(UA_WriterGroupDataType, dataSetWritersSize) - offsetof(UA_WriterGroupDataType, messageSettings) - sizeof(UA_ExtensionObject), /* .padding */ |
| 19071 | true, /* .isArray */ |
| 19072 | false /* .isOptional */ |
| 19073 | },}; |
| 19074 | |
| 19075 | /* FieldTargetDataType */ |
| 19076 | static UA_DataTypeMember FieldTargetDataType_members[7] = { |
| 19077 | { |
| 19078 | UA_TYPENAME("DataSetFieldId") /* .memberName */ |
| 19079 | &UA_TYPES[UA_TYPES_GUID], /* .memberType */ |
| 19080 | 0, /* .padding */ |
| 19081 | false, /* .isArray */ |
| 19082 | false /* .isOptional */ |
| 19083 | }, |
| 19084 | { |
| 19085 | UA_TYPENAME("ReceiverIndexRange") /* .memberName */ |
| 19086 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19087 | offsetof(UA_FieldTargetDataType, receiverIndexRange) - offsetof(UA_FieldTargetDataType, dataSetFieldId) - sizeof(UA_Guid), /* .padding */ |
| 19088 | false, /* .isArray */ |
| 19089 | false /* .isOptional */ |
| 19090 | }, |
| 19091 | { |
| 19092 | UA_TYPENAME("TargetNodeId") /* .memberName */ |
| 19093 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 19094 | offsetof(UA_FieldTargetDataType, targetNodeId) - offsetof(UA_FieldTargetDataType, receiverIndexRange) - sizeof(UA_String), /* .padding */ |
| 19095 | false, /* .isArray */ |
| 19096 | false /* .isOptional */ |
| 19097 | }, |
| 19098 | { |
| 19099 | UA_TYPENAME("AttributeId") /* .memberName */ |
| 19100 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 19101 | offsetof(UA_FieldTargetDataType, attributeId) - offsetof(UA_FieldTargetDataType, targetNodeId) - sizeof(UA_NodeId), /* .padding */ |
| 19102 | false, /* .isArray */ |
| 19103 | false /* .isOptional */ |
| 19104 | }, |
| 19105 | { |
| 19106 | UA_TYPENAME("WriteIndexRange") /* .memberName */ |
| 19107 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19108 | offsetof(UA_FieldTargetDataType, writeIndexRange) - offsetof(UA_FieldTargetDataType, attributeId) - sizeof(UA_UInt32), /* .padding */ |
| 19109 | false, /* .isArray */ |
| 19110 | false /* .isOptional */ |
| 19111 | }, |
| 19112 | { |
| 19113 | UA_TYPENAME("OverrideValueHandling") /* .memberName */ |
| 19114 | &UA_TYPES[UA_TYPES_OVERRIDEVALUEHANDLING], /* .memberType */ |
| 19115 | offsetof(UA_FieldTargetDataType, overrideValueHandling) - offsetof(UA_FieldTargetDataType, writeIndexRange) - sizeof(UA_String), /* .padding */ |
| 19116 | false, /* .isArray */ |
| 19117 | false /* .isOptional */ |
| 19118 | }, |
| 19119 | { |
| 19120 | UA_TYPENAME("OverrideValue") /* .memberName */ |
| 19121 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 19122 | offsetof(UA_FieldTargetDataType, overrideValue) - offsetof(UA_FieldTargetDataType, overrideValueHandling) - sizeof(UA_OverrideValueHandling), /* .padding */ |
| 19123 | false, /* .isArray */ |
| 19124 | false /* .isOptional */ |
| 19125 | },}; |
| 19126 | |
| 19127 | /* SubscribedDataSetMirrorDataType */ |
| 19128 | static UA_DataTypeMember SubscribedDataSetMirrorDataType_members[2] = { |
| 19129 | { |
| 19130 | UA_TYPENAME("ParentNodeName") /* .memberName */ |
| 19131 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19132 | 0, /* .padding */ |
| 19133 | false, /* .isArray */ |
| 19134 | false /* .isOptional */ |
| 19135 | }, |
| 19136 | { |
| 19137 | UA_TYPENAME("RolePermissions") /* .memberName */ |
| 19138 | &UA_TYPES[UA_TYPES_ROLEPERMISSIONTYPE], /* .memberType */ |
| 19139 | offsetof(UA_SubscribedDataSetMirrorDataType, rolePermissionsSize) - offsetof(UA_SubscribedDataSetMirrorDataType, parentNodeName) - sizeof(UA_String), /* .padding */ |
| 19140 | true, /* .isArray */ |
| 19141 | false /* .isOptional */ |
| 19142 | },}; |
| 19143 | |
| 19144 | /* SecurityGroupDataType */ |
| 19145 | static UA_DataTypeMember SecurityGroupDataType_members[9] = { |
| 19146 | { |
| 19147 | UA_TYPENAME("Name") /* .memberName */ |
| 19148 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19149 | 0, /* .padding */ |
| 19150 | false, /* .isArray */ |
| 19151 | false /* .isOptional */ |
| 19152 | }, |
| 19153 | { |
| 19154 | UA_TYPENAME("SecurityGroupFolder") /* .memberName */ |
| 19155 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19156 | offsetof(UA_SecurityGroupDataType, securityGroupFolderSize) - offsetof(UA_SecurityGroupDataType, name) - sizeof(UA_String), /* .padding */ |
| 19157 | true, /* .isArray */ |
| 19158 | false /* .isOptional */ |
| 19159 | }, |
| 19160 | { |
| 19161 | UA_TYPENAME("KeyLifetime") /* .memberName */ |
| 19162 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 19163 | offsetof(UA_SecurityGroupDataType, keyLifetime) - offsetof(UA_SecurityGroupDataType, securityGroupFolder) - sizeof(void *), /* .padding */ |
| 19164 | false, /* .isArray */ |
| 19165 | false /* .isOptional */ |
| 19166 | }, |
| 19167 | { |
| 19168 | UA_TYPENAME("SecurityPolicyUri") /* .memberName */ |
| 19169 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19170 | offsetof(UA_SecurityGroupDataType, securityPolicyUri) - offsetof(UA_SecurityGroupDataType, keyLifetime) - sizeof(UA_Double), /* .padding */ |
| 19171 | false, /* .isArray */ |
| 19172 | false /* .isOptional */ |
| 19173 | }, |
| 19174 | { |
| 19175 | UA_TYPENAME("MaxFutureKeyCount") /* .memberName */ |
| 19176 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 19177 | offsetof(UA_SecurityGroupDataType, maxFutureKeyCount) - offsetof(UA_SecurityGroupDataType, securityPolicyUri) - sizeof(UA_String), /* .padding */ |
| 19178 | false, /* .isArray */ |
| 19179 | false /* .isOptional */ |
| 19180 | }, |
| 19181 | { |
| 19182 | UA_TYPENAME("MaxPastKeyCount") /* .memberName */ |
| 19183 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 19184 | offsetof(UA_SecurityGroupDataType, maxPastKeyCount) - offsetof(UA_SecurityGroupDataType, maxFutureKeyCount) - sizeof(UA_UInt32), /* .padding */ |
| 19185 | false, /* .isArray */ |
| 19186 | false /* .isOptional */ |
| 19187 | }, |
| 19188 | { |
| 19189 | UA_TYPENAME("SecurityGroupId") /* .memberName */ |
| 19190 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19191 | offsetof(UA_SecurityGroupDataType, securityGroupId) - offsetof(UA_SecurityGroupDataType, maxPastKeyCount) - sizeof(UA_UInt32), /* .padding */ |
| 19192 | false, /* .isArray */ |
| 19193 | false /* .isOptional */ |
| 19194 | }, |
| 19195 | { |
| 19196 | UA_TYPENAME("RolePermissions") /* .memberName */ |
| 19197 | &UA_TYPES[UA_TYPES_ROLEPERMISSIONTYPE], /* .memberType */ |
| 19198 | offsetof(UA_SecurityGroupDataType, rolePermissionsSize) - offsetof(UA_SecurityGroupDataType, securityGroupId) - sizeof(UA_String), /* .padding */ |
| 19199 | true, /* .isArray */ |
| 19200 | false /* .isOptional */ |
| 19201 | }, |
| 19202 | { |
| 19203 | UA_TYPENAME("GroupProperties") /* .memberName */ |
| 19204 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 19205 | offsetof(UA_SecurityGroupDataType, groupPropertiesSize) - offsetof(UA_SecurityGroupDataType, rolePermissions) - sizeof(void *), /* .padding */ |
| 19206 | true, /* .isArray */ |
| 19207 | false /* .isOptional */ |
| 19208 | },}; |
| 19209 | |
| 19210 | /* PubSubKeyPushTargetDataType */ |
| 19211 | static UA_DataTypeMember PubSubKeyPushTargetDataType_members[9] = { |
| 19212 | { |
| 19213 | UA_TYPENAME("ApplicationUri") /* .memberName */ |
| 19214 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19215 | 0, /* .padding */ |
| 19216 | false, /* .isArray */ |
| 19217 | false /* .isOptional */ |
| 19218 | }, |
| 19219 | { |
| 19220 | UA_TYPENAME("PushTargetFolder") /* .memberName */ |
| 19221 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19222 | offsetof(UA_PubSubKeyPushTargetDataType, pushTargetFolderSize) - offsetof(UA_PubSubKeyPushTargetDataType, applicationUri) - sizeof(UA_String), /* .padding */ |
| 19223 | true, /* .isArray */ |
| 19224 | false /* .isOptional */ |
| 19225 | }, |
| 19226 | { |
| 19227 | UA_TYPENAME("EndpointUrl") /* .memberName */ |
| 19228 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19229 | offsetof(UA_PubSubKeyPushTargetDataType, endpointUrl) - offsetof(UA_PubSubKeyPushTargetDataType, pushTargetFolder) - sizeof(void *), /* .padding */ |
| 19230 | false, /* .isArray */ |
| 19231 | false /* .isOptional */ |
| 19232 | }, |
| 19233 | { |
| 19234 | UA_TYPENAME("SecurityPolicyUri") /* .memberName */ |
| 19235 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19236 | offsetof(UA_PubSubKeyPushTargetDataType, securityPolicyUri) - offsetof(UA_PubSubKeyPushTargetDataType, endpointUrl) - sizeof(UA_String), /* .padding */ |
| 19237 | false, /* .isArray */ |
| 19238 | false /* .isOptional */ |
| 19239 | }, |
| 19240 | { |
| 19241 | UA_TYPENAME("UserTokenType") /* .memberName */ |
| 19242 | &UA_TYPES[UA_TYPES_USERTOKENPOLICY], /* .memberType */ |
| 19243 | offsetof(UA_PubSubKeyPushTargetDataType, userTokenType) - offsetof(UA_PubSubKeyPushTargetDataType, securityPolicyUri) - sizeof(UA_String), /* .padding */ |
| 19244 | false, /* .isArray */ |
| 19245 | false /* .isOptional */ |
| 19246 | }, |
| 19247 | { |
| 19248 | UA_TYPENAME("RequestedKeyCount") /* .memberName */ |
| 19249 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 19250 | offsetof(UA_PubSubKeyPushTargetDataType, requestedKeyCount) - offsetof(UA_PubSubKeyPushTargetDataType, userTokenType) - sizeof(UA_UserTokenPolicy), /* .padding */ |
| 19251 | false, /* .isArray */ |
| 19252 | false /* .isOptional */ |
| 19253 | }, |
| 19254 | { |
| 19255 | UA_TYPENAME("RetryInterval") /* .memberName */ |
| 19256 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 19257 | offsetof(UA_PubSubKeyPushTargetDataType, retryInterval) - offsetof(UA_PubSubKeyPushTargetDataType, requestedKeyCount) - sizeof(UA_UInt16), /* .padding */ |
| 19258 | false, /* .isArray */ |
| 19259 | false /* .isOptional */ |
| 19260 | }, |
| 19261 | { |
| 19262 | UA_TYPENAME("PushTargetProperties") /* .memberName */ |
| 19263 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 19264 | offsetof(UA_PubSubKeyPushTargetDataType, pushTargetPropertiesSize) - offsetof(UA_PubSubKeyPushTargetDataType, retryInterval) - sizeof(UA_Double), /* .padding */ |
| 19265 | true, /* .isArray */ |
| 19266 | false /* .isOptional */ |
| 19267 | }, |
| 19268 | { |
| 19269 | UA_TYPENAME("SecurityGroups") /* .memberName */ |
| 19270 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19271 | offsetof(UA_PubSubKeyPushTargetDataType, securityGroupsSize) - offsetof(UA_PubSubKeyPushTargetDataType, pushTargetProperties) - sizeof(void *), /* .padding */ |
| 19272 | true, /* .isArray */ |
| 19273 | false /* .isOptional */ |
| 19274 | },}; |
| 19275 | |
| 19276 | /* EnumDefinition */ |
| 19277 | static UA_DataTypeMember EnumDefinition_members[1] = { |
| 19278 | { |
| 19279 | UA_TYPENAME("Fields") /* .memberName */ |
| 19280 | &UA_TYPES[UA_TYPES_ENUMFIELD], /* .memberType */ |
| 19281 | 0, /* .padding */ |
| 19282 | true, /* .isArray */ |
| 19283 | false /* .isOptional */ |
| 19284 | },}; |
| 19285 | |
| 19286 | /* ReadEventDetails */ |
| 19287 | static UA_DataTypeMember ReadEventDetails_members[4] = { |
| 19288 | { |
| 19289 | UA_TYPENAME("NumValuesPerNode") /* .memberName */ |
| 19290 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 19291 | 0, /* .padding */ |
| 19292 | false, /* .isArray */ |
| 19293 | false /* .isOptional */ |
| 19294 | }, |
| 19295 | { |
| 19296 | UA_TYPENAME("StartTime") /* .memberName */ |
| 19297 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 19298 | offsetof(UA_ReadEventDetails, startTime) - offsetof(UA_ReadEventDetails, numValuesPerNode) - sizeof(UA_UInt32), /* .padding */ |
| 19299 | false, /* .isArray */ |
| 19300 | false /* .isOptional */ |
| 19301 | }, |
| 19302 | { |
| 19303 | UA_TYPENAME("EndTime") /* .memberName */ |
| 19304 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 19305 | offsetof(UA_ReadEventDetails, endTime) - offsetof(UA_ReadEventDetails, startTime) - sizeof(UA_DateTime), /* .padding */ |
| 19306 | false, /* .isArray */ |
| 19307 | false /* .isOptional */ |
| 19308 | }, |
| 19309 | { |
| 19310 | UA_TYPENAME("Filter") /* .memberName */ |
| 19311 | &UA_TYPES[UA_TYPES_EVENTFILTER], /* .memberType */ |
| 19312 | offsetof(UA_ReadEventDetails, filter) - offsetof(UA_ReadEventDetails, endTime) - sizeof(UA_DateTime), /* .padding */ |
| 19313 | false, /* .isArray */ |
| 19314 | false /* .isOptional */ |
| 19315 | },}; |
| 19316 | |
| 19317 | /* ReadProcessedDetails */ |
| 19318 | static UA_DataTypeMember ReadProcessedDetails_members[5] = { |
| 19319 | { |
| 19320 | UA_TYPENAME("StartTime") /* .memberName */ |
| 19321 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 19322 | 0, /* .padding */ |
| 19323 | false, /* .isArray */ |
| 19324 | false /* .isOptional */ |
| 19325 | }, |
| 19326 | { |
| 19327 | UA_TYPENAME("EndTime") /* .memberName */ |
| 19328 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 19329 | offsetof(UA_ReadProcessedDetails, endTime) - offsetof(UA_ReadProcessedDetails, startTime) - sizeof(UA_DateTime), /* .padding */ |
| 19330 | false, /* .isArray */ |
| 19331 | false /* .isOptional */ |
| 19332 | }, |
| 19333 | { |
| 19334 | UA_TYPENAME("ProcessingInterval") /* .memberName */ |
| 19335 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 19336 | offsetof(UA_ReadProcessedDetails, processingInterval) - offsetof(UA_ReadProcessedDetails, endTime) - sizeof(UA_DateTime), /* .padding */ |
| 19337 | false, /* .isArray */ |
| 19338 | false /* .isOptional */ |
| 19339 | }, |
| 19340 | { |
| 19341 | UA_TYPENAME("AggregateType") /* .memberName */ |
| 19342 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 19343 | offsetof(UA_ReadProcessedDetails, aggregateTypeSize) - offsetof(UA_ReadProcessedDetails, processingInterval) - sizeof(UA_Double), /* .padding */ |
| 19344 | true, /* .isArray */ |
| 19345 | false /* .isOptional */ |
| 19346 | }, |
| 19347 | { |
| 19348 | UA_TYPENAME("AggregateConfiguration") /* .memberName */ |
| 19349 | &UA_TYPES[UA_TYPES_AGGREGATECONFIGURATION], /* .memberType */ |
| 19350 | offsetof(UA_ReadProcessedDetails, aggregateConfiguration) - offsetof(UA_ReadProcessedDetails, aggregateType) - sizeof(void *), /* .padding */ |
| 19351 | false, /* .isArray */ |
| 19352 | false /* .isOptional */ |
| 19353 | },}; |
| 19354 | |
| 19355 | /* ModificationInfo */ |
| 19356 | static UA_DataTypeMember ModificationInfo_members[3] = { |
| 19357 | { |
| 19358 | UA_TYPENAME("ModificationTime") /* .memberName */ |
| 19359 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 19360 | 0, /* .padding */ |
| 19361 | false, /* .isArray */ |
| 19362 | false /* .isOptional */ |
| 19363 | }, |
| 19364 | { |
| 19365 | UA_TYPENAME("UpdateType") /* .memberName */ |
| 19366 | &UA_TYPES[UA_TYPES_HISTORYUPDATETYPE], /* .memberType */ |
| 19367 | offsetof(UA_ModificationInfo, updateType) - offsetof(UA_ModificationInfo, modificationTime) - sizeof(UA_DateTime), /* .padding */ |
| 19368 | false, /* .isArray */ |
| 19369 | false /* .isOptional */ |
| 19370 | }, |
| 19371 | { |
| 19372 | UA_TYPENAME("UserName") /* .memberName */ |
| 19373 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19374 | offsetof(UA_ModificationInfo, userName) - offsetof(UA_ModificationInfo, updateType) - sizeof(UA_HistoryUpdateType), /* .padding */ |
| 19375 | false, /* .isArray */ |
| 19376 | false /* .isOptional */ |
| 19377 | },}; |
| 19378 | |
| 19379 | /* HistoryModifiedData */ |
| 19380 | static UA_DataTypeMember HistoryModifiedData_members[2] = { |
| 19381 | { |
| 19382 | UA_TYPENAME("DataValues") /* .memberName */ |
| 19383 | &UA_TYPES[UA_TYPES_DATAVALUE], /* .memberType */ |
| 19384 | 0, /* .padding */ |
| 19385 | true, /* .isArray */ |
| 19386 | false /* .isOptional */ |
| 19387 | }, |
| 19388 | { |
| 19389 | UA_TYPENAME("ModificationInfos") /* .memberName */ |
| 19390 | &UA_TYPES[UA_TYPES_MODIFICATIONINFO], /* .memberType */ |
| 19391 | offsetof(UA_HistoryModifiedData, modificationInfosSize) - offsetof(UA_HistoryModifiedData, dataValues) - sizeof(void *), /* .padding */ |
| 19392 | true, /* .isArray */ |
| 19393 | false /* .isOptional */ |
| 19394 | },}; |
| 19395 | |
| 19396 | /* HistoryEvent */ |
| 19397 | static UA_DataTypeMember HistoryEvent_members[1] = { |
| 19398 | { |
| 19399 | UA_TYPENAME("Events") /* .memberName */ |
| 19400 | &UA_TYPES[UA_TYPES_HISTORYEVENTFIELDLIST], /* .memberType */ |
| 19401 | 0, /* .padding */ |
| 19402 | true, /* .isArray */ |
| 19403 | false /* .isOptional */ |
| 19404 | },}; |
| 19405 | |
| 19406 | /* UpdateEventDetails */ |
| 19407 | static UA_DataTypeMember UpdateEventDetails_members[4] = { |
| 19408 | { |
| 19409 | UA_TYPENAME("NodeId") /* .memberName */ |
| 19410 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 19411 | 0, /* .padding */ |
| 19412 | false, /* .isArray */ |
| 19413 | false /* .isOptional */ |
| 19414 | }, |
| 19415 | { |
| 19416 | UA_TYPENAME("PerformInsertReplace") /* .memberName */ |
| 19417 | &UA_TYPES[UA_TYPES_PERFORMUPDATETYPE], /* .memberType */ |
| 19418 | offsetof(UA_UpdateEventDetails, performInsertReplace) - offsetof(UA_UpdateEventDetails, nodeId) - sizeof(UA_NodeId), /* .padding */ |
| 19419 | false, /* .isArray */ |
| 19420 | false /* .isOptional */ |
| 19421 | }, |
| 19422 | { |
| 19423 | UA_TYPENAME("Filter") /* .memberName */ |
| 19424 | &UA_TYPES[UA_TYPES_EVENTFILTER], /* .memberType */ |
| 19425 | offsetof(UA_UpdateEventDetails, filter) - offsetof(UA_UpdateEventDetails, performInsertReplace) - sizeof(UA_PerformUpdateType), /* .padding */ |
| 19426 | false, /* .isArray */ |
| 19427 | false /* .isOptional */ |
| 19428 | }, |
| 19429 | { |
| 19430 | UA_TYPENAME("EventData") /* .memberName */ |
| 19431 | &UA_TYPES[UA_TYPES_HISTORYEVENTFIELDLIST], /* .memberType */ |
| 19432 | offsetof(UA_UpdateEventDetails, eventDataSize) - offsetof(UA_UpdateEventDetails, filter) - sizeof(UA_EventFilter), /* .padding */ |
| 19433 | true, /* .isArray */ |
| 19434 | false /* .isOptional */ |
| 19435 | },}; |
| 19436 | |
| 19437 | /* DataChangeNotification */ |
| 19438 | static UA_DataTypeMember DataChangeNotification_members[2] = { |
| 19439 | { |
| 19440 | UA_TYPENAME("MonitoredItems") /* .memberName */ |
| 19441 | &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION], /* .memberType */ |
| 19442 | 0, /* .padding */ |
| 19443 | true, /* .isArray */ |
| 19444 | false /* .isOptional */ |
| 19445 | }, |
| 19446 | { |
| 19447 | UA_TYPENAME("DiagnosticInfos") /* .memberName */ |
| 19448 | &UA_TYPES[UA_TYPES_DIAGNOSTICINFO], /* .memberType */ |
| 19449 | offsetof(UA_DataChangeNotification, diagnosticInfosSize) - offsetof(UA_DataChangeNotification, monitoredItems) - sizeof(void *), /* .padding */ |
| 19450 | true, /* .isArray */ |
| 19451 | false /* .isOptional */ |
| 19452 | },}; |
| 19453 | |
| 19454 | /* EventNotificationList */ |
| 19455 | static UA_DataTypeMember EventNotificationList_members[1] = { |
| 19456 | { |
| 19457 | UA_TYPENAME("Events") /* .memberName */ |
| 19458 | &UA_TYPES[UA_TYPES_EVENTFIELDLIST], /* .memberType */ |
| 19459 | 0, /* .padding */ |
| 19460 | true, /* .isArray */ |
| 19461 | false /* .isOptional */ |
| 19462 | },}; |
| 19463 | |
| 19464 | /* SessionDiagnosticsDataType */ |
| 19465 | static UA_DataTypeMember SessionDiagnosticsDataType_members[43] = { |
| 19466 | { |
| 19467 | UA_TYPENAME("SessionId") /* .memberName */ |
| 19468 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 19469 | 0, /* .padding */ |
| 19470 | false, /* .isArray */ |
| 19471 | false /* .isOptional */ |
| 19472 | }, |
| 19473 | { |
| 19474 | UA_TYPENAME("SessionName") /* .memberName */ |
| 19475 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19476 | offsetof(UA_SessionDiagnosticsDataType, sessionName) - offsetof(UA_SessionDiagnosticsDataType, sessionId) - sizeof(UA_NodeId), /* .padding */ |
| 19477 | false, /* .isArray */ |
| 19478 | false /* .isOptional */ |
| 19479 | }, |
| 19480 | { |
| 19481 | UA_TYPENAME("ClientDescription") /* .memberName */ |
| 19482 | &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION], /* .memberType */ |
| 19483 | offsetof(UA_SessionDiagnosticsDataType, clientDescription) - offsetof(UA_SessionDiagnosticsDataType, sessionName) - sizeof(UA_String), /* .padding */ |
| 19484 | false, /* .isArray */ |
| 19485 | false /* .isOptional */ |
| 19486 | }, |
| 19487 | { |
| 19488 | UA_TYPENAME("ServerUri") /* .memberName */ |
| 19489 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19490 | offsetof(UA_SessionDiagnosticsDataType, serverUri) - offsetof(UA_SessionDiagnosticsDataType, clientDescription) - sizeof(UA_ApplicationDescription), /* .padding */ |
| 19491 | false, /* .isArray */ |
| 19492 | false /* .isOptional */ |
| 19493 | }, |
| 19494 | { |
| 19495 | UA_TYPENAME("EndpointUrl") /* .memberName */ |
| 19496 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19497 | offsetof(UA_SessionDiagnosticsDataType, endpointUrl) - offsetof(UA_SessionDiagnosticsDataType, serverUri) - sizeof(UA_String), /* .padding */ |
| 19498 | false, /* .isArray */ |
| 19499 | false /* .isOptional */ |
| 19500 | }, |
| 19501 | { |
| 19502 | UA_TYPENAME("LocaleIds") /* .memberName */ |
| 19503 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19504 | offsetof(UA_SessionDiagnosticsDataType, localeIdsSize) - offsetof(UA_SessionDiagnosticsDataType, endpointUrl) - sizeof(UA_String), /* .padding */ |
| 19505 | true, /* .isArray */ |
| 19506 | false /* .isOptional */ |
| 19507 | }, |
| 19508 | { |
| 19509 | UA_TYPENAME("ActualSessionTimeout") /* .memberName */ |
| 19510 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 19511 | offsetof(UA_SessionDiagnosticsDataType, actualSessionTimeout) - offsetof(UA_SessionDiagnosticsDataType, localeIds) - sizeof(void *), /* .padding */ |
| 19512 | false, /* .isArray */ |
| 19513 | false /* .isOptional */ |
| 19514 | }, |
| 19515 | { |
| 19516 | UA_TYPENAME("MaxResponseMessageSize") /* .memberName */ |
| 19517 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 19518 | offsetof(UA_SessionDiagnosticsDataType, maxResponseMessageSize) - offsetof(UA_SessionDiagnosticsDataType, actualSessionTimeout) - sizeof(UA_Double), /* .padding */ |
| 19519 | false, /* .isArray */ |
| 19520 | false /* .isOptional */ |
| 19521 | }, |
| 19522 | { |
| 19523 | UA_TYPENAME("ClientConnectionTime") /* .memberName */ |
| 19524 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 19525 | offsetof(UA_SessionDiagnosticsDataType, clientConnectionTime) - offsetof(UA_SessionDiagnosticsDataType, maxResponseMessageSize) - sizeof(UA_UInt32), /* .padding */ |
| 19526 | false, /* .isArray */ |
| 19527 | false /* .isOptional */ |
| 19528 | }, |
| 19529 | { |
| 19530 | UA_TYPENAME("ClientLastContactTime") /* .memberName */ |
| 19531 | &UA_TYPES[UA_TYPES_DATETIME], /* .memberType */ |
| 19532 | offsetof(UA_SessionDiagnosticsDataType, clientLastContactTime) - offsetof(UA_SessionDiagnosticsDataType, clientConnectionTime) - sizeof(UA_DateTime), /* .padding */ |
| 19533 | false, /* .isArray */ |
| 19534 | false /* .isOptional */ |
| 19535 | }, |
| 19536 | { |
| 19537 | UA_TYPENAME("CurrentSubscriptionsCount") /* .memberName */ |
| 19538 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 19539 | offsetof(UA_SessionDiagnosticsDataType, currentSubscriptionsCount) - offsetof(UA_SessionDiagnosticsDataType, clientLastContactTime) - sizeof(UA_DateTime), /* .padding */ |
| 19540 | false, /* .isArray */ |
| 19541 | false /* .isOptional */ |
| 19542 | }, |
| 19543 | { |
| 19544 | UA_TYPENAME("CurrentMonitoredItemsCount") /* .memberName */ |
| 19545 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 19546 | offsetof(UA_SessionDiagnosticsDataType, currentMonitoredItemsCount) - offsetof(UA_SessionDiagnosticsDataType, currentSubscriptionsCount) - sizeof(UA_UInt32), /* .padding */ |
| 19547 | false, /* .isArray */ |
| 19548 | false /* .isOptional */ |
| 19549 | }, |
| 19550 | { |
| 19551 | UA_TYPENAME("CurrentPublishRequestsInQueue") /* .memberName */ |
| 19552 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 19553 | offsetof(UA_SessionDiagnosticsDataType, currentPublishRequestsInQueue) - offsetof(UA_SessionDiagnosticsDataType, currentMonitoredItemsCount) - sizeof(UA_UInt32), /* .padding */ |
| 19554 | false, /* .isArray */ |
| 19555 | false /* .isOptional */ |
| 19556 | }, |
| 19557 | { |
| 19558 | UA_TYPENAME("TotalRequestCount") /* .memberName */ |
| 19559 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19560 | offsetof(UA_SessionDiagnosticsDataType, totalRequestCount) - offsetof(UA_SessionDiagnosticsDataType, currentPublishRequestsInQueue) - sizeof(UA_UInt32), /* .padding */ |
| 19561 | false, /* .isArray */ |
| 19562 | false /* .isOptional */ |
| 19563 | }, |
| 19564 | { |
| 19565 | UA_TYPENAME("UnauthorizedRequestCount") /* .memberName */ |
| 19566 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 19567 | offsetof(UA_SessionDiagnosticsDataType, unauthorizedRequestCount) - offsetof(UA_SessionDiagnosticsDataType, totalRequestCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19568 | false, /* .isArray */ |
| 19569 | false /* .isOptional */ |
| 19570 | }, |
| 19571 | { |
| 19572 | UA_TYPENAME("ReadCount") /* .memberName */ |
| 19573 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19574 | offsetof(UA_SessionDiagnosticsDataType, readCount) - offsetof(UA_SessionDiagnosticsDataType, unauthorizedRequestCount) - sizeof(UA_UInt32), /* .padding */ |
| 19575 | false, /* .isArray */ |
| 19576 | false /* .isOptional */ |
| 19577 | }, |
| 19578 | { |
| 19579 | UA_TYPENAME("HistoryReadCount") /* .memberName */ |
| 19580 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19581 | offsetof(UA_SessionDiagnosticsDataType, historyReadCount) - offsetof(UA_SessionDiagnosticsDataType, readCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19582 | false, /* .isArray */ |
| 19583 | false /* .isOptional */ |
| 19584 | }, |
| 19585 | { |
| 19586 | UA_TYPENAME("WriteCount") /* .memberName */ |
| 19587 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19588 | offsetof(UA_SessionDiagnosticsDataType, writeCount) - offsetof(UA_SessionDiagnosticsDataType, historyReadCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19589 | false, /* .isArray */ |
| 19590 | false /* .isOptional */ |
| 19591 | }, |
| 19592 | { |
| 19593 | UA_TYPENAME("HistoryUpdateCount") /* .memberName */ |
| 19594 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19595 | offsetof(UA_SessionDiagnosticsDataType, historyUpdateCount) - offsetof(UA_SessionDiagnosticsDataType, writeCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19596 | false, /* .isArray */ |
| 19597 | false /* .isOptional */ |
| 19598 | }, |
| 19599 | { |
| 19600 | UA_TYPENAME("CallCount") /* .memberName */ |
| 19601 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19602 | offsetof(UA_SessionDiagnosticsDataType, callCount) - offsetof(UA_SessionDiagnosticsDataType, historyUpdateCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19603 | false, /* .isArray */ |
| 19604 | false /* .isOptional */ |
| 19605 | }, |
| 19606 | { |
| 19607 | UA_TYPENAME("CreateMonitoredItemsCount") /* .memberName */ |
| 19608 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19609 | offsetof(UA_SessionDiagnosticsDataType, createMonitoredItemsCount) - offsetof(UA_SessionDiagnosticsDataType, callCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19610 | false, /* .isArray */ |
| 19611 | false /* .isOptional */ |
| 19612 | }, |
| 19613 | { |
| 19614 | UA_TYPENAME("ModifyMonitoredItemsCount") /* .memberName */ |
| 19615 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19616 | offsetof(UA_SessionDiagnosticsDataType, modifyMonitoredItemsCount) - offsetof(UA_SessionDiagnosticsDataType, createMonitoredItemsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19617 | false, /* .isArray */ |
| 19618 | false /* .isOptional */ |
| 19619 | }, |
| 19620 | { |
| 19621 | UA_TYPENAME("SetMonitoringModeCount") /* .memberName */ |
| 19622 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19623 | offsetof(UA_SessionDiagnosticsDataType, setMonitoringModeCount) - offsetof(UA_SessionDiagnosticsDataType, modifyMonitoredItemsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19624 | false, /* .isArray */ |
| 19625 | false /* .isOptional */ |
| 19626 | }, |
| 19627 | { |
| 19628 | UA_TYPENAME("SetTriggeringCount") /* .memberName */ |
| 19629 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19630 | offsetof(UA_SessionDiagnosticsDataType, setTriggeringCount) - offsetof(UA_SessionDiagnosticsDataType, setMonitoringModeCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19631 | false, /* .isArray */ |
| 19632 | false /* .isOptional */ |
| 19633 | }, |
| 19634 | { |
| 19635 | UA_TYPENAME("DeleteMonitoredItemsCount") /* .memberName */ |
| 19636 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19637 | offsetof(UA_SessionDiagnosticsDataType, deleteMonitoredItemsCount) - offsetof(UA_SessionDiagnosticsDataType, setTriggeringCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19638 | false, /* .isArray */ |
| 19639 | false /* .isOptional */ |
| 19640 | }, |
| 19641 | { |
| 19642 | UA_TYPENAME("CreateSubscriptionCount") /* .memberName */ |
| 19643 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19644 | offsetof(UA_SessionDiagnosticsDataType, createSubscriptionCount) - offsetof(UA_SessionDiagnosticsDataType, deleteMonitoredItemsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19645 | false, /* .isArray */ |
| 19646 | false /* .isOptional */ |
| 19647 | }, |
| 19648 | { |
| 19649 | UA_TYPENAME("ModifySubscriptionCount") /* .memberName */ |
| 19650 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19651 | offsetof(UA_SessionDiagnosticsDataType, modifySubscriptionCount) - offsetof(UA_SessionDiagnosticsDataType, createSubscriptionCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19652 | false, /* .isArray */ |
| 19653 | false /* .isOptional */ |
| 19654 | }, |
| 19655 | { |
| 19656 | UA_TYPENAME("SetPublishingModeCount") /* .memberName */ |
| 19657 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19658 | offsetof(UA_SessionDiagnosticsDataType, setPublishingModeCount) - offsetof(UA_SessionDiagnosticsDataType, modifySubscriptionCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19659 | false, /* .isArray */ |
| 19660 | false /* .isOptional */ |
| 19661 | }, |
| 19662 | { |
| 19663 | UA_TYPENAME("PublishCount") /* .memberName */ |
| 19664 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19665 | offsetof(UA_SessionDiagnosticsDataType, publishCount) - offsetof(UA_SessionDiagnosticsDataType, setPublishingModeCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19666 | false, /* .isArray */ |
| 19667 | false /* .isOptional */ |
| 19668 | }, |
| 19669 | { |
| 19670 | UA_TYPENAME("RepublishCount") /* .memberName */ |
| 19671 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19672 | offsetof(UA_SessionDiagnosticsDataType, republishCount) - offsetof(UA_SessionDiagnosticsDataType, publishCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19673 | false, /* .isArray */ |
| 19674 | false /* .isOptional */ |
| 19675 | }, |
| 19676 | { |
| 19677 | UA_TYPENAME("TransferSubscriptionsCount") /* .memberName */ |
| 19678 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19679 | offsetof(UA_SessionDiagnosticsDataType, transferSubscriptionsCount) - offsetof(UA_SessionDiagnosticsDataType, republishCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19680 | false, /* .isArray */ |
| 19681 | false /* .isOptional */ |
| 19682 | }, |
| 19683 | { |
| 19684 | UA_TYPENAME("DeleteSubscriptionsCount") /* .memberName */ |
| 19685 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19686 | offsetof(UA_SessionDiagnosticsDataType, deleteSubscriptionsCount) - offsetof(UA_SessionDiagnosticsDataType, transferSubscriptionsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19687 | false, /* .isArray */ |
| 19688 | false /* .isOptional */ |
| 19689 | }, |
| 19690 | { |
| 19691 | UA_TYPENAME("AddNodesCount") /* .memberName */ |
| 19692 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19693 | offsetof(UA_SessionDiagnosticsDataType, addNodesCount) - offsetof(UA_SessionDiagnosticsDataType, deleteSubscriptionsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19694 | false, /* .isArray */ |
| 19695 | false /* .isOptional */ |
| 19696 | }, |
| 19697 | { |
| 19698 | UA_TYPENAME("AddReferencesCount") /* .memberName */ |
| 19699 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19700 | offsetof(UA_SessionDiagnosticsDataType, addReferencesCount) - offsetof(UA_SessionDiagnosticsDataType, addNodesCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19701 | false, /* .isArray */ |
| 19702 | false /* .isOptional */ |
| 19703 | }, |
| 19704 | { |
| 19705 | UA_TYPENAME("DeleteNodesCount") /* .memberName */ |
| 19706 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19707 | offsetof(UA_SessionDiagnosticsDataType, deleteNodesCount) - offsetof(UA_SessionDiagnosticsDataType, addReferencesCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19708 | false, /* .isArray */ |
| 19709 | false /* .isOptional */ |
| 19710 | }, |
| 19711 | { |
| 19712 | UA_TYPENAME("DeleteReferencesCount") /* .memberName */ |
| 19713 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19714 | offsetof(UA_SessionDiagnosticsDataType, deleteReferencesCount) - offsetof(UA_SessionDiagnosticsDataType, deleteNodesCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19715 | false, /* .isArray */ |
| 19716 | false /* .isOptional */ |
| 19717 | }, |
| 19718 | { |
| 19719 | UA_TYPENAME("BrowseCount") /* .memberName */ |
| 19720 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19721 | offsetof(UA_SessionDiagnosticsDataType, browseCount) - offsetof(UA_SessionDiagnosticsDataType, deleteReferencesCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19722 | false, /* .isArray */ |
| 19723 | false /* .isOptional */ |
| 19724 | }, |
| 19725 | { |
| 19726 | UA_TYPENAME("BrowseNextCount") /* .memberName */ |
| 19727 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19728 | offsetof(UA_SessionDiagnosticsDataType, browseNextCount) - offsetof(UA_SessionDiagnosticsDataType, browseCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19729 | false, /* .isArray */ |
| 19730 | false /* .isOptional */ |
| 19731 | }, |
| 19732 | { |
| 19733 | UA_TYPENAME("TranslateBrowsePathsToNodeIdsCount") /* .memberName */ |
| 19734 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19735 | offsetof(UA_SessionDiagnosticsDataType, translateBrowsePathsToNodeIdsCount) - offsetof(UA_SessionDiagnosticsDataType, browseNextCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19736 | false, /* .isArray */ |
| 19737 | false /* .isOptional */ |
| 19738 | }, |
| 19739 | { |
| 19740 | UA_TYPENAME("QueryFirstCount") /* .memberName */ |
| 19741 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19742 | offsetof(UA_SessionDiagnosticsDataType, queryFirstCount) - offsetof(UA_SessionDiagnosticsDataType, translateBrowsePathsToNodeIdsCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19743 | false, /* .isArray */ |
| 19744 | false /* .isOptional */ |
| 19745 | }, |
| 19746 | { |
| 19747 | UA_TYPENAME("QueryNextCount") /* .memberName */ |
| 19748 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19749 | offsetof(UA_SessionDiagnosticsDataType, queryNextCount) - offsetof(UA_SessionDiagnosticsDataType, queryFirstCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19750 | false, /* .isArray */ |
| 19751 | false /* .isOptional */ |
| 19752 | }, |
| 19753 | { |
| 19754 | UA_TYPENAME("RegisterNodesCount") /* .memberName */ |
| 19755 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19756 | offsetof(UA_SessionDiagnosticsDataType, registerNodesCount) - offsetof(UA_SessionDiagnosticsDataType, queryNextCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19757 | false, /* .isArray */ |
| 19758 | false /* .isOptional */ |
| 19759 | }, |
| 19760 | { |
| 19761 | UA_TYPENAME("UnregisterNodesCount") /* .memberName */ |
| 19762 | &UA_TYPES[UA_TYPES_SERVICECOUNTERDATATYPE], /* .memberType */ |
| 19763 | offsetof(UA_SessionDiagnosticsDataType, unregisterNodesCount) - offsetof(UA_SessionDiagnosticsDataType, registerNodesCount) - sizeof(UA_ServiceCounterDataType), /* .padding */ |
| 19764 | false, /* .isArray */ |
| 19765 | false /* .isOptional */ |
| 19766 | },}; |
| 19767 | |
| 19768 | /* EnumDescription */ |
| 19769 | static UA_DataTypeMember EnumDescription_members[4] = { |
| 19770 | { |
| 19771 | UA_TYPENAME("DataTypeId") /* .memberName */ |
| 19772 | &UA_TYPES[UA_TYPES_NODEID], /* .memberType */ |
| 19773 | 0, /* .padding */ |
| 19774 | false, /* .isArray */ |
| 19775 | false /* .isOptional */ |
| 19776 | }, |
| 19777 | { |
| 19778 | UA_TYPENAME("Name") /* .memberName */ |
| 19779 | &UA_TYPES[UA_TYPES_QUALIFIEDNAME], /* .memberType */ |
| 19780 | offsetof(UA_EnumDescription, name) - offsetof(UA_EnumDescription, dataTypeId) - sizeof(UA_NodeId), /* .padding */ |
| 19781 | false, /* .isArray */ |
| 19782 | false /* .isOptional */ |
| 19783 | }, |
| 19784 | { |
| 19785 | UA_TYPENAME("EnumDefinition") /* .memberName */ |
| 19786 | &UA_TYPES[UA_TYPES_ENUMDEFINITION], /* .memberType */ |
| 19787 | offsetof(UA_EnumDescription, enumDefinition) - offsetof(UA_EnumDescription, name) - sizeof(UA_QualifiedName), /* .padding */ |
| 19788 | false, /* .isArray */ |
| 19789 | false /* .isOptional */ |
| 19790 | }, |
| 19791 | { |
| 19792 | UA_TYPENAME("BuiltInType") /* .memberName */ |
| 19793 | &UA_TYPES[UA_TYPES_BYTE], /* .memberType */ |
| 19794 | offsetof(UA_EnumDescription, builtInType) - offsetof(UA_EnumDescription, enumDefinition) - sizeof(UA_EnumDefinition), /* .padding */ |
| 19795 | false, /* .isArray */ |
| 19796 | false /* .isOptional */ |
| 19797 | },}; |
| 19798 | |
| 19799 | /* UABinaryFileDataType */ |
| 19800 | static UA_DataTypeMember UABinaryFileDataType_members[7] = { |
| 19801 | { |
| 19802 | UA_TYPENAME("Namespaces") /* .memberName */ |
| 19803 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19804 | 0, /* .padding */ |
| 19805 | true, /* .isArray */ |
| 19806 | false /* .isOptional */ |
| 19807 | }, |
| 19808 | { |
| 19809 | UA_TYPENAME("StructureDataTypes") /* .memberName */ |
| 19810 | &UA_TYPES[UA_TYPES_STRUCTUREDESCRIPTION], /* .memberType */ |
| 19811 | offsetof(UA_UABinaryFileDataType, structureDataTypesSize) - offsetof(UA_UABinaryFileDataType, namespaces) - sizeof(void *), /* .padding */ |
| 19812 | true, /* .isArray */ |
| 19813 | false /* .isOptional */ |
| 19814 | }, |
| 19815 | { |
| 19816 | UA_TYPENAME("EnumDataTypes") /* .memberName */ |
| 19817 | &UA_TYPES[UA_TYPES_ENUMDESCRIPTION], /* .memberType */ |
| 19818 | offsetof(UA_UABinaryFileDataType, enumDataTypesSize) - offsetof(UA_UABinaryFileDataType, structureDataTypes) - sizeof(void *), /* .padding */ |
| 19819 | true, /* .isArray */ |
| 19820 | false /* .isOptional */ |
| 19821 | }, |
| 19822 | { |
| 19823 | UA_TYPENAME("SimpleDataTypes") /* .memberName */ |
| 19824 | &UA_TYPES[UA_TYPES_SIMPLETYPEDESCRIPTION], /* .memberType */ |
| 19825 | offsetof(UA_UABinaryFileDataType, simpleDataTypesSize) - offsetof(UA_UABinaryFileDataType, enumDataTypes) - sizeof(void *), /* .padding */ |
| 19826 | true, /* .isArray */ |
| 19827 | false /* .isOptional */ |
| 19828 | }, |
| 19829 | { |
| 19830 | UA_TYPENAME("SchemaLocation") /* .memberName */ |
| 19831 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19832 | offsetof(UA_UABinaryFileDataType, schemaLocation) - offsetof(UA_UABinaryFileDataType, simpleDataTypes) - sizeof(void *), /* .padding */ |
| 19833 | false, /* .isArray */ |
| 19834 | false /* .isOptional */ |
| 19835 | }, |
| 19836 | { |
| 19837 | UA_TYPENAME("FileHeader") /* .memberName */ |
| 19838 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 19839 | offsetof(UA_UABinaryFileDataType, fileHeaderSize) - offsetof(UA_UABinaryFileDataType, schemaLocation) - sizeof(UA_String), /* .padding */ |
| 19840 | true, /* .isArray */ |
| 19841 | false /* .isOptional */ |
| 19842 | }, |
| 19843 | { |
| 19844 | UA_TYPENAME("Body") /* .memberName */ |
| 19845 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 19846 | offsetof(UA_UABinaryFileDataType, body) - offsetof(UA_UABinaryFileDataType, fileHeader) - sizeof(void *), /* .padding */ |
| 19847 | false, /* .isArray */ |
| 19848 | false /* .isOptional */ |
| 19849 | },}; |
| 19850 | |
| 19851 | /* DataSetMetaDataType */ |
| 19852 | static UA_DataTypeMember DataSetMetaDataType_members[9] = { |
| 19853 | { |
| 19854 | UA_TYPENAME("Namespaces") /* .memberName */ |
| 19855 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19856 | 0, /* .padding */ |
| 19857 | true, /* .isArray */ |
| 19858 | false /* .isOptional */ |
| 19859 | }, |
| 19860 | { |
| 19861 | UA_TYPENAME("StructureDataTypes") /* .memberName */ |
| 19862 | &UA_TYPES[UA_TYPES_STRUCTUREDESCRIPTION], /* .memberType */ |
| 19863 | offsetof(UA_DataSetMetaDataType, structureDataTypesSize) - offsetof(UA_DataSetMetaDataType, namespaces) - sizeof(void *), /* .padding */ |
| 19864 | true, /* .isArray */ |
| 19865 | false /* .isOptional */ |
| 19866 | }, |
| 19867 | { |
| 19868 | UA_TYPENAME("EnumDataTypes") /* .memberName */ |
| 19869 | &UA_TYPES[UA_TYPES_ENUMDESCRIPTION], /* .memberType */ |
| 19870 | offsetof(UA_DataSetMetaDataType, enumDataTypesSize) - offsetof(UA_DataSetMetaDataType, structureDataTypes) - sizeof(void *), /* .padding */ |
| 19871 | true, /* .isArray */ |
| 19872 | false /* .isOptional */ |
| 19873 | }, |
| 19874 | { |
| 19875 | UA_TYPENAME("SimpleDataTypes") /* .memberName */ |
| 19876 | &UA_TYPES[UA_TYPES_SIMPLETYPEDESCRIPTION], /* .memberType */ |
| 19877 | offsetof(UA_DataSetMetaDataType, simpleDataTypesSize) - offsetof(UA_DataSetMetaDataType, enumDataTypes) - sizeof(void *), /* .padding */ |
| 19878 | true, /* .isArray */ |
| 19879 | false /* .isOptional */ |
| 19880 | }, |
| 19881 | { |
| 19882 | UA_TYPENAME("Name") /* .memberName */ |
| 19883 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19884 | offsetof(UA_DataSetMetaDataType, name) - offsetof(UA_DataSetMetaDataType, simpleDataTypes) - sizeof(void *), /* .padding */ |
| 19885 | false, /* .isArray */ |
| 19886 | false /* .isOptional */ |
| 19887 | }, |
| 19888 | { |
| 19889 | UA_TYPENAME("Description") /* .memberName */ |
| 19890 | &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], /* .memberType */ |
| 19891 | offsetof(UA_DataSetMetaDataType, description) - offsetof(UA_DataSetMetaDataType, name) - sizeof(UA_String), /* .padding */ |
| 19892 | false, /* .isArray */ |
| 19893 | false /* .isOptional */ |
| 19894 | }, |
| 19895 | { |
| 19896 | UA_TYPENAME("Fields") /* .memberName */ |
| 19897 | &UA_TYPES[UA_TYPES_FIELDMETADATA], /* .memberType */ |
| 19898 | offsetof(UA_DataSetMetaDataType, fieldsSize) - offsetof(UA_DataSetMetaDataType, description) - sizeof(UA_LocalizedText), /* .padding */ |
| 19899 | true, /* .isArray */ |
| 19900 | false /* .isOptional */ |
| 19901 | }, |
| 19902 | { |
| 19903 | UA_TYPENAME("DataSetClassId") /* .memberName */ |
| 19904 | &UA_TYPES[UA_TYPES_GUID], /* .memberType */ |
| 19905 | offsetof(UA_DataSetMetaDataType, dataSetClassId) - offsetof(UA_DataSetMetaDataType, fields) - sizeof(void *), /* .padding */ |
| 19906 | false, /* .isArray */ |
| 19907 | false /* .isOptional */ |
| 19908 | }, |
| 19909 | { |
| 19910 | UA_TYPENAME("ConfigurationVersion") /* .memberName */ |
| 19911 | &UA_TYPES[UA_TYPES_CONFIGURATIONVERSIONDATATYPE], /* .memberType */ |
| 19912 | offsetof(UA_DataSetMetaDataType, configurationVersion) - offsetof(UA_DataSetMetaDataType, dataSetClassId) - sizeof(UA_Guid), /* .padding */ |
| 19913 | false, /* .isArray */ |
| 19914 | false /* .isOptional */ |
| 19915 | },}; |
| 19916 | |
| 19917 | /* PublishedDataSetDataType */ |
| 19918 | static UA_DataTypeMember PublishedDataSetDataType_members[5] = { |
| 19919 | { |
| 19920 | UA_TYPENAME("Name") /* .memberName */ |
| 19921 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19922 | 0, /* .padding */ |
| 19923 | false, /* .isArray */ |
| 19924 | false /* .isOptional */ |
| 19925 | }, |
| 19926 | { |
| 19927 | UA_TYPENAME("DataSetFolder") /* .memberName */ |
| 19928 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19929 | offsetof(UA_PublishedDataSetDataType, dataSetFolderSize) - offsetof(UA_PublishedDataSetDataType, name) - sizeof(UA_String), /* .padding */ |
| 19930 | true, /* .isArray */ |
| 19931 | false /* .isOptional */ |
| 19932 | }, |
| 19933 | { |
| 19934 | UA_TYPENAME("DataSetMetaData") /* .memberName */ |
| 19935 | &UA_TYPES[UA_TYPES_DATASETMETADATATYPE], /* .memberType */ |
| 19936 | offsetof(UA_PublishedDataSetDataType, dataSetMetaData) - offsetof(UA_PublishedDataSetDataType, dataSetFolder) - sizeof(void *), /* .padding */ |
| 19937 | false, /* .isArray */ |
| 19938 | false /* .isOptional */ |
| 19939 | }, |
| 19940 | { |
| 19941 | UA_TYPENAME("ExtensionFields") /* .memberName */ |
| 19942 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 19943 | offsetof(UA_PublishedDataSetDataType, extensionFieldsSize) - offsetof(UA_PublishedDataSetDataType, dataSetMetaData) - sizeof(UA_DataSetMetaDataType), /* .padding */ |
| 19944 | true, /* .isArray */ |
| 19945 | false /* .isOptional */ |
| 19946 | }, |
| 19947 | { |
| 19948 | UA_TYPENAME("DataSetSource") /* .memberName */ |
| 19949 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 19950 | offsetof(UA_PublishedDataSetDataType, dataSetSource) - offsetof(UA_PublishedDataSetDataType, extensionFields) - sizeof(void *), /* .padding */ |
| 19951 | false, /* .isArray */ |
| 19952 | false /* .isOptional */ |
| 19953 | },}; |
| 19954 | |
| 19955 | /* DataSetReaderDataType */ |
| 19956 | static UA_DataTypeMember DataSetReaderDataType_members[17] = { |
| 19957 | { |
| 19958 | UA_TYPENAME("Name") /* .memberName */ |
| 19959 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 19960 | 0, /* .padding */ |
| 19961 | false, /* .isArray */ |
| 19962 | false /* .isOptional */ |
| 19963 | }, |
| 19964 | { |
| 19965 | UA_TYPENAME("Enabled") /* .memberName */ |
| 19966 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 19967 | offsetof(UA_DataSetReaderDataType, enabled) - offsetof(UA_DataSetReaderDataType, name) - sizeof(UA_String), /* .padding */ |
| 19968 | false, /* .isArray */ |
| 19969 | false /* .isOptional */ |
| 19970 | }, |
| 19971 | { |
| 19972 | UA_TYPENAME("PublisherId") /* .memberName */ |
| 19973 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 19974 | offsetof(UA_DataSetReaderDataType, publisherId) - offsetof(UA_DataSetReaderDataType, enabled) - sizeof(UA_Boolean), /* .padding */ |
| 19975 | false, /* .isArray */ |
| 19976 | false /* .isOptional */ |
| 19977 | }, |
| 19978 | { |
| 19979 | UA_TYPENAME("WriterGroupId") /* .memberName */ |
| 19980 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 19981 | offsetof(UA_DataSetReaderDataType, writerGroupId) - offsetof(UA_DataSetReaderDataType, publisherId) - sizeof(UA_Variant), /* .padding */ |
| 19982 | false, /* .isArray */ |
| 19983 | false /* .isOptional */ |
| 19984 | }, |
| 19985 | { |
| 19986 | UA_TYPENAME("DataSetWriterId") /* .memberName */ |
| 19987 | &UA_TYPES[UA_TYPES_UINT16], /* .memberType */ |
| 19988 | offsetof(UA_DataSetReaderDataType, dataSetWriterId) - offsetof(UA_DataSetReaderDataType, writerGroupId) - sizeof(UA_UInt16), /* .padding */ |
| 19989 | false, /* .isArray */ |
| 19990 | false /* .isOptional */ |
| 19991 | }, |
| 19992 | { |
| 19993 | UA_TYPENAME("DataSetMetaData") /* .memberName */ |
| 19994 | &UA_TYPES[UA_TYPES_DATASETMETADATATYPE], /* .memberType */ |
| 19995 | offsetof(UA_DataSetReaderDataType, dataSetMetaData) - offsetof(UA_DataSetReaderDataType, dataSetWriterId) - sizeof(UA_UInt16), /* .padding */ |
| 19996 | false, /* .isArray */ |
| 19997 | false /* .isOptional */ |
| 19998 | }, |
| 19999 | { |
| 20000 | UA_TYPENAME("DataSetFieldContentMask") /* .memberName */ |
| 20001 | &UA_TYPES[UA_TYPES_DATASETFIELDCONTENTMASK], /* .memberType */ |
| 20002 | offsetof(UA_DataSetReaderDataType, dataSetFieldContentMask) - offsetof(UA_DataSetReaderDataType, dataSetMetaData) - sizeof(UA_DataSetMetaDataType), /* .padding */ |
| 20003 | false, /* .isArray */ |
| 20004 | false /* .isOptional */ |
| 20005 | }, |
| 20006 | { |
| 20007 | UA_TYPENAME("MessageReceiveTimeout") /* .memberName */ |
| 20008 | &UA_TYPES[UA_TYPES_DOUBLE], /* .memberType */ |
| 20009 | offsetof(UA_DataSetReaderDataType, messageReceiveTimeout) - offsetof(UA_DataSetReaderDataType, dataSetFieldContentMask) - sizeof(UA_DataSetFieldContentMask), /* .padding */ |
| 20010 | false, /* .isArray */ |
| 20011 | false /* .isOptional */ |
| 20012 | }, |
| 20013 | { |
| 20014 | UA_TYPENAME("KeyFrameCount") /* .memberName */ |
| 20015 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 20016 | offsetof(UA_DataSetReaderDataType, keyFrameCount) - offsetof(UA_DataSetReaderDataType, messageReceiveTimeout) - sizeof(UA_Double), /* .padding */ |
| 20017 | false, /* .isArray */ |
| 20018 | false /* .isOptional */ |
| 20019 | }, |
| 20020 | { |
| 20021 | UA_TYPENAME("HeaderLayoutUri") /* .memberName */ |
| 20022 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 20023 | offsetof(UA_DataSetReaderDataType, headerLayoutUri) - offsetof(UA_DataSetReaderDataType, keyFrameCount) - sizeof(UA_UInt32), /* .padding */ |
| 20024 | false, /* .isArray */ |
| 20025 | false /* .isOptional */ |
| 20026 | }, |
| 20027 | { |
| 20028 | UA_TYPENAME("SecurityMode") /* .memberName */ |
| 20029 | &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */ |
| 20030 | offsetof(UA_DataSetReaderDataType, securityMode) - offsetof(UA_DataSetReaderDataType, headerLayoutUri) - sizeof(UA_String), /* .padding */ |
| 20031 | false, /* .isArray */ |
| 20032 | false /* .isOptional */ |
| 20033 | }, |
| 20034 | { |
| 20035 | UA_TYPENAME("SecurityGroupId") /* .memberName */ |
| 20036 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 20037 | offsetof(UA_DataSetReaderDataType, securityGroupId) - offsetof(UA_DataSetReaderDataType, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */ |
| 20038 | false, /* .isArray */ |
| 20039 | false /* .isOptional */ |
| 20040 | }, |
| 20041 | { |
| 20042 | UA_TYPENAME("SecurityKeyServices") /* .memberName */ |
| 20043 | &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */ |
| 20044 | offsetof(UA_DataSetReaderDataType, securityKeyServicesSize) - offsetof(UA_DataSetReaderDataType, securityGroupId) - sizeof(UA_String), /* .padding */ |
| 20045 | true, /* .isArray */ |
| 20046 | false /* .isOptional */ |
| 20047 | }, |
| 20048 | { |
| 20049 | UA_TYPENAME("DataSetReaderProperties") /* .memberName */ |
| 20050 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 20051 | offsetof(UA_DataSetReaderDataType, dataSetReaderPropertiesSize) - offsetof(UA_DataSetReaderDataType, securityKeyServices) - sizeof(void *), /* .padding */ |
| 20052 | true, /* .isArray */ |
| 20053 | false /* .isOptional */ |
| 20054 | }, |
| 20055 | { |
| 20056 | UA_TYPENAME("TransportSettings") /* .memberName */ |
| 20057 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 20058 | offsetof(UA_DataSetReaderDataType, transportSettings) - offsetof(UA_DataSetReaderDataType, dataSetReaderProperties) - sizeof(void *), /* .padding */ |
| 20059 | false, /* .isArray */ |
| 20060 | false /* .isOptional */ |
| 20061 | }, |
| 20062 | { |
| 20063 | UA_TYPENAME("MessageSettings") /* .memberName */ |
| 20064 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 20065 | offsetof(UA_DataSetReaderDataType, messageSettings) - offsetof(UA_DataSetReaderDataType, transportSettings) - sizeof(UA_ExtensionObject), /* .padding */ |
| 20066 | false, /* .isArray */ |
| 20067 | false /* .isOptional */ |
| 20068 | }, |
| 20069 | { |
| 20070 | UA_TYPENAME("SubscribedDataSet") /* .memberName */ |
| 20071 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 20072 | offsetof(UA_DataSetReaderDataType, subscribedDataSet) - offsetof(UA_DataSetReaderDataType, messageSettings) - sizeof(UA_ExtensionObject), /* .padding */ |
| 20073 | false, /* .isArray */ |
| 20074 | false /* .isOptional */ |
| 20075 | },}; |
| 20076 | |
| 20077 | /* TargetVariablesDataType */ |
| 20078 | static UA_DataTypeMember TargetVariablesDataType_members[1] = { |
| 20079 | { |
| 20080 | UA_TYPENAME("TargetVariables") /* .memberName */ |
| 20081 | &UA_TYPES[UA_TYPES_FIELDTARGETDATATYPE], /* .memberType */ |
| 20082 | 0, /* .padding */ |
| 20083 | true, /* .isArray */ |
| 20084 | false /* .isOptional */ |
| 20085 | },}; |
| 20086 | |
| 20087 | /* StandaloneSubscribedDataSetDataType */ |
| 20088 | static UA_DataTypeMember StandaloneSubscribedDataSetDataType_members[4] = { |
| 20089 | { |
| 20090 | UA_TYPENAME("Name") /* .memberName */ |
| 20091 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 20092 | 0, /* .padding */ |
| 20093 | false, /* .isArray */ |
| 20094 | false /* .isOptional */ |
| 20095 | }, |
| 20096 | { |
| 20097 | UA_TYPENAME("DataSetFolder") /* .memberName */ |
| 20098 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 20099 | offsetof(UA_StandaloneSubscribedDataSetDataType, dataSetFolderSize) - offsetof(UA_StandaloneSubscribedDataSetDataType, name) - sizeof(UA_String), /* .padding */ |
| 20100 | true, /* .isArray */ |
| 20101 | false /* .isOptional */ |
| 20102 | }, |
| 20103 | { |
| 20104 | UA_TYPENAME("DataSetMetaData") /* .memberName */ |
| 20105 | &UA_TYPES[UA_TYPES_DATASETMETADATATYPE], /* .memberType */ |
| 20106 | offsetof(UA_StandaloneSubscribedDataSetDataType, dataSetMetaData) - offsetof(UA_StandaloneSubscribedDataSetDataType, dataSetFolder) - sizeof(void *), /* .padding */ |
| 20107 | false, /* .isArray */ |
| 20108 | false /* .isOptional */ |
| 20109 | }, |
| 20110 | { |
| 20111 | UA_TYPENAME("SubscribedDataSet") /* .memberName */ |
| 20112 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 20113 | offsetof(UA_StandaloneSubscribedDataSetDataType, subscribedDataSet) - offsetof(UA_StandaloneSubscribedDataSetDataType, dataSetMetaData) - sizeof(UA_DataSetMetaDataType), /* .padding */ |
| 20114 | false, /* .isArray */ |
| 20115 | false /* .isOptional */ |
| 20116 | },}; |
| 20117 | |
| 20118 | /* DataTypeSchemaHeader */ |
| 20119 | static UA_DataTypeMember DataTypeSchemaHeader_members[4] = { |
| 20120 | { |
| 20121 | UA_TYPENAME("Namespaces") /* .memberName */ |
| 20122 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 20123 | 0, /* .padding */ |
| 20124 | true, /* .isArray */ |
| 20125 | false /* .isOptional */ |
| 20126 | }, |
| 20127 | { |
| 20128 | UA_TYPENAME("StructureDataTypes") /* .memberName */ |
| 20129 | &UA_TYPES[UA_TYPES_STRUCTUREDESCRIPTION], /* .memberType */ |
| 20130 | offsetof(UA_DataTypeSchemaHeader, structureDataTypesSize) - offsetof(UA_DataTypeSchemaHeader, namespaces) - sizeof(void *), /* .padding */ |
| 20131 | true, /* .isArray */ |
| 20132 | false /* .isOptional */ |
| 20133 | }, |
| 20134 | { |
| 20135 | UA_TYPENAME("EnumDataTypes") /* .memberName */ |
| 20136 | &UA_TYPES[UA_TYPES_ENUMDESCRIPTION], /* .memberType */ |
| 20137 | offsetof(UA_DataTypeSchemaHeader, enumDataTypesSize) - offsetof(UA_DataTypeSchemaHeader, structureDataTypes) - sizeof(void *), /* .padding */ |
| 20138 | true, /* .isArray */ |
| 20139 | false /* .isOptional */ |
| 20140 | }, |
| 20141 | { |
| 20142 | UA_TYPENAME("SimpleDataTypes") /* .memberName */ |
| 20143 | &UA_TYPES[UA_TYPES_SIMPLETYPEDESCRIPTION], /* .memberType */ |
| 20144 | offsetof(UA_DataTypeSchemaHeader, simpleDataTypesSize) - offsetof(UA_DataTypeSchemaHeader, enumDataTypes) - sizeof(void *), /* .padding */ |
| 20145 | true, /* .isArray */ |
| 20146 | false /* .isOptional */ |
| 20147 | },}; |
| 20148 | |
| 20149 | /* ReaderGroupDataType */ |
| 20150 | static UA_DataTypeMember ReaderGroupDataType_members[10] = { |
| 20151 | { |
| 20152 | UA_TYPENAME("Name") /* .memberName */ |
| 20153 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 20154 | 0, /* .padding */ |
| 20155 | false, /* .isArray */ |
| 20156 | false /* .isOptional */ |
| 20157 | }, |
| 20158 | { |
| 20159 | UA_TYPENAME("Enabled") /* .memberName */ |
| 20160 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 20161 | offsetof(UA_ReaderGroupDataType, enabled) - offsetof(UA_ReaderGroupDataType, name) - sizeof(UA_String), /* .padding */ |
| 20162 | false, /* .isArray */ |
| 20163 | false /* .isOptional */ |
| 20164 | }, |
| 20165 | { |
| 20166 | UA_TYPENAME("SecurityMode") /* .memberName */ |
| 20167 | &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], /* .memberType */ |
| 20168 | offsetof(UA_ReaderGroupDataType, securityMode) - offsetof(UA_ReaderGroupDataType, enabled) - sizeof(UA_Boolean), /* .padding */ |
| 20169 | false, /* .isArray */ |
| 20170 | false /* .isOptional */ |
| 20171 | }, |
| 20172 | { |
| 20173 | UA_TYPENAME("SecurityGroupId") /* .memberName */ |
| 20174 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 20175 | offsetof(UA_ReaderGroupDataType, securityGroupId) - offsetof(UA_ReaderGroupDataType, securityMode) - sizeof(UA_MessageSecurityMode), /* .padding */ |
| 20176 | false, /* .isArray */ |
| 20177 | false /* .isOptional */ |
| 20178 | }, |
| 20179 | { |
| 20180 | UA_TYPENAME("SecurityKeyServices") /* .memberName */ |
| 20181 | &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */ |
| 20182 | offsetof(UA_ReaderGroupDataType, securityKeyServicesSize) - offsetof(UA_ReaderGroupDataType, securityGroupId) - sizeof(UA_String), /* .padding */ |
| 20183 | true, /* .isArray */ |
| 20184 | false /* .isOptional */ |
| 20185 | }, |
| 20186 | { |
| 20187 | UA_TYPENAME("MaxNetworkMessageSize") /* .memberName */ |
| 20188 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 20189 | offsetof(UA_ReaderGroupDataType, maxNetworkMessageSize) - offsetof(UA_ReaderGroupDataType, securityKeyServices) - sizeof(void *), /* .padding */ |
| 20190 | false, /* .isArray */ |
| 20191 | false /* .isOptional */ |
| 20192 | }, |
| 20193 | { |
| 20194 | UA_TYPENAME("GroupProperties") /* .memberName */ |
| 20195 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 20196 | offsetof(UA_ReaderGroupDataType, groupPropertiesSize) - offsetof(UA_ReaderGroupDataType, maxNetworkMessageSize) - sizeof(UA_UInt32), /* .padding */ |
| 20197 | true, /* .isArray */ |
| 20198 | false /* .isOptional */ |
| 20199 | }, |
| 20200 | { |
| 20201 | UA_TYPENAME("TransportSettings") /* .memberName */ |
| 20202 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 20203 | offsetof(UA_ReaderGroupDataType, transportSettings) - offsetof(UA_ReaderGroupDataType, groupProperties) - sizeof(void *), /* .padding */ |
| 20204 | false, /* .isArray */ |
| 20205 | false /* .isOptional */ |
| 20206 | }, |
| 20207 | { |
| 20208 | UA_TYPENAME("MessageSettings") /* .memberName */ |
| 20209 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 20210 | offsetof(UA_ReaderGroupDataType, messageSettings) - offsetof(UA_ReaderGroupDataType, transportSettings) - sizeof(UA_ExtensionObject), /* .padding */ |
| 20211 | false, /* .isArray */ |
| 20212 | false /* .isOptional */ |
| 20213 | }, |
| 20214 | { |
| 20215 | UA_TYPENAME("DataSetReaders") /* .memberName */ |
| 20216 | &UA_TYPES[UA_TYPES_DATASETREADERDATATYPE], /* .memberType */ |
| 20217 | offsetof(UA_ReaderGroupDataType, dataSetReadersSize) - offsetof(UA_ReaderGroupDataType, messageSettings) - sizeof(UA_ExtensionObject), /* .padding */ |
| 20218 | true, /* .isArray */ |
| 20219 | false /* .isOptional */ |
| 20220 | },}; |
| 20221 | |
| 20222 | /* PubSubConnectionDataType */ |
| 20223 | static UA_DataTypeMember PubSubConnectionDataType_members[9] = { |
| 20224 | { |
| 20225 | UA_TYPENAME("Name") /* .memberName */ |
| 20226 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 20227 | 0, /* .padding */ |
| 20228 | false, /* .isArray */ |
| 20229 | false /* .isOptional */ |
| 20230 | }, |
| 20231 | { |
| 20232 | UA_TYPENAME("Enabled") /* .memberName */ |
| 20233 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 20234 | offsetof(UA_PubSubConnectionDataType, enabled) - offsetof(UA_PubSubConnectionDataType, name) - sizeof(UA_String), /* .padding */ |
| 20235 | false, /* .isArray */ |
| 20236 | false /* .isOptional */ |
| 20237 | }, |
| 20238 | { |
| 20239 | UA_TYPENAME("PublisherId") /* .memberName */ |
| 20240 | &UA_TYPES[UA_TYPES_VARIANT], /* .memberType */ |
| 20241 | offsetof(UA_PubSubConnectionDataType, publisherId) - offsetof(UA_PubSubConnectionDataType, enabled) - sizeof(UA_Boolean), /* .padding */ |
| 20242 | false, /* .isArray */ |
| 20243 | false /* .isOptional */ |
| 20244 | }, |
| 20245 | { |
| 20246 | UA_TYPENAME("TransportProfileUri") /* .memberName */ |
| 20247 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 20248 | offsetof(UA_PubSubConnectionDataType, transportProfileUri) - offsetof(UA_PubSubConnectionDataType, publisherId) - sizeof(UA_Variant), /* .padding */ |
| 20249 | false, /* .isArray */ |
| 20250 | false /* .isOptional */ |
| 20251 | }, |
| 20252 | { |
| 20253 | UA_TYPENAME("Address") /* .memberName */ |
| 20254 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 20255 | offsetof(UA_PubSubConnectionDataType, address) - offsetof(UA_PubSubConnectionDataType, transportProfileUri) - sizeof(UA_String), /* .padding */ |
| 20256 | false, /* .isArray */ |
| 20257 | false /* .isOptional */ |
| 20258 | }, |
| 20259 | { |
| 20260 | UA_TYPENAME("ConnectionProperties") /* .memberName */ |
| 20261 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 20262 | offsetof(UA_PubSubConnectionDataType, connectionPropertiesSize) - offsetof(UA_PubSubConnectionDataType, address) - sizeof(UA_ExtensionObject), /* .padding */ |
| 20263 | true, /* .isArray */ |
| 20264 | false /* .isOptional */ |
| 20265 | }, |
| 20266 | { |
| 20267 | UA_TYPENAME("TransportSettings") /* .memberName */ |
| 20268 | &UA_TYPES[UA_TYPES_EXTENSIONOBJECT], /* .memberType */ |
| 20269 | offsetof(UA_PubSubConnectionDataType, transportSettings) - offsetof(UA_PubSubConnectionDataType, connectionProperties) - sizeof(void *), /* .padding */ |
| 20270 | false, /* .isArray */ |
| 20271 | false /* .isOptional */ |
| 20272 | }, |
| 20273 | { |
| 20274 | UA_TYPENAME("WriterGroups") /* .memberName */ |
| 20275 | &UA_TYPES[UA_TYPES_WRITERGROUPDATATYPE], /* .memberType */ |
| 20276 | offsetof(UA_PubSubConnectionDataType, writerGroupsSize) - offsetof(UA_PubSubConnectionDataType, transportSettings) - sizeof(UA_ExtensionObject), /* .padding */ |
| 20277 | true, /* .isArray */ |
| 20278 | false /* .isOptional */ |
| 20279 | }, |
| 20280 | { |
| 20281 | UA_TYPENAME("ReaderGroups") /* .memberName */ |
| 20282 | &UA_TYPES[UA_TYPES_READERGROUPDATATYPE], /* .memberType */ |
| 20283 | offsetof(UA_PubSubConnectionDataType, readerGroupsSize) - offsetof(UA_PubSubConnectionDataType, writerGroups) - sizeof(void *), /* .padding */ |
| 20284 | true, /* .isArray */ |
| 20285 | false /* .isOptional */ |
| 20286 | },}; |
| 20287 | |
| 20288 | /* PubSubConfigurationDataType */ |
| 20289 | static UA_DataTypeMember PubSubConfigurationDataType_members[3] = { |
| 20290 | { |
| 20291 | UA_TYPENAME("PublishedDataSets") /* .memberName */ |
| 20292 | &UA_TYPES[UA_TYPES_PUBLISHEDDATASETDATATYPE], /* .memberType */ |
| 20293 | 0, /* .padding */ |
| 20294 | true, /* .isArray */ |
| 20295 | false /* .isOptional */ |
| 20296 | }, |
| 20297 | { |
| 20298 | UA_TYPENAME("Connections") /* .memberName */ |
| 20299 | &UA_TYPES[UA_TYPES_PUBSUBCONNECTIONDATATYPE], /* .memberType */ |
| 20300 | offsetof(UA_PubSubConfigurationDataType, connectionsSize) - offsetof(UA_PubSubConfigurationDataType, publishedDataSets) - sizeof(void *), /* .padding */ |
| 20301 | true, /* .isArray */ |
| 20302 | false /* .isOptional */ |
| 20303 | }, |
| 20304 | { |
| 20305 | UA_TYPENAME("Enabled") /* .memberName */ |
| 20306 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 20307 | offsetof(UA_PubSubConfigurationDataType, enabled) - offsetof(UA_PubSubConfigurationDataType, connections) - sizeof(void *), /* .padding */ |
| 20308 | false, /* .isArray */ |
| 20309 | false /* .isOptional */ |
| 20310 | },}; |
| 20311 | |
| 20312 | /* PubSubConfiguration2DataType */ |
| 20313 | static UA_DataTypeMember PubSubConfiguration2DataType_members[10] = { |
| 20314 | { |
| 20315 | UA_TYPENAME("PublishedDataSets") /* .memberName */ |
| 20316 | &UA_TYPES[UA_TYPES_PUBLISHEDDATASETDATATYPE], /* .memberType */ |
| 20317 | 0, /* .padding */ |
| 20318 | true, /* .isArray */ |
| 20319 | false /* .isOptional */ |
| 20320 | }, |
| 20321 | { |
| 20322 | UA_TYPENAME("Connections") /* .memberName */ |
| 20323 | &UA_TYPES[UA_TYPES_PUBSUBCONNECTIONDATATYPE], /* .memberType */ |
| 20324 | offsetof(UA_PubSubConfiguration2DataType, connectionsSize) - offsetof(UA_PubSubConfiguration2DataType, publishedDataSets) - sizeof(void *), /* .padding */ |
| 20325 | true, /* .isArray */ |
| 20326 | false /* .isOptional */ |
| 20327 | }, |
| 20328 | { |
| 20329 | UA_TYPENAME("Enabled") /* .memberName */ |
| 20330 | &UA_TYPES[UA_TYPES_BOOLEAN], /* .memberType */ |
| 20331 | offsetof(UA_PubSubConfiguration2DataType, enabled) - offsetof(UA_PubSubConfiguration2DataType, connections) - sizeof(void *), /* .padding */ |
| 20332 | false, /* .isArray */ |
| 20333 | false /* .isOptional */ |
| 20334 | }, |
| 20335 | { |
| 20336 | UA_TYPENAME("SubscribedDataSets") /* .memberName */ |
| 20337 | &UA_TYPES[UA_TYPES_STANDALONESUBSCRIBEDDATASETDATATYPE], /* .memberType */ |
| 20338 | offsetof(UA_PubSubConfiguration2DataType, subscribedDataSetsSize) - offsetof(UA_PubSubConfiguration2DataType, enabled) - sizeof(UA_Boolean), /* .padding */ |
| 20339 | true, /* .isArray */ |
| 20340 | false /* .isOptional */ |
| 20341 | }, |
| 20342 | { |
| 20343 | UA_TYPENAME("DataSetClasses") /* .memberName */ |
| 20344 | &UA_TYPES[UA_TYPES_DATASETMETADATATYPE], /* .memberType */ |
| 20345 | offsetof(UA_PubSubConfiguration2DataType, dataSetClassesSize) - offsetof(UA_PubSubConfiguration2DataType, subscribedDataSets) - sizeof(void *), /* .padding */ |
| 20346 | true, /* .isArray */ |
| 20347 | false /* .isOptional */ |
| 20348 | }, |
| 20349 | { |
| 20350 | UA_TYPENAME("DefaultSecurityKeyServices") /* .memberName */ |
| 20351 | &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION], /* .memberType */ |
| 20352 | offsetof(UA_PubSubConfiguration2DataType, defaultSecurityKeyServicesSize) - offsetof(UA_PubSubConfiguration2DataType, dataSetClasses) - sizeof(void *), /* .padding */ |
| 20353 | true, /* .isArray */ |
| 20354 | false /* .isOptional */ |
| 20355 | }, |
| 20356 | { |
| 20357 | UA_TYPENAME("SecurityGroups") /* .memberName */ |
| 20358 | &UA_TYPES[UA_TYPES_SECURITYGROUPDATATYPE], /* .memberType */ |
| 20359 | offsetof(UA_PubSubConfiguration2DataType, securityGroupsSize) - offsetof(UA_PubSubConfiguration2DataType, defaultSecurityKeyServices) - sizeof(void *), /* .padding */ |
| 20360 | true, /* .isArray */ |
| 20361 | false /* .isOptional */ |
| 20362 | }, |
| 20363 | { |
| 20364 | UA_TYPENAME("PubSubKeyPushTargets") /* .memberName */ |
| 20365 | &UA_TYPES[UA_TYPES_PUBSUBKEYPUSHTARGETDATATYPE], /* .memberType */ |
| 20366 | offsetof(UA_PubSubConfiguration2DataType, pubSubKeyPushTargetsSize) - offsetof(UA_PubSubConfiguration2DataType, securityGroups) - sizeof(void *), /* .padding */ |
| 20367 | true, /* .isArray */ |
| 20368 | false /* .isOptional */ |
| 20369 | }, |
| 20370 | { |
| 20371 | UA_TYPENAME("ConfigurationVersion") /* .memberName */ |
| 20372 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 20373 | offsetof(UA_PubSubConfiguration2DataType, configurationVersion) - offsetof(UA_PubSubConfiguration2DataType, pubSubKeyPushTargets) - sizeof(void *), /* .padding */ |
| 20374 | false, /* .isArray */ |
| 20375 | false /* .isOptional */ |
| 20376 | }, |
| 20377 | { |
| 20378 | UA_TYPENAME("ConfigurationProperties") /* .memberName */ |
| 20379 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR], /* .memberType */ |
| 20380 | offsetof(UA_PubSubConfiguration2DataType, configurationPropertiesSize) - offsetof(UA_PubSubConfiguration2DataType, configurationVersion) - sizeof(UA_UInt32), /* .padding */ |
| 20381 | true, /* .isArray */ |
| 20382 | false /* .isOptional */ |
| 20383 | },}; |
| 20384 | UA_DataType UA_TYPES[UA_TYPES_COUNT] = { |
| 20385 | /* Boolean */ |
| 20386 | { |
| 20387 | UA_TYPENAME("Boolean") /* .typeName */ |
| 20388 | {0, UA_NODEIDTYPE_NUMERIC, {1LU}}, /* .typeId */ |
| 20389 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20390 | sizeof(UA_Boolean), /* .memSize */ |
| 20391 | UA_DATATYPEKIND_BOOLEAN, /* .typeKind */ |
| 20392 | true, /* .pointerFree */ |
| 20393 | false, /* .overlayable */ |
| 20394 | 0, /* .membersSize */ |
| 20395 | Boolean_members /* .members */ |
| 20396 | }, |
| 20397 | /* SByte */ |
| 20398 | { |
| 20399 | UA_TYPENAME("SByte") /* .typeName */ |
| 20400 | {0, UA_NODEIDTYPE_NUMERIC, {2LU}}, /* .typeId */ |
| 20401 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20402 | sizeof(UA_SByte), /* .memSize */ |
| 20403 | UA_DATATYPEKIND_SBYTE, /* .typeKind */ |
| 20404 | true, /* .pointerFree */ |
| 20405 | true, /* .overlayable */ |
| 20406 | 0, /* .membersSize */ |
| 20407 | SByte_members /* .members */ |
| 20408 | }, |
| 20409 | /* Byte */ |
| 20410 | { |
| 20411 | UA_TYPENAME("Byte") /* .typeName */ |
| 20412 | {0, UA_NODEIDTYPE_NUMERIC, {3LU}}, /* .typeId */ |
| 20413 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20414 | sizeof(UA_Byte), /* .memSize */ |
| 20415 | UA_DATATYPEKIND_BYTE, /* .typeKind */ |
| 20416 | true, /* .pointerFree */ |
| 20417 | true, /* .overlayable */ |
| 20418 | 0, /* .membersSize */ |
| 20419 | Byte_members /* .members */ |
| 20420 | }, |
| 20421 | /* Int16 */ |
| 20422 | { |
| 20423 | UA_TYPENAME("Int16") /* .typeName */ |
| 20424 | {0, UA_NODEIDTYPE_NUMERIC, {4LU}}, /* .typeId */ |
| 20425 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20426 | sizeof(UA_Int16), /* .memSize */ |
| 20427 | UA_DATATYPEKIND_INT16, /* .typeKind */ |
| 20428 | true, /* .pointerFree */ |
| 20429 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20430 | 0, /* .membersSize */ |
| 20431 | Int16_members /* .members */ |
| 20432 | }, |
| 20433 | /* UInt16 */ |
| 20434 | { |
| 20435 | UA_TYPENAME("UInt16") /* .typeName */ |
| 20436 | {0, UA_NODEIDTYPE_NUMERIC, {5LU}}, /* .typeId */ |
| 20437 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20438 | sizeof(UA_UInt16), /* .memSize */ |
| 20439 | UA_DATATYPEKIND_UINT16, /* .typeKind */ |
| 20440 | true, /* .pointerFree */ |
| 20441 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20442 | 0, /* .membersSize */ |
| 20443 | UInt16_members /* .members */ |
| 20444 | }, |
| 20445 | /* Int32 */ |
| 20446 | { |
| 20447 | UA_TYPENAME("Int32") /* .typeName */ |
| 20448 | {0, UA_NODEIDTYPE_NUMERIC, {6LU}}, /* .typeId */ |
| 20449 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20450 | sizeof(UA_Int32), /* .memSize */ |
| 20451 | UA_DATATYPEKIND_INT32, /* .typeKind */ |
| 20452 | true, /* .pointerFree */ |
| 20453 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20454 | 0, /* .membersSize */ |
| 20455 | Int32_members /* .members */ |
| 20456 | }, |
| 20457 | /* UInt32 */ |
| 20458 | { |
| 20459 | UA_TYPENAME("UInt32") /* .typeName */ |
| 20460 | {0, UA_NODEIDTYPE_NUMERIC, {7LU}}, /* .typeId */ |
| 20461 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20462 | sizeof(UA_UInt32), /* .memSize */ |
| 20463 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 20464 | true, /* .pointerFree */ |
| 20465 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20466 | 0, /* .membersSize */ |
| 20467 | UInt32_members /* .members */ |
| 20468 | }, |
| 20469 | /* Int64 */ |
| 20470 | { |
| 20471 | UA_TYPENAME("Int64") /* .typeName */ |
| 20472 | {0, UA_NODEIDTYPE_NUMERIC, {8LU}}, /* .typeId */ |
| 20473 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20474 | sizeof(UA_Int64), /* .memSize */ |
| 20475 | UA_DATATYPEKIND_INT64, /* .typeKind */ |
| 20476 | true, /* .pointerFree */ |
| 20477 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20478 | 0, /* .membersSize */ |
| 20479 | Int64_members /* .members */ |
| 20480 | }, |
| 20481 | /* UInt64 */ |
| 20482 | { |
| 20483 | UA_TYPENAME("UInt64") /* .typeName */ |
| 20484 | {0, UA_NODEIDTYPE_NUMERIC, {9LU}}, /* .typeId */ |
| 20485 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20486 | sizeof(UA_UInt64), /* .memSize */ |
| 20487 | UA_DATATYPEKIND_UINT64, /* .typeKind */ |
| 20488 | true, /* .pointerFree */ |
| 20489 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20490 | 0, /* .membersSize */ |
| 20491 | UInt64_members /* .members */ |
| 20492 | }, |
| 20493 | /* Float */ |
| 20494 | { |
| 20495 | UA_TYPENAME("Float") /* .typeName */ |
| 20496 | {0, UA_NODEIDTYPE_NUMERIC, {10LU}}, /* .typeId */ |
| 20497 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20498 | sizeof(UA_Float), /* .memSize */ |
| 20499 | UA_DATATYPEKIND_FLOAT, /* .typeKind */ |
| 20500 | true, /* .pointerFree */ |
| 20501 | UA_BINARY_OVERLAYABLE_FLOAT, /* .overlayable */ |
| 20502 | 0, /* .membersSize */ |
| 20503 | Float_members /* .members */ |
| 20504 | }, |
| 20505 | /* Double */ |
| 20506 | { |
| 20507 | UA_TYPENAME("Double") /* .typeName */ |
| 20508 | {0, UA_NODEIDTYPE_NUMERIC, {11LU}}, /* .typeId */ |
| 20509 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20510 | sizeof(UA_Double), /* .memSize */ |
| 20511 | UA_DATATYPEKIND_DOUBLE, /* .typeKind */ |
| 20512 | true, /* .pointerFree */ |
| 20513 | UA_BINARY_OVERLAYABLE_FLOAT, /* .overlayable */ |
| 20514 | 0, /* .membersSize */ |
| 20515 | Double_members /* .members */ |
| 20516 | }, |
| 20517 | /* String */ |
| 20518 | { |
| 20519 | UA_TYPENAME("String") /* .typeName */ |
| 20520 | {0, UA_NODEIDTYPE_NUMERIC, {12LU}}, /* .typeId */ |
| 20521 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20522 | sizeof(UA_String), /* .memSize */ |
| 20523 | UA_DATATYPEKIND_STRING, /* .typeKind */ |
| 20524 | false, /* .pointerFree */ |
| 20525 | false, /* .overlayable */ |
| 20526 | 0, /* .membersSize */ |
| 20527 | String_members /* .members */ |
| 20528 | }, |
| 20529 | /* DateTime */ |
| 20530 | { |
| 20531 | UA_TYPENAME("DateTime") /* .typeName */ |
| 20532 | {0, UA_NODEIDTYPE_NUMERIC, {13LU}}, /* .typeId */ |
| 20533 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20534 | sizeof(UA_DateTime), /* .memSize */ |
| 20535 | UA_DATATYPEKIND_DATETIME, /* .typeKind */ |
| 20536 | true, /* .pointerFree */ |
| 20537 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20538 | 0, /* .membersSize */ |
| 20539 | DateTime_members /* .members */ |
| 20540 | }, |
| 20541 | /* Guid */ |
| 20542 | { |
| 20543 | UA_TYPENAME("Guid") /* .typeName */ |
| 20544 | {0, UA_NODEIDTYPE_NUMERIC, {14LU}}, /* .typeId */ |
| 20545 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20546 | sizeof(UA_Guid), /* .memSize */ |
| 20547 | UA_DATATYPEKIND_GUID, /* .typeKind */ |
| 20548 | true, /* .pointerFree */ |
| 20549 | (UA_BINARY_OVERLAYABLE_INTEGER && offsetof(UA_Guid, data2) == sizeof(UA_UInt32) && offsetof(UA_Guid, data3) == (sizeof(UA_UInt16) + sizeof(UA_UInt32)) && offsetof(UA_Guid, data4) == (2*sizeof(UA_UInt32))), /* .overlayable */ |
| 20550 | 0, /* .membersSize */ |
| 20551 | Guid_members /* .members */ |
| 20552 | }, |
| 20553 | /* ByteString */ |
| 20554 | { |
| 20555 | UA_TYPENAME("ByteString") /* .typeName */ |
| 20556 | {0, UA_NODEIDTYPE_NUMERIC, {15LU}}, /* .typeId */ |
| 20557 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20558 | sizeof(UA_ByteString), /* .memSize */ |
| 20559 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 20560 | false, /* .pointerFree */ |
| 20561 | false, /* .overlayable */ |
| 20562 | 0, /* .membersSize */ |
| 20563 | ByteString_members /* .members */ |
| 20564 | }, |
| 20565 | /* XmlElement */ |
| 20566 | { |
| 20567 | UA_TYPENAME("XmlElement") /* .typeName */ |
| 20568 | {0, UA_NODEIDTYPE_NUMERIC, {16LU}}, /* .typeId */ |
| 20569 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20570 | sizeof(UA_XmlElement), /* .memSize */ |
| 20571 | UA_DATATYPEKIND_XMLELEMENT, /* .typeKind */ |
| 20572 | false, /* .pointerFree */ |
| 20573 | false, /* .overlayable */ |
| 20574 | 0, /* .membersSize */ |
| 20575 | XmlElement_members /* .members */ |
| 20576 | }, |
| 20577 | /* NodeId */ |
| 20578 | { |
| 20579 | UA_TYPENAME("NodeId") /* .typeName */ |
| 20580 | {0, UA_NODEIDTYPE_NUMERIC, {17LU}}, /* .typeId */ |
| 20581 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20582 | sizeof(UA_NodeId), /* .memSize */ |
| 20583 | UA_DATATYPEKIND_NODEID, /* .typeKind */ |
| 20584 | false, /* .pointerFree */ |
| 20585 | false, /* .overlayable */ |
| 20586 | 0, /* .membersSize */ |
| 20587 | NodeId_members /* .members */ |
| 20588 | }, |
| 20589 | /* ExpandedNodeId */ |
| 20590 | { |
| 20591 | UA_TYPENAME("ExpandedNodeId") /* .typeName */ |
| 20592 | {0, UA_NODEIDTYPE_NUMERIC, {18LU}}, /* .typeId */ |
| 20593 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20594 | sizeof(UA_ExpandedNodeId), /* .memSize */ |
| 20595 | UA_DATATYPEKIND_EXPANDEDNODEID, /* .typeKind */ |
| 20596 | false, /* .pointerFree */ |
| 20597 | false, /* .overlayable */ |
| 20598 | 0, /* .membersSize */ |
| 20599 | ExpandedNodeId_members /* .members */ |
| 20600 | }, |
| 20601 | /* StatusCode */ |
| 20602 | { |
| 20603 | UA_TYPENAME("StatusCode") /* .typeName */ |
| 20604 | {0, UA_NODEIDTYPE_NUMERIC, {19LU}}, /* .typeId */ |
| 20605 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20606 | sizeof(UA_StatusCode), /* .memSize */ |
| 20607 | UA_DATATYPEKIND_STATUSCODE, /* .typeKind */ |
| 20608 | true, /* .pointerFree */ |
| 20609 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20610 | 0, /* .membersSize */ |
| 20611 | StatusCode_members /* .members */ |
| 20612 | }, |
| 20613 | /* QualifiedName */ |
| 20614 | { |
| 20615 | UA_TYPENAME("QualifiedName") /* .typeName */ |
| 20616 | {0, UA_NODEIDTYPE_NUMERIC, {20LU}}, /* .typeId */ |
| 20617 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20618 | sizeof(UA_QualifiedName), /* .memSize */ |
| 20619 | UA_DATATYPEKIND_QUALIFIEDNAME, /* .typeKind */ |
| 20620 | false, /* .pointerFree */ |
| 20621 | false, /* .overlayable */ |
| 20622 | 0, /* .membersSize */ |
| 20623 | QualifiedName_members /* .members */ |
| 20624 | }, |
| 20625 | /* LocalizedText */ |
| 20626 | { |
| 20627 | UA_TYPENAME("LocalizedText") /* .typeName */ |
| 20628 | {0, UA_NODEIDTYPE_NUMERIC, {21LU}}, /* .typeId */ |
| 20629 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20630 | sizeof(UA_LocalizedText), /* .memSize */ |
| 20631 | UA_DATATYPEKIND_LOCALIZEDTEXT, /* .typeKind */ |
| 20632 | false, /* .pointerFree */ |
| 20633 | false, /* .overlayable */ |
| 20634 | 0, /* .membersSize */ |
| 20635 | LocalizedText_members /* .members */ |
| 20636 | }, |
| 20637 | /* ExtensionObject */ |
| 20638 | { |
| 20639 | UA_TYPENAME("ExtensionObject") /* .typeName */ |
| 20640 | {0, UA_NODEIDTYPE_NUMERIC, {22LU}}, /* .typeId */ |
| 20641 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20642 | sizeof(UA_ExtensionObject), /* .memSize */ |
| 20643 | UA_DATATYPEKIND_EXTENSIONOBJECT, /* .typeKind */ |
| 20644 | false, /* .pointerFree */ |
| 20645 | false, /* .overlayable */ |
| 20646 | 0, /* .membersSize */ |
| 20647 | ExtensionObject_members /* .members */ |
| 20648 | }, |
| 20649 | /* DataValue */ |
| 20650 | { |
| 20651 | UA_TYPENAME("DataValue") /* .typeName */ |
| 20652 | {0, UA_NODEIDTYPE_NUMERIC, {23LU}}, /* .typeId */ |
| 20653 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20654 | sizeof(UA_DataValue), /* .memSize */ |
| 20655 | UA_DATATYPEKIND_DATAVALUE, /* .typeKind */ |
| 20656 | false, /* .pointerFree */ |
| 20657 | false, /* .overlayable */ |
| 20658 | 0, /* .membersSize */ |
| 20659 | DataValue_members /* .members */ |
| 20660 | }, |
| 20661 | /* Variant */ |
| 20662 | { |
| 20663 | UA_TYPENAME("Variant") /* .typeName */ |
| 20664 | {0, UA_NODEIDTYPE_NUMERIC, {24LU}}, /* .typeId */ |
| 20665 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20666 | sizeof(UA_Variant), /* .memSize */ |
| 20667 | UA_DATATYPEKIND_VARIANT, /* .typeKind */ |
| 20668 | false, /* .pointerFree */ |
| 20669 | false, /* .overlayable */ |
| 20670 | 0, /* .membersSize */ |
| 20671 | Variant_members /* .members */ |
| 20672 | }, |
| 20673 | /* DiagnosticInfo */ |
| 20674 | { |
| 20675 | UA_TYPENAME("DiagnosticInfo") /* .typeName */ |
| 20676 | {0, UA_NODEIDTYPE_NUMERIC, {25LU}}, /* .typeId */ |
| 20677 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20678 | sizeof(UA_DiagnosticInfo), /* .memSize */ |
| 20679 | UA_DATATYPEKIND_DIAGNOSTICINFO, /* .typeKind */ |
| 20680 | false, /* .pointerFree */ |
| 20681 | false, /* .overlayable */ |
| 20682 | 0, /* .membersSize */ |
| 20683 | DiagnosticInfo_members /* .members */ |
| 20684 | }, |
| 20685 | /* NamingRuleType */ |
| 20686 | { |
| 20687 | UA_TYPENAME("NamingRuleType") /* .typeName */ |
| 20688 | {0, UA_NODEIDTYPE_NUMERIC, {120LU}}, /* .typeId */ |
| 20689 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20690 | sizeof(UA_NamingRuleType), /* .memSize */ |
| 20691 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 20692 | true, /* .pointerFree */ |
| 20693 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20694 | 0, /* .membersSize */ |
| 20695 | NamingRuleType_members /* .members */ |
| 20696 | }, |
| 20697 | /* Enumeration */ |
| 20698 | { |
| 20699 | UA_TYPENAME("Enumeration") /* .typeName */ |
| 20700 | {0, UA_NODEIDTYPE_NUMERIC, {29LU}}, /* .typeId */ |
| 20701 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20702 | sizeof(UA_Enumeration), /* .memSize */ |
| 20703 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 20704 | true, /* .pointerFree */ |
| 20705 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20706 | 0, /* .membersSize */ |
| 20707 | Enumeration_members /* .members */ |
| 20708 | }, |
| 20709 | /* ImageBMP */ |
| 20710 | { |
| 20711 | UA_TYPENAME("ImageBMP") /* .typeName */ |
| 20712 | {0, UA_NODEIDTYPE_NUMERIC, {2000LU}}, /* .typeId */ |
| 20713 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20714 | sizeof(UA_ImageBMP), /* .memSize */ |
| 20715 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 20716 | false, /* .pointerFree */ |
| 20717 | false, /* .overlayable */ |
| 20718 | 0, /* .membersSize */ |
| 20719 | ImageBMP_members /* .members */ |
| 20720 | }, |
| 20721 | /* ImageGIF */ |
| 20722 | { |
| 20723 | UA_TYPENAME("ImageGIF") /* .typeName */ |
| 20724 | {0, UA_NODEIDTYPE_NUMERIC, {2001LU}}, /* .typeId */ |
| 20725 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20726 | sizeof(UA_ImageGIF), /* .memSize */ |
| 20727 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 20728 | false, /* .pointerFree */ |
| 20729 | false, /* .overlayable */ |
| 20730 | 0, /* .membersSize */ |
| 20731 | ImageGIF_members /* .members */ |
| 20732 | }, |
| 20733 | /* ImageJPG */ |
| 20734 | { |
| 20735 | UA_TYPENAME("ImageJPG") /* .typeName */ |
| 20736 | {0, UA_NODEIDTYPE_NUMERIC, {2002LU}}, /* .typeId */ |
| 20737 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20738 | sizeof(UA_ImageJPG), /* .memSize */ |
| 20739 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 20740 | false, /* .pointerFree */ |
| 20741 | false, /* .overlayable */ |
| 20742 | 0, /* .membersSize */ |
| 20743 | ImageJPG_members /* .members */ |
| 20744 | }, |
| 20745 | /* ImagePNG */ |
| 20746 | { |
| 20747 | UA_TYPENAME("ImagePNG") /* .typeName */ |
| 20748 | {0, UA_NODEIDTYPE_NUMERIC, {2003LU}}, /* .typeId */ |
| 20749 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20750 | sizeof(UA_ImagePNG), /* .memSize */ |
| 20751 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 20752 | false, /* .pointerFree */ |
| 20753 | false, /* .overlayable */ |
| 20754 | 0, /* .membersSize */ |
| 20755 | ImagePNG_members /* .members */ |
| 20756 | }, |
| 20757 | /* AudioDataType */ |
| 20758 | { |
| 20759 | UA_TYPENAME("AudioDataType") /* .typeName */ |
| 20760 | {0, UA_NODEIDTYPE_NUMERIC, {16307LU}}, /* .typeId */ |
| 20761 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20762 | sizeof(UA_AudioDataType), /* .memSize */ |
| 20763 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 20764 | false, /* .pointerFree */ |
| 20765 | false, /* .overlayable */ |
| 20766 | 0, /* .membersSize */ |
| 20767 | AudioDataType_members /* .members */ |
| 20768 | }, |
| 20769 | /* UriString */ |
| 20770 | { |
| 20771 | UA_TYPENAME("UriString") /* .typeName */ |
| 20772 | {0, UA_NODEIDTYPE_NUMERIC, {23751LU}}, /* .typeId */ |
| 20773 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20774 | sizeof(UA_UriString), /* .memSize */ |
| 20775 | UA_DATATYPEKIND_STRING, /* .typeKind */ |
| 20776 | false, /* .pointerFree */ |
| 20777 | false, /* .overlayable */ |
| 20778 | 0, /* .membersSize */ |
| 20779 | UriString_members /* .members */ |
| 20780 | }, |
| 20781 | /* BitFieldMaskDataType */ |
| 20782 | { |
| 20783 | UA_TYPENAME("BitFieldMaskDataType") /* .typeName */ |
| 20784 | {0, UA_NODEIDTYPE_NUMERIC, {11737LU}}, /* .typeId */ |
| 20785 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20786 | sizeof(UA_BitFieldMaskDataType), /* .memSize */ |
| 20787 | UA_DATATYPEKIND_UINT64, /* .typeKind */ |
| 20788 | false, /* .pointerFree */ |
| 20789 | false, /* .overlayable */ |
| 20790 | 0, /* .membersSize */ |
| 20791 | BitFieldMaskDataType_members /* .members */ |
| 20792 | }, |
| 20793 | /* SemanticVersionString */ |
| 20794 | { |
| 20795 | UA_TYPENAME("SemanticVersionString") /* .typeName */ |
| 20796 | {0, UA_NODEIDTYPE_NUMERIC, {24263LU}}, /* .typeId */ |
| 20797 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20798 | sizeof(UA_SemanticVersionString), /* .memSize */ |
| 20799 | UA_DATATYPEKIND_STRING, /* .typeKind */ |
| 20800 | false, /* .pointerFree */ |
| 20801 | false, /* .overlayable */ |
| 20802 | 0, /* .membersSize */ |
| 20803 | SemanticVersionString_members /* .members */ |
| 20804 | }, |
| 20805 | /* KeyValuePair */ |
| 20806 | { |
| 20807 | UA_TYPENAME("KeyValuePair") /* .typeName */ |
| 20808 | {0, UA_NODEIDTYPE_NUMERIC, {14533LU}}, /* .typeId */ |
| 20809 | {0, UA_NODEIDTYPE_NUMERIC, {14846LU}}, /* .binaryEncodingId */ |
| 20810 | sizeof(UA_KeyValuePair), /* .memSize */ |
| 20811 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20812 | false, /* .pointerFree */ |
| 20813 | false, /* .overlayable */ |
| 20814 | 2, /* .membersSize */ |
| 20815 | KeyValuePair_members /* .members */ |
| 20816 | }, |
| 20817 | /* AdditionalParametersType */ |
| 20818 | { |
| 20819 | UA_TYPENAME("AdditionalParametersType") /* .typeName */ |
| 20820 | {0, UA_NODEIDTYPE_NUMERIC, {16313LU}}, /* .typeId */ |
| 20821 | {0, UA_NODEIDTYPE_NUMERIC, {17537LU}}, /* .binaryEncodingId */ |
| 20822 | sizeof(UA_AdditionalParametersType), /* .memSize */ |
| 20823 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20824 | false, /* .pointerFree */ |
| 20825 | false, /* .overlayable */ |
| 20826 | 1, /* .membersSize */ |
| 20827 | AdditionalParametersType_members /* .members */ |
| 20828 | }, |
| 20829 | /* EphemeralKeyType */ |
| 20830 | { |
| 20831 | UA_TYPENAME("EphemeralKeyType") /* .typeName */ |
| 20832 | {0, UA_NODEIDTYPE_NUMERIC, {17548LU}}, /* .typeId */ |
| 20833 | {0, UA_NODEIDTYPE_NUMERIC, {17549LU}}, /* .binaryEncodingId */ |
| 20834 | sizeof(UA_EphemeralKeyType), /* .memSize */ |
| 20835 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20836 | false, /* .pointerFree */ |
| 20837 | false, /* .overlayable */ |
| 20838 | 2, /* .membersSize */ |
| 20839 | EphemeralKeyType_members /* .members */ |
| 20840 | }, |
| 20841 | /* RationalNumber */ |
| 20842 | { |
| 20843 | UA_TYPENAME("RationalNumber") /* .typeName */ |
| 20844 | {0, UA_NODEIDTYPE_NUMERIC, {18806LU}}, /* .typeId */ |
| 20845 | {0, UA_NODEIDTYPE_NUMERIC, {18815LU}}, /* .binaryEncodingId */ |
| 20846 | sizeof(UA_RationalNumber), /* .memSize */ |
| 20847 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20848 | true, /* .pointerFree */ |
| 20849 | false, /* .overlayable */ |
| 20850 | 2, /* .membersSize */ |
| 20851 | RationalNumber_members /* .members */ |
| 20852 | }, |
| 20853 | /* ThreeDVector */ |
| 20854 | { |
| 20855 | UA_TYPENAME("ThreeDVector") /* .typeName */ |
| 20856 | {0, UA_NODEIDTYPE_NUMERIC, {18808LU}}, /* .typeId */ |
| 20857 | {0, UA_NODEIDTYPE_NUMERIC, {18817LU}}, /* .binaryEncodingId */ |
| 20858 | sizeof(UA_ThreeDVector), /* .memSize */ |
| 20859 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20860 | true, /* .pointerFree */ |
| 20861 | false, /* .overlayable */ |
| 20862 | 3, /* .membersSize */ |
| 20863 | ThreeDVector_members /* .members */ |
| 20864 | }, |
| 20865 | /* ThreeDCartesianCoordinates */ |
| 20866 | { |
| 20867 | UA_TYPENAME("ThreeDCartesianCoordinates") /* .typeName */ |
| 20868 | {0, UA_NODEIDTYPE_NUMERIC, {18810LU}}, /* .typeId */ |
| 20869 | {0, UA_NODEIDTYPE_NUMERIC, {18819LU}}, /* .binaryEncodingId */ |
| 20870 | sizeof(UA_ThreeDCartesianCoordinates), /* .memSize */ |
| 20871 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20872 | true, /* .pointerFree */ |
| 20873 | false, /* .overlayable */ |
| 20874 | 3, /* .membersSize */ |
| 20875 | ThreeDCartesianCoordinates_members /* .members */ |
| 20876 | }, |
| 20877 | /* ThreeDOrientation */ |
| 20878 | { |
| 20879 | UA_TYPENAME("ThreeDOrientation") /* .typeName */ |
| 20880 | {0, UA_NODEIDTYPE_NUMERIC, {18812LU}}, /* .typeId */ |
| 20881 | {0, UA_NODEIDTYPE_NUMERIC, {18821LU}}, /* .binaryEncodingId */ |
| 20882 | sizeof(UA_ThreeDOrientation), /* .memSize */ |
| 20883 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20884 | true, /* .pointerFree */ |
| 20885 | false, /* .overlayable */ |
| 20886 | 3, /* .membersSize */ |
| 20887 | ThreeDOrientation_members /* .members */ |
| 20888 | }, |
| 20889 | /* ThreeDFrame */ |
| 20890 | { |
| 20891 | UA_TYPENAME("ThreeDFrame") /* .typeName */ |
| 20892 | {0, UA_NODEIDTYPE_NUMERIC, {18814LU}}, /* .typeId */ |
| 20893 | {0, UA_NODEIDTYPE_NUMERIC, {18823LU}}, /* .binaryEncodingId */ |
| 20894 | sizeof(UA_ThreeDFrame), /* .memSize */ |
| 20895 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20896 | true, /* .pointerFree */ |
| 20897 | false, /* .overlayable */ |
| 20898 | 2, /* .membersSize */ |
| 20899 | ThreeDFrame_members /* .members */ |
| 20900 | }, |
| 20901 | /* OpenFileMode */ |
| 20902 | { |
| 20903 | UA_TYPENAME("OpenFileMode") /* .typeName */ |
| 20904 | {0, UA_NODEIDTYPE_NUMERIC, {11939LU}}, /* .typeId */ |
| 20905 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20906 | sizeof(UA_OpenFileMode), /* .memSize */ |
| 20907 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 20908 | true, /* .pointerFree */ |
| 20909 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20910 | 0, /* .membersSize */ |
| 20911 | OpenFileMode_members /* .members */ |
| 20912 | }, |
| 20913 | /* IdentityCriteriaType */ |
| 20914 | { |
| 20915 | UA_TYPENAME("IdentityCriteriaType") /* .typeName */ |
| 20916 | {0, UA_NODEIDTYPE_NUMERIC, {15632LU}}, /* .typeId */ |
| 20917 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20918 | sizeof(UA_IdentityCriteriaType), /* .memSize */ |
| 20919 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 20920 | true, /* .pointerFree */ |
| 20921 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20922 | 0, /* .membersSize */ |
| 20923 | IdentityCriteriaType_members /* .members */ |
| 20924 | }, |
| 20925 | /* IdentityMappingRuleType */ |
| 20926 | { |
| 20927 | UA_TYPENAME("IdentityMappingRuleType") /* .typeName */ |
| 20928 | {0, UA_NODEIDTYPE_NUMERIC, {15634LU}}, /* .typeId */ |
| 20929 | {0, UA_NODEIDTYPE_NUMERIC, {15736LU}}, /* .binaryEncodingId */ |
| 20930 | sizeof(UA_IdentityMappingRuleType), /* .memSize */ |
| 20931 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20932 | false, /* .pointerFree */ |
| 20933 | false, /* .overlayable */ |
| 20934 | 2, /* .membersSize */ |
| 20935 | IdentityMappingRuleType_members /* .members */ |
| 20936 | }, |
| 20937 | /* CurrencyUnitType */ |
| 20938 | { |
| 20939 | UA_TYPENAME("CurrencyUnitType") /* .typeName */ |
| 20940 | {0, UA_NODEIDTYPE_NUMERIC, {23498LU}}, /* .typeId */ |
| 20941 | {0, UA_NODEIDTYPE_NUMERIC, {23507LU}}, /* .binaryEncodingId */ |
| 20942 | sizeof(UA_CurrencyUnitType), /* .memSize */ |
| 20943 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20944 | false, /* .pointerFree */ |
| 20945 | false, /* .overlayable */ |
| 20946 | 4, /* .membersSize */ |
| 20947 | CurrencyUnitType_members /* .members */ |
| 20948 | }, |
| 20949 | /* TrustListMasks */ |
| 20950 | { |
| 20951 | UA_TYPENAME("TrustListMasks") /* .typeName */ |
| 20952 | {0, UA_NODEIDTYPE_NUMERIC, {12552LU}}, /* .typeId */ |
| 20953 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 20954 | sizeof(UA_TrustListMasks), /* .memSize */ |
| 20955 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 20956 | true, /* .pointerFree */ |
| 20957 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 20958 | 0, /* .membersSize */ |
| 20959 | TrustListMasks_members /* .members */ |
| 20960 | }, |
| 20961 | /* TrustListDataType */ |
| 20962 | { |
| 20963 | UA_TYPENAME("TrustListDataType") /* .typeName */ |
| 20964 | {0, UA_NODEIDTYPE_NUMERIC, {12554LU}}, /* .typeId */ |
| 20965 | {0, UA_NODEIDTYPE_NUMERIC, {12680LU}}, /* .binaryEncodingId */ |
| 20966 | sizeof(UA_TrustListDataType), /* .memSize */ |
| 20967 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20968 | false, /* .pointerFree */ |
| 20969 | false, /* .overlayable */ |
| 20970 | 5, /* .membersSize */ |
| 20971 | TrustListDataType_members /* .members */ |
| 20972 | }, |
| 20973 | /* DecimalDataType */ |
| 20974 | { |
| 20975 | UA_TYPENAME("DecimalDataType") /* .typeName */ |
| 20976 | {0, UA_NODEIDTYPE_NUMERIC, {17861LU}}, /* .typeId */ |
| 20977 | {0, UA_NODEIDTYPE_NUMERIC, {17863LU}}, /* .binaryEncodingId */ |
| 20978 | sizeof(UA_DecimalDataType), /* .memSize */ |
| 20979 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20980 | false, /* .pointerFree */ |
| 20981 | false, /* .overlayable */ |
| 20982 | 2, /* .membersSize */ |
| 20983 | DecimalDataType_members /* .members */ |
| 20984 | }, |
| 20985 | /* DataTypeDescription */ |
| 20986 | { |
| 20987 | UA_TYPENAME("DataTypeDescription") /* .typeName */ |
| 20988 | {0, UA_NODEIDTYPE_NUMERIC, {14525LU}}, /* .typeId */ |
| 20989 | {0, UA_NODEIDTYPE_NUMERIC, {125LU}}, /* .binaryEncodingId */ |
| 20990 | sizeof(UA_DataTypeDescription), /* .memSize */ |
| 20991 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 20992 | false, /* .pointerFree */ |
| 20993 | false, /* .overlayable */ |
| 20994 | 2, /* .membersSize */ |
| 20995 | DataTypeDescription_members /* .members */ |
| 20996 | }, |
| 20997 | /* SimpleTypeDescription */ |
| 20998 | { |
| 20999 | UA_TYPENAME("SimpleTypeDescription") /* .typeName */ |
| 21000 | {0, UA_NODEIDTYPE_NUMERIC, {15005LU}}, /* .typeId */ |
| 21001 | {0, UA_NODEIDTYPE_NUMERIC, {15421LU}}, /* .binaryEncodingId */ |
| 21002 | sizeof(UA_SimpleTypeDescription), /* .memSize */ |
| 21003 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21004 | false, /* .pointerFree */ |
| 21005 | false, /* .overlayable */ |
| 21006 | 4, /* .membersSize */ |
| 21007 | SimpleTypeDescription_members /* .members */ |
| 21008 | }, |
| 21009 | /* PortableQualifiedName */ |
| 21010 | { |
| 21011 | UA_TYPENAME("PortableQualifiedName") /* .typeName */ |
| 21012 | {0, UA_NODEIDTYPE_NUMERIC, {24105LU}}, /* .typeId */ |
| 21013 | {0, UA_NODEIDTYPE_NUMERIC, {24108LU}}, /* .binaryEncodingId */ |
| 21014 | sizeof(UA_PortableQualifiedName), /* .memSize */ |
| 21015 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21016 | false, /* .pointerFree */ |
| 21017 | false, /* .overlayable */ |
| 21018 | 2, /* .membersSize */ |
| 21019 | PortableQualifiedName_members /* .members */ |
| 21020 | }, |
| 21021 | /* PortableNodeId */ |
| 21022 | { |
| 21023 | UA_TYPENAME("PortableNodeId") /* .typeName */ |
| 21024 | {0, UA_NODEIDTYPE_NUMERIC, {24106LU}}, /* .typeId */ |
| 21025 | {0, UA_NODEIDTYPE_NUMERIC, {24109LU}}, /* .binaryEncodingId */ |
| 21026 | sizeof(UA_PortableNodeId), /* .memSize */ |
| 21027 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21028 | false, /* .pointerFree */ |
| 21029 | false, /* .overlayable */ |
| 21030 | 2, /* .membersSize */ |
| 21031 | PortableNodeId_members /* .members */ |
| 21032 | }, |
| 21033 | /* UnsignedRationalNumber */ |
| 21034 | { |
| 21035 | UA_TYPENAME("UnsignedRationalNumber") /* .typeName */ |
| 21036 | {0, UA_NODEIDTYPE_NUMERIC, {24107LU}}, /* .typeId */ |
| 21037 | {0, UA_NODEIDTYPE_NUMERIC, {24110LU}}, /* .binaryEncodingId */ |
| 21038 | sizeof(UA_UnsignedRationalNumber), /* .memSize */ |
| 21039 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21040 | true, /* .pointerFree */ |
| 21041 | false, /* .overlayable */ |
| 21042 | 2, /* .membersSize */ |
| 21043 | UnsignedRationalNumber_members /* .members */ |
| 21044 | }, |
| 21045 | /* PubSubState */ |
| 21046 | { |
| 21047 | UA_TYPENAME("PubSubState") /* .typeName */ |
| 21048 | {0, UA_NODEIDTYPE_NUMERIC, {14647LU}}, /* .typeId */ |
| 21049 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21050 | sizeof(UA_PubSubState), /* .memSize */ |
| 21051 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21052 | true, /* .pointerFree */ |
| 21053 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21054 | 0, /* .membersSize */ |
| 21055 | PubSubState_members /* .members */ |
| 21056 | }, |
| 21057 | /* DataSetFieldFlags */ |
| 21058 | { |
| 21059 | UA_TYPENAME("DataSetFieldFlags") /* .typeName */ |
| 21060 | {0, UA_NODEIDTYPE_NUMERIC, {15904LU}}, /* .typeId */ |
| 21061 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21062 | sizeof(UA_DataSetFieldFlags), /* .memSize */ |
| 21063 | UA_DATATYPEKIND_UINT16, /* .typeKind */ |
| 21064 | true, /* .pointerFree */ |
| 21065 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21066 | 0, /* .membersSize */ |
| 21067 | DataSetFieldFlags_members /* .members */ |
| 21068 | }, |
| 21069 | /* ConfigurationVersionDataType */ |
| 21070 | { |
| 21071 | UA_TYPENAME("ConfigurationVersionDataType") /* .typeName */ |
| 21072 | {0, UA_NODEIDTYPE_NUMERIC, {14593LU}}, /* .typeId */ |
| 21073 | {0, UA_NODEIDTYPE_NUMERIC, {14847LU}}, /* .binaryEncodingId */ |
| 21074 | sizeof(UA_ConfigurationVersionDataType), /* .memSize */ |
| 21075 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21076 | true, /* .pointerFree */ |
| 21077 | false, /* .overlayable */ |
| 21078 | 2, /* .membersSize */ |
| 21079 | ConfigurationVersionDataType_members /* .members */ |
| 21080 | }, |
| 21081 | /* PublishedVariableDataType */ |
| 21082 | { |
| 21083 | UA_TYPENAME("PublishedVariableDataType") /* .typeName */ |
| 21084 | {0, UA_NODEIDTYPE_NUMERIC, {14273LU}}, /* .typeId */ |
| 21085 | {0, UA_NODEIDTYPE_NUMERIC, {14323LU}}, /* .binaryEncodingId */ |
| 21086 | sizeof(UA_PublishedVariableDataType), /* .memSize */ |
| 21087 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21088 | false, /* .pointerFree */ |
| 21089 | false, /* .overlayable */ |
| 21090 | 8, /* .membersSize */ |
| 21091 | PublishedVariableDataType_members /* .members */ |
| 21092 | }, |
| 21093 | /* PublishedDataItemsDataType */ |
| 21094 | { |
| 21095 | UA_TYPENAME("PublishedDataItemsDataType") /* .typeName */ |
| 21096 | {0, UA_NODEIDTYPE_NUMERIC, {15581LU}}, /* .typeId */ |
| 21097 | {0, UA_NODEIDTYPE_NUMERIC, {15679LU}}, /* .binaryEncodingId */ |
| 21098 | sizeof(UA_PublishedDataItemsDataType), /* .memSize */ |
| 21099 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21100 | false, /* .pointerFree */ |
| 21101 | false, /* .overlayable */ |
| 21102 | 1, /* .membersSize */ |
| 21103 | PublishedDataItemsDataType_members /* .members */ |
| 21104 | }, |
| 21105 | /* PublishedDataSetCustomSourceDataType */ |
| 21106 | { |
| 21107 | UA_TYPENAME("PublishedDataSetCustomSourceDataType") /* .typeName */ |
| 21108 | {0, UA_NODEIDTYPE_NUMERIC, {25269LU}}, /* .typeId */ |
| 21109 | {0, UA_NODEIDTYPE_NUMERIC, {25529LU}}, /* .binaryEncodingId */ |
| 21110 | sizeof(UA_PublishedDataSetCustomSourceDataType), /* .memSize */ |
| 21111 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21112 | true, /* .pointerFree */ |
| 21113 | false, /* .overlayable */ |
| 21114 | 1, /* .membersSize */ |
| 21115 | PublishedDataSetCustomSourceDataType_members /* .members */ |
| 21116 | }, |
| 21117 | /* DataSetFieldContentMask */ |
| 21118 | { |
| 21119 | UA_TYPENAME("DataSetFieldContentMask") /* .typeName */ |
| 21120 | {0, UA_NODEIDTYPE_NUMERIC, {15583LU}}, /* .typeId */ |
| 21121 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21122 | sizeof(UA_DataSetFieldContentMask), /* .memSize */ |
| 21123 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 21124 | true, /* .pointerFree */ |
| 21125 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21126 | 0, /* .membersSize */ |
| 21127 | DataSetFieldContentMask_members /* .members */ |
| 21128 | }, |
| 21129 | /* DataSetWriterDataType */ |
| 21130 | { |
| 21131 | UA_TYPENAME("DataSetWriterDataType") /* .typeName */ |
| 21132 | {0, UA_NODEIDTYPE_NUMERIC, {15597LU}}, /* .typeId */ |
| 21133 | {0, UA_NODEIDTYPE_NUMERIC, {15682LU}}, /* .binaryEncodingId */ |
| 21134 | sizeof(UA_DataSetWriterDataType), /* .memSize */ |
| 21135 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21136 | false, /* .pointerFree */ |
| 21137 | false, /* .overlayable */ |
| 21138 | 9, /* .membersSize */ |
| 21139 | DataSetWriterDataType_members /* .members */ |
| 21140 | }, |
| 21141 | /* NetworkAddressDataType */ |
| 21142 | { |
| 21143 | UA_TYPENAME("NetworkAddressDataType") /* .typeName */ |
| 21144 | {0, UA_NODEIDTYPE_NUMERIC, {15502LU}}, /* .typeId */ |
| 21145 | {0, UA_NODEIDTYPE_NUMERIC, {21151LU}}, /* .binaryEncodingId */ |
| 21146 | sizeof(UA_NetworkAddressDataType), /* .memSize */ |
| 21147 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21148 | false, /* .pointerFree */ |
| 21149 | false, /* .overlayable */ |
| 21150 | 1, /* .membersSize */ |
| 21151 | NetworkAddressDataType_members /* .members */ |
| 21152 | }, |
| 21153 | /* NetworkAddressUrlDataType */ |
| 21154 | { |
| 21155 | UA_TYPENAME("NetworkAddressUrlDataType") /* .typeName */ |
| 21156 | {0, UA_NODEIDTYPE_NUMERIC, {15510LU}}, /* .typeId */ |
| 21157 | {0, UA_NODEIDTYPE_NUMERIC, {21152LU}}, /* .binaryEncodingId */ |
| 21158 | sizeof(UA_NetworkAddressUrlDataType), /* .memSize */ |
| 21159 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21160 | false, /* .pointerFree */ |
| 21161 | false, /* .overlayable */ |
| 21162 | 2, /* .membersSize */ |
| 21163 | NetworkAddressUrlDataType_members /* .members */ |
| 21164 | }, |
| 21165 | /* OverrideValueHandling */ |
| 21166 | { |
| 21167 | UA_TYPENAME("OverrideValueHandling") /* .typeName */ |
| 21168 | {0, UA_NODEIDTYPE_NUMERIC, {15874LU}}, /* .typeId */ |
| 21169 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21170 | sizeof(UA_OverrideValueHandling), /* .memSize */ |
| 21171 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21172 | true, /* .pointerFree */ |
| 21173 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21174 | 0, /* .membersSize */ |
| 21175 | OverrideValueHandling_members /* .members */ |
| 21176 | }, |
| 21177 | /* StandaloneSubscribedDataSetRefDataType */ |
| 21178 | { |
| 21179 | UA_TYPENAME("StandaloneSubscribedDataSetRefDataType") /* .typeName */ |
| 21180 | {0, UA_NODEIDTYPE_NUMERIC, {23599LU}}, /* .typeId */ |
| 21181 | {0, UA_NODEIDTYPE_NUMERIC, {23851LU}}, /* .binaryEncodingId */ |
| 21182 | sizeof(UA_StandaloneSubscribedDataSetRefDataType), /* .memSize */ |
| 21183 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21184 | false, /* .pointerFree */ |
| 21185 | false, /* .overlayable */ |
| 21186 | 1, /* .membersSize */ |
| 21187 | StandaloneSubscribedDataSetRefDataType_members /* .members */ |
| 21188 | }, |
| 21189 | /* DataSetOrderingType */ |
| 21190 | { |
| 21191 | UA_TYPENAME("DataSetOrderingType") /* .typeName */ |
| 21192 | {0, UA_NODEIDTYPE_NUMERIC, {20408LU}}, /* .typeId */ |
| 21193 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21194 | sizeof(UA_DataSetOrderingType), /* .memSize */ |
| 21195 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21196 | true, /* .pointerFree */ |
| 21197 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21198 | 0, /* .membersSize */ |
| 21199 | DataSetOrderingType_members /* .members */ |
| 21200 | }, |
| 21201 | /* UadpNetworkMessageContentMask */ |
| 21202 | { |
| 21203 | UA_TYPENAME("UadpNetworkMessageContentMask") /* .typeName */ |
| 21204 | {0, UA_NODEIDTYPE_NUMERIC, {15642LU}}, /* .typeId */ |
| 21205 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21206 | sizeof(UA_UadpNetworkMessageContentMask), /* .memSize */ |
| 21207 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 21208 | true, /* .pointerFree */ |
| 21209 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21210 | 0, /* .membersSize */ |
| 21211 | UadpNetworkMessageContentMask_members /* .members */ |
| 21212 | }, |
| 21213 | /* UadpWriterGroupMessageDataType */ |
| 21214 | { |
| 21215 | UA_TYPENAME("UadpWriterGroupMessageDataType") /* .typeName */ |
| 21216 | {0, UA_NODEIDTYPE_NUMERIC, {15645LU}}, /* .typeId */ |
| 21217 | {0, UA_NODEIDTYPE_NUMERIC, {15715LU}}, /* .binaryEncodingId */ |
| 21218 | sizeof(UA_UadpWriterGroupMessageDataType), /* .memSize */ |
| 21219 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21220 | false, /* .pointerFree */ |
| 21221 | false, /* .overlayable */ |
| 21222 | 5, /* .membersSize */ |
| 21223 | UadpWriterGroupMessageDataType_members /* .members */ |
| 21224 | }, |
| 21225 | /* UadpDataSetMessageContentMask */ |
| 21226 | { |
| 21227 | UA_TYPENAME("UadpDataSetMessageContentMask") /* .typeName */ |
| 21228 | {0, UA_NODEIDTYPE_NUMERIC, {15646LU}}, /* .typeId */ |
| 21229 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21230 | sizeof(UA_UadpDataSetMessageContentMask), /* .memSize */ |
| 21231 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 21232 | true, /* .pointerFree */ |
| 21233 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21234 | 0, /* .membersSize */ |
| 21235 | UadpDataSetMessageContentMask_members /* .members */ |
| 21236 | }, |
| 21237 | /* UadpDataSetWriterMessageDataType */ |
| 21238 | { |
| 21239 | UA_TYPENAME("UadpDataSetWriterMessageDataType") /* .typeName */ |
| 21240 | {0, UA_NODEIDTYPE_NUMERIC, {15652LU}}, /* .typeId */ |
| 21241 | {0, UA_NODEIDTYPE_NUMERIC, {15717LU}}, /* .binaryEncodingId */ |
| 21242 | sizeof(UA_UadpDataSetWriterMessageDataType), /* .memSize */ |
| 21243 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21244 | true, /* .pointerFree */ |
| 21245 | false, /* .overlayable */ |
| 21246 | 4, /* .membersSize */ |
| 21247 | UadpDataSetWriterMessageDataType_members /* .members */ |
| 21248 | }, |
| 21249 | /* UadpDataSetReaderMessageDataType */ |
| 21250 | { |
| 21251 | UA_TYPENAME("UadpDataSetReaderMessageDataType") /* .typeName */ |
| 21252 | {0, UA_NODEIDTYPE_NUMERIC, {15653LU}}, /* .typeId */ |
| 21253 | {0, UA_NODEIDTYPE_NUMERIC, {15718LU}}, /* .binaryEncodingId */ |
| 21254 | sizeof(UA_UadpDataSetReaderMessageDataType), /* .memSize */ |
| 21255 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21256 | true, /* .pointerFree */ |
| 21257 | false, /* .overlayable */ |
| 21258 | 9, /* .membersSize */ |
| 21259 | UadpDataSetReaderMessageDataType_members /* .members */ |
| 21260 | }, |
| 21261 | /* JsonNetworkMessageContentMask */ |
| 21262 | { |
| 21263 | UA_TYPENAME("JsonNetworkMessageContentMask") /* .typeName */ |
| 21264 | {0, UA_NODEIDTYPE_NUMERIC, {15654LU}}, /* .typeId */ |
| 21265 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21266 | sizeof(UA_JsonNetworkMessageContentMask), /* .memSize */ |
| 21267 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 21268 | true, /* .pointerFree */ |
| 21269 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21270 | 0, /* .membersSize */ |
| 21271 | JsonNetworkMessageContentMask_members /* .members */ |
| 21272 | }, |
| 21273 | /* JsonWriterGroupMessageDataType */ |
| 21274 | { |
| 21275 | UA_TYPENAME("JsonWriterGroupMessageDataType") /* .typeName */ |
| 21276 | {0, UA_NODEIDTYPE_NUMERIC, {15657LU}}, /* .typeId */ |
| 21277 | {0, UA_NODEIDTYPE_NUMERIC, {15719LU}}, /* .binaryEncodingId */ |
| 21278 | sizeof(UA_JsonWriterGroupMessageDataType), /* .memSize */ |
| 21279 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21280 | true, /* .pointerFree */ |
| 21281 | false, /* .overlayable */ |
| 21282 | 1, /* .membersSize */ |
| 21283 | JsonWriterGroupMessageDataType_members /* .members */ |
| 21284 | }, |
| 21285 | /* JsonDataSetMessageContentMask */ |
| 21286 | { |
| 21287 | UA_TYPENAME("JsonDataSetMessageContentMask") /* .typeName */ |
| 21288 | {0, UA_NODEIDTYPE_NUMERIC, {15658LU}}, /* .typeId */ |
| 21289 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21290 | sizeof(UA_JsonDataSetMessageContentMask), /* .memSize */ |
| 21291 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 21292 | true, /* .pointerFree */ |
| 21293 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21294 | 0, /* .membersSize */ |
| 21295 | JsonDataSetMessageContentMask_members /* .members */ |
| 21296 | }, |
| 21297 | /* JsonDataSetWriterMessageDataType */ |
| 21298 | { |
| 21299 | UA_TYPENAME("JsonDataSetWriterMessageDataType") /* .typeName */ |
| 21300 | {0, UA_NODEIDTYPE_NUMERIC, {15664LU}}, /* .typeId */ |
| 21301 | {0, UA_NODEIDTYPE_NUMERIC, {15724LU}}, /* .binaryEncodingId */ |
| 21302 | sizeof(UA_JsonDataSetWriterMessageDataType), /* .memSize */ |
| 21303 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21304 | true, /* .pointerFree */ |
| 21305 | false, /* .overlayable */ |
| 21306 | 1, /* .membersSize */ |
| 21307 | JsonDataSetWriterMessageDataType_members /* .members */ |
| 21308 | }, |
| 21309 | /* JsonDataSetReaderMessageDataType */ |
| 21310 | { |
| 21311 | UA_TYPENAME("JsonDataSetReaderMessageDataType") /* .typeName */ |
| 21312 | {0, UA_NODEIDTYPE_NUMERIC, {15665LU}}, /* .typeId */ |
| 21313 | {0, UA_NODEIDTYPE_NUMERIC, {15725LU}}, /* .binaryEncodingId */ |
| 21314 | sizeof(UA_JsonDataSetReaderMessageDataType), /* .memSize */ |
| 21315 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21316 | true, /* .pointerFree */ |
| 21317 | false, /* .overlayable */ |
| 21318 | 2, /* .membersSize */ |
| 21319 | JsonDataSetReaderMessageDataType_members /* .members */ |
| 21320 | }, |
| 21321 | /* TransmitQosPriorityDataType */ |
| 21322 | { |
| 21323 | UA_TYPENAME("TransmitQosPriorityDataType") /* .typeName */ |
| 21324 | {0, UA_NODEIDTYPE_NUMERIC, {23605LU}}, /* .typeId */ |
| 21325 | {0, UA_NODEIDTYPE_NUMERIC, {23857LU}}, /* .binaryEncodingId */ |
| 21326 | sizeof(UA_TransmitQosPriorityDataType), /* .memSize */ |
| 21327 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21328 | false, /* .pointerFree */ |
| 21329 | false, /* .overlayable */ |
| 21330 | 1, /* .membersSize */ |
| 21331 | TransmitQosPriorityDataType_members /* .members */ |
| 21332 | }, |
| 21333 | /* ReceiveQosPriorityDataType */ |
| 21334 | { |
| 21335 | UA_TYPENAME("ReceiveQosPriorityDataType") /* .typeName */ |
| 21336 | {0, UA_NODEIDTYPE_NUMERIC, {23609LU}}, /* .typeId */ |
| 21337 | {0, UA_NODEIDTYPE_NUMERIC, {23861LU}}, /* .binaryEncodingId */ |
| 21338 | sizeof(UA_ReceiveQosPriorityDataType), /* .memSize */ |
| 21339 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21340 | false, /* .pointerFree */ |
| 21341 | false, /* .overlayable */ |
| 21342 | 1, /* .membersSize */ |
| 21343 | ReceiveQosPriorityDataType_members /* .members */ |
| 21344 | }, |
| 21345 | /* DatagramConnectionTransportDataType */ |
| 21346 | { |
| 21347 | UA_TYPENAME("DatagramConnectionTransportDataType") /* .typeName */ |
| 21348 | {0, UA_NODEIDTYPE_NUMERIC, {17467LU}}, /* .typeId */ |
| 21349 | {0, UA_NODEIDTYPE_NUMERIC, {17468LU}}, /* .binaryEncodingId */ |
| 21350 | sizeof(UA_DatagramConnectionTransportDataType), /* .memSize */ |
| 21351 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21352 | false, /* .pointerFree */ |
| 21353 | false, /* .overlayable */ |
| 21354 | 1, /* .membersSize */ |
| 21355 | DatagramConnectionTransportDataType_members /* .members */ |
| 21356 | }, |
| 21357 | /* DatagramConnectionTransport2DataType */ |
| 21358 | { |
| 21359 | UA_TYPENAME("DatagramConnectionTransport2DataType") /* .typeName */ |
| 21360 | {0, UA_NODEIDTYPE_NUMERIC, {23612LU}}, /* .typeId */ |
| 21361 | {0, UA_NODEIDTYPE_NUMERIC, {23864LU}}, /* .binaryEncodingId */ |
| 21362 | sizeof(UA_DatagramConnectionTransport2DataType), /* .memSize */ |
| 21363 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21364 | false, /* .pointerFree */ |
| 21365 | false, /* .overlayable */ |
| 21366 | 5, /* .membersSize */ |
| 21367 | DatagramConnectionTransport2DataType_members /* .members */ |
| 21368 | }, |
| 21369 | /* DatagramWriterGroupTransportDataType */ |
| 21370 | { |
| 21371 | UA_TYPENAME("DatagramWriterGroupTransportDataType") /* .typeName */ |
| 21372 | {0, UA_NODEIDTYPE_NUMERIC, {15532LU}}, /* .typeId */ |
| 21373 | {0, UA_NODEIDTYPE_NUMERIC, {21155LU}}, /* .binaryEncodingId */ |
| 21374 | sizeof(UA_DatagramWriterGroupTransportDataType), /* .memSize */ |
| 21375 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21376 | true, /* .pointerFree */ |
| 21377 | false, /* .overlayable */ |
| 21378 | 2, /* .membersSize */ |
| 21379 | DatagramWriterGroupTransportDataType_members /* .members */ |
| 21380 | }, |
| 21381 | /* DatagramWriterGroupTransport2DataType */ |
| 21382 | { |
| 21383 | UA_TYPENAME("DatagramWriterGroupTransport2DataType") /* .typeName */ |
| 21384 | {0, UA_NODEIDTYPE_NUMERIC, {23613LU}}, /* .typeId */ |
| 21385 | {0, UA_NODEIDTYPE_NUMERIC, {23865LU}}, /* .binaryEncodingId */ |
| 21386 | sizeof(UA_DatagramWriterGroupTransport2DataType), /* .memSize */ |
| 21387 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21388 | false, /* .pointerFree */ |
| 21389 | false, /* .overlayable */ |
| 21390 | 7, /* .membersSize */ |
| 21391 | DatagramWriterGroupTransport2DataType_members /* .members */ |
| 21392 | }, |
| 21393 | /* DatagramDataSetReaderTransportDataType */ |
| 21394 | { |
| 21395 | UA_TYPENAME("DatagramDataSetReaderTransportDataType") /* .typeName */ |
| 21396 | {0, UA_NODEIDTYPE_NUMERIC, {23614LU}}, /* .typeId */ |
| 21397 | {0, UA_NODEIDTYPE_NUMERIC, {23866LU}}, /* .binaryEncodingId */ |
| 21398 | sizeof(UA_DatagramDataSetReaderTransportDataType), /* .memSize */ |
| 21399 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21400 | false, /* .pointerFree */ |
| 21401 | false, /* .overlayable */ |
| 21402 | 4, /* .membersSize */ |
| 21403 | DatagramDataSetReaderTransportDataType_members /* .members */ |
| 21404 | }, |
| 21405 | /* BrokerConnectionTransportDataType */ |
| 21406 | { |
| 21407 | UA_TYPENAME("BrokerConnectionTransportDataType") /* .typeName */ |
| 21408 | {0, UA_NODEIDTYPE_NUMERIC, {15007LU}}, /* .typeId */ |
| 21409 | {0, UA_NODEIDTYPE_NUMERIC, {15479LU}}, /* .binaryEncodingId */ |
| 21410 | sizeof(UA_BrokerConnectionTransportDataType), /* .memSize */ |
| 21411 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21412 | false, /* .pointerFree */ |
| 21413 | false, /* .overlayable */ |
| 21414 | 2, /* .membersSize */ |
| 21415 | BrokerConnectionTransportDataType_members /* .members */ |
| 21416 | }, |
| 21417 | /* BrokerTransportQualityOfService */ |
| 21418 | { |
| 21419 | UA_TYPENAME("BrokerTransportQualityOfService") /* .typeName */ |
| 21420 | {0, UA_NODEIDTYPE_NUMERIC, {15008LU}}, /* .typeId */ |
| 21421 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21422 | sizeof(UA_BrokerTransportQualityOfService), /* .memSize */ |
| 21423 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21424 | true, /* .pointerFree */ |
| 21425 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21426 | 0, /* .membersSize */ |
| 21427 | BrokerTransportQualityOfService_members /* .members */ |
| 21428 | }, |
| 21429 | /* BrokerWriterGroupTransportDataType */ |
| 21430 | { |
| 21431 | UA_TYPENAME("BrokerWriterGroupTransportDataType") /* .typeName */ |
| 21432 | {0, UA_NODEIDTYPE_NUMERIC, {15667LU}}, /* .typeId */ |
| 21433 | {0, UA_NODEIDTYPE_NUMERIC, {15727LU}}, /* .binaryEncodingId */ |
| 21434 | sizeof(UA_BrokerWriterGroupTransportDataType), /* .memSize */ |
| 21435 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21436 | false, /* .pointerFree */ |
| 21437 | false, /* .overlayable */ |
| 21438 | 4, /* .membersSize */ |
| 21439 | BrokerWriterGroupTransportDataType_members /* .members */ |
| 21440 | }, |
| 21441 | /* BrokerDataSetWriterTransportDataType */ |
| 21442 | { |
| 21443 | UA_TYPENAME("BrokerDataSetWriterTransportDataType") /* .typeName */ |
| 21444 | {0, UA_NODEIDTYPE_NUMERIC, {15669LU}}, /* .typeId */ |
| 21445 | {0, UA_NODEIDTYPE_NUMERIC, {15729LU}}, /* .binaryEncodingId */ |
| 21446 | sizeof(UA_BrokerDataSetWriterTransportDataType), /* .memSize */ |
| 21447 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21448 | false, /* .pointerFree */ |
| 21449 | false, /* .overlayable */ |
| 21450 | 6, /* .membersSize */ |
| 21451 | BrokerDataSetWriterTransportDataType_members /* .members */ |
| 21452 | }, |
| 21453 | /* BrokerDataSetReaderTransportDataType */ |
| 21454 | { |
| 21455 | UA_TYPENAME("BrokerDataSetReaderTransportDataType") /* .typeName */ |
| 21456 | {0, UA_NODEIDTYPE_NUMERIC, {15670LU}}, /* .typeId */ |
| 21457 | {0, UA_NODEIDTYPE_NUMERIC, {15733LU}}, /* .binaryEncodingId */ |
| 21458 | sizeof(UA_BrokerDataSetReaderTransportDataType), /* .memSize */ |
| 21459 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21460 | false, /* .pointerFree */ |
| 21461 | false, /* .overlayable */ |
| 21462 | 5, /* .membersSize */ |
| 21463 | BrokerDataSetReaderTransportDataType_members /* .members */ |
| 21464 | }, |
| 21465 | /* PubSubConfigurationRefMask */ |
| 21466 | { |
| 21467 | UA_TYPENAME("PubSubConfigurationRefMask") /* .typeName */ |
| 21468 | {0, UA_NODEIDTYPE_NUMERIC, {25517LU}}, /* .typeId */ |
| 21469 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21470 | sizeof(UA_PubSubConfigurationRefMask), /* .memSize */ |
| 21471 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 21472 | true, /* .pointerFree */ |
| 21473 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21474 | 0, /* .membersSize */ |
| 21475 | PubSubConfigurationRefMask_members /* .members */ |
| 21476 | }, |
| 21477 | /* PubSubConfigurationRefDataType */ |
| 21478 | { |
| 21479 | UA_TYPENAME("PubSubConfigurationRefDataType") /* .typeName */ |
| 21480 | {0, UA_NODEIDTYPE_NUMERIC, {25519LU}}, /* .typeId */ |
| 21481 | {0, UA_NODEIDTYPE_NUMERIC, {25531LU}}, /* .binaryEncodingId */ |
| 21482 | sizeof(UA_PubSubConfigurationRefDataType), /* .memSize */ |
| 21483 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21484 | true, /* .pointerFree */ |
| 21485 | false, /* .overlayable */ |
| 21486 | 4, /* .membersSize */ |
| 21487 | PubSubConfigurationRefDataType_members /* .members */ |
| 21488 | }, |
| 21489 | /* PubSubConfigurationValueDataType */ |
| 21490 | { |
| 21491 | UA_TYPENAME("PubSubConfigurationValueDataType") /* .typeName */ |
| 21492 | {0, UA_NODEIDTYPE_NUMERIC, {25520LU}}, /* .typeId */ |
| 21493 | {0, UA_NODEIDTYPE_NUMERIC, {25532LU}}, /* .binaryEncodingId */ |
| 21494 | sizeof(UA_PubSubConfigurationValueDataType), /* .memSize */ |
| 21495 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21496 | false, /* .pointerFree */ |
| 21497 | false, /* .overlayable */ |
| 21498 | 3, /* .membersSize */ |
| 21499 | PubSubConfigurationValueDataType_members /* .members */ |
| 21500 | }, |
| 21501 | /* DiagnosticsLevel */ |
| 21502 | { |
| 21503 | UA_TYPENAME("DiagnosticsLevel") /* .typeName */ |
| 21504 | {0, UA_NODEIDTYPE_NUMERIC, {19723LU}}, /* .typeId */ |
| 21505 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21506 | sizeof(UA_DiagnosticsLevel), /* .memSize */ |
| 21507 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21508 | true, /* .pointerFree */ |
| 21509 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21510 | 0, /* .membersSize */ |
| 21511 | DiagnosticsLevel_members /* .members */ |
| 21512 | }, |
| 21513 | /* PubSubDiagnosticsCounterClassification */ |
| 21514 | { |
| 21515 | UA_TYPENAME("PubSubDiagnosticsCounterClassification") /* .typeName */ |
| 21516 | {0, UA_NODEIDTYPE_NUMERIC, {19730LU}}, /* .typeId */ |
| 21517 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21518 | sizeof(UA_PubSubDiagnosticsCounterClassification), /* .memSize */ |
| 21519 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21520 | true, /* .pointerFree */ |
| 21521 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21522 | 0, /* .membersSize */ |
| 21523 | PubSubDiagnosticsCounterClassification_members /* .members */ |
| 21524 | }, |
| 21525 | /* AliasNameDataType */ |
| 21526 | { |
| 21527 | UA_TYPENAME("AliasNameDataType") /* .typeName */ |
| 21528 | {0, UA_NODEIDTYPE_NUMERIC, {23468LU}}, /* .typeId */ |
| 21529 | {0, UA_NODEIDTYPE_NUMERIC, {23499LU}}, /* .binaryEncodingId */ |
| 21530 | sizeof(UA_AliasNameDataType), /* .memSize */ |
| 21531 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21532 | false, /* .pointerFree */ |
| 21533 | false, /* .overlayable */ |
| 21534 | 2, /* .membersSize */ |
| 21535 | AliasNameDataType_members /* .members */ |
| 21536 | }, |
| 21537 | /* PasswordOptionsMask */ |
| 21538 | { |
| 21539 | UA_TYPENAME("PasswordOptionsMask") /* .typeName */ |
| 21540 | {0, UA_NODEIDTYPE_NUMERIC, {24277LU}}, /* .typeId */ |
| 21541 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21542 | sizeof(UA_PasswordOptionsMask), /* .memSize */ |
| 21543 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 21544 | true, /* .pointerFree */ |
| 21545 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21546 | 0, /* .membersSize */ |
| 21547 | PasswordOptionsMask_members /* .members */ |
| 21548 | }, |
| 21549 | /* UserConfigurationMask */ |
| 21550 | { |
| 21551 | UA_TYPENAME("UserConfigurationMask") /* .typeName */ |
| 21552 | {0, UA_NODEIDTYPE_NUMERIC, {24279LU}}, /* .typeId */ |
| 21553 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21554 | sizeof(UA_UserConfigurationMask), /* .memSize */ |
| 21555 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 21556 | true, /* .pointerFree */ |
| 21557 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21558 | 0, /* .membersSize */ |
| 21559 | UserConfigurationMask_members /* .members */ |
| 21560 | }, |
| 21561 | /* UserManagementDataType */ |
| 21562 | { |
| 21563 | UA_TYPENAME("UserManagementDataType") /* .typeName */ |
| 21564 | {0, UA_NODEIDTYPE_NUMERIC, {24281LU}}, /* .typeId */ |
| 21565 | {0, UA_NODEIDTYPE_NUMERIC, {24292LU}}, /* .binaryEncodingId */ |
| 21566 | sizeof(UA_UserManagementDataType), /* .memSize */ |
| 21567 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21568 | false, /* .pointerFree */ |
| 21569 | false, /* .overlayable */ |
| 21570 | 3, /* .membersSize */ |
| 21571 | UserManagementDataType_members /* .members */ |
| 21572 | }, |
| 21573 | /* Duplex */ |
| 21574 | { |
| 21575 | UA_TYPENAME("Duplex") /* .typeName */ |
| 21576 | {0, UA_NODEIDTYPE_NUMERIC, {24210LU}}, /* .typeId */ |
| 21577 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21578 | sizeof(UA_Duplex), /* .memSize */ |
| 21579 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21580 | true, /* .pointerFree */ |
| 21581 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21582 | 0, /* .membersSize */ |
| 21583 | Duplex_members /* .members */ |
| 21584 | }, |
| 21585 | /* InterfaceAdminStatus */ |
| 21586 | { |
| 21587 | UA_TYPENAME("InterfaceAdminStatus") /* .typeName */ |
| 21588 | {0, UA_NODEIDTYPE_NUMERIC, {24212LU}}, /* .typeId */ |
| 21589 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21590 | sizeof(UA_InterfaceAdminStatus), /* .memSize */ |
| 21591 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21592 | true, /* .pointerFree */ |
| 21593 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21594 | 0, /* .membersSize */ |
| 21595 | InterfaceAdminStatus_members /* .members */ |
| 21596 | }, |
| 21597 | /* InterfaceOperStatus */ |
| 21598 | { |
| 21599 | UA_TYPENAME("InterfaceOperStatus") /* .typeName */ |
| 21600 | {0, UA_NODEIDTYPE_NUMERIC, {24214LU}}, /* .typeId */ |
| 21601 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21602 | sizeof(UA_InterfaceOperStatus), /* .memSize */ |
| 21603 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21604 | true, /* .pointerFree */ |
| 21605 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21606 | 0, /* .membersSize */ |
| 21607 | InterfaceOperStatus_members /* .members */ |
| 21608 | }, |
| 21609 | /* NegotiationStatus */ |
| 21610 | { |
| 21611 | UA_TYPENAME("NegotiationStatus") /* .typeName */ |
| 21612 | {0, UA_NODEIDTYPE_NUMERIC, {24216LU}}, /* .typeId */ |
| 21613 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21614 | sizeof(UA_NegotiationStatus), /* .memSize */ |
| 21615 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21616 | true, /* .pointerFree */ |
| 21617 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21618 | 0, /* .membersSize */ |
| 21619 | NegotiationStatus_members /* .members */ |
| 21620 | }, |
| 21621 | /* TsnFailureCode */ |
| 21622 | { |
| 21623 | UA_TYPENAME("TsnFailureCode") /* .typeName */ |
| 21624 | {0, UA_NODEIDTYPE_NUMERIC, {24218LU}}, /* .typeId */ |
| 21625 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21626 | sizeof(UA_TsnFailureCode), /* .memSize */ |
| 21627 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21628 | true, /* .pointerFree */ |
| 21629 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21630 | 0, /* .membersSize */ |
| 21631 | TsnFailureCode_members /* .members */ |
| 21632 | }, |
| 21633 | /* TsnStreamState */ |
| 21634 | { |
| 21635 | UA_TYPENAME("TsnStreamState") /* .typeName */ |
| 21636 | {0, UA_NODEIDTYPE_NUMERIC, {24220LU}}, /* .typeId */ |
| 21637 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21638 | sizeof(UA_TsnStreamState), /* .memSize */ |
| 21639 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21640 | true, /* .pointerFree */ |
| 21641 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21642 | 0, /* .membersSize */ |
| 21643 | TsnStreamState_members /* .members */ |
| 21644 | }, |
| 21645 | /* TsnTalkerStatus */ |
| 21646 | { |
| 21647 | UA_TYPENAME("TsnTalkerStatus") /* .typeName */ |
| 21648 | {0, UA_NODEIDTYPE_NUMERIC, {24222LU}}, /* .typeId */ |
| 21649 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21650 | sizeof(UA_TsnTalkerStatus), /* .memSize */ |
| 21651 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21652 | true, /* .pointerFree */ |
| 21653 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21654 | 0, /* .membersSize */ |
| 21655 | TsnTalkerStatus_members /* .members */ |
| 21656 | }, |
| 21657 | /* TsnListenerStatus */ |
| 21658 | { |
| 21659 | UA_TYPENAME("TsnListenerStatus") /* .typeName */ |
| 21660 | {0, UA_NODEIDTYPE_NUMERIC, {24224LU}}, /* .typeId */ |
| 21661 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21662 | sizeof(UA_TsnListenerStatus), /* .memSize */ |
| 21663 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21664 | true, /* .pointerFree */ |
| 21665 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21666 | 0, /* .membersSize */ |
| 21667 | TsnListenerStatus_members /* .members */ |
| 21668 | }, |
| 21669 | /* PriorityMappingEntryType */ |
| 21670 | { |
| 21671 | UA_TYPENAME("PriorityMappingEntryType") /* .typeName */ |
| 21672 | {0, UA_NODEIDTYPE_NUMERIC, {25220LU}}, /* .typeId */ |
| 21673 | {0, UA_NODEIDTYPE_NUMERIC, {25239LU}}, /* .binaryEncodingId */ |
| 21674 | sizeof(UA_PriorityMappingEntryType), /* .memSize */ |
| 21675 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21676 | false, /* .pointerFree */ |
| 21677 | false, /* .overlayable */ |
| 21678 | 4, /* .membersSize */ |
| 21679 | PriorityMappingEntryType_members /* .members */ |
| 21680 | }, |
| 21681 | /* IdType */ |
| 21682 | { |
| 21683 | UA_TYPENAME("IdType") /* .typeName */ |
| 21684 | {0, UA_NODEIDTYPE_NUMERIC, {256LU}}, /* .typeId */ |
| 21685 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21686 | sizeof(UA_IdType), /* .memSize */ |
| 21687 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21688 | true, /* .pointerFree */ |
| 21689 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21690 | 0, /* .membersSize */ |
| 21691 | IdType_members /* .members */ |
| 21692 | }, |
| 21693 | /* NodeClass */ |
| 21694 | { |
| 21695 | UA_TYPENAME("NodeClass") /* .typeName */ |
| 21696 | {0, UA_NODEIDTYPE_NUMERIC, {257LU}}, /* .typeId */ |
| 21697 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21698 | sizeof(UA_NodeClass), /* .memSize */ |
| 21699 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21700 | true, /* .pointerFree */ |
| 21701 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21702 | 0, /* .membersSize */ |
| 21703 | NodeClass_members /* .members */ |
| 21704 | }, |
| 21705 | /* PermissionType */ |
| 21706 | { |
| 21707 | UA_TYPENAME("PermissionType") /* .typeName */ |
| 21708 | {0, UA_NODEIDTYPE_NUMERIC, {94LU}}, /* .typeId */ |
| 21709 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21710 | sizeof(UA_PermissionType), /* .memSize */ |
| 21711 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 21712 | true, /* .pointerFree */ |
| 21713 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21714 | 0, /* .membersSize */ |
| 21715 | PermissionType_members /* .members */ |
| 21716 | }, |
| 21717 | /* AccessLevelType */ |
| 21718 | { |
| 21719 | UA_TYPENAME("AccessLevelType") /* .typeName */ |
| 21720 | {0, UA_NODEIDTYPE_NUMERIC, {15031LU}}, /* .typeId */ |
| 21721 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21722 | sizeof(UA_AccessLevelType), /* .memSize */ |
| 21723 | UA_DATATYPEKIND_BYTE, /* .typeKind */ |
| 21724 | true, /* .pointerFree */ |
| 21725 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21726 | 0, /* .membersSize */ |
| 21727 | AccessLevelType_members /* .members */ |
| 21728 | }, |
| 21729 | /* AccessLevelExType */ |
| 21730 | { |
| 21731 | UA_TYPENAME("AccessLevelExType") /* .typeName */ |
| 21732 | {0, UA_NODEIDTYPE_NUMERIC, {15406LU}}, /* .typeId */ |
| 21733 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21734 | sizeof(UA_AccessLevelExType), /* .memSize */ |
| 21735 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 21736 | true, /* .pointerFree */ |
| 21737 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21738 | 0, /* .membersSize */ |
| 21739 | AccessLevelExType_members /* .members */ |
| 21740 | }, |
| 21741 | /* EventNotifierType */ |
| 21742 | { |
| 21743 | UA_TYPENAME("EventNotifierType") /* .typeName */ |
| 21744 | {0, UA_NODEIDTYPE_NUMERIC, {15033LU}}, /* .typeId */ |
| 21745 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21746 | sizeof(UA_EventNotifierType), /* .memSize */ |
| 21747 | UA_DATATYPEKIND_BYTE, /* .typeKind */ |
| 21748 | true, /* .pointerFree */ |
| 21749 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21750 | 0, /* .membersSize */ |
| 21751 | EventNotifierType_members /* .members */ |
| 21752 | }, |
| 21753 | /* AccessRestrictionType */ |
| 21754 | { |
| 21755 | UA_TYPENAME("AccessRestrictionType") /* .typeName */ |
| 21756 | {0, UA_NODEIDTYPE_NUMERIC, {95LU}}, /* .typeId */ |
| 21757 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21758 | sizeof(UA_AccessRestrictionType), /* .memSize */ |
| 21759 | UA_DATATYPEKIND_UINT16, /* .typeKind */ |
| 21760 | true, /* .pointerFree */ |
| 21761 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21762 | 0, /* .membersSize */ |
| 21763 | AccessRestrictionType_members /* .members */ |
| 21764 | }, |
| 21765 | /* RolePermissionType */ |
| 21766 | { |
| 21767 | UA_TYPENAME("RolePermissionType") /* .typeName */ |
| 21768 | {0, UA_NODEIDTYPE_NUMERIC, {96LU}}, /* .typeId */ |
| 21769 | {0, UA_NODEIDTYPE_NUMERIC, {128LU}}, /* .binaryEncodingId */ |
| 21770 | sizeof(UA_RolePermissionType), /* .memSize */ |
| 21771 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21772 | false, /* .pointerFree */ |
| 21773 | false, /* .overlayable */ |
| 21774 | 2, /* .membersSize */ |
| 21775 | RolePermissionType_members /* .members */ |
| 21776 | }, |
| 21777 | /* StructureType */ |
| 21778 | { |
| 21779 | UA_TYPENAME("StructureType") /* .typeName */ |
| 21780 | {0, UA_NODEIDTYPE_NUMERIC, {98LU}}, /* .typeId */ |
| 21781 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21782 | sizeof(UA_StructureType), /* .memSize */ |
| 21783 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 21784 | true, /* .pointerFree */ |
| 21785 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 21786 | 0, /* .membersSize */ |
| 21787 | StructureType_members /* .members */ |
| 21788 | }, |
| 21789 | /* StructureField */ |
| 21790 | { |
| 21791 | UA_TYPENAME("StructureField") /* .typeName */ |
| 21792 | {0, UA_NODEIDTYPE_NUMERIC, {101LU}}, /* .typeId */ |
| 21793 | {0, UA_NODEIDTYPE_NUMERIC, {14844LU}}, /* .binaryEncodingId */ |
| 21794 | sizeof(UA_StructureField), /* .memSize */ |
| 21795 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21796 | false, /* .pointerFree */ |
| 21797 | false, /* .overlayable */ |
| 21798 | 7, /* .membersSize */ |
| 21799 | StructureField_members /* .members */ |
| 21800 | }, |
| 21801 | /* StructureDefinition */ |
| 21802 | { |
| 21803 | UA_TYPENAME("StructureDefinition") /* .typeName */ |
| 21804 | {0, UA_NODEIDTYPE_NUMERIC, {99LU}}, /* .typeId */ |
| 21805 | {0, UA_NODEIDTYPE_NUMERIC, {122LU}}, /* .binaryEncodingId */ |
| 21806 | sizeof(UA_StructureDefinition), /* .memSize */ |
| 21807 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21808 | false, /* .pointerFree */ |
| 21809 | false, /* .overlayable */ |
| 21810 | 4, /* .membersSize */ |
| 21811 | StructureDefinition_members /* .members */ |
| 21812 | }, |
| 21813 | /* ReferenceNode */ |
| 21814 | { |
| 21815 | UA_TYPENAME("ReferenceNode") /* .typeName */ |
| 21816 | {0, UA_NODEIDTYPE_NUMERIC, {285LU}}, /* .typeId */ |
| 21817 | {0, UA_NODEIDTYPE_NUMERIC, {287LU}}, /* .binaryEncodingId */ |
| 21818 | sizeof(UA_ReferenceNode), /* .memSize */ |
| 21819 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21820 | false, /* .pointerFree */ |
| 21821 | false, /* .overlayable */ |
| 21822 | 3, /* .membersSize */ |
| 21823 | ReferenceNode_members /* .members */ |
| 21824 | }, |
| 21825 | /* Argument */ |
| 21826 | { |
| 21827 | UA_TYPENAME("Argument") /* .typeName */ |
| 21828 | {0, UA_NODEIDTYPE_NUMERIC, {296LU}}, /* .typeId */ |
| 21829 | {0, UA_NODEIDTYPE_NUMERIC, {298LU}}, /* .binaryEncodingId */ |
| 21830 | sizeof(UA_Argument), /* .memSize */ |
| 21831 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21832 | false, /* .pointerFree */ |
| 21833 | false, /* .overlayable */ |
| 21834 | 5, /* .membersSize */ |
| 21835 | Argument_members /* .members */ |
| 21836 | }, |
| 21837 | /* EnumValueType */ |
| 21838 | { |
| 21839 | UA_TYPENAME("EnumValueType") /* .typeName */ |
| 21840 | {0, UA_NODEIDTYPE_NUMERIC, {7594LU}}, /* .typeId */ |
| 21841 | {0, UA_NODEIDTYPE_NUMERIC, {8251LU}}, /* .binaryEncodingId */ |
| 21842 | sizeof(UA_EnumValueType), /* .memSize */ |
| 21843 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21844 | false, /* .pointerFree */ |
| 21845 | false, /* .overlayable */ |
| 21846 | 3, /* .membersSize */ |
| 21847 | EnumValueType_members /* .members */ |
| 21848 | }, |
| 21849 | /* EnumField */ |
| 21850 | { |
| 21851 | UA_TYPENAME("EnumField") /* .typeName */ |
| 21852 | {0, UA_NODEIDTYPE_NUMERIC, {102LU}}, /* .typeId */ |
| 21853 | {0, UA_NODEIDTYPE_NUMERIC, {14845LU}}, /* .binaryEncodingId */ |
| 21854 | sizeof(UA_EnumField), /* .memSize */ |
| 21855 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21856 | false, /* .pointerFree */ |
| 21857 | false, /* .overlayable */ |
| 21858 | 4, /* .membersSize */ |
| 21859 | EnumField_members /* .members */ |
| 21860 | }, |
| 21861 | /* OptionSet */ |
| 21862 | { |
| 21863 | UA_TYPENAME("OptionSet") /* .typeName */ |
| 21864 | {0, UA_NODEIDTYPE_NUMERIC, {12755LU}}, /* .typeId */ |
| 21865 | {0, UA_NODEIDTYPE_NUMERIC, {12765LU}}, /* .binaryEncodingId */ |
| 21866 | sizeof(UA_OptionSet), /* .memSize */ |
| 21867 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21868 | false, /* .pointerFree */ |
| 21869 | false, /* .overlayable */ |
| 21870 | 2, /* .membersSize */ |
| 21871 | OptionSet_members /* .members */ |
| 21872 | }, |
| 21873 | /* NormalizedString */ |
| 21874 | { |
| 21875 | UA_TYPENAME("NormalizedString") /* .typeName */ |
| 21876 | {0, UA_NODEIDTYPE_NUMERIC, {12877LU}}, /* .typeId */ |
| 21877 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21878 | sizeof(UA_NormalizedString), /* .memSize */ |
| 21879 | UA_DATATYPEKIND_STRING, /* .typeKind */ |
| 21880 | false, /* .pointerFree */ |
| 21881 | false, /* .overlayable */ |
| 21882 | 0, /* .membersSize */ |
| 21883 | NormalizedString_members /* .members */ |
| 21884 | }, |
| 21885 | /* DecimalString */ |
| 21886 | { |
| 21887 | UA_TYPENAME("DecimalString") /* .typeName */ |
| 21888 | {0, UA_NODEIDTYPE_NUMERIC, {12878LU}}, /* .typeId */ |
| 21889 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21890 | sizeof(UA_DecimalString), /* .memSize */ |
| 21891 | UA_DATATYPEKIND_STRING, /* .typeKind */ |
| 21892 | false, /* .pointerFree */ |
| 21893 | false, /* .overlayable */ |
| 21894 | 0, /* .membersSize */ |
| 21895 | DecimalString_members /* .members */ |
| 21896 | }, |
| 21897 | /* DurationString */ |
| 21898 | { |
| 21899 | UA_TYPENAME("DurationString") /* .typeName */ |
| 21900 | {0, UA_NODEIDTYPE_NUMERIC, {12879LU}}, /* .typeId */ |
| 21901 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21902 | sizeof(UA_DurationString), /* .memSize */ |
| 21903 | UA_DATATYPEKIND_STRING, /* .typeKind */ |
| 21904 | false, /* .pointerFree */ |
| 21905 | false, /* .overlayable */ |
| 21906 | 0, /* .membersSize */ |
| 21907 | DurationString_members /* .members */ |
| 21908 | }, |
| 21909 | /* TimeString */ |
| 21910 | { |
| 21911 | UA_TYPENAME("TimeString") /* .typeName */ |
| 21912 | {0, UA_NODEIDTYPE_NUMERIC, {12880LU}}, /* .typeId */ |
| 21913 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21914 | sizeof(UA_TimeString), /* .memSize */ |
| 21915 | UA_DATATYPEKIND_STRING, /* .typeKind */ |
| 21916 | false, /* .pointerFree */ |
| 21917 | false, /* .overlayable */ |
| 21918 | 0, /* .membersSize */ |
| 21919 | TimeString_members /* .members */ |
| 21920 | }, |
| 21921 | /* DateString */ |
| 21922 | { |
| 21923 | UA_TYPENAME("DateString") /* .typeName */ |
| 21924 | {0, UA_NODEIDTYPE_NUMERIC, {12881LU}}, /* .typeId */ |
| 21925 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21926 | sizeof(UA_DateString), /* .memSize */ |
| 21927 | UA_DATATYPEKIND_STRING, /* .typeKind */ |
| 21928 | false, /* .pointerFree */ |
| 21929 | false, /* .overlayable */ |
| 21930 | 0, /* .membersSize */ |
| 21931 | DateString_members /* .members */ |
| 21932 | }, |
| 21933 | /* Duration */ |
| 21934 | { |
| 21935 | UA_TYPENAME("Duration") /* .typeName */ |
| 21936 | {0, UA_NODEIDTYPE_NUMERIC, {290LU}}, /* .typeId */ |
| 21937 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21938 | sizeof(UA_Duration), /* .memSize */ |
| 21939 | UA_DATATYPEKIND_DOUBLE, /* .typeKind */ |
| 21940 | false, /* .pointerFree */ |
| 21941 | false, /* .overlayable */ |
| 21942 | 0, /* .membersSize */ |
| 21943 | Duration_members /* .members */ |
| 21944 | }, |
| 21945 | /* UtcTime */ |
| 21946 | { |
| 21947 | UA_TYPENAME("UtcTime") /* .typeName */ |
| 21948 | {0, UA_NODEIDTYPE_NUMERIC, {294LU}}, /* .typeId */ |
| 21949 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21950 | sizeof(UA_UtcTime), /* .memSize */ |
| 21951 | UA_DATATYPEKIND_DATETIME, /* .typeKind */ |
| 21952 | false, /* .pointerFree */ |
| 21953 | false, /* .overlayable */ |
| 21954 | 0, /* .membersSize */ |
| 21955 | UtcTime_members /* .members */ |
| 21956 | }, |
| 21957 | /* LocaleId */ |
| 21958 | { |
| 21959 | UA_TYPENAME("LocaleId") /* .typeName */ |
| 21960 | {0, UA_NODEIDTYPE_NUMERIC, {295LU}}, /* .typeId */ |
| 21961 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21962 | sizeof(UA_LocaleId), /* .memSize */ |
| 21963 | UA_DATATYPEKIND_STRING, /* .typeKind */ |
| 21964 | false, /* .pointerFree */ |
| 21965 | false, /* .overlayable */ |
| 21966 | 0, /* .membersSize */ |
| 21967 | LocaleId_members /* .members */ |
| 21968 | }, |
| 21969 | /* TimeZoneDataType */ |
| 21970 | { |
| 21971 | UA_TYPENAME("TimeZoneDataType") /* .typeName */ |
| 21972 | {0, UA_NODEIDTYPE_NUMERIC, {8912LU}}, /* .typeId */ |
| 21973 | {0, UA_NODEIDTYPE_NUMERIC, {8917LU}}, /* .binaryEncodingId */ |
| 21974 | sizeof(UA_TimeZoneDataType), /* .memSize */ |
| 21975 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 21976 | true, /* .pointerFree */ |
| 21977 | false, /* .overlayable */ |
| 21978 | 2, /* .membersSize */ |
| 21979 | TimeZoneDataType_members /* .members */ |
| 21980 | }, |
| 21981 | /* Index */ |
| 21982 | { |
| 21983 | UA_TYPENAME("Index") /* .typeName */ |
| 21984 | {0, UA_NODEIDTYPE_NUMERIC, {17588LU}}, /* .typeId */ |
| 21985 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21986 | sizeof(UA_Index), /* .memSize */ |
| 21987 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 21988 | false, /* .pointerFree */ |
| 21989 | false, /* .overlayable */ |
| 21990 | 0, /* .membersSize */ |
| 21991 | Index_members /* .members */ |
| 21992 | }, |
| 21993 | /* IntegerId */ |
| 21994 | { |
| 21995 | UA_TYPENAME("IntegerId") /* .typeName */ |
| 21996 | {0, UA_NODEIDTYPE_NUMERIC, {288LU}}, /* .typeId */ |
| 21997 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 21998 | sizeof(UA_IntegerId), /* .memSize */ |
| 21999 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 22000 | false, /* .pointerFree */ |
| 22001 | false, /* .overlayable */ |
| 22002 | 0, /* .membersSize */ |
| 22003 | IntegerId_members /* .members */ |
| 22004 | }, |
| 22005 | /* ApplicationType */ |
| 22006 | { |
| 22007 | UA_TYPENAME("ApplicationType") /* .typeName */ |
| 22008 | {0, UA_NODEIDTYPE_NUMERIC, {307LU}}, /* .typeId */ |
| 22009 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22010 | sizeof(UA_ApplicationType), /* .memSize */ |
| 22011 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 22012 | true, /* .pointerFree */ |
| 22013 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 22014 | 0, /* .membersSize */ |
| 22015 | ApplicationType_members /* .members */ |
| 22016 | }, |
| 22017 | /* ApplicationDescription */ |
| 22018 | { |
| 22019 | UA_TYPENAME("ApplicationDescription") /* .typeName */ |
| 22020 | {0, UA_NODEIDTYPE_NUMERIC, {308LU}}, /* .typeId */ |
| 22021 | {0, UA_NODEIDTYPE_NUMERIC, {310LU}}, /* .binaryEncodingId */ |
| 22022 | sizeof(UA_ApplicationDescription), /* .memSize */ |
| 22023 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22024 | false, /* .pointerFree */ |
| 22025 | false, /* .overlayable */ |
| 22026 | 7, /* .membersSize */ |
| 22027 | ApplicationDescription_members /* .members */ |
| 22028 | }, |
| 22029 | /* RequestHeader */ |
| 22030 | { |
| 22031 | UA_TYPENAME("RequestHeader") /* .typeName */ |
| 22032 | {0, UA_NODEIDTYPE_NUMERIC, {389LU}}, /* .typeId */ |
| 22033 | {0, UA_NODEIDTYPE_NUMERIC, {391LU}}, /* .binaryEncodingId */ |
| 22034 | sizeof(UA_RequestHeader), /* .memSize */ |
| 22035 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22036 | false, /* .pointerFree */ |
| 22037 | false, /* .overlayable */ |
| 22038 | 7, /* .membersSize */ |
| 22039 | RequestHeader_members /* .members */ |
| 22040 | }, |
| 22041 | /* ResponseHeader */ |
| 22042 | { |
| 22043 | UA_TYPENAME("ResponseHeader") /* .typeName */ |
| 22044 | {0, UA_NODEIDTYPE_NUMERIC, {392LU}}, /* .typeId */ |
| 22045 | {0, UA_NODEIDTYPE_NUMERIC, {394LU}}, /* .binaryEncodingId */ |
| 22046 | sizeof(UA_ResponseHeader), /* .memSize */ |
| 22047 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22048 | false, /* .pointerFree */ |
| 22049 | false, /* .overlayable */ |
| 22050 | 6, /* .membersSize */ |
| 22051 | ResponseHeader_members /* .members */ |
| 22052 | }, |
| 22053 | /* VersionTime */ |
| 22054 | { |
| 22055 | UA_TYPENAME("VersionTime") /* .typeName */ |
| 22056 | {0, UA_NODEIDTYPE_NUMERIC, {20998LU}}, /* .typeId */ |
| 22057 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22058 | sizeof(UA_VersionTime), /* .memSize */ |
| 22059 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 22060 | false, /* .pointerFree */ |
| 22061 | false, /* .overlayable */ |
| 22062 | 0, /* .membersSize */ |
| 22063 | VersionTime_members /* .members */ |
| 22064 | }, |
| 22065 | /* ServiceFault */ |
| 22066 | { |
| 22067 | UA_TYPENAME("ServiceFault") /* .typeName */ |
| 22068 | {0, UA_NODEIDTYPE_NUMERIC, {395LU}}, /* .typeId */ |
| 22069 | {0, UA_NODEIDTYPE_NUMERIC, {397LU}}, /* .binaryEncodingId */ |
| 22070 | sizeof(UA_ServiceFault), /* .memSize */ |
| 22071 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22072 | false, /* .pointerFree */ |
| 22073 | false, /* .overlayable */ |
| 22074 | 1, /* .membersSize */ |
| 22075 | ServiceFault_members /* .members */ |
| 22076 | }, |
| 22077 | /* SessionlessInvokeRequestType */ |
| 22078 | { |
| 22079 | UA_TYPENAME("SessionlessInvokeRequestType") /* .typeName */ |
| 22080 | {0, UA_NODEIDTYPE_NUMERIC, {15901LU}}, /* .typeId */ |
| 22081 | {0, UA_NODEIDTYPE_NUMERIC, {15903LU}}, /* .binaryEncodingId */ |
| 22082 | sizeof(UA_SessionlessInvokeRequestType), /* .memSize */ |
| 22083 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22084 | false, /* .pointerFree */ |
| 22085 | false, /* .overlayable */ |
| 22086 | 5, /* .membersSize */ |
| 22087 | SessionlessInvokeRequestType_members /* .members */ |
| 22088 | }, |
| 22089 | /* SessionlessInvokeResponseType */ |
| 22090 | { |
| 22091 | UA_TYPENAME("SessionlessInvokeResponseType") /* .typeName */ |
| 22092 | {0, UA_NODEIDTYPE_NUMERIC, {20999LU}}, /* .typeId */ |
| 22093 | {0, UA_NODEIDTYPE_NUMERIC, {21001LU}}, /* .binaryEncodingId */ |
| 22094 | sizeof(UA_SessionlessInvokeResponseType), /* .memSize */ |
| 22095 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22096 | false, /* .pointerFree */ |
| 22097 | false, /* .overlayable */ |
| 22098 | 3, /* .membersSize */ |
| 22099 | SessionlessInvokeResponseType_members /* .members */ |
| 22100 | }, |
| 22101 | /* FindServersRequest */ |
| 22102 | { |
| 22103 | UA_TYPENAME("FindServersRequest") /* .typeName */ |
| 22104 | {0, UA_NODEIDTYPE_NUMERIC, {420LU}}, /* .typeId */ |
| 22105 | {0, UA_NODEIDTYPE_NUMERIC, {422LU}}, /* .binaryEncodingId */ |
| 22106 | sizeof(UA_FindServersRequest), /* .memSize */ |
| 22107 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22108 | false, /* .pointerFree */ |
| 22109 | false, /* .overlayable */ |
| 22110 | 4, /* .membersSize */ |
| 22111 | FindServersRequest_members /* .members */ |
| 22112 | }, |
| 22113 | /* FindServersResponse */ |
| 22114 | { |
| 22115 | UA_TYPENAME("FindServersResponse") /* .typeName */ |
| 22116 | {0, UA_NODEIDTYPE_NUMERIC, {423LU}}, /* .typeId */ |
| 22117 | {0, UA_NODEIDTYPE_NUMERIC, {425LU}}, /* .binaryEncodingId */ |
| 22118 | sizeof(UA_FindServersResponse), /* .memSize */ |
| 22119 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22120 | false, /* .pointerFree */ |
| 22121 | false, /* .overlayable */ |
| 22122 | 2, /* .membersSize */ |
| 22123 | FindServersResponse_members /* .members */ |
| 22124 | }, |
| 22125 | /* ServerOnNetwork */ |
| 22126 | { |
| 22127 | UA_TYPENAME("ServerOnNetwork") /* .typeName */ |
| 22128 | {0, UA_NODEIDTYPE_NUMERIC, {12189LU}}, /* .typeId */ |
| 22129 | {0, UA_NODEIDTYPE_NUMERIC, {12207LU}}, /* .binaryEncodingId */ |
| 22130 | sizeof(UA_ServerOnNetwork), /* .memSize */ |
| 22131 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22132 | false, /* .pointerFree */ |
| 22133 | false, /* .overlayable */ |
| 22134 | 4, /* .membersSize */ |
| 22135 | ServerOnNetwork_members /* .members */ |
| 22136 | }, |
| 22137 | /* FindServersOnNetworkRequest */ |
| 22138 | { |
| 22139 | UA_TYPENAME("FindServersOnNetworkRequest") /* .typeName */ |
| 22140 | {0, UA_NODEIDTYPE_NUMERIC, {12190LU}}, /* .typeId */ |
| 22141 | {0, UA_NODEIDTYPE_NUMERIC, {12208LU}}, /* .binaryEncodingId */ |
| 22142 | sizeof(UA_FindServersOnNetworkRequest), /* .memSize */ |
| 22143 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22144 | false, /* .pointerFree */ |
| 22145 | false, /* .overlayable */ |
| 22146 | 4, /* .membersSize */ |
| 22147 | FindServersOnNetworkRequest_members /* .members */ |
| 22148 | }, |
| 22149 | /* FindServersOnNetworkResponse */ |
| 22150 | { |
| 22151 | UA_TYPENAME("FindServersOnNetworkResponse") /* .typeName */ |
| 22152 | {0, UA_NODEIDTYPE_NUMERIC, {12191LU}}, /* .typeId */ |
| 22153 | {0, UA_NODEIDTYPE_NUMERIC, {12209LU}}, /* .binaryEncodingId */ |
| 22154 | sizeof(UA_FindServersOnNetworkResponse), /* .memSize */ |
| 22155 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22156 | false, /* .pointerFree */ |
| 22157 | false, /* .overlayable */ |
| 22158 | 3, /* .membersSize */ |
| 22159 | FindServersOnNetworkResponse_members /* .members */ |
| 22160 | }, |
| 22161 | /* ApplicationInstanceCertificate */ |
| 22162 | { |
| 22163 | UA_TYPENAME("ApplicationInstanceCertificate") /* .typeName */ |
| 22164 | {0, UA_NODEIDTYPE_NUMERIC, {311LU}}, /* .typeId */ |
| 22165 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22166 | sizeof(UA_ApplicationInstanceCertificate), /* .memSize */ |
| 22167 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 22168 | false, /* .pointerFree */ |
| 22169 | false, /* .overlayable */ |
| 22170 | 0, /* .membersSize */ |
| 22171 | ApplicationInstanceCertificate_members /* .members */ |
| 22172 | }, |
| 22173 | /* MessageSecurityMode */ |
| 22174 | { |
| 22175 | UA_TYPENAME("MessageSecurityMode") /* .typeName */ |
| 22176 | {0, UA_NODEIDTYPE_NUMERIC, {302LU}}, /* .typeId */ |
| 22177 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22178 | sizeof(UA_MessageSecurityMode), /* .memSize */ |
| 22179 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 22180 | true, /* .pointerFree */ |
| 22181 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 22182 | 0, /* .membersSize */ |
| 22183 | MessageSecurityMode_members /* .members */ |
| 22184 | }, |
| 22185 | /* UserTokenType */ |
| 22186 | { |
| 22187 | UA_TYPENAME("UserTokenType") /* .typeName */ |
| 22188 | {0, UA_NODEIDTYPE_NUMERIC, {303LU}}, /* .typeId */ |
| 22189 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22190 | sizeof(UA_UserTokenType), /* .memSize */ |
| 22191 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 22192 | true, /* .pointerFree */ |
| 22193 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 22194 | 0, /* .membersSize */ |
| 22195 | UserTokenType_members /* .members */ |
| 22196 | }, |
| 22197 | /* UserTokenPolicy */ |
| 22198 | { |
| 22199 | UA_TYPENAME("UserTokenPolicy") /* .typeName */ |
| 22200 | {0, UA_NODEIDTYPE_NUMERIC, {304LU}}, /* .typeId */ |
| 22201 | {0, UA_NODEIDTYPE_NUMERIC, {306LU}}, /* .binaryEncodingId */ |
| 22202 | sizeof(UA_UserTokenPolicy), /* .memSize */ |
| 22203 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22204 | false, /* .pointerFree */ |
| 22205 | false, /* .overlayable */ |
| 22206 | 5, /* .membersSize */ |
| 22207 | UserTokenPolicy_members /* .members */ |
| 22208 | }, |
| 22209 | /* EndpointDescription */ |
| 22210 | { |
| 22211 | UA_TYPENAME("EndpointDescription") /* .typeName */ |
| 22212 | {0, UA_NODEIDTYPE_NUMERIC, {312LU}}, /* .typeId */ |
| 22213 | {0, UA_NODEIDTYPE_NUMERIC, {314LU}}, /* .binaryEncodingId */ |
| 22214 | sizeof(UA_EndpointDescription), /* .memSize */ |
| 22215 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22216 | false, /* .pointerFree */ |
| 22217 | false, /* .overlayable */ |
| 22218 | 8, /* .membersSize */ |
| 22219 | EndpointDescription_members /* .members */ |
| 22220 | }, |
| 22221 | /* GetEndpointsRequest */ |
| 22222 | { |
| 22223 | UA_TYPENAME("GetEndpointsRequest") /* .typeName */ |
| 22224 | {0, UA_NODEIDTYPE_NUMERIC, {426LU}}, /* .typeId */ |
| 22225 | {0, UA_NODEIDTYPE_NUMERIC, {428LU}}, /* .binaryEncodingId */ |
| 22226 | sizeof(UA_GetEndpointsRequest), /* .memSize */ |
| 22227 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22228 | false, /* .pointerFree */ |
| 22229 | false, /* .overlayable */ |
| 22230 | 4, /* .membersSize */ |
| 22231 | GetEndpointsRequest_members /* .members */ |
| 22232 | }, |
| 22233 | /* GetEndpointsResponse */ |
| 22234 | { |
| 22235 | UA_TYPENAME("GetEndpointsResponse") /* .typeName */ |
| 22236 | {0, UA_NODEIDTYPE_NUMERIC, {429LU}}, /* .typeId */ |
| 22237 | {0, UA_NODEIDTYPE_NUMERIC, {431LU}}, /* .binaryEncodingId */ |
| 22238 | sizeof(UA_GetEndpointsResponse), /* .memSize */ |
| 22239 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22240 | false, /* .pointerFree */ |
| 22241 | false, /* .overlayable */ |
| 22242 | 2, /* .membersSize */ |
| 22243 | GetEndpointsResponse_members /* .members */ |
| 22244 | }, |
| 22245 | /* RegisteredServer */ |
| 22246 | { |
| 22247 | UA_TYPENAME("RegisteredServer") /* .typeName */ |
| 22248 | {0, UA_NODEIDTYPE_NUMERIC, {432LU}}, /* .typeId */ |
| 22249 | {0, UA_NODEIDTYPE_NUMERIC, {434LU}}, /* .binaryEncodingId */ |
| 22250 | sizeof(UA_RegisteredServer), /* .memSize */ |
| 22251 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22252 | false, /* .pointerFree */ |
| 22253 | false, /* .overlayable */ |
| 22254 | 8, /* .membersSize */ |
| 22255 | RegisteredServer_members /* .members */ |
| 22256 | }, |
| 22257 | /* RegisterServerRequest */ |
| 22258 | { |
| 22259 | UA_TYPENAME("RegisterServerRequest") /* .typeName */ |
| 22260 | {0, UA_NODEIDTYPE_NUMERIC, {435LU}}, /* .typeId */ |
| 22261 | {0, UA_NODEIDTYPE_NUMERIC, {437LU}}, /* .binaryEncodingId */ |
| 22262 | sizeof(UA_RegisterServerRequest), /* .memSize */ |
| 22263 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22264 | false, /* .pointerFree */ |
| 22265 | false, /* .overlayable */ |
| 22266 | 2, /* .membersSize */ |
| 22267 | RegisterServerRequest_members /* .members */ |
| 22268 | }, |
| 22269 | /* RegisterServerResponse */ |
| 22270 | { |
| 22271 | UA_TYPENAME("RegisterServerResponse") /* .typeName */ |
| 22272 | {0, UA_NODEIDTYPE_NUMERIC, {438LU}}, /* .typeId */ |
| 22273 | {0, UA_NODEIDTYPE_NUMERIC, {440LU}}, /* .binaryEncodingId */ |
| 22274 | sizeof(UA_RegisterServerResponse), /* .memSize */ |
| 22275 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22276 | false, /* .pointerFree */ |
| 22277 | false, /* .overlayable */ |
| 22278 | 1, /* .membersSize */ |
| 22279 | RegisterServerResponse_members /* .members */ |
| 22280 | }, |
| 22281 | /* MdnsDiscoveryConfiguration */ |
| 22282 | { |
| 22283 | UA_TYPENAME("MdnsDiscoveryConfiguration") /* .typeName */ |
| 22284 | {0, UA_NODEIDTYPE_NUMERIC, {12891LU}}, /* .typeId */ |
| 22285 | {0, UA_NODEIDTYPE_NUMERIC, {12901LU}}, /* .binaryEncodingId */ |
| 22286 | sizeof(UA_MdnsDiscoveryConfiguration), /* .memSize */ |
| 22287 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22288 | false, /* .pointerFree */ |
| 22289 | false, /* .overlayable */ |
| 22290 | 2, /* .membersSize */ |
| 22291 | MdnsDiscoveryConfiguration_members /* .members */ |
| 22292 | }, |
| 22293 | /* RegisterServer2Request */ |
| 22294 | { |
| 22295 | UA_TYPENAME("RegisterServer2Request") /* .typeName */ |
| 22296 | {0, UA_NODEIDTYPE_NUMERIC, {12193LU}}, /* .typeId */ |
| 22297 | {0, UA_NODEIDTYPE_NUMERIC, {12211LU}}, /* .binaryEncodingId */ |
| 22298 | sizeof(UA_RegisterServer2Request), /* .memSize */ |
| 22299 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22300 | false, /* .pointerFree */ |
| 22301 | false, /* .overlayable */ |
| 22302 | 3, /* .membersSize */ |
| 22303 | RegisterServer2Request_members /* .members */ |
| 22304 | }, |
| 22305 | /* RegisterServer2Response */ |
| 22306 | { |
| 22307 | UA_TYPENAME("RegisterServer2Response") /* .typeName */ |
| 22308 | {0, UA_NODEIDTYPE_NUMERIC, {12194LU}}, /* .typeId */ |
| 22309 | {0, UA_NODEIDTYPE_NUMERIC, {12212LU}}, /* .binaryEncodingId */ |
| 22310 | sizeof(UA_RegisterServer2Response), /* .memSize */ |
| 22311 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22312 | false, /* .pointerFree */ |
| 22313 | false, /* .overlayable */ |
| 22314 | 3, /* .membersSize */ |
| 22315 | RegisterServer2Response_members /* .members */ |
| 22316 | }, |
| 22317 | /* SecurityTokenRequestType */ |
| 22318 | { |
| 22319 | UA_TYPENAME("SecurityTokenRequestType") /* .typeName */ |
| 22320 | {0, UA_NODEIDTYPE_NUMERIC, {315LU}}, /* .typeId */ |
| 22321 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22322 | sizeof(UA_SecurityTokenRequestType), /* .memSize */ |
| 22323 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 22324 | true, /* .pointerFree */ |
| 22325 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 22326 | 0, /* .membersSize */ |
| 22327 | SecurityTokenRequestType_members /* .members */ |
| 22328 | }, |
| 22329 | /* ChannelSecurityToken */ |
| 22330 | { |
| 22331 | UA_TYPENAME("ChannelSecurityToken") /* .typeName */ |
| 22332 | {0, UA_NODEIDTYPE_NUMERIC, {441LU}}, /* .typeId */ |
| 22333 | {0, UA_NODEIDTYPE_NUMERIC, {443LU}}, /* .binaryEncodingId */ |
| 22334 | sizeof(UA_ChannelSecurityToken), /* .memSize */ |
| 22335 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22336 | true, /* .pointerFree */ |
| 22337 | false, /* .overlayable */ |
| 22338 | 4, /* .membersSize */ |
| 22339 | ChannelSecurityToken_members /* .members */ |
| 22340 | }, |
| 22341 | /* OpenSecureChannelRequest */ |
| 22342 | { |
| 22343 | UA_TYPENAME("OpenSecureChannelRequest") /* .typeName */ |
| 22344 | {0, UA_NODEIDTYPE_NUMERIC, {444LU}}, /* .typeId */ |
| 22345 | {0, UA_NODEIDTYPE_NUMERIC, {446LU}}, /* .binaryEncodingId */ |
| 22346 | sizeof(UA_OpenSecureChannelRequest), /* .memSize */ |
| 22347 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22348 | false, /* .pointerFree */ |
| 22349 | false, /* .overlayable */ |
| 22350 | 6, /* .membersSize */ |
| 22351 | OpenSecureChannelRequest_members /* .members */ |
| 22352 | }, |
| 22353 | /* OpenSecureChannelResponse */ |
| 22354 | { |
| 22355 | UA_TYPENAME("OpenSecureChannelResponse") /* .typeName */ |
| 22356 | {0, UA_NODEIDTYPE_NUMERIC, {447LU}}, /* .typeId */ |
| 22357 | {0, UA_NODEIDTYPE_NUMERIC, {449LU}}, /* .binaryEncodingId */ |
| 22358 | sizeof(UA_OpenSecureChannelResponse), /* .memSize */ |
| 22359 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22360 | false, /* .pointerFree */ |
| 22361 | false, /* .overlayable */ |
| 22362 | 4, /* .membersSize */ |
| 22363 | OpenSecureChannelResponse_members /* .members */ |
| 22364 | }, |
| 22365 | /* CloseSecureChannelRequest */ |
| 22366 | { |
| 22367 | UA_TYPENAME("CloseSecureChannelRequest") /* .typeName */ |
| 22368 | {0, UA_NODEIDTYPE_NUMERIC, {450LU}}, /* .typeId */ |
| 22369 | {0, UA_NODEIDTYPE_NUMERIC, {452LU}}, /* .binaryEncodingId */ |
| 22370 | sizeof(UA_CloseSecureChannelRequest), /* .memSize */ |
| 22371 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22372 | false, /* .pointerFree */ |
| 22373 | false, /* .overlayable */ |
| 22374 | 1, /* .membersSize */ |
| 22375 | CloseSecureChannelRequest_members /* .members */ |
| 22376 | }, |
| 22377 | /* CloseSecureChannelResponse */ |
| 22378 | { |
| 22379 | UA_TYPENAME("CloseSecureChannelResponse") /* .typeName */ |
| 22380 | {0, UA_NODEIDTYPE_NUMERIC, {453LU}}, /* .typeId */ |
| 22381 | {0, UA_NODEIDTYPE_NUMERIC, {455LU}}, /* .binaryEncodingId */ |
| 22382 | sizeof(UA_CloseSecureChannelResponse), /* .memSize */ |
| 22383 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22384 | false, /* .pointerFree */ |
| 22385 | false, /* .overlayable */ |
| 22386 | 1, /* .membersSize */ |
| 22387 | CloseSecureChannelResponse_members /* .members */ |
| 22388 | }, |
| 22389 | /* SignedSoftwareCertificate */ |
| 22390 | { |
| 22391 | UA_TYPENAME("SignedSoftwareCertificate") /* .typeName */ |
| 22392 | {0, UA_NODEIDTYPE_NUMERIC, {344LU}}, /* .typeId */ |
| 22393 | {0, UA_NODEIDTYPE_NUMERIC, {346LU}}, /* .binaryEncodingId */ |
| 22394 | sizeof(UA_SignedSoftwareCertificate), /* .memSize */ |
| 22395 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22396 | false, /* .pointerFree */ |
| 22397 | false, /* .overlayable */ |
| 22398 | 2, /* .membersSize */ |
| 22399 | SignedSoftwareCertificate_members /* .members */ |
| 22400 | }, |
| 22401 | /* SessionAuthenticationToken */ |
| 22402 | { |
| 22403 | UA_TYPENAME("SessionAuthenticationToken") /* .typeName */ |
| 22404 | {0, UA_NODEIDTYPE_NUMERIC, {388LU}}, /* .typeId */ |
| 22405 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22406 | sizeof(UA_SessionAuthenticationToken), /* .memSize */ |
| 22407 | UA_DATATYPEKIND_NODEID, /* .typeKind */ |
| 22408 | false, /* .pointerFree */ |
| 22409 | false, /* .overlayable */ |
| 22410 | 0, /* .membersSize */ |
| 22411 | SessionAuthenticationToken_members /* .members */ |
| 22412 | }, |
| 22413 | /* SignatureData */ |
| 22414 | { |
| 22415 | UA_TYPENAME("SignatureData") /* .typeName */ |
| 22416 | {0, UA_NODEIDTYPE_NUMERIC, {456LU}}, /* .typeId */ |
| 22417 | {0, UA_NODEIDTYPE_NUMERIC, {458LU}}, /* .binaryEncodingId */ |
| 22418 | sizeof(UA_SignatureData), /* .memSize */ |
| 22419 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22420 | false, /* .pointerFree */ |
| 22421 | false, /* .overlayable */ |
| 22422 | 2, /* .membersSize */ |
| 22423 | SignatureData_members /* .members */ |
| 22424 | }, |
| 22425 | /* CreateSessionRequest */ |
| 22426 | { |
| 22427 | UA_TYPENAME("CreateSessionRequest") /* .typeName */ |
| 22428 | {0, UA_NODEIDTYPE_NUMERIC, {459LU}}, /* .typeId */ |
| 22429 | {0, UA_NODEIDTYPE_NUMERIC, {461LU}}, /* .binaryEncodingId */ |
| 22430 | sizeof(UA_CreateSessionRequest), /* .memSize */ |
| 22431 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22432 | false, /* .pointerFree */ |
| 22433 | false, /* .overlayable */ |
| 22434 | 9, /* .membersSize */ |
| 22435 | CreateSessionRequest_members /* .members */ |
| 22436 | }, |
| 22437 | /* CreateSessionResponse */ |
| 22438 | { |
| 22439 | UA_TYPENAME("CreateSessionResponse") /* .typeName */ |
| 22440 | {0, UA_NODEIDTYPE_NUMERIC, {462LU}}, /* .typeId */ |
| 22441 | {0, UA_NODEIDTYPE_NUMERIC, {464LU}}, /* .binaryEncodingId */ |
| 22442 | sizeof(UA_CreateSessionResponse), /* .memSize */ |
| 22443 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22444 | false, /* .pointerFree */ |
| 22445 | false, /* .overlayable */ |
| 22446 | 10, /* .membersSize */ |
| 22447 | CreateSessionResponse_members /* .members */ |
| 22448 | }, |
| 22449 | /* UserIdentityToken */ |
| 22450 | { |
| 22451 | UA_TYPENAME("UserIdentityToken") /* .typeName */ |
| 22452 | {0, UA_NODEIDTYPE_NUMERIC, {316LU}}, /* .typeId */ |
| 22453 | {0, UA_NODEIDTYPE_NUMERIC, {318LU}}, /* .binaryEncodingId */ |
| 22454 | sizeof(UA_UserIdentityToken), /* .memSize */ |
| 22455 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22456 | false, /* .pointerFree */ |
| 22457 | false, /* .overlayable */ |
| 22458 | 1, /* .membersSize */ |
| 22459 | UserIdentityToken_members /* .members */ |
| 22460 | }, |
| 22461 | /* AnonymousIdentityToken */ |
| 22462 | { |
| 22463 | UA_TYPENAME("AnonymousIdentityToken") /* .typeName */ |
| 22464 | {0, UA_NODEIDTYPE_NUMERIC, {319LU}}, /* .typeId */ |
| 22465 | {0, UA_NODEIDTYPE_NUMERIC, {321LU}}, /* .binaryEncodingId */ |
| 22466 | sizeof(UA_AnonymousIdentityToken), /* .memSize */ |
| 22467 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22468 | false, /* .pointerFree */ |
| 22469 | false, /* .overlayable */ |
| 22470 | 1, /* .membersSize */ |
| 22471 | AnonymousIdentityToken_members /* .members */ |
| 22472 | }, |
| 22473 | /* UserNameIdentityToken */ |
| 22474 | { |
| 22475 | UA_TYPENAME("UserNameIdentityToken") /* .typeName */ |
| 22476 | {0, UA_NODEIDTYPE_NUMERIC, {322LU}}, /* .typeId */ |
| 22477 | {0, UA_NODEIDTYPE_NUMERIC, {324LU}}, /* .binaryEncodingId */ |
| 22478 | sizeof(UA_UserNameIdentityToken), /* .memSize */ |
| 22479 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22480 | false, /* .pointerFree */ |
| 22481 | false, /* .overlayable */ |
| 22482 | 4, /* .membersSize */ |
| 22483 | UserNameIdentityToken_members /* .members */ |
| 22484 | }, |
| 22485 | /* X509IdentityToken */ |
| 22486 | { |
| 22487 | UA_TYPENAME("X509IdentityToken") /* .typeName */ |
| 22488 | {0, UA_NODEIDTYPE_NUMERIC, {325LU}}, /* .typeId */ |
| 22489 | {0, UA_NODEIDTYPE_NUMERIC, {327LU}}, /* .binaryEncodingId */ |
| 22490 | sizeof(UA_X509IdentityToken), /* .memSize */ |
| 22491 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22492 | false, /* .pointerFree */ |
| 22493 | false, /* .overlayable */ |
| 22494 | 2, /* .membersSize */ |
| 22495 | X509IdentityToken_members /* .members */ |
| 22496 | }, |
| 22497 | /* IssuedIdentityToken */ |
| 22498 | { |
| 22499 | UA_TYPENAME("IssuedIdentityToken") /* .typeName */ |
| 22500 | {0, UA_NODEIDTYPE_NUMERIC, {938LU}}, /* .typeId */ |
| 22501 | {0, UA_NODEIDTYPE_NUMERIC, {940LU}}, /* .binaryEncodingId */ |
| 22502 | sizeof(UA_IssuedIdentityToken), /* .memSize */ |
| 22503 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22504 | false, /* .pointerFree */ |
| 22505 | false, /* .overlayable */ |
| 22506 | 3, /* .membersSize */ |
| 22507 | IssuedIdentityToken_members /* .members */ |
| 22508 | }, |
| 22509 | /* RsaEncryptedSecret */ |
| 22510 | { |
| 22511 | UA_TYPENAME("RsaEncryptedSecret") /* .typeName */ |
| 22512 | {0, UA_NODEIDTYPE_NUMERIC, {17545LU}}, /* .typeId */ |
| 22513 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22514 | sizeof(UA_RsaEncryptedSecret), /* .memSize */ |
| 22515 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 22516 | false, /* .pointerFree */ |
| 22517 | false, /* .overlayable */ |
| 22518 | 0, /* .membersSize */ |
| 22519 | RsaEncryptedSecret_members /* .members */ |
| 22520 | }, |
| 22521 | /* EccEncryptedSecret */ |
| 22522 | { |
| 22523 | UA_TYPENAME("EccEncryptedSecret") /* .typeName */ |
| 22524 | {0, UA_NODEIDTYPE_NUMERIC, {17546LU}}, /* .typeId */ |
| 22525 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22526 | sizeof(UA_EccEncryptedSecret), /* .memSize */ |
| 22527 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 22528 | false, /* .pointerFree */ |
| 22529 | false, /* .overlayable */ |
| 22530 | 0, /* .membersSize */ |
| 22531 | EccEncryptedSecret_members /* .members */ |
| 22532 | }, |
| 22533 | /* ActivateSessionRequest */ |
| 22534 | { |
| 22535 | UA_TYPENAME("ActivateSessionRequest") /* .typeName */ |
| 22536 | {0, UA_NODEIDTYPE_NUMERIC, {465LU}}, /* .typeId */ |
| 22537 | {0, UA_NODEIDTYPE_NUMERIC, {467LU}}, /* .binaryEncodingId */ |
| 22538 | sizeof(UA_ActivateSessionRequest), /* .memSize */ |
| 22539 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22540 | false, /* .pointerFree */ |
| 22541 | false, /* .overlayable */ |
| 22542 | 6, /* .membersSize */ |
| 22543 | ActivateSessionRequest_members /* .members */ |
| 22544 | }, |
| 22545 | /* ActivateSessionResponse */ |
| 22546 | { |
| 22547 | UA_TYPENAME("ActivateSessionResponse") /* .typeName */ |
| 22548 | {0, UA_NODEIDTYPE_NUMERIC, {468LU}}, /* .typeId */ |
| 22549 | {0, UA_NODEIDTYPE_NUMERIC, {470LU}}, /* .binaryEncodingId */ |
| 22550 | sizeof(UA_ActivateSessionResponse), /* .memSize */ |
| 22551 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22552 | false, /* .pointerFree */ |
| 22553 | false, /* .overlayable */ |
| 22554 | 4, /* .membersSize */ |
| 22555 | ActivateSessionResponse_members /* .members */ |
| 22556 | }, |
| 22557 | /* CloseSessionRequest */ |
| 22558 | { |
| 22559 | UA_TYPENAME("CloseSessionRequest") /* .typeName */ |
| 22560 | {0, UA_NODEIDTYPE_NUMERIC, {471LU}}, /* .typeId */ |
| 22561 | {0, UA_NODEIDTYPE_NUMERIC, {473LU}}, /* .binaryEncodingId */ |
| 22562 | sizeof(UA_CloseSessionRequest), /* .memSize */ |
| 22563 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22564 | false, /* .pointerFree */ |
| 22565 | false, /* .overlayable */ |
| 22566 | 2, /* .membersSize */ |
| 22567 | CloseSessionRequest_members /* .members */ |
| 22568 | }, |
| 22569 | /* CloseSessionResponse */ |
| 22570 | { |
| 22571 | UA_TYPENAME("CloseSessionResponse") /* .typeName */ |
| 22572 | {0, UA_NODEIDTYPE_NUMERIC, {474LU}}, /* .typeId */ |
| 22573 | {0, UA_NODEIDTYPE_NUMERIC, {476LU}}, /* .binaryEncodingId */ |
| 22574 | sizeof(UA_CloseSessionResponse), /* .memSize */ |
| 22575 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22576 | false, /* .pointerFree */ |
| 22577 | false, /* .overlayable */ |
| 22578 | 1, /* .membersSize */ |
| 22579 | CloseSessionResponse_members /* .members */ |
| 22580 | }, |
| 22581 | /* CancelRequest */ |
| 22582 | { |
| 22583 | UA_TYPENAME("CancelRequest") /* .typeName */ |
| 22584 | {0, UA_NODEIDTYPE_NUMERIC, {477LU}}, /* .typeId */ |
| 22585 | {0, UA_NODEIDTYPE_NUMERIC, {479LU}}, /* .binaryEncodingId */ |
| 22586 | sizeof(UA_CancelRequest), /* .memSize */ |
| 22587 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22588 | false, /* .pointerFree */ |
| 22589 | false, /* .overlayable */ |
| 22590 | 2, /* .membersSize */ |
| 22591 | CancelRequest_members /* .members */ |
| 22592 | }, |
| 22593 | /* CancelResponse */ |
| 22594 | { |
| 22595 | UA_TYPENAME("CancelResponse") /* .typeName */ |
| 22596 | {0, UA_NODEIDTYPE_NUMERIC, {480LU}}, /* .typeId */ |
| 22597 | {0, UA_NODEIDTYPE_NUMERIC, {482LU}}, /* .binaryEncodingId */ |
| 22598 | sizeof(UA_CancelResponse), /* .memSize */ |
| 22599 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22600 | false, /* .pointerFree */ |
| 22601 | false, /* .overlayable */ |
| 22602 | 2, /* .membersSize */ |
| 22603 | CancelResponse_members /* .members */ |
| 22604 | }, |
| 22605 | /* NodeAttributesMask */ |
| 22606 | { |
| 22607 | UA_TYPENAME("NodeAttributesMask") /* .typeName */ |
| 22608 | {0, UA_NODEIDTYPE_NUMERIC, {348LU}}, /* .typeId */ |
| 22609 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22610 | sizeof(UA_NodeAttributesMask), /* .memSize */ |
| 22611 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 22612 | true, /* .pointerFree */ |
| 22613 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 22614 | 0, /* .membersSize */ |
| 22615 | NodeAttributesMask_members /* .members */ |
| 22616 | }, |
| 22617 | /* NodeAttributes */ |
| 22618 | { |
| 22619 | UA_TYPENAME("NodeAttributes") /* .typeName */ |
| 22620 | {0, UA_NODEIDTYPE_NUMERIC, {349LU}}, /* .typeId */ |
| 22621 | {0, UA_NODEIDTYPE_NUMERIC, {351LU}}, /* .binaryEncodingId */ |
| 22622 | sizeof(UA_NodeAttributes), /* .memSize */ |
| 22623 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22624 | false, /* .pointerFree */ |
| 22625 | false, /* .overlayable */ |
| 22626 | 5, /* .membersSize */ |
| 22627 | NodeAttributes_members /* .members */ |
| 22628 | }, |
| 22629 | /* ObjectAttributes */ |
| 22630 | { |
| 22631 | UA_TYPENAME("ObjectAttributes") /* .typeName */ |
| 22632 | {0, UA_NODEIDTYPE_NUMERIC, {352LU}}, /* .typeId */ |
| 22633 | {0, UA_NODEIDTYPE_NUMERIC, {354LU}}, /* .binaryEncodingId */ |
| 22634 | sizeof(UA_ObjectAttributes), /* .memSize */ |
| 22635 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22636 | false, /* .pointerFree */ |
| 22637 | false, /* .overlayable */ |
| 22638 | 6, /* .membersSize */ |
| 22639 | ObjectAttributes_members /* .members */ |
| 22640 | }, |
| 22641 | /* VariableAttributes */ |
| 22642 | { |
| 22643 | UA_TYPENAME("VariableAttributes") /* .typeName */ |
| 22644 | {0, UA_NODEIDTYPE_NUMERIC, {355LU}}, /* .typeId */ |
| 22645 | {0, UA_NODEIDTYPE_NUMERIC, {357LU}}, /* .binaryEncodingId */ |
| 22646 | sizeof(UA_VariableAttributes), /* .memSize */ |
| 22647 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22648 | false, /* .pointerFree */ |
| 22649 | false, /* .overlayable */ |
| 22650 | 13, /* .membersSize */ |
| 22651 | VariableAttributes_members /* .members */ |
| 22652 | }, |
| 22653 | /* MethodAttributes */ |
| 22654 | { |
| 22655 | UA_TYPENAME("MethodAttributes") /* .typeName */ |
| 22656 | {0, UA_NODEIDTYPE_NUMERIC, {358LU}}, /* .typeId */ |
| 22657 | {0, UA_NODEIDTYPE_NUMERIC, {360LU}}, /* .binaryEncodingId */ |
| 22658 | sizeof(UA_MethodAttributes), /* .memSize */ |
| 22659 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22660 | false, /* .pointerFree */ |
| 22661 | false, /* .overlayable */ |
| 22662 | 7, /* .membersSize */ |
| 22663 | MethodAttributes_members /* .members */ |
| 22664 | }, |
| 22665 | /* ObjectTypeAttributes */ |
| 22666 | { |
| 22667 | UA_TYPENAME("ObjectTypeAttributes") /* .typeName */ |
| 22668 | {0, UA_NODEIDTYPE_NUMERIC, {361LU}}, /* .typeId */ |
| 22669 | {0, UA_NODEIDTYPE_NUMERIC, {363LU}}, /* .binaryEncodingId */ |
| 22670 | sizeof(UA_ObjectTypeAttributes), /* .memSize */ |
| 22671 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22672 | false, /* .pointerFree */ |
| 22673 | false, /* .overlayable */ |
| 22674 | 6, /* .membersSize */ |
| 22675 | ObjectTypeAttributes_members /* .members */ |
| 22676 | }, |
| 22677 | /* VariableTypeAttributes */ |
| 22678 | { |
| 22679 | UA_TYPENAME("VariableTypeAttributes") /* .typeName */ |
| 22680 | {0, UA_NODEIDTYPE_NUMERIC, {364LU}}, /* .typeId */ |
| 22681 | {0, UA_NODEIDTYPE_NUMERIC, {366LU}}, /* .binaryEncodingId */ |
| 22682 | sizeof(UA_VariableTypeAttributes), /* .memSize */ |
| 22683 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22684 | false, /* .pointerFree */ |
| 22685 | false, /* .overlayable */ |
| 22686 | 10, /* .membersSize */ |
| 22687 | VariableTypeAttributes_members /* .members */ |
| 22688 | }, |
| 22689 | /* ReferenceTypeAttributes */ |
| 22690 | { |
| 22691 | UA_TYPENAME("ReferenceTypeAttributes") /* .typeName */ |
| 22692 | {0, UA_NODEIDTYPE_NUMERIC, {367LU}}, /* .typeId */ |
| 22693 | {0, UA_NODEIDTYPE_NUMERIC, {369LU}}, /* .binaryEncodingId */ |
| 22694 | sizeof(UA_ReferenceTypeAttributes), /* .memSize */ |
| 22695 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22696 | false, /* .pointerFree */ |
| 22697 | false, /* .overlayable */ |
| 22698 | 8, /* .membersSize */ |
| 22699 | ReferenceTypeAttributes_members /* .members */ |
| 22700 | }, |
| 22701 | /* DataTypeAttributes */ |
| 22702 | { |
| 22703 | UA_TYPENAME("DataTypeAttributes") /* .typeName */ |
| 22704 | {0, UA_NODEIDTYPE_NUMERIC, {370LU}}, /* .typeId */ |
| 22705 | {0, UA_NODEIDTYPE_NUMERIC, {372LU}}, /* .binaryEncodingId */ |
| 22706 | sizeof(UA_DataTypeAttributes), /* .memSize */ |
| 22707 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22708 | false, /* .pointerFree */ |
| 22709 | false, /* .overlayable */ |
| 22710 | 6, /* .membersSize */ |
| 22711 | DataTypeAttributes_members /* .members */ |
| 22712 | }, |
| 22713 | /* ViewAttributes */ |
| 22714 | { |
| 22715 | UA_TYPENAME("ViewAttributes") /* .typeName */ |
| 22716 | {0, UA_NODEIDTYPE_NUMERIC, {373LU}}, /* .typeId */ |
| 22717 | {0, UA_NODEIDTYPE_NUMERIC, {375LU}}, /* .binaryEncodingId */ |
| 22718 | sizeof(UA_ViewAttributes), /* .memSize */ |
| 22719 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22720 | false, /* .pointerFree */ |
| 22721 | false, /* .overlayable */ |
| 22722 | 7, /* .membersSize */ |
| 22723 | ViewAttributes_members /* .members */ |
| 22724 | }, |
| 22725 | /* GenericAttributeValue */ |
| 22726 | { |
| 22727 | UA_TYPENAME("GenericAttributeValue") /* .typeName */ |
| 22728 | {0, UA_NODEIDTYPE_NUMERIC, {17606LU}}, /* .typeId */ |
| 22729 | {0, UA_NODEIDTYPE_NUMERIC, {17610LU}}, /* .binaryEncodingId */ |
| 22730 | sizeof(UA_GenericAttributeValue), /* .memSize */ |
| 22731 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22732 | false, /* .pointerFree */ |
| 22733 | false, /* .overlayable */ |
| 22734 | 2, /* .membersSize */ |
| 22735 | GenericAttributeValue_members /* .members */ |
| 22736 | }, |
| 22737 | /* GenericAttributes */ |
| 22738 | { |
| 22739 | UA_TYPENAME("GenericAttributes") /* .typeName */ |
| 22740 | {0, UA_NODEIDTYPE_NUMERIC, {17607LU}}, /* .typeId */ |
| 22741 | {0, UA_NODEIDTYPE_NUMERIC, {17611LU}}, /* .binaryEncodingId */ |
| 22742 | sizeof(UA_GenericAttributes), /* .memSize */ |
| 22743 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22744 | false, /* .pointerFree */ |
| 22745 | false, /* .overlayable */ |
| 22746 | 6, /* .membersSize */ |
| 22747 | GenericAttributes_members /* .members */ |
| 22748 | }, |
| 22749 | /* AddNodesItem */ |
| 22750 | { |
| 22751 | UA_TYPENAME("AddNodesItem") /* .typeName */ |
| 22752 | {0, UA_NODEIDTYPE_NUMERIC, {376LU}}, /* .typeId */ |
| 22753 | {0, UA_NODEIDTYPE_NUMERIC, {378LU}}, /* .binaryEncodingId */ |
| 22754 | sizeof(UA_AddNodesItem), /* .memSize */ |
| 22755 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22756 | false, /* .pointerFree */ |
| 22757 | false, /* .overlayable */ |
| 22758 | 7, /* .membersSize */ |
| 22759 | AddNodesItem_members /* .members */ |
| 22760 | }, |
| 22761 | /* AddNodesResult */ |
| 22762 | { |
| 22763 | UA_TYPENAME("AddNodesResult") /* .typeName */ |
| 22764 | {0, UA_NODEIDTYPE_NUMERIC, {483LU}}, /* .typeId */ |
| 22765 | {0, UA_NODEIDTYPE_NUMERIC, {485LU}}, /* .binaryEncodingId */ |
| 22766 | sizeof(UA_AddNodesResult), /* .memSize */ |
| 22767 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22768 | false, /* .pointerFree */ |
| 22769 | false, /* .overlayable */ |
| 22770 | 2, /* .membersSize */ |
| 22771 | AddNodesResult_members /* .members */ |
| 22772 | }, |
| 22773 | /* AddNodesRequest */ |
| 22774 | { |
| 22775 | UA_TYPENAME("AddNodesRequest") /* .typeName */ |
| 22776 | {0, UA_NODEIDTYPE_NUMERIC, {486LU}}, /* .typeId */ |
| 22777 | {0, UA_NODEIDTYPE_NUMERIC, {488LU}}, /* .binaryEncodingId */ |
| 22778 | sizeof(UA_AddNodesRequest), /* .memSize */ |
| 22779 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22780 | false, /* .pointerFree */ |
| 22781 | false, /* .overlayable */ |
| 22782 | 2, /* .membersSize */ |
| 22783 | AddNodesRequest_members /* .members */ |
| 22784 | }, |
| 22785 | /* AddNodesResponse */ |
| 22786 | { |
| 22787 | UA_TYPENAME("AddNodesResponse") /* .typeName */ |
| 22788 | {0, UA_NODEIDTYPE_NUMERIC, {489LU}}, /* .typeId */ |
| 22789 | {0, UA_NODEIDTYPE_NUMERIC, {491LU}}, /* .binaryEncodingId */ |
| 22790 | sizeof(UA_AddNodesResponse), /* .memSize */ |
| 22791 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22792 | false, /* .pointerFree */ |
| 22793 | false, /* .overlayable */ |
| 22794 | 3, /* .membersSize */ |
| 22795 | AddNodesResponse_members /* .members */ |
| 22796 | }, |
| 22797 | /* AddReferencesItem */ |
| 22798 | { |
| 22799 | UA_TYPENAME("AddReferencesItem") /* .typeName */ |
| 22800 | {0, UA_NODEIDTYPE_NUMERIC, {379LU}}, /* .typeId */ |
| 22801 | {0, UA_NODEIDTYPE_NUMERIC, {381LU}}, /* .binaryEncodingId */ |
| 22802 | sizeof(UA_AddReferencesItem), /* .memSize */ |
| 22803 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22804 | false, /* .pointerFree */ |
| 22805 | false, /* .overlayable */ |
| 22806 | 6, /* .membersSize */ |
| 22807 | AddReferencesItem_members /* .members */ |
| 22808 | }, |
| 22809 | /* AddReferencesRequest */ |
| 22810 | { |
| 22811 | UA_TYPENAME("AddReferencesRequest") /* .typeName */ |
| 22812 | {0, UA_NODEIDTYPE_NUMERIC, {492LU}}, /* .typeId */ |
| 22813 | {0, UA_NODEIDTYPE_NUMERIC, {494LU}}, /* .binaryEncodingId */ |
| 22814 | sizeof(UA_AddReferencesRequest), /* .memSize */ |
| 22815 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22816 | false, /* .pointerFree */ |
| 22817 | false, /* .overlayable */ |
| 22818 | 2, /* .membersSize */ |
| 22819 | AddReferencesRequest_members /* .members */ |
| 22820 | }, |
| 22821 | /* AddReferencesResponse */ |
| 22822 | { |
| 22823 | UA_TYPENAME("AddReferencesResponse") /* .typeName */ |
| 22824 | {0, UA_NODEIDTYPE_NUMERIC, {495LU}}, /* .typeId */ |
| 22825 | {0, UA_NODEIDTYPE_NUMERIC, {497LU}}, /* .binaryEncodingId */ |
| 22826 | sizeof(UA_AddReferencesResponse), /* .memSize */ |
| 22827 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22828 | false, /* .pointerFree */ |
| 22829 | false, /* .overlayable */ |
| 22830 | 3, /* .membersSize */ |
| 22831 | AddReferencesResponse_members /* .members */ |
| 22832 | }, |
| 22833 | /* DeleteNodesItem */ |
| 22834 | { |
| 22835 | UA_TYPENAME("DeleteNodesItem") /* .typeName */ |
| 22836 | {0, UA_NODEIDTYPE_NUMERIC, {382LU}}, /* .typeId */ |
| 22837 | {0, UA_NODEIDTYPE_NUMERIC, {384LU}}, /* .binaryEncodingId */ |
| 22838 | sizeof(UA_DeleteNodesItem), /* .memSize */ |
| 22839 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22840 | false, /* .pointerFree */ |
| 22841 | false, /* .overlayable */ |
| 22842 | 2, /* .membersSize */ |
| 22843 | DeleteNodesItem_members /* .members */ |
| 22844 | }, |
| 22845 | /* DeleteNodesRequest */ |
| 22846 | { |
| 22847 | UA_TYPENAME("DeleteNodesRequest") /* .typeName */ |
| 22848 | {0, UA_NODEIDTYPE_NUMERIC, {498LU}}, /* .typeId */ |
| 22849 | {0, UA_NODEIDTYPE_NUMERIC, {500LU}}, /* .binaryEncodingId */ |
| 22850 | sizeof(UA_DeleteNodesRequest), /* .memSize */ |
| 22851 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22852 | false, /* .pointerFree */ |
| 22853 | false, /* .overlayable */ |
| 22854 | 2, /* .membersSize */ |
| 22855 | DeleteNodesRequest_members /* .members */ |
| 22856 | }, |
| 22857 | /* DeleteNodesResponse */ |
| 22858 | { |
| 22859 | UA_TYPENAME("DeleteNodesResponse") /* .typeName */ |
| 22860 | {0, UA_NODEIDTYPE_NUMERIC, {501LU}}, /* .typeId */ |
| 22861 | {0, UA_NODEIDTYPE_NUMERIC, {503LU}}, /* .binaryEncodingId */ |
| 22862 | sizeof(UA_DeleteNodesResponse), /* .memSize */ |
| 22863 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22864 | false, /* .pointerFree */ |
| 22865 | false, /* .overlayable */ |
| 22866 | 3, /* .membersSize */ |
| 22867 | DeleteNodesResponse_members /* .members */ |
| 22868 | }, |
| 22869 | /* DeleteReferencesItem */ |
| 22870 | { |
| 22871 | UA_TYPENAME("DeleteReferencesItem") /* .typeName */ |
| 22872 | {0, UA_NODEIDTYPE_NUMERIC, {385LU}}, /* .typeId */ |
| 22873 | {0, UA_NODEIDTYPE_NUMERIC, {387LU}}, /* .binaryEncodingId */ |
| 22874 | sizeof(UA_DeleteReferencesItem), /* .memSize */ |
| 22875 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22876 | false, /* .pointerFree */ |
| 22877 | false, /* .overlayable */ |
| 22878 | 5, /* .membersSize */ |
| 22879 | DeleteReferencesItem_members /* .members */ |
| 22880 | }, |
| 22881 | /* DeleteReferencesRequest */ |
| 22882 | { |
| 22883 | UA_TYPENAME("DeleteReferencesRequest") /* .typeName */ |
| 22884 | {0, UA_NODEIDTYPE_NUMERIC, {504LU}}, /* .typeId */ |
| 22885 | {0, UA_NODEIDTYPE_NUMERIC, {506LU}}, /* .binaryEncodingId */ |
| 22886 | sizeof(UA_DeleteReferencesRequest), /* .memSize */ |
| 22887 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22888 | false, /* .pointerFree */ |
| 22889 | false, /* .overlayable */ |
| 22890 | 2, /* .membersSize */ |
| 22891 | DeleteReferencesRequest_members /* .members */ |
| 22892 | }, |
| 22893 | /* DeleteReferencesResponse */ |
| 22894 | { |
| 22895 | UA_TYPENAME("DeleteReferencesResponse") /* .typeName */ |
| 22896 | {0, UA_NODEIDTYPE_NUMERIC, {507LU}}, /* .typeId */ |
| 22897 | {0, UA_NODEIDTYPE_NUMERIC, {509LU}}, /* .binaryEncodingId */ |
| 22898 | sizeof(UA_DeleteReferencesResponse), /* .memSize */ |
| 22899 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22900 | false, /* .pointerFree */ |
| 22901 | false, /* .overlayable */ |
| 22902 | 3, /* .membersSize */ |
| 22903 | DeleteReferencesResponse_members /* .members */ |
| 22904 | }, |
| 22905 | /* AttributeWriteMask */ |
| 22906 | { |
| 22907 | UA_TYPENAME("AttributeWriteMask") /* .typeName */ |
| 22908 | {0, UA_NODEIDTYPE_NUMERIC, {347LU}}, /* .typeId */ |
| 22909 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22910 | sizeof(UA_AttributeWriteMask), /* .memSize */ |
| 22911 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 22912 | true, /* .pointerFree */ |
| 22913 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 22914 | 0, /* .membersSize */ |
| 22915 | AttributeWriteMask_members /* .members */ |
| 22916 | }, |
| 22917 | /* BrowseDirection */ |
| 22918 | { |
| 22919 | UA_TYPENAME("BrowseDirection") /* .typeName */ |
| 22920 | {0, UA_NODEIDTYPE_NUMERIC, {510LU}}, /* .typeId */ |
| 22921 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22922 | sizeof(UA_BrowseDirection), /* .memSize */ |
| 22923 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 22924 | true, /* .pointerFree */ |
| 22925 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 22926 | 0, /* .membersSize */ |
| 22927 | BrowseDirection_members /* .members */ |
| 22928 | }, |
| 22929 | /* ViewDescription */ |
| 22930 | { |
| 22931 | UA_TYPENAME("ViewDescription") /* .typeName */ |
| 22932 | {0, UA_NODEIDTYPE_NUMERIC, {511LU}}, /* .typeId */ |
| 22933 | {0, UA_NODEIDTYPE_NUMERIC, {513LU}}, /* .binaryEncodingId */ |
| 22934 | sizeof(UA_ViewDescription), /* .memSize */ |
| 22935 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22936 | false, /* .pointerFree */ |
| 22937 | false, /* .overlayable */ |
| 22938 | 3, /* .membersSize */ |
| 22939 | ViewDescription_members /* .members */ |
| 22940 | }, |
| 22941 | /* BrowseDescription */ |
| 22942 | { |
| 22943 | UA_TYPENAME("BrowseDescription") /* .typeName */ |
| 22944 | {0, UA_NODEIDTYPE_NUMERIC, {514LU}}, /* .typeId */ |
| 22945 | {0, UA_NODEIDTYPE_NUMERIC, {516LU}}, /* .binaryEncodingId */ |
| 22946 | sizeof(UA_BrowseDescription), /* .memSize */ |
| 22947 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22948 | false, /* .pointerFree */ |
| 22949 | false, /* .overlayable */ |
| 22950 | 6, /* .membersSize */ |
| 22951 | BrowseDescription_members /* .members */ |
| 22952 | }, |
| 22953 | /* BrowseResultMask */ |
| 22954 | { |
| 22955 | UA_TYPENAME("BrowseResultMask") /* .typeName */ |
| 22956 | {0, UA_NODEIDTYPE_NUMERIC, {517LU}}, /* .typeId */ |
| 22957 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22958 | sizeof(UA_BrowseResultMask), /* .memSize */ |
| 22959 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 22960 | true, /* .pointerFree */ |
| 22961 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 22962 | 0, /* .membersSize */ |
| 22963 | BrowseResultMask_members /* .members */ |
| 22964 | }, |
| 22965 | /* ReferenceDescription */ |
| 22966 | { |
| 22967 | UA_TYPENAME("ReferenceDescription") /* .typeName */ |
| 22968 | {0, UA_NODEIDTYPE_NUMERIC, {518LU}}, /* .typeId */ |
| 22969 | {0, UA_NODEIDTYPE_NUMERIC, {520LU}}, /* .binaryEncodingId */ |
| 22970 | sizeof(UA_ReferenceDescription), /* .memSize */ |
| 22971 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22972 | false, /* .pointerFree */ |
| 22973 | false, /* .overlayable */ |
| 22974 | 7, /* .membersSize */ |
| 22975 | ReferenceDescription_members /* .members */ |
| 22976 | }, |
| 22977 | /* ContinuationPoint */ |
| 22978 | { |
| 22979 | UA_TYPENAME("ContinuationPoint") /* .typeName */ |
| 22980 | {0, UA_NODEIDTYPE_NUMERIC, {521LU}}, /* .typeId */ |
| 22981 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 22982 | sizeof(UA_ContinuationPoint), /* .memSize */ |
| 22983 | UA_DATATYPEKIND_BYTESTRING, /* .typeKind */ |
| 22984 | false, /* .pointerFree */ |
| 22985 | false, /* .overlayable */ |
| 22986 | 0, /* .membersSize */ |
| 22987 | ContinuationPoint_members /* .members */ |
| 22988 | }, |
| 22989 | /* BrowseResult */ |
| 22990 | { |
| 22991 | UA_TYPENAME("BrowseResult") /* .typeName */ |
| 22992 | {0, UA_NODEIDTYPE_NUMERIC, {522LU}}, /* .typeId */ |
| 22993 | {0, UA_NODEIDTYPE_NUMERIC, {524LU}}, /* .binaryEncodingId */ |
| 22994 | sizeof(UA_BrowseResult), /* .memSize */ |
| 22995 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 22996 | false, /* .pointerFree */ |
| 22997 | false, /* .overlayable */ |
| 22998 | 3, /* .membersSize */ |
| 22999 | BrowseResult_members /* .members */ |
| 23000 | }, |
| 23001 | /* BrowseRequest */ |
| 23002 | { |
| 23003 | UA_TYPENAME("BrowseRequest") /* .typeName */ |
| 23004 | {0, UA_NODEIDTYPE_NUMERIC, {525LU}}, /* .typeId */ |
| 23005 | {0, UA_NODEIDTYPE_NUMERIC, {527LU}}, /* .binaryEncodingId */ |
| 23006 | sizeof(UA_BrowseRequest), /* .memSize */ |
| 23007 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23008 | false, /* .pointerFree */ |
| 23009 | false, /* .overlayable */ |
| 23010 | 4, /* .membersSize */ |
| 23011 | BrowseRequest_members /* .members */ |
| 23012 | }, |
| 23013 | /* BrowseResponse */ |
| 23014 | { |
| 23015 | UA_TYPENAME("BrowseResponse") /* .typeName */ |
| 23016 | {0, UA_NODEIDTYPE_NUMERIC, {528LU}}, /* .typeId */ |
| 23017 | {0, UA_NODEIDTYPE_NUMERIC, {530LU}}, /* .binaryEncodingId */ |
| 23018 | sizeof(UA_BrowseResponse), /* .memSize */ |
| 23019 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23020 | false, /* .pointerFree */ |
| 23021 | false, /* .overlayable */ |
| 23022 | 3, /* .membersSize */ |
| 23023 | BrowseResponse_members /* .members */ |
| 23024 | }, |
| 23025 | /* BrowseNextRequest */ |
| 23026 | { |
| 23027 | UA_TYPENAME("BrowseNextRequest") /* .typeName */ |
| 23028 | {0, UA_NODEIDTYPE_NUMERIC, {531LU}}, /* .typeId */ |
| 23029 | {0, UA_NODEIDTYPE_NUMERIC, {533LU}}, /* .binaryEncodingId */ |
| 23030 | sizeof(UA_BrowseNextRequest), /* .memSize */ |
| 23031 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23032 | false, /* .pointerFree */ |
| 23033 | false, /* .overlayable */ |
| 23034 | 3, /* .membersSize */ |
| 23035 | BrowseNextRequest_members /* .members */ |
| 23036 | }, |
| 23037 | /* BrowseNextResponse */ |
| 23038 | { |
| 23039 | UA_TYPENAME("BrowseNextResponse") /* .typeName */ |
| 23040 | {0, UA_NODEIDTYPE_NUMERIC, {534LU}}, /* .typeId */ |
| 23041 | {0, UA_NODEIDTYPE_NUMERIC, {536LU}}, /* .binaryEncodingId */ |
| 23042 | sizeof(UA_BrowseNextResponse), /* .memSize */ |
| 23043 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23044 | false, /* .pointerFree */ |
| 23045 | false, /* .overlayable */ |
| 23046 | 3, /* .membersSize */ |
| 23047 | BrowseNextResponse_members /* .members */ |
| 23048 | }, |
| 23049 | /* RelativePathElement */ |
| 23050 | { |
| 23051 | UA_TYPENAME("RelativePathElement") /* .typeName */ |
| 23052 | {0, UA_NODEIDTYPE_NUMERIC, {537LU}}, /* .typeId */ |
| 23053 | {0, UA_NODEIDTYPE_NUMERIC, {539LU}}, /* .binaryEncodingId */ |
| 23054 | sizeof(UA_RelativePathElement), /* .memSize */ |
| 23055 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23056 | false, /* .pointerFree */ |
| 23057 | false, /* .overlayable */ |
| 23058 | 4, /* .membersSize */ |
| 23059 | RelativePathElement_members /* .members */ |
| 23060 | }, |
| 23061 | /* RelativePath */ |
| 23062 | { |
| 23063 | UA_TYPENAME("RelativePath") /* .typeName */ |
| 23064 | {0, UA_NODEIDTYPE_NUMERIC, {540LU}}, /* .typeId */ |
| 23065 | {0, UA_NODEIDTYPE_NUMERIC, {542LU}}, /* .binaryEncodingId */ |
| 23066 | sizeof(UA_RelativePath), /* .memSize */ |
| 23067 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23068 | false, /* .pointerFree */ |
| 23069 | false, /* .overlayable */ |
| 23070 | 1, /* .membersSize */ |
| 23071 | RelativePath_members /* .members */ |
| 23072 | }, |
| 23073 | /* BrowsePath */ |
| 23074 | { |
| 23075 | UA_TYPENAME("BrowsePath") /* .typeName */ |
| 23076 | {0, UA_NODEIDTYPE_NUMERIC, {543LU}}, /* .typeId */ |
| 23077 | {0, UA_NODEIDTYPE_NUMERIC, {545LU}}, /* .binaryEncodingId */ |
| 23078 | sizeof(UA_BrowsePath), /* .memSize */ |
| 23079 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23080 | false, /* .pointerFree */ |
| 23081 | false, /* .overlayable */ |
| 23082 | 2, /* .membersSize */ |
| 23083 | BrowsePath_members /* .members */ |
| 23084 | }, |
| 23085 | /* BrowsePathTarget */ |
| 23086 | { |
| 23087 | UA_TYPENAME("BrowsePathTarget") /* .typeName */ |
| 23088 | {0, UA_NODEIDTYPE_NUMERIC, {546LU}}, /* .typeId */ |
| 23089 | {0, UA_NODEIDTYPE_NUMERIC, {548LU}}, /* .binaryEncodingId */ |
| 23090 | sizeof(UA_BrowsePathTarget), /* .memSize */ |
| 23091 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23092 | false, /* .pointerFree */ |
| 23093 | false, /* .overlayable */ |
| 23094 | 2, /* .membersSize */ |
| 23095 | BrowsePathTarget_members /* .members */ |
| 23096 | }, |
| 23097 | /* BrowsePathResult */ |
| 23098 | { |
| 23099 | UA_TYPENAME("BrowsePathResult") /* .typeName */ |
| 23100 | {0, UA_NODEIDTYPE_NUMERIC, {549LU}}, /* .typeId */ |
| 23101 | {0, UA_NODEIDTYPE_NUMERIC, {551LU}}, /* .binaryEncodingId */ |
| 23102 | sizeof(UA_BrowsePathResult), /* .memSize */ |
| 23103 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23104 | false, /* .pointerFree */ |
| 23105 | false, /* .overlayable */ |
| 23106 | 2, /* .membersSize */ |
| 23107 | BrowsePathResult_members /* .members */ |
| 23108 | }, |
| 23109 | /* TranslateBrowsePathsToNodeIdsRequest */ |
| 23110 | { |
| 23111 | UA_TYPENAME("TranslateBrowsePathsToNodeIdsRequest") /* .typeName */ |
| 23112 | {0, UA_NODEIDTYPE_NUMERIC, {552LU}}, /* .typeId */ |
| 23113 | {0, UA_NODEIDTYPE_NUMERIC, {554LU}}, /* .binaryEncodingId */ |
| 23114 | sizeof(UA_TranslateBrowsePathsToNodeIdsRequest), /* .memSize */ |
| 23115 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23116 | false, /* .pointerFree */ |
| 23117 | false, /* .overlayable */ |
| 23118 | 2, /* .membersSize */ |
| 23119 | TranslateBrowsePathsToNodeIdsRequest_members /* .members */ |
| 23120 | }, |
| 23121 | /* TranslateBrowsePathsToNodeIdsResponse */ |
| 23122 | { |
| 23123 | UA_TYPENAME("TranslateBrowsePathsToNodeIdsResponse") /* .typeName */ |
| 23124 | {0, UA_NODEIDTYPE_NUMERIC, {555LU}}, /* .typeId */ |
| 23125 | {0, UA_NODEIDTYPE_NUMERIC, {557LU}}, /* .binaryEncodingId */ |
| 23126 | sizeof(UA_TranslateBrowsePathsToNodeIdsResponse), /* .memSize */ |
| 23127 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23128 | false, /* .pointerFree */ |
| 23129 | false, /* .overlayable */ |
| 23130 | 3, /* .membersSize */ |
| 23131 | TranslateBrowsePathsToNodeIdsResponse_members /* .members */ |
| 23132 | }, |
| 23133 | /* RegisterNodesRequest */ |
| 23134 | { |
| 23135 | UA_TYPENAME("RegisterNodesRequest") /* .typeName */ |
| 23136 | {0, UA_NODEIDTYPE_NUMERIC, {558LU}}, /* .typeId */ |
| 23137 | {0, UA_NODEIDTYPE_NUMERIC, {560LU}}, /* .binaryEncodingId */ |
| 23138 | sizeof(UA_RegisterNodesRequest), /* .memSize */ |
| 23139 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23140 | false, /* .pointerFree */ |
| 23141 | false, /* .overlayable */ |
| 23142 | 2, /* .membersSize */ |
| 23143 | RegisterNodesRequest_members /* .members */ |
| 23144 | }, |
| 23145 | /* RegisterNodesResponse */ |
| 23146 | { |
| 23147 | UA_TYPENAME("RegisterNodesResponse") /* .typeName */ |
| 23148 | {0, UA_NODEIDTYPE_NUMERIC, {561LU}}, /* .typeId */ |
| 23149 | {0, UA_NODEIDTYPE_NUMERIC, {563LU}}, /* .binaryEncodingId */ |
| 23150 | sizeof(UA_RegisterNodesResponse), /* .memSize */ |
| 23151 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23152 | false, /* .pointerFree */ |
| 23153 | false, /* .overlayable */ |
| 23154 | 2, /* .membersSize */ |
| 23155 | RegisterNodesResponse_members /* .members */ |
| 23156 | }, |
| 23157 | /* UnregisterNodesRequest */ |
| 23158 | { |
| 23159 | UA_TYPENAME("UnregisterNodesRequest") /* .typeName */ |
| 23160 | {0, UA_NODEIDTYPE_NUMERIC, {564LU}}, /* .typeId */ |
| 23161 | {0, UA_NODEIDTYPE_NUMERIC, {566LU}}, /* .binaryEncodingId */ |
| 23162 | sizeof(UA_UnregisterNodesRequest), /* .memSize */ |
| 23163 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23164 | false, /* .pointerFree */ |
| 23165 | false, /* .overlayable */ |
| 23166 | 2, /* .membersSize */ |
| 23167 | UnregisterNodesRequest_members /* .members */ |
| 23168 | }, |
| 23169 | /* UnregisterNodesResponse */ |
| 23170 | { |
| 23171 | UA_TYPENAME("UnregisterNodesResponse") /* .typeName */ |
| 23172 | {0, UA_NODEIDTYPE_NUMERIC, {567LU}}, /* .typeId */ |
| 23173 | {0, UA_NODEIDTYPE_NUMERIC, {569LU}}, /* .binaryEncodingId */ |
| 23174 | sizeof(UA_UnregisterNodesResponse), /* .memSize */ |
| 23175 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23176 | false, /* .pointerFree */ |
| 23177 | false, /* .overlayable */ |
| 23178 | 1, /* .membersSize */ |
| 23179 | UnregisterNodesResponse_members /* .members */ |
| 23180 | }, |
| 23181 | /* Counter */ |
| 23182 | { |
| 23183 | UA_TYPENAME("Counter") /* .typeName */ |
| 23184 | {0, UA_NODEIDTYPE_NUMERIC, {289LU}}, /* .typeId */ |
| 23185 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 23186 | sizeof(UA_Counter), /* .memSize */ |
| 23187 | UA_DATATYPEKIND_UINT32, /* .typeKind */ |
| 23188 | false, /* .pointerFree */ |
| 23189 | false, /* .overlayable */ |
| 23190 | 0, /* .membersSize */ |
| 23191 | Counter_members /* .members */ |
| 23192 | }, |
| 23193 | /* OpaqueNumericRange */ |
| 23194 | { |
| 23195 | UA_TYPENAME("OpaqueNumericRange") /* .typeName */ |
| 23196 | {0, UA_NODEIDTYPE_NUMERIC, {291LU}}, /* .typeId */ |
| 23197 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 23198 | sizeof(UA_OpaqueNumericRange), /* .memSize */ |
| 23199 | UA_DATATYPEKIND_STRING, /* .typeKind */ |
| 23200 | false, /* .pointerFree */ |
| 23201 | false, /* .overlayable */ |
| 23202 | 0, /* .membersSize */ |
| 23203 | OpaqueNumericRange_members /* .members */ |
| 23204 | }, |
| 23205 | /* EndpointConfiguration */ |
| 23206 | { |
| 23207 | UA_TYPENAME("EndpointConfiguration") /* .typeName */ |
| 23208 | {0, UA_NODEIDTYPE_NUMERIC, {331LU}}, /* .typeId */ |
| 23209 | {0, UA_NODEIDTYPE_NUMERIC, {333LU}}, /* .binaryEncodingId */ |
| 23210 | sizeof(UA_EndpointConfiguration), /* .memSize */ |
| 23211 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23212 | true, /* .pointerFree */ |
| 23213 | false, /* .overlayable */ |
| 23214 | 9, /* .membersSize */ |
| 23215 | EndpointConfiguration_members /* .members */ |
| 23216 | }, |
| 23217 | /* QueryDataDescription */ |
| 23218 | { |
| 23219 | UA_TYPENAME("QueryDataDescription") /* .typeName */ |
| 23220 | {0, UA_NODEIDTYPE_NUMERIC, {570LU}}, /* .typeId */ |
| 23221 | {0, UA_NODEIDTYPE_NUMERIC, {572LU}}, /* .binaryEncodingId */ |
| 23222 | sizeof(UA_QueryDataDescription), /* .memSize */ |
| 23223 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23224 | false, /* .pointerFree */ |
| 23225 | false, /* .overlayable */ |
| 23226 | 3, /* .membersSize */ |
| 23227 | QueryDataDescription_members /* .members */ |
| 23228 | }, |
| 23229 | /* NodeTypeDescription */ |
| 23230 | { |
| 23231 | UA_TYPENAME("NodeTypeDescription") /* .typeName */ |
| 23232 | {0, UA_NODEIDTYPE_NUMERIC, {573LU}}, /* .typeId */ |
| 23233 | {0, UA_NODEIDTYPE_NUMERIC, {575LU}}, /* .binaryEncodingId */ |
| 23234 | sizeof(UA_NodeTypeDescription), /* .memSize */ |
| 23235 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23236 | false, /* .pointerFree */ |
| 23237 | false, /* .overlayable */ |
| 23238 | 3, /* .membersSize */ |
| 23239 | NodeTypeDescription_members /* .members */ |
| 23240 | }, |
| 23241 | /* FilterOperator */ |
| 23242 | { |
| 23243 | UA_TYPENAME("FilterOperator") /* .typeName */ |
| 23244 | {0, UA_NODEIDTYPE_NUMERIC, {576LU}}, /* .typeId */ |
| 23245 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 23246 | sizeof(UA_FilterOperator), /* .memSize */ |
| 23247 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 23248 | true, /* .pointerFree */ |
| 23249 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 23250 | 0, /* .membersSize */ |
| 23251 | FilterOperator_members /* .members */ |
| 23252 | }, |
| 23253 | /* QueryDataSet */ |
| 23254 | { |
| 23255 | UA_TYPENAME("QueryDataSet") /* .typeName */ |
| 23256 | {0, UA_NODEIDTYPE_NUMERIC, {577LU}}, /* .typeId */ |
| 23257 | {0, UA_NODEIDTYPE_NUMERIC, {579LU}}, /* .binaryEncodingId */ |
| 23258 | sizeof(UA_QueryDataSet), /* .memSize */ |
| 23259 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23260 | false, /* .pointerFree */ |
| 23261 | false, /* .overlayable */ |
| 23262 | 3, /* .membersSize */ |
| 23263 | QueryDataSet_members /* .members */ |
| 23264 | }, |
| 23265 | /* NodeReference */ |
| 23266 | { |
| 23267 | UA_TYPENAME("NodeReference") /* .typeName */ |
| 23268 | {0, UA_NODEIDTYPE_NUMERIC, {580LU}}, /* .typeId */ |
| 23269 | {0, UA_NODEIDTYPE_NUMERIC, {582LU}}, /* .binaryEncodingId */ |
| 23270 | sizeof(UA_NodeReference), /* .memSize */ |
| 23271 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23272 | false, /* .pointerFree */ |
| 23273 | false, /* .overlayable */ |
| 23274 | 4, /* .membersSize */ |
| 23275 | NodeReference_members /* .members */ |
| 23276 | }, |
| 23277 | /* ContentFilterElement */ |
| 23278 | { |
| 23279 | UA_TYPENAME("ContentFilterElement") /* .typeName */ |
| 23280 | {0, UA_NODEIDTYPE_NUMERIC, {583LU}}, /* .typeId */ |
| 23281 | {0, UA_NODEIDTYPE_NUMERIC, {585LU}}, /* .binaryEncodingId */ |
| 23282 | sizeof(UA_ContentFilterElement), /* .memSize */ |
| 23283 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23284 | false, /* .pointerFree */ |
| 23285 | false, /* .overlayable */ |
| 23286 | 2, /* .membersSize */ |
| 23287 | ContentFilterElement_members /* .members */ |
| 23288 | }, |
| 23289 | /* ContentFilter */ |
| 23290 | { |
| 23291 | UA_TYPENAME("ContentFilter") /* .typeName */ |
| 23292 | {0, UA_NODEIDTYPE_NUMERIC, {586LU}}, /* .typeId */ |
| 23293 | {0, UA_NODEIDTYPE_NUMERIC, {588LU}}, /* .binaryEncodingId */ |
| 23294 | sizeof(UA_ContentFilter), /* .memSize */ |
| 23295 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23296 | false, /* .pointerFree */ |
| 23297 | false, /* .overlayable */ |
| 23298 | 1, /* .membersSize */ |
| 23299 | ContentFilter_members /* .members */ |
| 23300 | }, |
| 23301 | /* ElementOperand */ |
| 23302 | { |
| 23303 | UA_TYPENAME("ElementOperand") /* .typeName */ |
| 23304 | {0, UA_NODEIDTYPE_NUMERIC, {592LU}}, /* .typeId */ |
| 23305 | {0, UA_NODEIDTYPE_NUMERIC, {594LU}}, /* .binaryEncodingId */ |
| 23306 | sizeof(UA_ElementOperand), /* .memSize */ |
| 23307 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23308 | true, /* .pointerFree */ |
| 23309 | false, /* .overlayable */ |
| 23310 | 1, /* .membersSize */ |
| 23311 | ElementOperand_members /* .members */ |
| 23312 | }, |
| 23313 | /* LiteralOperand */ |
| 23314 | { |
| 23315 | UA_TYPENAME("LiteralOperand") /* .typeName */ |
| 23316 | {0, UA_NODEIDTYPE_NUMERIC, {595LU}}, /* .typeId */ |
| 23317 | {0, UA_NODEIDTYPE_NUMERIC, {597LU}}, /* .binaryEncodingId */ |
| 23318 | sizeof(UA_LiteralOperand), /* .memSize */ |
| 23319 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23320 | false, /* .pointerFree */ |
| 23321 | false, /* .overlayable */ |
| 23322 | 1, /* .membersSize */ |
| 23323 | LiteralOperand_members /* .members */ |
| 23324 | }, |
| 23325 | /* AttributeOperand */ |
| 23326 | { |
| 23327 | UA_TYPENAME("AttributeOperand") /* .typeName */ |
| 23328 | {0, UA_NODEIDTYPE_NUMERIC, {598LU}}, /* .typeId */ |
| 23329 | {0, UA_NODEIDTYPE_NUMERIC, {600LU}}, /* .binaryEncodingId */ |
| 23330 | sizeof(UA_AttributeOperand), /* .memSize */ |
| 23331 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23332 | false, /* .pointerFree */ |
| 23333 | false, /* .overlayable */ |
| 23334 | 5, /* .membersSize */ |
| 23335 | AttributeOperand_members /* .members */ |
| 23336 | }, |
| 23337 | /* SimpleAttributeOperand */ |
| 23338 | { |
| 23339 | UA_TYPENAME("SimpleAttributeOperand") /* .typeName */ |
| 23340 | {0, UA_NODEIDTYPE_NUMERIC, {601LU}}, /* .typeId */ |
| 23341 | {0, UA_NODEIDTYPE_NUMERIC, {603LU}}, /* .binaryEncodingId */ |
| 23342 | sizeof(UA_SimpleAttributeOperand), /* .memSize */ |
| 23343 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23344 | false, /* .pointerFree */ |
| 23345 | false, /* .overlayable */ |
| 23346 | 4, /* .membersSize */ |
| 23347 | SimpleAttributeOperand_members /* .members */ |
| 23348 | }, |
| 23349 | /* ContentFilterElementResult */ |
| 23350 | { |
| 23351 | UA_TYPENAME("ContentFilterElementResult") /* .typeName */ |
| 23352 | {0, UA_NODEIDTYPE_NUMERIC, {604LU}}, /* .typeId */ |
| 23353 | {0, UA_NODEIDTYPE_NUMERIC, {606LU}}, /* .binaryEncodingId */ |
| 23354 | sizeof(UA_ContentFilterElementResult), /* .memSize */ |
| 23355 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23356 | false, /* .pointerFree */ |
| 23357 | false, /* .overlayable */ |
| 23358 | 3, /* .membersSize */ |
| 23359 | ContentFilterElementResult_members /* .members */ |
| 23360 | }, |
| 23361 | /* ContentFilterResult */ |
| 23362 | { |
| 23363 | UA_TYPENAME("ContentFilterResult") /* .typeName */ |
| 23364 | {0, UA_NODEIDTYPE_NUMERIC, {607LU}}, /* .typeId */ |
| 23365 | {0, UA_NODEIDTYPE_NUMERIC, {609LU}}, /* .binaryEncodingId */ |
| 23366 | sizeof(UA_ContentFilterResult), /* .memSize */ |
| 23367 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23368 | false, /* .pointerFree */ |
| 23369 | false, /* .overlayable */ |
| 23370 | 2, /* .membersSize */ |
| 23371 | ContentFilterResult_members /* .members */ |
| 23372 | }, |
| 23373 | /* ParsingResult */ |
| 23374 | { |
| 23375 | UA_TYPENAME("ParsingResult") /* .typeName */ |
| 23376 | {0, UA_NODEIDTYPE_NUMERIC, {610LU}}, /* .typeId */ |
| 23377 | {0, UA_NODEIDTYPE_NUMERIC, {612LU}}, /* .binaryEncodingId */ |
| 23378 | sizeof(UA_ParsingResult), /* .memSize */ |
| 23379 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23380 | false, /* .pointerFree */ |
| 23381 | false, /* .overlayable */ |
| 23382 | 3, /* .membersSize */ |
| 23383 | ParsingResult_members /* .members */ |
| 23384 | }, |
| 23385 | /* QueryFirstRequest */ |
| 23386 | { |
| 23387 | UA_TYPENAME("QueryFirstRequest") /* .typeName */ |
| 23388 | {0, UA_NODEIDTYPE_NUMERIC, {613LU}}, /* .typeId */ |
| 23389 | {0, UA_NODEIDTYPE_NUMERIC, {615LU}}, /* .binaryEncodingId */ |
| 23390 | sizeof(UA_QueryFirstRequest), /* .memSize */ |
| 23391 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23392 | false, /* .pointerFree */ |
| 23393 | false, /* .overlayable */ |
| 23394 | 6, /* .membersSize */ |
| 23395 | QueryFirstRequest_members /* .members */ |
| 23396 | }, |
| 23397 | /* QueryFirstResponse */ |
| 23398 | { |
| 23399 | UA_TYPENAME("QueryFirstResponse") /* .typeName */ |
| 23400 | {0, UA_NODEIDTYPE_NUMERIC, {616LU}}, /* .typeId */ |
| 23401 | {0, UA_NODEIDTYPE_NUMERIC, {618LU}}, /* .binaryEncodingId */ |
| 23402 | sizeof(UA_QueryFirstResponse), /* .memSize */ |
| 23403 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23404 | false, /* .pointerFree */ |
| 23405 | false, /* .overlayable */ |
| 23406 | 6, /* .membersSize */ |
| 23407 | QueryFirstResponse_members /* .members */ |
| 23408 | }, |
| 23409 | /* QueryNextRequest */ |
| 23410 | { |
| 23411 | UA_TYPENAME("QueryNextRequest") /* .typeName */ |
| 23412 | {0, UA_NODEIDTYPE_NUMERIC, {619LU}}, /* .typeId */ |
| 23413 | {0, UA_NODEIDTYPE_NUMERIC, {621LU}}, /* .binaryEncodingId */ |
| 23414 | sizeof(UA_QueryNextRequest), /* .memSize */ |
| 23415 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23416 | false, /* .pointerFree */ |
| 23417 | false, /* .overlayable */ |
| 23418 | 3, /* .membersSize */ |
| 23419 | QueryNextRequest_members /* .members */ |
| 23420 | }, |
| 23421 | /* QueryNextResponse */ |
| 23422 | { |
| 23423 | UA_TYPENAME("QueryNextResponse") /* .typeName */ |
| 23424 | {0, UA_NODEIDTYPE_NUMERIC, {622LU}}, /* .typeId */ |
| 23425 | {0, UA_NODEIDTYPE_NUMERIC, {624LU}}, /* .binaryEncodingId */ |
| 23426 | sizeof(UA_QueryNextResponse), /* .memSize */ |
| 23427 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23428 | false, /* .pointerFree */ |
| 23429 | false, /* .overlayable */ |
| 23430 | 3, /* .membersSize */ |
| 23431 | QueryNextResponse_members /* .members */ |
| 23432 | }, |
| 23433 | /* TimestampsToReturn */ |
| 23434 | { |
| 23435 | UA_TYPENAME("TimestampsToReturn") /* .typeName */ |
| 23436 | {0, UA_NODEIDTYPE_NUMERIC, {625LU}}, /* .typeId */ |
| 23437 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 23438 | sizeof(UA_TimestampsToReturn), /* .memSize */ |
| 23439 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 23440 | true, /* .pointerFree */ |
| 23441 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 23442 | 0, /* .membersSize */ |
| 23443 | TimestampsToReturn_members /* .members */ |
| 23444 | }, |
| 23445 | /* ReadValueId */ |
| 23446 | { |
| 23447 | UA_TYPENAME("ReadValueId") /* .typeName */ |
| 23448 | {0, UA_NODEIDTYPE_NUMERIC, {626LU}}, /* .typeId */ |
| 23449 | {0, UA_NODEIDTYPE_NUMERIC, {628LU}}, /* .binaryEncodingId */ |
| 23450 | sizeof(UA_ReadValueId), /* .memSize */ |
| 23451 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23452 | false, /* .pointerFree */ |
| 23453 | false, /* .overlayable */ |
| 23454 | 4, /* .membersSize */ |
| 23455 | ReadValueId_members /* .members */ |
| 23456 | }, |
| 23457 | /* ReadRequest */ |
| 23458 | { |
| 23459 | UA_TYPENAME("ReadRequest") /* .typeName */ |
| 23460 | {0, UA_NODEIDTYPE_NUMERIC, {629LU}}, /* .typeId */ |
| 23461 | {0, UA_NODEIDTYPE_NUMERIC, {631LU}}, /* .binaryEncodingId */ |
| 23462 | sizeof(UA_ReadRequest), /* .memSize */ |
| 23463 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23464 | false, /* .pointerFree */ |
| 23465 | false, /* .overlayable */ |
| 23466 | 4, /* .membersSize */ |
| 23467 | ReadRequest_members /* .members */ |
| 23468 | }, |
| 23469 | /* ReadResponse */ |
| 23470 | { |
| 23471 | UA_TYPENAME("ReadResponse") /* .typeName */ |
| 23472 | {0, UA_NODEIDTYPE_NUMERIC, {632LU}}, /* .typeId */ |
| 23473 | {0, UA_NODEIDTYPE_NUMERIC, {634LU}}, /* .binaryEncodingId */ |
| 23474 | sizeof(UA_ReadResponse), /* .memSize */ |
| 23475 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23476 | false, /* .pointerFree */ |
| 23477 | false, /* .overlayable */ |
| 23478 | 3, /* .membersSize */ |
| 23479 | ReadResponse_members /* .members */ |
| 23480 | }, |
| 23481 | /* HistoryReadValueId */ |
| 23482 | { |
| 23483 | UA_TYPENAME("HistoryReadValueId") /* .typeName */ |
| 23484 | {0, UA_NODEIDTYPE_NUMERIC, {635LU}}, /* .typeId */ |
| 23485 | {0, UA_NODEIDTYPE_NUMERIC, {637LU}}, /* .binaryEncodingId */ |
| 23486 | sizeof(UA_HistoryReadValueId), /* .memSize */ |
| 23487 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23488 | false, /* .pointerFree */ |
| 23489 | false, /* .overlayable */ |
| 23490 | 4, /* .membersSize */ |
| 23491 | HistoryReadValueId_members /* .members */ |
| 23492 | }, |
| 23493 | /* HistoryReadResult */ |
| 23494 | { |
| 23495 | UA_TYPENAME("HistoryReadResult") /* .typeName */ |
| 23496 | {0, UA_NODEIDTYPE_NUMERIC, {638LU}}, /* .typeId */ |
| 23497 | {0, UA_NODEIDTYPE_NUMERIC, {640LU}}, /* .binaryEncodingId */ |
| 23498 | sizeof(UA_HistoryReadResult), /* .memSize */ |
| 23499 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23500 | false, /* .pointerFree */ |
| 23501 | false, /* .overlayable */ |
| 23502 | 3, /* .membersSize */ |
| 23503 | HistoryReadResult_members /* .members */ |
| 23504 | }, |
| 23505 | /* ReadRawModifiedDetails */ |
| 23506 | { |
| 23507 | UA_TYPENAME("ReadRawModifiedDetails") /* .typeName */ |
| 23508 | {0, UA_NODEIDTYPE_NUMERIC, {647LU}}, /* .typeId */ |
| 23509 | {0, UA_NODEIDTYPE_NUMERIC, {649LU}}, /* .binaryEncodingId */ |
| 23510 | sizeof(UA_ReadRawModifiedDetails), /* .memSize */ |
| 23511 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23512 | true, /* .pointerFree */ |
| 23513 | false, /* .overlayable */ |
| 23514 | 5, /* .membersSize */ |
| 23515 | ReadRawModifiedDetails_members /* .members */ |
| 23516 | }, |
| 23517 | /* ReadAtTimeDetails */ |
| 23518 | { |
| 23519 | UA_TYPENAME("ReadAtTimeDetails") /* .typeName */ |
| 23520 | {0, UA_NODEIDTYPE_NUMERIC, {653LU}}, /* .typeId */ |
| 23521 | {0, UA_NODEIDTYPE_NUMERIC, {655LU}}, /* .binaryEncodingId */ |
| 23522 | sizeof(UA_ReadAtTimeDetails), /* .memSize */ |
| 23523 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23524 | false, /* .pointerFree */ |
| 23525 | false, /* .overlayable */ |
| 23526 | 2, /* .membersSize */ |
| 23527 | ReadAtTimeDetails_members /* .members */ |
| 23528 | }, |
| 23529 | /* ReadAnnotationDataDetails */ |
| 23530 | { |
| 23531 | UA_TYPENAME("ReadAnnotationDataDetails") /* .typeName */ |
| 23532 | {0, UA_NODEIDTYPE_NUMERIC, {23497LU}}, /* .typeId */ |
| 23533 | {0, UA_NODEIDTYPE_NUMERIC, {23500LU}}, /* .binaryEncodingId */ |
| 23534 | sizeof(UA_ReadAnnotationDataDetails), /* .memSize */ |
| 23535 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23536 | false, /* .pointerFree */ |
| 23537 | false, /* .overlayable */ |
| 23538 | 1, /* .membersSize */ |
| 23539 | ReadAnnotationDataDetails_members /* .members */ |
| 23540 | }, |
| 23541 | /* HistoryData */ |
| 23542 | { |
| 23543 | UA_TYPENAME("HistoryData") /* .typeName */ |
| 23544 | {0, UA_NODEIDTYPE_NUMERIC, {656LU}}, /* .typeId */ |
| 23545 | {0, UA_NODEIDTYPE_NUMERIC, {658LU}}, /* .binaryEncodingId */ |
| 23546 | sizeof(UA_HistoryData), /* .memSize */ |
| 23547 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23548 | false, /* .pointerFree */ |
| 23549 | false, /* .overlayable */ |
| 23550 | 1, /* .membersSize */ |
| 23551 | HistoryData_members /* .members */ |
| 23552 | }, |
| 23553 | /* HistoryReadRequest */ |
| 23554 | { |
| 23555 | UA_TYPENAME("HistoryReadRequest") /* .typeName */ |
| 23556 | {0, UA_NODEIDTYPE_NUMERIC, {662LU}}, /* .typeId */ |
| 23557 | {0, UA_NODEIDTYPE_NUMERIC, {664LU}}, /* .binaryEncodingId */ |
| 23558 | sizeof(UA_HistoryReadRequest), /* .memSize */ |
| 23559 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23560 | false, /* .pointerFree */ |
| 23561 | false, /* .overlayable */ |
| 23562 | 5, /* .membersSize */ |
| 23563 | HistoryReadRequest_members /* .members */ |
| 23564 | }, |
| 23565 | /* HistoryReadResponse */ |
| 23566 | { |
| 23567 | UA_TYPENAME("HistoryReadResponse") /* .typeName */ |
| 23568 | {0, UA_NODEIDTYPE_NUMERIC, {665LU}}, /* .typeId */ |
| 23569 | {0, UA_NODEIDTYPE_NUMERIC, {667LU}}, /* .binaryEncodingId */ |
| 23570 | sizeof(UA_HistoryReadResponse), /* .memSize */ |
| 23571 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23572 | false, /* .pointerFree */ |
| 23573 | false, /* .overlayable */ |
| 23574 | 3, /* .membersSize */ |
| 23575 | HistoryReadResponse_members /* .members */ |
| 23576 | }, |
| 23577 | /* WriteValue */ |
| 23578 | { |
| 23579 | UA_TYPENAME("WriteValue") /* .typeName */ |
| 23580 | {0, UA_NODEIDTYPE_NUMERIC, {668LU}}, /* .typeId */ |
| 23581 | {0, UA_NODEIDTYPE_NUMERIC, {670LU}}, /* .binaryEncodingId */ |
| 23582 | sizeof(UA_WriteValue), /* .memSize */ |
| 23583 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23584 | false, /* .pointerFree */ |
| 23585 | false, /* .overlayable */ |
| 23586 | 4, /* .membersSize */ |
| 23587 | WriteValue_members /* .members */ |
| 23588 | }, |
| 23589 | /* WriteRequest */ |
| 23590 | { |
| 23591 | UA_TYPENAME("WriteRequest") /* .typeName */ |
| 23592 | {0, UA_NODEIDTYPE_NUMERIC, {671LU}}, /* .typeId */ |
| 23593 | {0, UA_NODEIDTYPE_NUMERIC, {673LU}}, /* .binaryEncodingId */ |
| 23594 | sizeof(UA_WriteRequest), /* .memSize */ |
| 23595 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23596 | false, /* .pointerFree */ |
| 23597 | false, /* .overlayable */ |
| 23598 | 2, /* .membersSize */ |
| 23599 | WriteRequest_members /* .members */ |
| 23600 | }, |
| 23601 | /* WriteResponse */ |
| 23602 | { |
| 23603 | UA_TYPENAME("WriteResponse") /* .typeName */ |
| 23604 | {0, UA_NODEIDTYPE_NUMERIC, {674LU}}, /* .typeId */ |
| 23605 | {0, UA_NODEIDTYPE_NUMERIC, {676LU}}, /* .binaryEncodingId */ |
| 23606 | sizeof(UA_WriteResponse), /* .memSize */ |
| 23607 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23608 | false, /* .pointerFree */ |
| 23609 | false, /* .overlayable */ |
| 23610 | 3, /* .membersSize */ |
| 23611 | WriteResponse_members /* .members */ |
| 23612 | }, |
| 23613 | /* HistoryUpdateDetails */ |
| 23614 | { |
| 23615 | UA_TYPENAME("HistoryUpdateDetails") /* .typeName */ |
| 23616 | {0, UA_NODEIDTYPE_NUMERIC, {677LU}}, /* .typeId */ |
| 23617 | {0, UA_NODEIDTYPE_NUMERIC, {679LU}}, /* .binaryEncodingId */ |
| 23618 | sizeof(UA_HistoryUpdateDetails), /* .memSize */ |
| 23619 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23620 | false, /* .pointerFree */ |
| 23621 | false, /* .overlayable */ |
| 23622 | 1, /* .membersSize */ |
| 23623 | HistoryUpdateDetails_members /* .members */ |
| 23624 | }, |
| 23625 | /* HistoryUpdateType */ |
| 23626 | { |
| 23627 | UA_TYPENAME("HistoryUpdateType") /* .typeName */ |
| 23628 | {0, UA_NODEIDTYPE_NUMERIC, {11234LU}}, /* .typeId */ |
| 23629 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 23630 | sizeof(UA_HistoryUpdateType), /* .memSize */ |
| 23631 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 23632 | true, /* .pointerFree */ |
| 23633 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 23634 | 0, /* .membersSize */ |
| 23635 | HistoryUpdateType_members /* .members */ |
| 23636 | }, |
| 23637 | /* PerformUpdateType */ |
| 23638 | { |
| 23639 | UA_TYPENAME("PerformUpdateType") /* .typeName */ |
| 23640 | {0, UA_NODEIDTYPE_NUMERIC, {11293LU}}, /* .typeId */ |
| 23641 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 23642 | sizeof(UA_PerformUpdateType), /* .memSize */ |
| 23643 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 23644 | true, /* .pointerFree */ |
| 23645 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 23646 | 0, /* .membersSize */ |
| 23647 | PerformUpdateType_members /* .members */ |
| 23648 | }, |
| 23649 | /* UpdateDataDetails */ |
| 23650 | { |
| 23651 | UA_TYPENAME("UpdateDataDetails") /* .typeName */ |
| 23652 | {0, UA_NODEIDTYPE_NUMERIC, {680LU}}, /* .typeId */ |
| 23653 | {0, UA_NODEIDTYPE_NUMERIC, {682LU}}, /* .binaryEncodingId */ |
| 23654 | sizeof(UA_UpdateDataDetails), /* .memSize */ |
| 23655 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23656 | false, /* .pointerFree */ |
| 23657 | false, /* .overlayable */ |
| 23658 | 3, /* .membersSize */ |
| 23659 | UpdateDataDetails_members /* .members */ |
| 23660 | }, |
| 23661 | /* UpdateStructureDataDetails */ |
| 23662 | { |
| 23663 | UA_TYPENAME("UpdateStructureDataDetails") /* .typeName */ |
| 23664 | {0, UA_NODEIDTYPE_NUMERIC, {11295LU}}, /* .typeId */ |
| 23665 | {0, UA_NODEIDTYPE_NUMERIC, {11300LU}}, /* .binaryEncodingId */ |
| 23666 | sizeof(UA_UpdateStructureDataDetails), /* .memSize */ |
| 23667 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23668 | false, /* .pointerFree */ |
| 23669 | false, /* .overlayable */ |
| 23670 | 3, /* .membersSize */ |
| 23671 | UpdateStructureDataDetails_members /* .members */ |
| 23672 | }, |
| 23673 | /* DeleteRawModifiedDetails */ |
| 23674 | { |
| 23675 | UA_TYPENAME("DeleteRawModifiedDetails") /* .typeName */ |
| 23676 | {0, UA_NODEIDTYPE_NUMERIC, {686LU}}, /* .typeId */ |
| 23677 | {0, UA_NODEIDTYPE_NUMERIC, {688LU}}, /* .binaryEncodingId */ |
| 23678 | sizeof(UA_DeleteRawModifiedDetails), /* .memSize */ |
| 23679 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23680 | false, /* .pointerFree */ |
| 23681 | false, /* .overlayable */ |
| 23682 | 4, /* .membersSize */ |
| 23683 | DeleteRawModifiedDetails_members /* .members */ |
| 23684 | }, |
| 23685 | /* DeleteAtTimeDetails */ |
| 23686 | { |
| 23687 | UA_TYPENAME("DeleteAtTimeDetails") /* .typeName */ |
| 23688 | {0, UA_NODEIDTYPE_NUMERIC, {689LU}}, /* .typeId */ |
| 23689 | {0, UA_NODEIDTYPE_NUMERIC, {691LU}}, /* .binaryEncodingId */ |
| 23690 | sizeof(UA_DeleteAtTimeDetails), /* .memSize */ |
| 23691 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23692 | false, /* .pointerFree */ |
| 23693 | false, /* .overlayable */ |
| 23694 | 2, /* .membersSize */ |
| 23695 | DeleteAtTimeDetails_members /* .members */ |
| 23696 | }, |
| 23697 | /* DeleteEventDetails */ |
| 23698 | { |
| 23699 | UA_TYPENAME("DeleteEventDetails") /* .typeName */ |
| 23700 | {0, UA_NODEIDTYPE_NUMERIC, {692LU}}, /* .typeId */ |
| 23701 | {0, UA_NODEIDTYPE_NUMERIC, {694LU}}, /* .binaryEncodingId */ |
| 23702 | sizeof(UA_DeleteEventDetails), /* .memSize */ |
| 23703 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23704 | false, /* .pointerFree */ |
| 23705 | false, /* .overlayable */ |
| 23706 | 2, /* .membersSize */ |
| 23707 | DeleteEventDetails_members /* .members */ |
| 23708 | }, |
| 23709 | /* HistoryUpdateResult */ |
| 23710 | { |
| 23711 | UA_TYPENAME("HistoryUpdateResult") /* .typeName */ |
| 23712 | {0, UA_NODEIDTYPE_NUMERIC, {695LU}}, /* .typeId */ |
| 23713 | {0, UA_NODEIDTYPE_NUMERIC, {697LU}}, /* .binaryEncodingId */ |
| 23714 | sizeof(UA_HistoryUpdateResult), /* .memSize */ |
| 23715 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23716 | false, /* .pointerFree */ |
| 23717 | false, /* .overlayable */ |
| 23718 | 3, /* .membersSize */ |
| 23719 | HistoryUpdateResult_members /* .members */ |
| 23720 | }, |
| 23721 | /* HistoryUpdateRequest */ |
| 23722 | { |
| 23723 | UA_TYPENAME("HistoryUpdateRequest") /* .typeName */ |
| 23724 | {0, UA_NODEIDTYPE_NUMERIC, {698LU}}, /* .typeId */ |
| 23725 | {0, UA_NODEIDTYPE_NUMERIC, {700LU}}, /* .binaryEncodingId */ |
| 23726 | sizeof(UA_HistoryUpdateRequest), /* .memSize */ |
| 23727 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23728 | false, /* .pointerFree */ |
| 23729 | false, /* .overlayable */ |
| 23730 | 2, /* .membersSize */ |
| 23731 | HistoryUpdateRequest_members /* .members */ |
| 23732 | }, |
| 23733 | /* HistoryUpdateResponse */ |
| 23734 | { |
| 23735 | UA_TYPENAME("HistoryUpdateResponse") /* .typeName */ |
| 23736 | {0, UA_NODEIDTYPE_NUMERIC, {701LU}}, /* .typeId */ |
| 23737 | {0, UA_NODEIDTYPE_NUMERIC, {703LU}}, /* .binaryEncodingId */ |
| 23738 | sizeof(UA_HistoryUpdateResponse), /* .memSize */ |
| 23739 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23740 | false, /* .pointerFree */ |
| 23741 | false, /* .overlayable */ |
| 23742 | 3, /* .membersSize */ |
| 23743 | HistoryUpdateResponse_members /* .members */ |
| 23744 | }, |
| 23745 | /* CallMethodRequest */ |
| 23746 | { |
| 23747 | UA_TYPENAME("CallMethodRequest") /* .typeName */ |
| 23748 | {0, UA_NODEIDTYPE_NUMERIC, {704LU}}, /* .typeId */ |
| 23749 | {0, UA_NODEIDTYPE_NUMERIC, {706LU}}, /* .binaryEncodingId */ |
| 23750 | sizeof(UA_CallMethodRequest), /* .memSize */ |
| 23751 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23752 | false, /* .pointerFree */ |
| 23753 | false, /* .overlayable */ |
| 23754 | 3, /* .membersSize */ |
| 23755 | CallMethodRequest_members /* .members */ |
| 23756 | }, |
| 23757 | /* CallMethodResult */ |
| 23758 | { |
| 23759 | UA_TYPENAME("CallMethodResult") /* .typeName */ |
| 23760 | {0, UA_NODEIDTYPE_NUMERIC, {707LU}}, /* .typeId */ |
| 23761 | {0, UA_NODEIDTYPE_NUMERIC, {709LU}}, /* .binaryEncodingId */ |
| 23762 | sizeof(UA_CallMethodResult), /* .memSize */ |
| 23763 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23764 | false, /* .pointerFree */ |
| 23765 | false, /* .overlayable */ |
| 23766 | 4, /* .membersSize */ |
| 23767 | CallMethodResult_members /* .members */ |
| 23768 | }, |
| 23769 | /* CallRequest */ |
| 23770 | { |
| 23771 | UA_TYPENAME("CallRequest") /* .typeName */ |
| 23772 | {0, UA_NODEIDTYPE_NUMERIC, {710LU}}, /* .typeId */ |
| 23773 | {0, UA_NODEIDTYPE_NUMERIC, {712LU}}, /* .binaryEncodingId */ |
| 23774 | sizeof(UA_CallRequest), /* .memSize */ |
| 23775 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23776 | false, /* .pointerFree */ |
| 23777 | false, /* .overlayable */ |
| 23778 | 2, /* .membersSize */ |
| 23779 | CallRequest_members /* .members */ |
| 23780 | }, |
| 23781 | /* CallResponse */ |
| 23782 | { |
| 23783 | UA_TYPENAME("CallResponse") /* .typeName */ |
| 23784 | {0, UA_NODEIDTYPE_NUMERIC, {713LU}}, /* .typeId */ |
| 23785 | {0, UA_NODEIDTYPE_NUMERIC, {715LU}}, /* .binaryEncodingId */ |
| 23786 | sizeof(UA_CallResponse), /* .memSize */ |
| 23787 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23788 | false, /* .pointerFree */ |
| 23789 | false, /* .overlayable */ |
| 23790 | 3, /* .membersSize */ |
| 23791 | CallResponse_members /* .members */ |
| 23792 | }, |
| 23793 | /* MonitoringMode */ |
| 23794 | { |
| 23795 | UA_TYPENAME("MonitoringMode") /* .typeName */ |
| 23796 | {0, UA_NODEIDTYPE_NUMERIC, {716LU}}, /* .typeId */ |
| 23797 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 23798 | sizeof(UA_MonitoringMode), /* .memSize */ |
| 23799 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 23800 | true, /* .pointerFree */ |
| 23801 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 23802 | 0, /* .membersSize */ |
| 23803 | MonitoringMode_members /* .members */ |
| 23804 | }, |
| 23805 | /* DataChangeTrigger */ |
| 23806 | { |
| 23807 | UA_TYPENAME("DataChangeTrigger") /* .typeName */ |
| 23808 | {0, UA_NODEIDTYPE_NUMERIC, {717LU}}, /* .typeId */ |
| 23809 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 23810 | sizeof(UA_DataChangeTrigger), /* .memSize */ |
| 23811 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 23812 | true, /* .pointerFree */ |
| 23813 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 23814 | 0, /* .membersSize */ |
| 23815 | DataChangeTrigger_members /* .members */ |
| 23816 | }, |
| 23817 | /* DeadbandType */ |
| 23818 | { |
| 23819 | UA_TYPENAME("DeadbandType") /* .typeName */ |
| 23820 | {0, UA_NODEIDTYPE_NUMERIC, {718LU}}, /* .typeId */ |
| 23821 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 23822 | sizeof(UA_DeadbandType), /* .memSize */ |
| 23823 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 23824 | true, /* .pointerFree */ |
| 23825 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 23826 | 0, /* .membersSize */ |
| 23827 | DeadbandType_members /* .members */ |
| 23828 | }, |
| 23829 | /* DataChangeFilter */ |
| 23830 | { |
| 23831 | UA_TYPENAME("DataChangeFilter") /* .typeName */ |
| 23832 | {0, UA_NODEIDTYPE_NUMERIC, {722LU}}, /* .typeId */ |
| 23833 | {0, UA_NODEIDTYPE_NUMERIC, {724LU}}, /* .binaryEncodingId */ |
| 23834 | sizeof(UA_DataChangeFilter), /* .memSize */ |
| 23835 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23836 | true, /* .pointerFree */ |
| 23837 | false, /* .overlayable */ |
| 23838 | 3, /* .membersSize */ |
| 23839 | DataChangeFilter_members /* .members */ |
| 23840 | }, |
| 23841 | /* EventFilter */ |
| 23842 | { |
| 23843 | UA_TYPENAME("EventFilter") /* .typeName */ |
| 23844 | {0, UA_NODEIDTYPE_NUMERIC, {725LU}}, /* .typeId */ |
| 23845 | {0, UA_NODEIDTYPE_NUMERIC, {727LU}}, /* .binaryEncodingId */ |
| 23846 | sizeof(UA_EventFilter), /* .memSize */ |
| 23847 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23848 | false, /* .pointerFree */ |
| 23849 | false, /* .overlayable */ |
| 23850 | 2, /* .membersSize */ |
| 23851 | EventFilter_members /* .members */ |
| 23852 | }, |
| 23853 | /* AggregateConfiguration */ |
| 23854 | { |
| 23855 | UA_TYPENAME("AggregateConfiguration") /* .typeName */ |
| 23856 | {0, UA_NODEIDTYPE_NUMERIC, {948LU}}, /* .typeId */ |
| 23857 | {0, UA_NODEIDTYPE_NUMERIC, {950LU}}, /* .binaryEncodingId */ |
| 23858 | sizeof(UA_AggregateConfiguration), /* .memSize */ |
| 23859 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23860 | true, /* .pointerFree */ |
| 23861 | false, /* .overlayable */ |
| 23862 | 5, /* .membersSize */ |
| 23863 | AggregateConfiguration_members /* .members */ |
| 23864 | }, |
| 23865 | /* AggregateFilter */ |
| 23866 | { |
| 23867 | UA_TYPENAME("AggregateFilter") /* .typeName */ |
| 23868 | {0, UA_NODEIDTYPE_NUMERIC, {728LU}}, /* .typeId */ |
| 23869 | {0, UA_NODEIDTYPE_NUMERIC, {730LU}}, /* .binaryEncodingId */ |
| 23870 | sizeof(UA_AggregateFilter), /* .memSize */ |
| 23871 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23872 | false, /* .pointerFree */ |
| 23873 | false, /* .overlayable */ |
| 23874 | 4, /* .membersSize */ |
| 23875 | AggregateFilter_members /* .members */ |
| 23876 | }, |
| 23877 | /* EventFilterResult */ |
| 23878 | { |
| 23879 | UA_TYPENAME("EventFilterResult") /* .typeName */ |
| 23880 | {0, UA_NODEIDTYPE_NUMERIC, {734LU}}, /* .typeId */ |
| 23881 | {0, UA_NODEIDTYPE_NUMERIC, {736LU}}, /* .binaryEncodingId */ |
| 23882 | sizeof(UA_EventFilterResult), /* .memSize */ |
| 23883 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23884 | false, /* .pointerFree */ |
| 23885 | false, /* .overlayable */ |
| 23886 | 3, /* .membersSize */ |
| 23887 | EventFilterResult_members /* .members */ |
| 23888 | }, |
| 23889 | /* AggregateFilterResult */ |
| 23890 | { |
| 23891 | UA_TYPENAME("AggregateFilterResult") /* .typeName */ |
| 23892 | {0, UA_NODEIDTYPE_NUMERIC, {737LU}}, /* .typeId */ |
| 23893 | {0, UA_NODEIDTYPE_NUMERIC, {739LU}}, /* .binaryEncodingId */ |
| 23894 | sizeof(UA_AggregateFilterResult), /* .memSize */ |
| 23895 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23896 | true, /* .pointerFree */ |
| 23897 | false, /* .overlayable */ |
| 23898 | 3, /* .membersSize */ |
| 23899 | AggregateFilterResult_members /* .members */ |
| 23900 | }, |
| 23901 | /* MonitoringParameters */ |
| 23902 | { |
| 23903 | UA_TYPENAME("MonitoringParameters") /* .typeName */ |
| 23904 | {0, UA_NODEIDTYPE_NUMERIC, {740LU}}, /* .typeId */ |
| 23905 | {0, UA_NODEIDTYPE_NUMERIC, {742LU}}, /* .binaryEncodingId */ |
| 23906 | sizeof(UA_MonitoringParameters), /* .memSize */ |
| 23907 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23908 | false, /* .pointerFree */ |
| 23909 | false, /* .overlayable */ |
| 23910 | 5, /* .membersSize */ |
| 23911 | MonitoringParameters_members /* .members */ |
| 23912 | }, |
| 23913 | /* MonitoredItemCreateRequest */ |
| 23914 | { |
| 23915 | UA_TYPENAME("MonitoredItemCreateRequest") /* .typeName */ |
| 23916 | {0, UA_NODEIDTYPE_NUMERIC, {743LU}}, /* .typeId */ |
| 23917 | {0, UA_NODEIDTYPE_NUMERIC, {745LU}}, /* .binaryEncodingId */ |
| 23918 | sizeof(UA_MonitoredItemCreateRequest), /* .memSize */ |
| 23919 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23920 | false, /* .pointerFree */ |
| 23921 | false, /* .overlayable */ |
| 23922 | 3, /* .membersSize */ |
| 23923 | MonitoredItemCreateRequest_members /* .members */ |
| 23924 | }, |
| 23925 | /* MonitoredItemCreateResult */ |
| 23926 | { |
| 23927 | UA_TYPENAME("MonitoredItemCreateResult") /* .typeName */ |
| 23928 | {0, UA_NODEIDTYPE_NUMERIC, {746LU}}, /* .typeId */ |
| 23929 | {0, UA_NODEIDTYPE_NUMERIC, {748LU}}, /* .binaryEncodingId */ |
| 23930 | sizeof(UA_MonitoredItemCreateResult), /* .memSize */ |
| 23931 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23932 | false, /* .pointerFree */ |
| 23933 | false, /* .overlayable */ |
| 23934 | 5, /* .membersSize */ |
| 23935 | MonitoredItemCreateResult_members /* .members */ |
| 23936 | }, |
| 23937 | /* CreateMonitoredItemsRequest */ |
| 23938 | { |
| 23939 | UA_TYPENAME("CreateMonitoredItemsRequest") /* .typeName */ |
| 23940 | {0, UA_NODEIDTYPE_NUMERIC, {749LU}}, /* .typeId */ |
| 23941 | {0, UA_NODEIDTYPE_NUMERIC, {751LU}}, /* .binaryEncodingId */ |
| 23942 | sizeof(UA_CreateMonitoredItemsRequest), /* .memSize */ |
| 23943 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23944 | false, /* .pointerFree */ |
| 23945 | false, /* .overlayable */ |
| 23946 | 4, /* .membersSize */ |
| 23947 | CreateMonitoredItemsRequest_members /* .members */ |
| 23948 | }, |
| 23949 | /* CreateMonitoredItemsResponse */ |
| 23950 | { |
| 23951 | UA_TYPENAME("CreateMonitoredItemsResponse") /* .typeName */ |
| 23952 | {0, UA_NODEIDTYPE_NUMERIC, {752LU}}, /* .typeId */ |
| 23953 | {0, UA_NODEIDTYPE_NUMERIC, {754LU}}, /* .binaryEncodingId */ |
| 23954 | sizeof(UA_CreateMonitoredItemsResponse), /* .memSize */ |
| 23955 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23956 | false, /* .pointerFree */ |
| 23957 | false, /* .overlayable */ |
| 23958 | 3, /* .membersSize */ |
| 23959 | CreateMonitoredItemsResponse_members /* .members */ |
| 23960 | }, |
| 23961 | /* MonitoredItemModifyRequest */ |
| 23962 | { |
| 23963 | UA_TYPENAME("MonitoredItemModifyRequest") /* .typeName */ |
| 23964 | {0, UA_NODEIDTYPE_NUMERIC, {755LU}}, /* .typeId */ |
| 23965 | {0, UA_NODEIDTYPE_NUMERIC, {757LU}}, /* .binaryEncodingId */ |
| 23966 | sizeof(UA_MonitoredItemModifyRequest), /* .memSize */ |
| 23967 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23968 | false, /* .pointerFree */ |
| 23969 | false, /* .overlayable */ |
| 23970 | 2, /* .membersSize */ |
| 23971 | MonitoredItemModifyRequest_members /* .members */ |
| 23972 | }, |
| 23973 | /* MonitoredItemModifyResult */ |
| 23974 | { |
| 23975 | UA_TYPENAME("MonitoredItemModifyResult") /* .typeName */ |
| 23976 | {0, UA_NODEIDTYPE_NUMERIC, {758LU}}, /* .typeId */ |
| 23977 | {0, UA_NODEIDTYPE_NUMERIC, {760LU}}, /* .binaryEncodingId */ |
| 23978 | sizeof(UA_MonitoredItemModifyResult), /* .memSize */ |
| 23979 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23980 | false, /* .pointerFree */ |
| 23981 | false, /* .overlayable */ |
| 23982 | 4, /* .membersSize */ |
| 23983 | MonitoredItemModifyResult_members /* .members */ |
| 23984 | }, |
| 23985 | /* ModifyMonitoredItemsRequest */ |
| 23986 | { |
| 23987 | UA_TYPENAME("ModifyMonitoredItemsRequest") /* .typeName */ |
| 23988 | {0, UA_NODEIDTYPE_NUMERIC, {761LU}}, /* .typeId */ |
| 23989 | {0, UA_NODEIDTYPE_NUMERIC, {763LU}}, /* .binaryEncodingId */ |
| 23990 | sizeof(UA_ModifyMonitoredItemsRequest), /* .memSize */ |
| 23991 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 23992 | false, /* .pointerFree */ |
| 23993 | false, /* .overlayable */ |
| 23994 | 4, /* .membersSize */ |
| 23995 | ModifyMonitoredItemsRequest_members /* .members */ |
| 23996 | }, |
| 23997 | /* ModifyMonitoredItemsResponse */ |
| 23998 | { |
| 23999 | UA_TYPENAME("ModifyMonitoredItemsResponse") /* .typeName */ |
| 24000 | {0, UA_NODEIDTYPE_NUMERIC, {764LU}}, /* .typeId */ |
| 24001 | {0, UA_NODEIDTYPE_NUMERIC, {766LU}}, /* .binaryEncodingId */ |
| 24002 | sizeof(UA_ModifyMonitoredItemsResponse), /* .memSize */ |
| 24003 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24004 | false, /* .pointerFree */ |
| 24005 | false, /* .overlayable */ |
| 24006 | 3, /* .membersSize */ |
| 24007 | ModifyMonitoredItemsResponse_members /* .members */ |
| 24008 | }, |
| 24009 | /* SetMonitoringModeRequest */ |
| 24010 | { |
| 24011 | UA_TYPENAME("SetMonitoringModeRequest") /* .typeName */ |
| 24012 | {0, UA_NODEIDTYPE_NUMERIC, {767LU}}, /* .typeId */ |
| 24013 | {0, UA_NODEIDTYPE_NUMERIC, {769LU}}, /* .binaryEncodingId */ |
| 24014 | sizeof(UA_SetMonitoringModeRequest), /* .memSize */ |
| 24015 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24016 | false, /* .pointerFree */ |
| 24017 | false, /* .overlayable */ |
| 24018 | 4, /* .membersSize */ |
| 24019 | SetMonitoringModeRequest_members /* .members */ |
| 24020 | }, |
| 24021 | /* SetMonitoringModeResponse */ |
| 24022 | { |
| 24023 | UA_TYPENAME("SetMonitoringModeResponse") /* .typeName */ |
| 24024 | {0, UA_NODEIDTYPE_NUMERIC, {770LU}}, /* .typeId */ |
| 24025 | {0, UA_NODEIDTYPE_NUMERIC, {772LU}}, /* .binaryEncodingId */ |
| 24026 | sizeof(UA_SetMonitoringModeResponse), /* .memSize */ |
| 24027 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24028 | false, /* .pointerFree */ |
| 24029 | false, /* .overlayable */ |
| 24030 | 3, /* .membersSize */ |
| 24031 | SetMonitoringModeResponse_members /* .members */ |
| 24032 | }, |
| 24033 | /* SetTriggeringRequest */ |
| 24034 | { |
| 24035 | UA_TYPENAME("SetTriggeringRequest") /* .typeName */ |
| 24036 | {0, UA_NODEIDTYPE_NUMERIC, {773LU}}, /* .typeId */ |
| 24037 | {0, UA_NODEIDTYPE_NUMERIC, {775LU}}, /* .binaryEncodingId */ |
| 24038 | sizeof(UA_SetTriggeringRequest), /* .memSize */ |
| 24039 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24040 | false, /* .pointerFree */ |
| 24041 | false, /* .overlayable */ |
| 24042 | 5, /* .membersSize */ |
| 24043 | SetTriggeringRequest_members /* .members */ |
| 24044 | }, |
| 24045 | /* SetTriggeringResponse */ |
| 24046 | { |
| 24047 | UA_TYPENAME("SetTriggeringResponse") /* .typeName */ |
| 24048 | {0, UA_NODEIDTYPE_NUMERIC, {776LU}}, /* .typeId */ |
| 24049 | {0, UA_NODEIDTYPE_NUMERIC, {778LU}}, /* .binaryEncodingId */ |
| 24050 | sizeof(UA_SetTriggeringResponse), /* .memSize */ |
| 24051 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24052 | false, /* .pointerFree */ |
| 24053 | false, /* .overlayable */ |
| 24054 | 5, /* .membersSize */ |
| 24055 | SetTriggeringResponse_members /* .members */ |
| 24056 | }, |
| 24057 | /* DeleteMonitoredItemsRequest */ |
| 24058 | { |
| 24059 | UA_TYPENAME("DeleteMonitoredItemsRequest") /* .typeName */ |
| 24060 | {0, UA_NODEIDTYPE_NUMERIC, {779LU}}, /* .typeId */ |
| 24061 | {0, UA_NODEIDTYPE_NUMERIC, {781LU}}, /* .binaryEncodingId */ |
| 24062 | sizeof(UA_DeleteMonitoredItemsRequest), /* .memSize */ |
| 24063 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24064 | false, /* .pointerFree */ |
| 24065 | false, /* .overlayable */ |
| 24066 | 3, /* .membersSize */ |
| 24067 | DeleteMonitoredItemsRequest_members /* .members */ |
| 24068 | }, |
| 24069 | /* DeleteMonitoredItemsResponse */ |
| 24070 | { |
| 24071 | UA_TYPENAME("DeleteMonitoredItemsResponse") /* .typeName */ |
| 24072 | {0, UA_NODEIDTYPE_NUMERIC, {782LU}}, /* .typeId */ |
| 24073 | {0, UA_NODEIDTYPE_NUMERIC, {784LU}}, /* .binaryEncodingId */ |
| 24074 | sizeof(UA_DeleteMonitoredItemsResponse), /* .memSize */ |
| 24075 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24076 | false, /* .pointerFree */ |
| 24077 | false, /* .overlayable */ |
| 24078 | 3, /* .membersSize */ |
| 24079 | DeleteMonitoredItemsResponse_members /* .members */ |
| 24080 | }, |
| 24081 | /* CreateSubscriptionRequest */ |
| 24082 | { |
| 24083 | UA_TYPENAME("CreateSubscriptionRequest") /* .typeName */ |
| 24084 | {0, UA_NODEIDTYPE_NUMERIC, {785LU}}, /* .typeId */ |
| 24085 | {0, UA_NODEIDTYPE_NUMERIC, {787LU}}, /* .binaryEncodingId */ |
| 24086 | sizeof(UA_CreateSubscriptionRequest), /* .memSize */ |
| 24087 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24088 | false, /* .pointerFree */ |
| 24089 | false, /* .overlayable */ |
| 24090 | 7, /* .membersSize */ |
| 24091 | CreateSubscriptionRequest_members /* .members */ |
| 24092 | }, |
| 24093 | /* CreateSubscriptionResponse */ |
| 24094 | { |
| 24095 | UA_TYPENAME("CreateSubscriptionResponse") /* .typeName */ |
| 24096 | {0, UA_NODEIDTYPE_NUMERIC, {788LU}}, /* .typeId */ |
| 24097 | {0, UA_NODEIDTYPE_NUMERIC, {790LU}}, /* .binaryEncodingId */ |
| 24098 | sizeof(UA_CreateSubscriptionResponse), /* .memSize */ |
| 24099 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24100 | false, /* .pointerFree */ |
| 24101 | false, /* .overlayable */ |
| 24102 | 5, /* .membersSize */ |
| 24103 | CreateSubscriptionResponse_members /* .members */ |
| 24104 | }, |
| 24105 | /* ModifySubscriptionRequest */ |
| 24106 | { |
| 24107 | UA_TYPENAME("ModifySubscriptionRequest") /* .typeName */ |
| 24108 | {0, UA_NODEIDTYPE_NUMERIC, {791LU}}, /* .typeId */ |
| 24109 | {0, UA_NODEIDTYPE_NUMERIC, {793LU}}, /* .binaryEncodingId */ |
| 24110 | sizeof(UA_ModifySubscriptionRequest), /* .memSize */ |
| 24111 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24112 | false, /* .pointerFree */ |
| 24113 | false, /* .overlayable */ |
| 24114 | 7, /* .membersSize */ |
| 24115 | ModifySubscriptionRequest_members /* .members */ |
| 24116 | }, |
| 24117 | /* ModifySubscriptionResponse */ |
| 24118 | { |
| 24119 | UA_TYPENAME("ModifySubscriptionResponse") /* .typeName */ |
| 24120 | {0, UA_NODEIDTYPE_NUMERIC, {794LU}}, /* .typeId */ |
| 24121 | {0, UA_NODEIDTYPE_NUMERIC, {796LU}}, /* .binaryEncodingId */ |
| 24122 | sizeof(UA_ModifySubscriptionResponse), /* .memSize */ |
| 24123 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24124 | false, /* .pointerFree */ |
| 24125 | false, /* .overlayable */ |
| 24126 | 4, /* .membersSize */ |
| 24127 | ModifySubscriptionResponse_members /* .members */ |
| 24128 | }, |
| 24129 | /* SetPublishingModeRequest */ |
| 24130 | { |
| 24131 | UA_TYPENAME("SetPublishingModeRequest") /* .typeName */ |
| 24132 | {0, UA_NODEIDTYPE_NUMERIC, {797LU}}, /* .typeId */ |
| 24133 | {0, UA_NODEIDTYPE_NUMERIC, {799LU}}, /* .binaryEncodingId */ |
| 24134 | sizeof(UA_SetPublishingModeRequest), /* .memSize */ |
| 24135 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24136 | false, /* .pointerFree */ |
| 24137 | false, /* .overlayable */ |
| 24138 | 3, /* .membersSize */ |
| 24139 | SetPublishingModeRequest_members /* .members */ |
| 24140 | }, |
| 24141 | /* SetPublishingModeResponse */ |
| 24142 | { |
| 24143 | UA_TYPENAME("SetPublishingModeResponse") /* .typeName */ |
| 24144 | {0, UA_NODEIDTYPE_NUMERIC, {800LU}}, /* .typeId */ |
| 24145 | {0, UA_NODEIDTYPE_NUMERIC, {802LU}}, /* .binaryEncodingId */ |
| 24146 | sizeof(UA_SetPublishingModeResponse), /* .memSize */ |
| 24147 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24148 | false, /* .pointerFree */ |
| 24149 | false, /* .overlayable */ |
| 24150 | 3, /* .membersSize */ |
| 24151 | SetPublishingModeResponse_members /* .members */ |
| 24152 | }, |
| 24153 | /* NotificationMessage */ |
| 24154 | { |
| 24155 | UA_TYPENAME("NotificationMessage") /* .typeName */ |
| 24156 | {0, UA_NODEIDTYPE_NUMERIC, {803LU}}, /* .typeId */ |
| 24157 | {0, UA_NODEIDTYPE_NUMERIC, {805LU}}, /* .binaryEncodingId */ |
| 24158 | sizeof(UA_NotificationMessage), /* .memSize */ |
| 24159 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24160 | false, /* .pointerFree */ |
| 24161 | false, /* .overlayable */ |
| 24162 | 3, /* .membersSize */ |
| 24163 | NotificationMessage_members /* .members */ |
| 24164 | }, |
| 24165 | /* MonitoredItemNotification */ |
| 24166 | { |
| 24167 | UA_TYPENAME("MonitoredItemNotification") /* .typeName */ |
| 24168 | {0, UA_NODEIDTYPE_NUMERIC, {806LU}}, /* .typeId */ |
| 24169 | {0, UA_NODEIDTYPE_NUMERIC, {808LU}}, /* .binaryEncodingId */ |
| 24170 | sizeof(UA_MonitoredItemNotification), /* .memSize */ |
| 24171 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24172 | false, /* .pointerFree */ |
| 24173 | false, /* .overlayable */ |
| 24174 | 2, /* .membersSize */ |
| 24175 | MonitoredItemNotification_members /* .members */ |
| 24176 | }, |
| 24177 | /* EventFieldList */ |
| 24178 | { |
| 24179 | UA_TYPENAME("EventFieldList") /* .typeName */ |
| 24180 | {0, UA_NODEIDTYPE_NUMERIC, {917LU}}, /* .typeId */ |
| 24181 | {0, UA_NODEIDTYPE_NUMERIC, {919LU}}, /* .binaryEncodingId */ |
| 24182 | sizeof(UA_EventFieldList), /* .memSize */ |
| 24183 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24184 | false, /* .pointerFree */ |
| 24185 | false, /* .overlayable */ |
| 24186 | 2, /* .membersSize */ |
| 24187 | EventFieldList_members /* .members */ |
| 24188 | }, |
| 24189 | /* HistoryEventFieldList */ |
| 24190 | { |
| 24191 | UA_TYPENAME("HistoryEventFieldList") /* .typeName */ |
| 24192 | {0, UA_NODEIDTYPE_NUMERIC, {920LU}}, /* .typeId */ |
| 24193 | {0, UA_NODEIDTYPE_NUMERIC, {922LU}}, /* .binaryEncodingId */ |
| 24194 | sizeof(UA_HistoryEventFieldList), /* .memSize */ |
| 24195 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24196 | false, /* .pointerFree */ |
| 24197 | false, /* .overlayable */ |
| 24198 | 1, /* .membersSize */ |
| 24199 | HistoryEventFieldList_members /* .members */ |
| 24200 | }, |
| 24201 | /* StatusChangeNotification */ |
| 24202 | { |
| 24203 | UA_TYPENAME("StatusChangeNotification") /* .typeName */ |
| 24204 | {0, UA_NODEIDTYPE_NUMERIC, {818LU}}, /* .typeId */ |
| 24205 | {0, UA_NODEIDTYPE_NUMERIC, {820LU}}, /* .binaryEncodingId */ |
| 24206 | sizeof(UA_StatusChangeNotification), /* .memSize */ |
| 24207 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24208 | false, /* .pointerFree */ |
| 24209 | false, /* .overlayable */ |
| 24210 | 2, /* .membersSize */ |
| 24211 | StatusChangeNotification_members /* .members */ |
| 24212 | }, |
| 24213 | /* SubscriptionAcknowledgement */ |
| 24214 | { |
| 24215 | UA_TYPENAME("SubscriptionAcknowledgement") /* .typeName */ |
| 24216 | {0, UA_NODEIDTYPE_NUMERIC, {821LU}}, /* .typeId */ |
| 24217 | {0, UA_NODEIDTYPE_NUMERIC, {823LU}}, /* .binaryEncodingId */ |
| 24218 | sizeof(UA_SubscriptionAcknowledgement), /* .memSize */ |
| 24219 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24220 | true, /* .pointerFree */ |
| 24221 | false, /* .overlayable */ |
| 24222 | 2, /* .membersSize */ |
| 24223 | SubscriptionAcknowledgement_members /* .members */ |
| 24224 | }, |
| 24225 | /* PublishRequest */ |
| 24226 | { |
| 24227 | UA_TYPENAME("PublishRequest") /* .typeName */ |
| 24228 | {0, UA_NODEIDTYPE_NUMERIC, {824LU}}, /* .typeId */ |
| 24229 | {0, UA_NODEIDTYPE_NUMERIC, {826LU}}, /* .binaryEncodingId */ |
| 24230 | sizeof(UA_PublishRequest), /* .memSize */ |
| 24231 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24232 | false, /* .pointerFree */ |
| 24233 | false, /* .overlayable */ |
| 24234 | 2, /* .membersSize */ |
| 24235 | PublishRequest_members /* .members */ |
| 24236 | }, |
| 24237 | /* PublishResponse */ |
| 24238 | { |
| 24239 | UA_TYPENAME("PublishResponse") /* .typeName */ |
| 24240 | {0, UA_NODEIDTYPE_NUMERIC, {827LU}}, /* .typeId */ |
| 24241 | {0, UA_NODEIDTYPE_NUMERIC, {829LU}}, /* .binaryEncodingId */ |
| 24242 | sizeof(UA_PublishResponse), /* .memSize */ |
| 24243 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24244 | false, /* .pointerFree */ |
| 24245 | false, /* .overlayable */ |
| 24246 | 7, /* .membersSize */ |
| 24247 | PublishResponse_members /* .members */ |
| 24248 | }, |
| 24249 | /* RepublishRequest */ |
| 24250 | { |
| 24251 | UA_TYPENAME("RepublishRequest") /* .typeName */ |
| 24252 | {0, UA_NODEIDTYPE_NUMERIC, {830LU}}, /* .typeId */ |
| 24253 | {0, UA_NODEIDTYPE_NUMERIC, {832LU}}, /* .binaryEncodingId */ |
| 24254 | sizeof(UA_RepublishRequest), /* .memSize */ |
| 24255 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24256 | false, /* .pointerFree */ |
| 24257 | false, /* .overlayable */ |
| 24258 | 3, /* .membersSize */ |
| 24259 | RepublishRequest_members /* .members */ |
| 24260 | }, |
| 24261 | /* RepublishResponse */ |
| 24262 | { |
| 24263 | UA_TYPENAME("RepublishResponse") /* .typeName */ |
| 24264 | {0, UA_NODEIDTYPE_NUMERIC, {833LU}}, /* .typeId */ |
| 24265 | {0, UA_NODEIDTYPE_NUMERIC, {835LU}}, /* .binaryEncodingId */ |
| 24266 | sizeof(UA_RepublishResponse), /* .memSize */ |
| 24267 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24268 | false, /* .pointerFree */ |
| 24269 | false, /* .overlayable */ |
| 24270 | 2, /* .membersSize */ |
| 24271 | RepublishResponse_members /* .members */ |
| 24272 | }, |
| 24273 | /* TransferResult */ |
| 24274 | { |
| 24275 | UA_TYPENAME("TransferResult") /* .typeName */ |
| 24276 | {0, UA_NODEIDTYPE_NUMERIC, {836LU}}, /* .typeId */ |
| 24277 | {0, UA_NODEIDTYPE_NUMERIC, {838LU}}, /* .binaryEncodingId */ |
| 24278 | sizeof(UA_TransferResult), /* .memSize */ |
| 24279 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24280 | false, /* .pointerFree */ |
| 24281 | false, /* .overlayable */ |
| 24282 | 2, /* .membersSize */ |
| 24283 | TransferResult_members /* .members */ |
| 24284 | }, |
| 24285 | /* TransferSubscriptionsRequest */ |
| 24286 | { |
| 24287 | UA_TYPENAME("TransferSubscriptionsRequest") /* .typeName */ |
| 24288 | {0, UA_NODEIDTYPE_NUMERIC, {839LU}}, /* .typeId */ |
| 24289 | {0, UA_NODEIDTYPE_NUMERIC, {841LU}}, /* .binaryEncodingId */ |
| 24290 | sizeof(UA_TransferSubscriptionsRequest), /* .memSize */ |
| 24291 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24292 | false, /* .pointerFree */ |
| 24293 | false, /* .overlayable */ |
| 24294 | 3, /* .membersSize */ |
| 24295 | TransferSubscriptionsRequest_members /* .members */ |
| 24296 | }, |
| 24297 | /* TransferSubscriptionsResponse */ |
| 24298 | { |
| 24299 | UA_TYPENAME("TransferSubscriptionsResponse") /* .typeName */ |
| 24300 | {0, UA_NODEIDTYPE_NUMERIC, {842LU}}, /* .typeId */ |
| 24301 | {0, UA_NODEIDTYPE_NUMERIC, {844LU}}, /* .binaryEncodingId */ |
| 24302 | sizeof(UA_TransferSubscriptionsResponse), /* .memSize */ |
| 24303 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24304 | false, /* .pointerFree */ |
| 24305 | false, /* .overlayable */ |
| 24306 | 3, /* .membersSize */ |
| 24307 | TransferSubscriptionsResponse_members /* .members */ |
| 24308 | }, |
| 24309 | /* DeleteSubscriptionsRequest */ |
| 24310 | { |
| 24311 | UA_TYPENAME("DeleteSubscriptionsRequest") /* .typeName */ |
| 24312 | {0, UA_NODEIDTYPE_NUMERIC, {845LU}}, /* .typeId */ |
| 24313 | {0, UA_NODEIDTYPE_NUMERIC, {847LU}}, /* .binaryEncodingId */ |
| 24314 | sizeof(UA_DeleteSubscriptionsRequest), /* .memSize */ |
| 24315 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24316 | false, /* .pointerFree */ |
| 24317 | false, /* .overlayable */ |
| 24318 | 2, /* .membersSize */ |
| 24319 | DeleteSubscriptionsRequest_members /* .members */ |
| 24320 | }, |
| 24321 | /* DeleteSubscriptionsResponse */ |
| 24322 | { |
| 24323 | UA_TYPENAME("DeleteSubscriptionsResponse") /* .typeName */ |
| 24324 | {0, UA_NODEIDTYPE_NUMERIC, {848LU}}, /* .typeId */ |
| 24325 | {0, UA_NODEIDTYPE_NUMERIC, {850LU}}, /* .binaryEncodingId */ |
| 24326 | sizeof(UA_DeleteSubscriptionsResponse), /* .memSize */ |
| 24327 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24328 | false, /* .pointerFree */ |
| 24329 | false, /* .overlayable */ |
| 24330 | 3, /* .membersSize */ |
| 24331 | DeleteSubscriptionsResponse_members /* .members */ |
| 24332 | }, |
| 24333 | /* BuildInfo */ |
| 24334 | { |
| 24335 | UA_TYPENAME("BuildInfo") /* .typeName */ |
| 24336 | {0, UA_NODEIDTYPE_NUMERIC, {338LU}}, /* .typeId */ |
| 24337 | {0, UA_NODEIDTYPE_NUMERIC, {340LU}}, /* .binaryEncodingId */ |
| 24338 | sizeof(UA_BuildInfo), /* .memSize */ |
| 24339 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24340 | false, /* .pointerFree */ |
| 24341 | false, /* .overlayable */ |
| 24342 | 6, /* .membersSize */ |
| 24343 | BuildInfo_members /* .members */ |
| 24344 | }, |
| 24345 | /* RedundancySupport */ |
| 24346 | { |
| 24347 | UA_TYPENAME("RedundancySupport") /* .typeName */ |
| 24348 | {0, UA_NODEIDTYPE_NUMERIC, {851LU}}, /* .typeId */ |
| 24349 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 24350 | sizeof(UA_RedundancySupport), /* .memSize */ |
| 24351 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 24352 | true, /* .pointerFree */ |
| 24353 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 24354 | 0, /* .membersSize */ |
| 24355 | RedundancySupport_members /* .members */ |
| 24356 | }, |
| 24357 | /* ServerState */ |
| 24358 | { |
| 24359 | UA_TYPENAME("ServerState") /* .typeName */ |
| 24360 | {0, UA_NODEIDTYPE_NUMERIC, {852LU}}, /* .typeId */ |
| 24361 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 24362 | sizeof(UA_ServerState), /* .memSize */ |
| 24363 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 24364 | true, /* .pointerFree */ |
| 24365 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 24366 | 0, /* .membersSize */ |
| 24367 | ServerState_members /* .members */ |
| 24368 | }, |
| 24369 | /* RedundantServerDataType */ |
| 24370 | { |
| 24371 | UA_TYPENAME("RedundantServerDataType") /* .typeName */ |
| 24372 | {0, UA_NODEIDTYPE_NUMERIC, {853LU}}, /* .typeId */ |
| 24373 | {0, UA_NODEIDTYPE_NUMERIC, {855LU}}, /* .binaryEncodingId */ |
| 24374 | sizeof(UA_RedundantServerDataType), /* .memSize */ |
| 24375 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24376 | false, /* .pointerFree */ |
| 24377 | false, /* .overlayable */ |
| 24378 | 3, /* .membersSize */ |
| 24379 | RedundantServerDataType_members /* .members */ |
| 24380 | }, |
| 24381 | /* EndpointUrlListDataType */ |
| 24382 | { |
| 24383 | UA_TYPENAME("EndpointUrlListDataType") /* .typeName */ |
| 24384 | {0, UA_NODEIDTYPE_NUMERIC, {11943LU}}, /* .typeId */ |
| 24385 | {0, UA_NODEIDTYPE_NUMERIC, {11957LU}}, /* .binaryEncodingId */ |
| 24386 | sizeof(UA_EndpointUrlListDataType), /* .memSize */ |
| 24387 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24388 | false, /* .pointerFree */ |
| 24389 | false, /* .overlayable */ |
| 24390 | 1, /* .membersSize */ |
| 24391 | EndpointUrlListDataType_members /* .members */ |
| 24392 | }, |
| 24393 | /* NetworkGroupDataType */ |
| 24394 | { |
| 24395 | UA_TYPENAME("NetworkGroupDataType") /* .typeName */ |
| 24396 | {0, UA_NODEIDTYPE_NUMERIC, {11944LU}}, /* .typeId */ |
| 24397 | {0, UA_NODEIDTYPE_NUMERIC, {11958LU}}, /* .binaryEncodingId */ |
| 24398 | sizeof(UA_NetworkGroupDataType), /* .memSize */ |
| 24399 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24400 | false, /* .pointerFree */ |
| 24401 | false, /* .overlayable */ |
| 24402 | 2, /* .membersSize */ |
| 24403 | NetworkGroupDataType_members /* .members */ |
| 24404 | }, |
| 24405 | /* SamplingIntervalDiagnosticsDataType */ |
| 24406 | { |
| 24407 | UA_TYPENAME("SamplingIntervalDiagnosticsDataType") /* .typeName */ |
| 24408 | {0, UA_NODEIDTYPE_NUMERIC, {856LU}}, /* .typeId */ |
| 24409 | {0, UA_NODEIDTYPE_NUMERIC, {858LU}}, /* .binaryEncodingId */ |
| 24410 | sizeof(UA_SamplingIntervalDiagnosticsDataType), /* .memSize */ |
| 24411 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24412 | true, /* .pointerFree */ |
| 24413 | false, /* .overlayable */ |
| 24414 | 4, /* .membersSize */ |
| 24415 | SamplingIntervalDiagnosticsDataType_members /* .members */ |
| 24416 | }, |
| 24417 | /* ServerDiagnosticsSummaryDataType */ |
| 24418 | { |
| 24419 | UA_TYPENAME("ServerDiagnosticsSummaryDataType") /* .typeName */ |
| 24420 | {0, UA_NODEIDTYPE_NUMERIC, {859LU}}, /* .typeId */ |
| 24421 | {0, UA_NODEIDTYPE_NUMERIC, {861LU}}, /* .binaryEncodingId */ |
| 24422 | sizeof(UA_ServerDiagnosticsSummaryDataType), /* .memSize */ |
| 24423 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24424 | true, /* .pointerFree */ |
| 24425 | false, /* .overlayable */ |
| 24426 | 12, /* .membersSize */ |
| 24427 | ServerDiagnosticsSummaryDataType_members /* .members */ |
| 24428 | }, |
| 24429 | /* ServerStatusDataType */ |
| 24430 | { |
| 24431 | UA_TYPENAME("ServerStatusDataType") /* .typeName */ |
| 24432 | {0, UA_NODEIDTYPE_NUMERIC, {862LU}}, /* .typeId */ |
| 24433 | {0, UA_NODEIDTYPE_NUMERIC, {864LU}}, /* .binaryEncodingId */ |
| 24434 | sizeof(UA_ServerStatusDataType), /* .memSize */ |
| 24435 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24436 | false, /* .pointerFree */ |
| 24437 | false, /* .overlayable */ |
| 24438 | 6, /* .membersSize */ |
| 24439 | ServerStatusDataType_members /* .members */ |
| 24440 | }, |
| 24441 | /* SessionSecurityDiagnosticsDataType */ |
| 24442 | { |
| 24443 | UA_TYPENAME("SessionSecurityDiagnosticsDataType") /* .typeName */ |
| 24444 | {0, UA_NODEIDTYPE_NUMERIC, {868LU}}, /* .typeId */ |
| 24445 | {0, UA_NODEIDTYPE_NUMERIC, {870LU}}, /* .binaryEncodingId */ |
| 24446 | sizeof(UA_SessionSecurityDiagnosticsDataType), /* .memSize */ |
| 24447 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24448 | false, /* .pointerFree */ |
| 24449 | false, /* .overlayable */ |
| 24450 | 9, /* .membersSize */ |
| 24451 | SessionSecurityDiagnosticsDataType_members /* .members */ |
| 24452 | }, |
| 24453 | /* ServiceCounterDataType */ |
| 24454 | { |
| 24455 | UA_TYPENAME("ServiceCounterDataType") /* .typeName */ |
| 24456 | {0, UA_NODEIDTYPE_NUMERIC, {871LU}}, /* .typeId */ |
| 24457 | {0, UA_NODEIDTYPE_NUMERIC, {873LU}}, /* .binaryEncodingId */ |
| 24458 | sizeof(UA_ServiceCounterDataType), /* .memSize */ |
| 24459 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24460 | true, /* .pointerFree */ |
| 24461 | false, /* .overlayable */ |
| 24462 | 2, /* .membersSize */ |
| 24463 | ServiceCounterDataType_members /* .members */ |
| 24464 | }, |
| 24465 | /* StatusResult */ |
| 24466 | { |
| 24467 | UA_TYPENAME("StatusResult") /* .typeName */ |
| 24468 | {0, UA_NODEIDTYPE_NUMERIC, {299LU}}, /* .typeId */ |
| 24469 | {0, UA_NODEIDTYPE_NUMERIC, {301LU}}, /* .binaryEncodingId */ |
| 24470 | sizeof(UA_StatusResult), /* .memSize */ |
| 24471 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24472 | false, /* .pointerFree */ |
| 24473 | false, /* .overlayable */ |
| 24474 | 2, /* .membersSize */ |
| 24475 | StatusResult_members /* .members */ |
| 24476 | }, |
| 24477 | /* SubscriptionDiagnosticsDataType */ |
| 24478 | { |
| 24479 | UA_TYPENAME("SubscriptionDiagnosticsDataType") /* .typeName */ |
| 24480 | {0, UA_NODEIDTYPE_NUMERIC, {874LU}}, /* .typeId */ |
| 24481 | {0, UA_NODEIDTYPE_NUMERIC, {876LU}}, /* .binaryEncodingId */ |
| 24482 | sizeof(UA_SubscriptionDiagnosticsDataType), /* .memSize */ |
| 24483 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24484 | false, /* .pointerFree */ |
| 24485 | false, /* .overlayable */ |
| 24486 | 31, /* .membersSize */ |
| 24487 | SubscriptionDiagnosticsDataType_members /* .members */ |
| 24488 | }, |
| 24489 | /* ModelChangeStructureVerbMask */ |
| 24490 | { |
| 24491 | UA_TYPENAME("ModelChangeStructureVerbMask") /* .typeName */ |
| 24492 | {0, UA_NODEIDTYPE_NUMERIC, {11941LU}}, /* .typeId */ |
| 24493 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 24494 | sizeof(UA_ModelChangeStructureVerbMask), /* .memSize */ |
| 24495 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 24496 | true, /* .pointerFree */ |
| 24497 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 24498 | 0, /* .membersSize */ |
| 24499 | ModelChangeStructureVerbMask_members /* .members */ |
| 24500 | }, |
| 24501 | /* ModelChangeStructureDataType */ |
| 24502 | { |
| 24503 | UA_TYPENAME("ModelChangeStructureDataType") /* .typeName */ |
| 24504 | {0, UA_NODEIDTYPE_NUMERIC, {877LU}}, /* .typeId */ |
| 24505 | {0, UA_NODEIDTYPE_NUMERIC, {879LU}}, /* .binaryEncodingId */ |
| 24506 | sizeof(UA_ModelChangeStructureDataType), /* .memSize */ |
| 24507 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24508 | false, /* .pointerFree */ |
| 24509 | false, /* .overlayable */ |
| 24510 | 3, /* .membersSize */ |
| 24511 | ModelChangeStructureDataType_members /* .members */ |
| 24512 | }, |
| 24513 | /* SemanticChangeStructureDataType */ |
| 24514 | { |
| 24515 | UA_TYPENAME("SemanticChangeStructureDataType") /* .typeName */ |
| 24516 | {0, UA_NODEIDTYPE_NUMERIC, {897LU}}, /* .typeId */ |
| 24517 | {0, UA_NODEIDTYPE_NUMERIC, {899LU}}, /* .binaryEncodingId */ |
| 24518 | sizeof(UA_SemanticChangeStructureDataType), /* .memSize */ |
| 24519 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24520 | false, /* .pointerFree */ |
| 24521 | false, /* .overlayable */ |
| 24522 | 2, /* .membersSize */ |
| 24523 | SemanticChangeStructureDataType_members /* .members */ |
| 24524 | }, |
| 24525 | /* Range */ |
| 24526 | { |
| 24527 | UA_TYPENAME("Range") /* .typeName */ |
| 24528 | {0, UA_NODEIDTYPE_NUMERIC, {884LU}}, /* .typeId */ |
| 24529 | {0, UA_NODEIDTYPE_NUMERIC, {886LU}}, /* .binaryEncodingId */ |
| 24530 | sizeof(UA_Range), /* .memSize */ |
| 24531 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24532 | true, /* .pointerFree */ |
| 24533 | false, /* .overlayable */ |
| 24534 | 2, /* .membersSize */ |
| 24535 | Range_members /* .members */ |
| 24536 | }, |
| 24537 | /* EUInformation */ |
| 24538 | { |
| 24539 | UA_TYPENAME("EUInformation") /* .typeName */ |
| 24540 | {0, UA_NODEIDTYPE_NUMERIC, {887LU}}, /* .typeId */ |
| 24541 | {0, UA_NODEIDTYPE_NUMERIC, {889LU}}, /* .binaryEncodingId */ |
| 24542 | sizeof(UA_EUInformation), /* .memSize */ |
| 24543 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24544 | false, /* .pointerFree */ |
| 24545 | false, /* .overlayable */ |
| 24546 | 4, /* .membersSize */ |
| 24547 | EUInformation_members /* .members */ |
| 24548 | }, |
| 24549 | /* AxisScaleEnumeration */ |
| 24550 | { |
| 24551 | UA_TYPENAME("AxisScaleEnumeration") /* .typeName */ |
| 24552 | {0, UA_NODEIDTYPE_NUMERIC, {12077LU}}, /* .typeId */ |
| 24553 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 24554 | sizeof(UA_AxisScaleEnumeration), /* .memSize */ |
| 24555 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 24556 | true, /* .pointerFree */ |
| 24557 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 24558 | 0, /* .membersSize */ |
| 24559 | AxisScaleEnumeration_members /* .members */ |
| 24560 | }, |
| 24561 | /* ComplexNumberType */ |
| 24562 | { |
| 24563 | UA_TYPENAME("ComplexNumberType") /* .typeName */ |
| 24564 | {0, UA_NODEIDTYPE_NUMERIC, {12171LU}}, /* .typeId */ |
| 24565 | {0, UA_NODEIDTYPE_NUMERIC, {12181LU}}, /* .binaryEncodingId */ |
| 24566 | sizeof(UA_ComplexNumberType), /* .memSize */ |
| 24567 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24568 | true, /* .pointerFree */ |
| 24569 | false, /* .overlayable */ |
| 24570 | 2, /* .membersSize */ |
| 24571 | ComplexNumberType_members /* .members */ |
| 24572 | }, |
| 24573 | /* DoubleComplexNumberType */ |
| 24574 | { |
| 24575 | UA_TYPENAME("DoubleComplexNumberType") /* .typeName */ |
| 24576 | {0, UA_NODEIDTYPE_NUMERIC, {12172LU}}, /* .typeId */ |
| 24577 | {0, UA_NODEIDTYPE_NUMERIC, {12182LU}}, /* .binaryEncodingId */ |
| 24578 | sizeof(UA_DoubleComplexNumberType), /* .memSize */ |
| 24579 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24580 | true, /* .pointerFree */ |
| 24581 | false, /* .overlayable */ |
| 24582 | 2, /* .membersSize */ |
| 24583 | DoubleComplexNumberType_members /* .members */ |
| 24584 | }, |
| 24585 | /* AxisInformation */ |
| 24586 | { |
| 24587 | UA_TYPENAME("AxisInformation") /* .typeName */ |
| 24588 | {0, UA_NODEIDTYPE_NUMERIC, {12079LU}}, /* .typeId */ |
| 24589 | {0, UA_NODEIDTYPE_NUMERIC, {12089LU}}, /* .binaryEncodingId */ |
| 24590 | sizeof(UA_AxisInformation), /* .memSize */ |
| 24591 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24592 | false, /* .pointerFree */ |
| 24593 | false, /* .overlayable */ |
| 24594 | 5, /* .membersSize */ |
| 24595 | AxisInformation_members /* .members */ |
| 24596 | }, |
| 24597 | /* XVType */ |
| 24598 | { |
| 24599 | UA_TYPENAME("XVType") /* .typeName */ |
| 24600 | {0, UA_NODEIDTYPE_NUMERIC, {12080LU}}, /* .typeId */ |
| 24601 | {0, UA_NODEIDTYPE_NUMERIC, {12090LU}}, /* .binaryEncodingId */ |
| 24602 | sizeof(UA_XVType), /* .memSize */ |
| 24603 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24604 | true, /* .pointerFree */ |
| 24605 | false, /* .overlayable */ |
| 24606 | 2, /* .membersSize */ |
| 24607 | XVType_members /* .members */ |
| 24608 | }, |
| 24609 | /* ProgramDiagnosticDataType */ |
| 24610 | { |
| 24611 | UA_TYPENAME("ProgramDiagnosticDataType") /* .typeName */ |
| 24612 | {0, UA_NODEIDTYPE_NUMERIC, {894LU}}, /* .typeId */ |
| 24613 | {0, UA_NODEIDTYPE_NUMERIC, {896LU}}, /* .binaryEncodingId */ |
| 24614 | sizeof(UA_ProgramDiagnosticDataType), /* .memSize */ |
| 24615 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24616 | false, /* .pointerFree */ |
| 24617 | false, /* .overlayable */ |
| 24618 | 10, /* .membersSize */ |
| 24619 | ProgramDiagnosticDataType_members /* .members */ |
| 24620 | }, |
| 24621 | /* ProgramDiagnostic2DataType */ |
| 24622 | { |
| 24623 | UA_TYPENAME("ProgramDiagnostic2DataType") /* .typeName */ |
| 24624 | {0, UA_NODEIDTYPE_NUMERIC, {24033LU}}, /* .typeId */ |
| 24625 | {0, UA_NODEIDTYPE_NUMERIC, {24034LU}}, /* .binaryEncodingId */ |
| 24626 | sizeof(UA_ProgramDiagnostic2DataType), /* .memSize */ |
| 24627 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24628 | false, /* .pointerFree */ |
| 24629 | false, /* .overlayable */ |
| 24630 | 12, /* .membersSize */ |
| 24631 | ProgramDiagnostic2DataType_members /* .members */ |
| 24632 | }, |
| 24633 | /* Annotation */ |
| 24634 | { |
| 24635 | UA_TYPENAME("Annotation") /* .typeName */ |
| 24636 | {0, UA_NODEIDTYPE_NUMERIC, {891LU}}, /* .typeId */ |
| 24637 | {0, UA_NODEIDTYPE_NUMERIC, {893LU}}, /* .binaryEncodingId */ |
| 24638 | sizeof(UA_Annotation), /* .memSize */ |
| 24639 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24640 | false, /* .pointerFree */ |
| 24641 | false, /* .overlayable */ |
| 24642 | 3, /* .membersSize */ |
| 24643 | Annotation_members /* .members */ |
| 24644 | }, |
| 24645 | /* ExceptionDeviationFormat */ |
| 24646 | { |
| 24647 | UA_TYPENAME("ExceptionDeviationFormat") /* .typeName */ |
| 24648 | {0, UA_NODEIDTYPE_NUMERIC, {890LU}}, /* .typeId */ |
| 24649 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 24650 | sizeof(UA_ExceptionDeviationFormat), /* .memSize */ |
| 24651 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 24652 | true, /* .pointerFree */ |
| 24653 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 24654 | 0, /* .membersSize */ |
| 24655 | ExceptionDeviationFormat_members /* .members */ |
| 24656 | }, |
| 24657 | /* EndpointType */ |
| 24658 | { |
| 24659 | UA_TYPENAME("EndpointType") /* .typeName */ |
| 24660 | {0, UA_NODEIDTYPE_NUMERIC, {15528LU}}, /* .typeId */ |
| 24661 | {0, UA_NODEIDTYPE_NUMERIC, {15671LU}}, /* .binaryEncodingId */ |
| 24662 | sizeof(UA_EndpointType), /* .memSize */ |
| 24663 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24664 | false, /* .pointerFree */ |
| 24665 | false, /* .overlayable */ |
| 24666 | 4, /* .membersSize */ |
| 24667 | EndpointType_members /* .members */ |
| 24668 | }, |
| 24669 | /* StructureDescription */ |
| 24670 | { |
| 24671 | UA_TYPENAME("StructureDescription") /* .typeName */ |
| 24672 | {0, UA_NODEIDTYPE_NUMERIC, {15487LU}}, /* .typeId */ |
| 24673 | {0, UA_NODEIDTYPE_NUMERIC, {126LU}}, /* .binaryEncodingId */ |
| 24674 | sizeof(UA_StructureDescription), /* .memSize */ |
| 24675 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24676 | false, /* .pointerFree */ |
| 24677 | false, /* .overlayable */ |
| 24678 | 3, /* .membersSize */ |
| 24679 | StructureDescription_members /* .members */ |
| 24680 | }, |
| 24681 | /* FieldMetaData */ |
| 24682 | { |
| 24683 | UA_TYPENAME("FieldMetaData") /* .typeName */ |
| 24684 | {0, UA_NODEIDTYPE_NUMERIC, {14524LU}}, /* .typeId */ |
| 24685 | {0, UA_NODEIDTYPE_NUMERIC, {14839LU}}, /* .binaryEncodingId */ |
| 24686 | sizeof(UA_FieldMetaData), /* .memSize */ |
| 24687 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24688 | false, /* .pointerFree */ |
| 24689 | false, /* .overlayable */ |
| 24690 | 10, /* .membersSize */ |
| 24691 | FieldMetaData_members /* .members */ |
| 24692 | }, |
| 24693 | /* PublishedEventsDataType */ |
| 24694 | { |
| 24695 | UA_TYPENAME("PublishedEventsDataType") /* .typeName */ |
| 24696 | {0, UA_NODEIDTYPE_NUMERIC, {15582LU}}, /* .typeId */ |
| 24697 | {0, UA_NODEIDTYPE_NUMERIC, {15681LU}}, /* .binaryEncodingId */ |
| 24698 | sizeof(UA_PublishedEventsDataType), /* .memSize */ |
| 24699 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24700 | false, /* .pointerFree */ |
| 24701 | false, /* .overlayable */ |
| 24702 | 3, /* .membersSize */ |
| 24703 | PublishedEventsDataType_members /* .members */ |
| 24704 | }, |
| 24705 | /* PubSubGroupDataType */ |
| 24706 | { |
| 24707 | UA_TYPENAME("PubSubGroupDataType") /* .typeName */ |
| 24708 | {0, UA_NODEIDTYPE_NUMERIC, {15609LU}}, /* .typeId */ |
| 24709 | {0, UA_NODEIDTYPE_NUMERIC, {15689LU}}, /* .binaryEncodingId */ |
| 24710 | sizeof(UA_PubSubGroupDataType), /* .memSize */ |
| 24711 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24712 | false, /* .pointerFree */ |
| 24713 | false, /* .overlayable */ |
| 24714 | 7, /* .membersSize */ |
| 24715 | PubSubGroupDataType_members /* .members */ |
| 24716 | }, |
| 24717 | /* WriterGroupDataType */ |
| 24718 | { |
| 24719 | UA_TYPENAME("WriterGroupDataType") /* .typeName */ |
| 24720 | {0, UA_NODEIDTYPE_NUMERIC, {15480LU}}, /* .typeId */ |
| 24721 | {0, UA_NODEIDTYPE_NUMERIC, {21150LU}}, /* .binaryEncodingId */ |
| 24722 | sizeof(UA_WriterGroupDataType), /* .memSize */ |
| 24723 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24724 | false, /* .pointerFree */ |
| 24725 | false, /* .overlayable */ |
| 24726 | 16, /* .membersSize */ |
| 24727 | WriterGroupDataType_members /* .members */ |
| 24728 | }, |
| 24729 | /* FieldTargetDataType */ |
| 24730 | { |
| 24731 | UA_TYPENAME("FieldTargetDataType") /* .typeName */ |
| 24732 | {0, UA_NODEIDTYPE_NUMERIC, {14744LU}}, /* .typeId */ |
| 24733 | {0, UA_NODEIDTYPE_NUMERIC, {14848LU}}, /* .binaryEncodingId */ |
| 24734 | sizeof(UA_FieldTargetDataType), /* .memSize */ |
| 24735 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24736 | false, /* .pointerFree */ |
| 24737 | false, /* .overlayable */ |
| 24738 | 7, /* .membersSize */ |
| 24739 | FieldTargetDataType_members /* .members */ |
| 24740 | }, |
| 24741 | /* SubscribedDataSetMirrorDataType */ |
| 24742 | { |
| 24743 | UA_TYPENAME("SubscribedDataSetMirrorDataType") /* .typeName */ |
| 24744 | {0, UA_NODEIDTYPE_NUMERIC, {15635LU}}, /* .typeId */ |
| 24745 | {0, UA_NODEIDTYPE_NUMERIC, {15713LU}}, /* .binaryEncodingId */ |
| 24746 | sizeof(UA_SubscribedDataSetMirrorDataType), /* .memSize */ |
| 24747 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24748 | false, /* .pointerFree */ |
| 24749 | false, /* .overlayable */ |
| 24750 | 2, /* .membersSize */ |
| 24751 | SubscribedDataSetMirrorDataType_members /* .members */ |
| 24752 | }, |
| 24753 | /* SecurityGroupDataType */ |
| 24754 | { |
| 24755 | UA_TYPENAME("SecurityGroupDataType") /* .typeName */ |
| 24756 | {0, UA_NODEIDTYPE_NUMERIC, {23601LU}}, /* .typeId */ |
| 24757 | {0, UA_NODEIDTYPE_NUMERIC, {23853LU}}, /* .binaryEncodingId */ |
| 24758 | sizeof(UA_SecurityGroupDataType), /* .memSize */ |
| 24759 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24760 | false, /* .pointerFree */ |
| 24761 | false, /* .overlayable */ |
| 24762 | 9, /* .membersSize */ |
| 24763 | SecurityGroupDataType_members /* .members */ |
| 24764 | }, |
| 24765 | /* PubSubKeyPushTargetDataType */ |
| 24766 | { |
| 24767 | UA_TYPENAME("PubSubKeyPushTargetDataType") /* .typeName */ |
| 24768 | {0, UA_NODEIDTYPE_NUMERIC, {25270LU}}, /* .typeId */ |
| 24769 | {0, UA_NODEIDTYPE_NUMERIC, {25530LU}}, /* .binaryEncodingId */ |
| 24770 | sizeof(UA_PubSubKeyPushTargetDataType), /* .memSize */ |
| 24771 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24772 | false, /* .pointerFree */ |
| 24773 | false, /* .overlayable */ |
| 24774 | 9, /* .membersSize */ |
| 24775 | PubSubKeyPushTargetDataType_members /* .members */ |
| 24776 | }, |
| 24777 | /* EnumDefinition */ |
| 24778 | { |
| 24779 | UA_TYPENAME("EnumDefinition") /* .typeName */ |
| 24780 | {0, UA_NODEIDTYPE_NUMERIC, {100LU}}, /* .typeId */ |
| 24781 | {0, UA_NODEIDTYPE_NUMERIC, {123LU}}, /* .binaryEncodingId */ |
| 24782 | sizeof(UA_EnumDefinition), /* .memSize */ |
| 24783 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24784 | false, /* .pointerFree */ |
| 24785 | false, /* .overlayable */ |
| 24786 | 1, /* .membersSize */ |
| 24787 | EnumDefinition_members /* .members */ |
| 24788 | }, |
| 24789 | /* ReadEventDetails */ |
| 24790 | { |
| 24791 | UA_TYPENAME("ReadEventDetails") /* .typeName */ |
| 24792 | {0, UA_NODEIDTYPE_NUMERIC, {644LU}}, /* .typeId */ |
| 24793 | {0, UA_NODEIDTYPE_NUMERIC, {646LU}}, /* .binaryEncodingId */ |
| 24794 | sizeof(UA_ReadEventDetails), /* .memSize */ |
| 24795 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24796 | false, /* .pointerFree */ |
| 24797 | false, /* .overlayable */ |
| 24798 | 4, /* .membersSize */ |
| 24799 | ReadEventDetails_members /* .members */ |
| 24800 | }, |
| 24801 | /* ReadProcessedDetails */ |
| 24802 | { |
| 24803 | UA_TYPENAME("ReadProcessedDetails") /* .typeName */ |
| 24804 | {0, UA_NODEIDTYPE_NUMERIC, {650LU}}, /* .typeId */ |
| 24805 | {0, UA_NODEIDTYPE_NUMERIC, {652LU}}, /* .binaryEncodingId */ |
| 24806 | sizeof(UA_ReadProcessedDetails), /* .memSize */ |
| 24807 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24808 | false, /* .pointerFree */ |
| 24809 | false, /* .overlayable */ |
| 24810 | 5, /* .membersSize */ |
| 24811 | ReadProcessedDetails_members /* .members */ |
| 24812 | }, |
| 24813 | /* ModificationInfo */ |
| 24814 | { |
| 24815 | UA_TYPENAME("ModificationInfo") /* .typeName */ |
| 24816 | {0, UA_NODEIDTYPE_NUMERIC, {11216LU}}, /* .typeId */ |
| 24817 | {0, UA_NODEIDTYPE_NUMERIC, {11226LU}}, /* .binaryEncodingId */ |
| 24818 | sizeof(UA_ModificationInfo), /* .memSize */ |
| 24819 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24820 | false, /* .pointerFree */ |
| 24821 | false, /* .overlayable */ |
| 24822 | 3, /* .membersSize */ |
| 24823 | ModificationInfo_members /* .members */ |
| 24824 | }, |
| 24825 | /* HistoryModifiedData */ |
| 24826 | { |
| 24827 | UA_TYPENAME("HistoryModifiedData") /* .typeName */ |
| 24828 | {0, UA_NODEIDTYPE_NUMERIC, {11217LU}}, /* .typeId */ |
| 24829 | {0, UA_NODEIDTYPE_NUMERIC, {11227LU}}, /* .binaryEncodingId */ |
| 24830 | sizeof(UA_HistoryModifiedData), /* .memSize */ |
| 24831 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24832 | false, /* .pointerFree */ |
| 24833 | false, /* .overlayable */ |
| 24834 | 2, /* .membersSize */ |
| 24835 | HistoryModifiedData_members /* .members */ |
| 24836 | }, |
| 24837 | /* HistoryEvent */ |
| 24838 | { |
| 24839 | UA_TYPENAME("HistoryEvent") /* .typeName */ |
| 24840 | {0, UA_NODEIDTYPE_NUMERIC, {659LU}}, /* .typeId */ |
| 24841 | {0, UA_NODEIDTYPE_NUMERIC, {661LU}}, /* .binaryEncodingId */ |
| 24842 | sizeof(UA_HistoryEvent), /* .memSize */ |
| 24843 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24844 | false, /* .pointerFree */ |
| 24845 | false, /* .overlayable */ |
| 24846 | 1, /* .membersSize */ |
| 24847 | HistoryEvent_members /* .members */ |
| 24848 | }, |
| 24849 | /* UpdateEventDetails */ |
| 24850 | { |
| 24851 | UA_TYPENAME("UpdateEventDetails") /* .typeName */ |
| 24852 | {0, UA_NODEIDTYPE_NUMERIC, {683LU}}, /* .typeId */ |
| 24853 | {0, UA_NODEIDTYPE_NUMERIC, {685LU}}, /* .binaryEncodingId */ |
| 24854 | sizeof(UA_UpdateEventDetails), /* .memSize */ |
| 24855 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24856 | false, /* .pointerFree */ |
| 24857 | false, /* .overlayable */ |
| 24858 | 4, /* .membersSize */ |
| 24859 | UpdateEventDetails_members /* .members */ |
| 24860 | }, |
| 24861 | /* DataChangeNotification */ |
| 24862 | { |
| 24863 | UA_TYPENAME("DataChangeNotification") /* .typeName */ |
| 24864 | {0, UA_NODEIDTYPE_NUMERIC, {809LU}}, /* .typeId */ |
| 24865 | {0, UA_NODEIDTYPE_NUMERIC, {811LU}}, /* .binaryEncodingId */ |
| 24866 | sizeof(UA_DataChangeNotification), /* .memSize */ |
| 24867 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24868 | false, /* .pointerFree */ |
| 24869 | false, /* .overlayable */ |
| 24870 | 2, /* .membersSize */ |
| 24871 | DataChangeNotification_members /* .members */ |
| 24872 | }, |
| 24873 | /* EventNotificationList */ |
| 24874 | { |
| 24875 | UA_TYPENAME("EventNotificationList") /* .typeName */ |
| 24876 | {0, UA_NODEIDTYPE_NUMERIC, {914LU}}, /* .typeId */ |
| 24877 | {0, UA_NODEIDTYPE_NUMERIC, {916LU}}, /* .binaryEncodingId */ |
| 24878 | sizeof(UA_EventNotificationList), /* .memSize */ |
| 24879 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24880 | false, /* .pointerFree */ |
| 24881 | false, /* .overlayable */ |
| 24882 | 1, /* .membersSize */ |
| 24883 | EventNotificationList_members /* .members */ |
| 24884 | }, |
| 24885 | /* SessionDiagnosticsDataType */ |
| 24886 | { |
| 24887 | UA_TYPENAME("SessionDiagnosticsDataType") /* .typeName */ |
| 24888 | {0, UA_NODEIDTYPE_NUMERIC, {865LU}}, /* .typeId */ |
| 24889 | {0, UA_NODEIDTYPE_NUMERIC, {867LU}}, /* .binaryEncodingId */ |
| 24890 | sizeof(UA_SessionDiagnosticsDataType), /* .memSize */ |
| 24891 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24892 | false, /* .pointerFree */ |
| 24893 | false, /* .overlayable */ |
| 24894 | 43, /* .membersSize */ |
| 24895 | SessionDiagnosticsDataType_members /* .members */ |
| 24896 | }, |
| 24897 | /* EnumDescription */ |
| 24898 | { |
| 24899 | UA_TYPENAME("EnumDescription") /* .typeName */ |
| 24900 | {0, UA_NODEIDTYPE_NUMERIC, {15488LU}}, /* .typeId */ |
| 24901 | {0, UA_NODEIDTYPE_NUMERIC, {127LU}}, /* .binaryEncodingId */ |
| 24902 | sizeof(UA_EnumDescription), /* .memSize */ |
| 24903 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24904 | false, /* .pointerFree */ |
| 24905 | false, /* .overlayable */ |
| 24906 | 4, /* .membersSize */ |
| 24907 | EnumDescription_members /* .members */ |
| 24908 | }, |
| 24909 | /* UABinaryFileDataType */ |
| 24910 | { |
| 24911 | UA_TYPENAME("UABinaryFileDataType") /* .typeName */ |
| 24912 | {0, UA_NODEIDTYPE_NUMERIC, {15006LU}}, /* .typeId */ |
| 24913 | {0, UA_NODEIDTYPE_NUMERIC, {15422LU}}, /* .binaryEncodingId */ |
| 24914 | sizeof(UA_UABinaryFileDataType), /* .memSize */ |
| 24915 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24916 | false, /* .pointerFree */ |
| 24917 | false, /* .overlayable */ |
| 24918 | 7, /* .membersSize */ |
| 24919 | UABinaryFileDataType_members /* .members */ |
| 24920 | }, |
| 24921 | /* DataSetMetaDataType */ |
| 24922 | { |
| 24923 | UA_TYPENAME("DataSetMetaDataType") /* .typeName */ |
| 24924 | {0, UA_NODEIDTYPE_NUMERIC, {14523LU}}, /* .typeId */ |
| 24925 | {0, UA_NODEIDTYPE_NUMERIC, {124LU}}, /* .binaryEncodingId */ |
| 24926 | sizeof(UA_DataSetMetaDataType), /* .memSize */ |
| 24927 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24928 | false, /* .pointerFree */ |
| 24929 | false, /* .overlayable */ |
| 24930 | 9, /* .membersSize */ |
| 24931 | DataSetMetaDataType_members /* .members */ |
| 24932 | }, |
| 24933 | /* PublishedDataSetDataType */ |
| 24934 | { |
| 24935 | UA_TYPENAME("PublishedDataSetDataType") /* .typeName */ |
| 24936 | {0, UA_NODEIDTYPE_NUMERIC, {15578LU}}, /* .typeId */ |
| 24937 | {0, UA_NODEIDTYPE_NUMERIC, {15677LU}}, /* .binaryEncodingId */ |
| 24938 | sizeof(UA_PublishedDataSetDataType), /* .memSize */ |
| 24939 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24940 | false, /* .pointerFree */ |
| 24941 | false, /* .overlayable */ |
| 24942 | 5, /* .membersSize */ |
| 24943 | PublishedDataSetDataType_members /* .members */ |
| 24944 | }, |
| 24945 | /* DataSetReaderDataType */ |
| 24946 | { |
| 24947 | UA_TYPENAME("DataSetReaderDataType") /* .typeName */ |
| 24948 | {0, UA_NODEIDTYPE_NUMERIC, {15623LU}}, /* .typeId */ |
| 24949 | {0, UA_NODEIDTYPE_NUMERIC, {15703LU}}, /* .binaryEncodingId */ |
| 24950 | sizeof(UA_DataSetReaderDataType), /* .memSize */ |
| 24951 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24952 | false, /* .pointerFree */ |
| 24953 | false, /* .overlayable */ |
| 24954 | 17, /* .membersSize */ |
| 24955 | DataSetReaderDataType_members /* .members */ |
| 24956 | }, |
| 24957 | /* TargetVariablesDataType */ |
| 24958 | { |
| 24959 | UA_TYPENAME("TargetVariablesDataType") /* .typeName */ |
| 24960 | {0, UA_NODEIDTYPE_NUMERIC, {15631LU}}, /* .typeId */ |
| 24961 | {0, UA_NODEIDTYPE_NUMERIC, {15712LU}}, /* .binaryEncodingId */ |
| 24962 | sizeof(UA_TargetVariablesDataType), /* .memSize */ |
| 24963 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24964 | false, /* .pointerFree */ |
| 24965 | false, /* .overlayable */ |
| 24966 | 1, /* .membersSize */ |
| 24967 | TargetVariablesDataType_members /* .members */ |
| 24968 | }, |
| 24969 | /* StandaloneSubscribedDataSetDataType */ |
| 24970 | { |
| 24971 | UA_TYPENAME("StandaloneSubscribedDataSetDataType") /* .typeName */ |
| 24972 | {0, UA_NODEIDTYPE_NUMERIC, {23600LU}}, /* .typeId */ |
| 24973 | {0, UA_NODEIDTYPE_NUMERIC, {23852LU}}, /* .binaryEncodingId */ |
| 24974 | sizeof(UA_StandaloneSubscribedDataSetDataType), /* .memSize */ |
| 24975 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24976 | false, /* .pointerFree */ |
| 24977 | false, /* .overlayable */ |
| 24978 | 4, /* .membersSize */ |
| 24979 | StandaloneSubscribedDataSetDataType_members /* .members */ |
| 24980 | }, |
| 24981 | /* DataTypeSchemaHeader */ |
| 24982 | { |
| 24983 | UA_TYPENAME("DataTypeSchemaHeader") /* .typeName */ |
| 24984 | {0, UA_NODEIDTYPE_NUMERIC, {15534LU}}, /* .typeId */ |
| 24985 | {0, UA_NODEIDTYPE_NUMERIC, {15676LU}}, /* .binaryEncodingId */ |
| 24986 | sizeof(UA_DataTypeSchemaHeader), /* .memSize */ |
| 24987 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 24988 | false, /* .pointerFree */ |
| 24989 | false, /* .overlayable */ |
| 24990 | 4, /* .membersSize */ |
| 24991 | DataTypeSchemaHeader_members /* .members */ |
| 24992 | }, |
| 24993 | /* ReaderGroupDataType */ |
| 24994 | { |
| 24995 | UA_TYPENAME("ReaderGroupDataType") /* .typeName */ |
| 24996 | {0, UA_NODEIDTYPE_NUMERIC, {15520LU}}, /* .typeId */ |
| 24997 | {0, UA_NODEIDTYPE_NUMERIC, {21153LU}}, /* .binaryEncodingId */ |
| 24998 | sizeof(UA_ReaderGroupDataType), /* .memSize */ |
| 24999 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25000 | false, /* .pointerFree */ |
| 25001 | false, /* .overlayable */ |
| 25002 | 10, /* .membersSize */ |
| 25003 | ReaderGroupDataType_members /* .members */ |
| 25004 | }, |
| 25005 | /* PubSubConnectionDataType */ |
| 25006 | { |
| 25007 | UA_TYPENAME("PubSubConnectionDataType") /* .typeName */ |
| 25008 | {0, UA_NODEIDTYPE_NUMERIC, {15617LU}}, /* .typeId */ |
| 25009 | {0, UA_NODEIDTYPE_NUMERIC, {15694LU}}, /* .binaryEncodingId */ |
| 25010 | sizeof(UA_PubSubConnectionDataType), /* .memSize */ |
| 25011 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25012 | false, /* .pointerFree */ |
| 25013 | false, /* .overlayable */ |
| 25014 | 9, /* .membersSize */ |
| 25015 | PubSubConnectionDataType_members /* .members */ |
| 25016 | }, |
| 25017 | /* PubSubConfigurationDataType */ |
| 25018 | { |
| 25019 | UA_TYPENAME("PubSubConfigurationDataType") /* .typeName */ |
| 25020 | {0, UA_NODEIDTYPE_NUMERIC, {15530LU}}, /* .typeId */ |
| 25021 | {0, UA_NODEIDTYPE_NUMERIC, {21154LU}}, /* .binaryEncodingId */ |
| 25022 | sizeof(UA_PubSubConfigurationDataType), /* .memSize */ |
| 25023 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25024 | false, /* .pointerFree */ |
| 25025 | false, /* .overlayable */ |
| 25026 | 3, /* .membersSize */ |
| 25027 | PubSubConfigurationDataType_members /* .members */ |
| 25028 | }, |
| 25029 | /* PubSubConfiguration2DataType */ |
| 25030 | { |
| 25031 | UA_TYPENAME("PubSubConfiguration2DataType") /* .typeName */ |
| 25032 | {0, UA_NODEIDTYPE_NUMERIC, {23602LU}}, /* .typeId */ |
| 25033 | {0, UA_NODEIDTYPE_NUMERIC, {23854LU}}, /* .binaryEncodingId */ |
| 25034 | sizeof(UA_PubSubConfiguration2DataType), /* .memSize */ |
| 25035 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25036 | false, /* .pointerFree */ |
| 25037 | false, /* .overlayable */ |
| 25038 | 10, /* .membersSize */ |
| 25039 | PubSubConfiguration2DataType_members /* .members */ |
| 25040 | }, |
| 25041 | }; |
| 25042 | |
| 25043 | |
| 25044 | /**** amalgamated original file "/build/src_generated/open62541/transport_generated.c" ****/ |
| 25045 | |
| 25046 | /********************************** |
| 25047 | * Autogenerated -- do not modify * |
| 25048 | **********************************/ |
| 25049 | |
| 25050 | |
| 25051 | /* MessageType */ |
| 25052 | #define MessageType_members NULL |
| 25053 | |
| 25054 | /* ChunkType */ |
| 25055 | #define ChunkType_members NULL |
| 25056 | |
| 25057 | /* TcpMessageHeader */ |
| 25058 | static UA_DataTypeMember TcpMessageHeader_members[2] = { |
| 25059 | { |
| 25060 | UA_TYPENAME("MessageTypeAndChunkType") /* .memberName */ |
| 25061 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25062 | 0, /* .padding */ |
| 25063 | false, /* .isArray */ |
| 25064 | false /* .isOptional */ |
| 25065 | }, |
| 25066 | { |
| 25067 | UA_TYPENAME("MessageSize") /* .memberName */ |
| 25068 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25069 | offsetof(UA_TcpMessageHeader, messageSize) - offsetof(UA_TcpMessageHeader, messageTypeAndChunkType) - sizeof(UA_UInt32), /* .padding */ |
| 25070 | false, /* .isArray */ |
| 25071 | false /* .isOptional */ |
| 25072 | },}; |
| 25073 | |
| 25074 | /* TcpHelloMessage */ |
| 25075 | static UA_DataTypeMember TcpHelloMessage_members[6] = { |
| 25076 | { |
| 25077 | UA_TYPENAME("ProtocolVersion") /* .memberName */ |
| 25078 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25079 | 0, /* .padding */ |
| 25080 | false, /* .isArray */ |
| 25081 | false /* .isOptional */ |
| 25082 | }, |
| 25083 | { |
| 25084 | UA_TYPENAME("ReceiveBufferSize") /* .memberName */ |
| 25085 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25086 | offsetof(UA_TcpHelloMessage, receiveBufferSize) - offsetof(UA_TcpHelloMessage, protocolVersion) - sizeof(UA_UInt32), /* .padding */ |
| 25087 | false, /* .isArray */ |
| 25088 | false /* .isOptional */ |
| 25089 | }, |
| 25090 | { |
| 25091 | UA_TYPENAME("SendBufferSize") /* .memberName */ |
| 25092 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25093 | offsetof(UA_TcpHelloMessage, sendBufferSize) - offsetof(UA_TcpHelloMessage, receiveBufferSize) - sizeof(UA_UInt32), /* .padding */ |
| 25094 | false, /* .isArray */ |
| 25095 | false /* .isOptional */ |
| 25096 | }, |
| 25097 | { |
| 25098 | UA_TYPENAME("MaxMessageSize") /* .memberName */ |
| 25099 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25100 | offsetof(UA_TcpHelloMessage, maxMessageSize) - offsetof(UA_TcpHelloMessage, sendBufferSize) - sizeof(UA_UInt32), /* .padding */ |
| 25101 | false, /* .isArray */ |
| 25102 | false /* .isOptional */ |
| 25103 | }, |
| 25104 | { |
| 25105 | UA_TYPENAME("MaxChunkCount") /* .memberName */ |
| 25106 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25107 | offsetof(UA_TcpHelloMessage, maxChunkCount) - offsetof(UA_TcpHelloMessage, maxMessageSize) - sizeof(UA_UInt32), /* .padding */ |
| 25108 | false, /* .isArray */ |
| 25109 | false /* .isOptional */ |
| 25110 | }, |
| 25111 | { |
| 25112 | UA_TYPENAME("EndpointUrl") /* .memberName */ |
| 25113 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 25114 | offsetof(UA_TcpHelloMessage, endpointUrl) - offsetof(UA_TcpHelloMessage, maxChunkCount) - sizeof(UA_UInt32), /* .padding */ |
| 25115 | false, /* .isArray */ |
| 25116 | false /* .isOptional */ |
| 25117 | },}; |
| 25118 | |
| 25119 | /* TcpReverseHelloMessage */ |
| 25120 | static UA_DataTypeMember TcpReverseHelloMessage_members[2] = { |
| 25121 | { |
| 25122 | UA_TYPENAME("ServerUri") /* .memberName */ |
| 25123 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 25124 | 0, /* .padding */ |
| 25125 | false, /* .isArray */ |
| 25126 | false /* .isOptional */ |
| 25127 | }, |
| 25128 | { |
| 25129 | UA_TYPENAME("EndpointUrl") /* .memberName */ |
| 25130 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 25131 | offsetof(UA_TcpReverseHelloMessage, endpointUrl) - offsetof(UA_TcpReverseHelloMessage, serverUri) - sizeof(UA_String), /* .padding */ |
| 25132 | false, /* .isArray */ |
| 25133 | false /* .isOptional */ |
| 25134 | },}; |
| 25135 | |
| 25136 | /* TcpAcknowledgeMessage */ |
| 25137 | static UA_DataTypeMember TcpAcknowledgeMessage_members[5] = { |
| 25138 | { |
| 25139 | UA_TYPENAME("ProtocolVersion") /* .memberName */ |
| 25140 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25141 | 0, /* .padding */ |
| 25142 | false, /* .isArray */ |
| 25143 | false /* .isOptional */ |
| 25144 | }, |
| 25145 | { |
| 25146 | UA_TYPENAME("ReceiveBufferSize") /* .memberName */ |
| 25147 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25148 | offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - offsetof(UA_TcpAcknowledgeMessage, protocolVersion) - sizeof(UA_UInt32), /* .padding */ |
| 25149 | false, /* .isArray */ |
| 25150 | false /* .isOptional */ |
| 25151 | }, |
| 25152 | { |
| 25153 | UA_TYPENAME("SendBufferSize") /* .memberName */ |
| 25154 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25155 | offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - offsetof(UA_TcpAcknowledgeMessage, receiveBufferSize) - sizeof(UA_UInt32), /* .padding */ |
| 25156 | false, /* .isArray */ |
| 25157 | false /* .isOptional */ |
| 25158 | }, |
| 25159 | { |
| 25160 | UA_TYPENAME("MaxMessageSize") /* .memberName */ |
| 25161 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25162 | offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - offsetof(UA_TcpAcknowledgeMessage, sendBufferSize) - sizeof(UA_UInt32), /* .padding */ |
| 25163 | false, /* .isArray */ |
| 25164 | false /* .isOptional */ |
| 25165 | }, |
| 25166 | { |
| 25167 | UA_TYPENAME("MaxChunkCount") /* .memberName */ |
| 25168 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25169 | offsetof(UA_TcpAcknowledgeMessage, maxChunkCount) - offsetof(UA_TcpAcknowledgeMessage, maxMessageSize) - sizeof(UA_UInt32), /* .padding */ |
| 25170 | false, /* .isArray */ |
| 25171 | false /* .isOptional */ |
| 25172 | },}; |
| 25173 | |
| 25174 | /* TcpErrorMessage */ |
| 25175 | static UA_DataTypeMember TcpErrorMessage_members[2] = { |
| 25176 | { |
| 25177 | UA_TYPENAME("Error") /* .memberName */ |
| 25178 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25179 | 0, /* .padding */ |
| 25180 | false, /* .isArray */ |
| 25181 | false /* .isOptional */ |
| 25182 | }, |
| 25183 | { |
| 25184 | UA_TYPENAME("Reason") /* .memberName */ |
| 25185 | &UA_TYPES[UA_TYPES_STRING], /* .memberType */ |
| 25186 | offsetof(UA_TcpErrorMessage, reason) - offsetof(UA_TcpErrorMessage, error) - sizeof(UA_UInt32), /* .padding */ |
| 25187 | false, /* .isArray */ |
| 25188 | false /* .isOptional */ |
| 25189 | },}; |
| 25190 | |
| 25191 | /* AsymmetricAlgorithmSecurityHeader */ |
| 25192 | static UA_DataTypeMember AsymmetricAlgorithmSecurityHeader_members[3] = { |
| 25193 | { |
| 25194 | UA_TYPENAME("SecurityPolicyUri") /* .memberName */ |
| 25195 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 25196 | 0, /* .padding */ |
| 25197 | false, /* .isArray */ |
| 25198 | false /* .isOptional */ |
| 25199 | }, |
| 25200 | { |
| 25201 | UA_TYPENAME("SenderCertificate") /* .memberName */ |
| 25202 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 25203 | offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, securityPolicyUri) - sizeof(UA_ByteString), /* .padding */ |
| 25204 | false, /* .isArray */ |
| 25205 | false /* .isOptional */ |
| 25206 | }, |
| 25207 | { |
| 25208 | UA_TYPENAME("ReceiverCertificateThumbprint") /* .memberName */ |
| 25209 | &UA_TYPES[UA_TYPES_BYTESTRING], /* .memberType */ |
| 25210 | offsetof(UA_AsymmetricAlgorithmSecurityHeader, receiverCertificateThumbprint) - offsetof(UA_AsymmetricAlgorithmSecurityHeader, senderCertificate) - sizeof(UA_ByteString), /* .padding */ |
| 25211 | false, /* .isArray */ |
| 25212 | false /* .isOptional */ |
| 25213 | },}; |
| 25214 | |
| 25215 | /* SequenceHeader */ |
| 25216 | static UA_DataTypeMember SequenceHeader_members[2] = { |
| 25217 | { |
| 25218 | UA_TYPENAME("SequenceNumber") /* .memberName */ |
| 25219 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25220 | 0, /* .padding */ |
| 25221 | false, /* .isArray */ |
| 25222 | false /* .isOptional */ |
| 25223 | }, |
| 25224 | { |
| 25225 | UA_TYPENAME("RequestId") /* .memberName */ |
| 25226 | &UA_TYPES[UA_TYPES_UINT32], /* .memberType */ |
| 25227 | offsetof(UA_SequenceHeader, requestId) - offsetof(UA_SequenceHeader, sequenceNumber) - sizeof(UA_UInt32), /* .padding */ |
| 25228 | false, /* .isArray */ |
| 25229 | false /* .isOptional */ |
| 25230 | },}; |
| 25231 | UA_DataType UA_TRANSPORT[UA_TRANSPORT_COUNT] = { |
| 25232 | /* MessageType */ |
| 25233 | { |
| 25234 | UA_TYPENAME("MessageType") /* .typeName */ |
| 25235 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */ |
| 25236 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 25237 | sizeof(UA_MessageType), /* .memSize */ |
| 25238 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 25239 | true, /* .pointerFree */ |
| 25240 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 25241 | 0, /* .membersSize */ |
| 25242 | MessageType_members /* .members */ |
| 25243 | }, |
| 25244 | /* ChunkType */ |
| 25245 | { |
| 25246 | UA_TYPENAME("ChunkType") /* .typeName */ |
| 25247 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */ |
| 25248 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 25249 | sizeof(UA_ChunkType), /* .memSize */ |
| 25250 | UA_DATATYPEKIND_ENUM, /* .typeKind */ |
| 25251 | true, /* .pointerFree */ |
| 25252 | UA_BINARY_OVERLAYABLE_INTEGER, /* .overlayable */ |
| 25253 | 0, /* .membersSize */ |
| 25254 | ChunkType_members /* .members */ |
| 25255 | }, |
| 25256 | /* TcpMessageHeader */ |
| 25257 | { |
| 25258 | UA_TYPENAME("TcpMessageHeader") /* .typeName */ |
| 25259 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */ |
| 25260 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 25261 | sizeof(UA_TcpMessageHeader), /* .memSize */ |
| 25262 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25263 | true, /* .pointerFree */ |
| 25264 | false, /* .overlayable */ |
| 25265 | 2, /* .membersSize */ |
| 25266 | TcpMessageHeader_members /* .members */ |
| 25267 | }, |
| 25268 | /* TcpHelloMessage */ |
| 25269 | { |
| 25270 | UA_TYPENAME("TcpHelloMessage") /* .typeName */ |
| 25271 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */ |
| 25272 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 25273 | sizeof(UA_TcpHelloMessage), /* .memSize */ |
| 25274 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25275 | false, /* .pointerFree */ |
| 25276 | false, /* .overlayable */ |
| 25277 | 6, /* .membersSize */ |
| 25278 | TcpHelloMessage_members /* .members */ |
| 25279 | }, |
| 25280 | /* TcpReverseHelloMessage */ |
| 25281 | { |
| 25282 | UA_TYPENAME("TcpReverseHelloMessage") /* .typeName */ |
| 25283 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */ |
| 25284 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 25285 | sizeof(UA_TcpReverseHelloMessage), /* .memSize */ |
| 25286 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25287 | false, /* .pointerFree */ |
| 25288 | false, /* .overlayable */ |
| 25289 | 2, /* .membersSize */ |
| 25290 | TcpReverseHelloMessage_members /* .members */ |
| 25291 | }, |
| 25292 | /* TcpAcknowledgeMessage */ |
| 25293 | { |
| 25294 | UA_TYPENAME("TcpAcknowledgeMessage") /* .typeName */ |
| 25295 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */ |
| 25296 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 25297 | sizeof(UA_TcpAcknowledgeMessage), /* .memSize */ |
| 25298 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25299 | true, /* .pointerFree */ |
| 25300 | false, /* .overlayable */ |
| 25301 | 5, /* .membersSize */ |
| 25302 | TcpAcknowledgeMessage_members /* .members */ |
| 25303 | }, |
| 25304 | /* TcpErrorMessage */ |
| 25305 | { |
| 25306 | UA_TYPENAME("TcpErrorMessage") /* .typeName */ |
| 25307 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */ |
| 25308 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 25309 | sizeof(UA_TcpErrorMessage), /* .memSize */ |
| 25310 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25311 | false, /* .pointerFree */ |
| 25312 | false, /* .overlayable */ |
| 25313 | 2, /* .membersSize */ |
| 25314 | TcpErrorMessage_members /* .members */ |
| 25315 | }, |
| 25316 | /* AsymmetricAlgorithmSecurityHeader */ |
| 25317 | { |
| 25318 | UA_TYPENAME("AsymmetricAlgorithmSecurityHeader") /* .typeName */ |
| 25319 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */ |
| 25320 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 25321 | sizeof(UA_AsymmetricAlgorithmSecurityHeader), /* .memSize */ |
| 25322 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25323 | false, /* .pointerFree */ |
| 25324 | false, /* .overlayable */ |
| 25325 | 3, /* .membersSize */ |
| 25326 | AsymmetricAlgorithmSecurityHeader_members /* .members */ |
| 25327 | }, |
| 25328 | /* SequenceHeader */ |
| 25329 | { |
| 25330 | UA_TYPENAME("SequenceHeader") /* .typeName */ |
| 25331 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .typeId */ |
| 25332 | {0, UA_NODEIDTYPE_NUMERIC, {0}}, /* .binaryEncodingId */ |
| 25333 | sizeof(UA_SequenceHeader), /* .memSize */ |
| 25334 | UA_DATATYPEKIND_STRUCTURE, /* .typeKind */ |
| 25335 | true, /* .pointerFree */ |
| 25336 | false, /* .overlayable */ |
| 25337 | 2, /* .membersSize */ |
| 25338 | SequenceHeader_members /* .members */ |
| 25339 | }, |
| 25340 | }; |
| 25341 | |
| 25342 | |
| 25343 | /**** amalgamated original file "/build/src_generated/open62541/statuscodes.c" ****/ |
| 25344 | |
| 25345 | /********************************** |
| 25346 | * Autogenerated -- do not modify * |
| 25347 | **********************************/ |
| 25348 | |
| 25349 | |
| 25350 | typedef struct { |
| 25351 | UA_StatusCode code; |
| 25352 | const char *name; |
| 25353 | } UA_StatusCodeName; |
| 25354 | |
| 25355 | #ifndef UA_ENABLE_STATUSCODE_DESCRIPTIONS |
| 25356 | static const char * emptyStatusCodeName = ""; |
| 25357 | const char * UA_StatusCode_name(UA_StatusCode code) { |
| 25358 | return emptyStatusCodeName; |
| 25359 | } |
| 25360 | #else |
| 25361 | static const size_t statusCodeDescriptionsSize = 252; |
| 25362 | static const UA_StatusCodeName statusCodeDescriptions[252] = { |
| 25363 | {UA_STATUSCODE_GOOD, "Good"}, |
| 25364 | {UA_STATUSCODE_GOOD, "Good"}, |
| 25365 | {UA_STATUSCODE_UNCERTAIN, "Uncertain"}, |
| 25366 | {UA_STATUSCODE_BAD, "Bad"}, |
| 25367 | {UA_STATUSCODE_BADUNEXPECTEDERROR, "BadUnexpectedError"}, |
| 25368 | {UA_STATUSCODE_BADINTERNALERROR, "BadInternalError"}, |
| 25369 | {UA_STATUSCODE_BADOUTOFMEMORY, "BadOutOfMemory"}, |
| 25370 | {UA_STATUSCODE_BADRESOURCEUNAVAILABLE, "BadResourceUnavailable"}, |
| 25371 | {UA_STATUSCODE_BADCOMMUNICATIONERROR, "BadCommunicationError"}, |
| 25372 | {UA_STATUSCODE_BADENCODINGERROR, "BadEncodingError"}, |
| 25373 | {UA_STATUSCODE_BADDECODINGERROR, "BadDecodingError"}, |
| 25374 | {UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED, "BadEncodingLimitsExceeded"}, |
| 25375 | {UA_STATUSCODE_BADREQUESTTOOLARGE, "BadRequestTooLarge"}, |
| 25376 | {UA_STATUSCODE_BADRESPONSETOOLARGE, "BadResponseTooLarge"}, |
| 25377 | {UA_STATUSCODE_BADUNKNOWNRESPONSE, "BadUnknownResponse"}, |
| 25378 | {UA_STATUSCODE_BADTIMEOUT, "BadTimeout"}, |
| 25379 | {UA_STATUSCODE_BADSERVICEUNSUPPORTED, "BadServiceUnsupported"}, |
| 25380 | {UA_STATUSCODE_BADSHUTDOWN, "BadShutdown"}, |
| 25381 | {UA_STATUSCODE_BADSERVERNOTCONNECTED, "BadServerNotConnected"}, |
| 25382 | {UA_STATUSCODE_BADSERVERHALTED, "BadServerHalted"}, |
| 25383 | {UA_STATUSCODE_BADNOTHINGTODO, "BadNothingToDo"}, |
| 25384 | {UA_STATUSCODE_BADTOOMANYOPERATIONS, "BadTooManyOperations"}, |
| 25385 | {UA_STATUSCODE_BADTOOMANYMONITOREDITEMS, "BadTooManyMonitoredItems"}, |
| 25386 | {UA_STATUSCODE_BADDATATYPEIDUNKNOWN, "BadDataTypeIdUnknown"}, |
| 25387 | {UA_STATUSCODE_BADCERTIFICATEINVALID, "BadCertificateInvalid"}, |
| 25388 | {UA_STATUSCODE_BADSECURITYCHECKSFAILED, "BadSecurityChecksFailed"}, |
| 25389 | {UA_STATUSCODE_BADCERTIFICATEPOLICYCHECKFAILED, "BadCertificatePolicyCheckFailed"}, |
| 25390 | {UA_STATUSCODE_BADCERTIFICATETIMEINVALID, "BadCertificateTimeInvalid"}, |
| 25391 | {UA_STATUSCODE_BADCERTIFICATEISSUERTIMEINVALID, "BadCertificateIssuerTimeInvalid"}, |
| 25392 | {UA_STATUSCODE_BADCERTIFICATEHOSTNAMEINVALID, "BadCertificateHostNameInvalid"}, |
| 25393 | {UA_STATUSCODE_BADCERTIFICATEURIINVALID, "BadCertificateUriInvalid"}, |
| 25394 | {UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED, "BadCertificateUseNotAllowed"}, |
| 25395 | {UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED, "BadCertificateIssuerUseNotAllowed"}, |
| 25396 | {UA_STATUSCODE_BADCERTIFICATEUNTRUSTED, "BadCertificateUntrusted"}, |
| 25397 | {UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN, "BadCertificateRevocationUnknown"}, |
| 25398 | {UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN, "BadCertificateIssuerRevocationUnknown"}, |
| 25399 | {UA_STATUSCODE_BADCERTIFICATEREVOKED, "BadCertificateRevoked"}, |
| 25400 | {UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED, "BadCertificateIssuerRevoked"}, |
| 25401 | {UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE, "BadCertificateChainIncomplete"}, |
| 25402 | {UA_STATUSCODE_BADUSERACCESSDENIED, "BadUserAccessDenied"}, |
| 25403 | {UA_STATUSCODE_BADIDENTITYTOKENINVALID, "BadIdentityTokenInvalid"}, |
| 25404 | {UA_STATUSCODE_BADIDENTITYTOKENREJECTED, "BadIdentityTokenRejected"}, |
| 25405 | {UA_STATUSCODE_BADSECURECHANNELIDINVALID, "BadSecureChannelIdInvalid"}, |
| 25406 | {UA_STATUSCODE_BADINVALIDTIMESTAMP, "BadInvalidTimestamp"}, |
| 25407 | {UA_STATUSCODE_BADNONCEINVALID, "BadNonceInvalid"}, |
| 25408 | {UA_STATUSCODE_BADSESSIONIDINVALID, "BadSessionIdInvalid"}, |
| 25409 | {UA_STATUSCODE_BADSESSIONCLOSED, "BadSessionClosed"}, |
| 25410 | {UA_STATUSCODE_BADSESSIONNOTACTIVATED, "BadSessionNotActivated"}, |
| 25411 | {UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID, "BadSubscriptionIdInvalid"}, |
| 25412 | {UA_STATUSCODE_BADREQUESTHEADERINVALID, "BadRequestHeaderInvalid"}, |
| 25413 | {UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID, "BadTimestampsToReturnInvalid"}, |
| 25414 | {UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT, "BadRequestCancelledByClient"}, |
| 25415 | {UA_STATUSCODE_BADTOOMANYARGUMENTS, "BadTooManyArguments"}, |
| 25416 | {UA_STATUSCODE_BADLICENSEEXPIRED, "BadLicenseExpired"}, |
| 25417 | {UA_STATUSCODE_BADLICENSELIMITSEXCEEDED, "BadLicenseLimitsExceeded"}, |
| 25418 | {UA_STATUSCODE_BADLICENSENOTAVAILABLE, "BadLicenseNotAvailable"}, |
| 25419 | {UA_STATUSCODE_GOODSUBSCRIPTIONTRANSFERRED, "GoodSubscriptionTransferred"}, |
| 25420 | {UA_STATUSCODE_GOODCOMPLETESASYNCHRONOUSLY, "GoodCompletesAsynchronously"}, |
| 25421 | {UA_STATUSCODE_GOODOVERLOAD, "GoodOverload"}, |
| 25422 | {UA_STATUSCODE_GOODCLAMPED, "GoodClamped"}, |
| 25423 | {UA_STATUSCODE_BADNOCOMMUNICATION, "BadNoCommunication"}, |
| 25424 | {UA_STATUSCODE_BADWAITINGFORINITIALDATA, "BadWaitingForInitialData"}, |
| 25425 | {UA_STATUSCODE_BADNODEIDINVALID, "BadNodeIdInvalid"}, |
| 25426 | {UA_STATUSCODE_BADNODEIDUNKNOWN, "BadNodeIdUnknown"}, |
| 25427 | {UA_STATUSCODE_BADATTRIBUTEIDINVALID, "BadAttributeIdInvalid"}, |
| 25428 | {UA_STATUSCODE_BADINDEXRANGEINVALID, "BadIndexRangeInvalid"}, |
| 25429 | {UA_STATUSCODE_BADINDEXRANGENODATA, "BadIndexRangeNoData"}, |
| 25430 | {UA_STATUSCODE_BADDATAENCODINGINVALID, "BadDataEncodingInvalid"}, |
| 25431 | {UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED, "BadDataEncodingUnsupported"}, |
| 25432 | {UA_STATUSCODE_BADNOTREADABLE, "BadNotReadable"}, |
| 25433 | {UA_STATUSCODE_BADNOTWRITABLE, "BadNotWritable"}, |
| 25434 | {UA_STATUSCODE_BADOUTOFRANGE, "BadOutOfRange"}, |
| 25435 | {UA_STATUSCODE_BADNOTSUPPORTED, "BadNotSupported"}, |
| 25436 | {UA_STATUSCODE_BADNOTFOUND, "BadNotFound"}, |
| 25437 | {UA_STATUSCODE_BADOBJECTDELETED, "BadObjectDeleted"}, |
| 25438 | {UA_STATUSCODE_BADNOTIMPLEMENTED, "BadNotImplemented"}, |
| 25439 | {UA_STATUSCODE_BADMONITORINGMODEINVALID, "BadMonitoringModeInvalid"}, |
| 25440 | {UA_STATUSCODE_BADMONITOREDITEMIDINVALID, "BadMonitoredItemIdInvalid"}, |
| 25441 | {UA_STATUSCODE_BADMONITOREDITEMFILTERINVALID, "BadMonitoredItemFilterInvalid"}, |
| 25442 | {UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED, "BadMonitoredItemFilterUnsupported"}, |
| 25443 | {UA_STATUSCODE_BADFILTERNOTALLOWED, "BadFilterNotAllowed"}, |
| 25444 | {UA_STATUSCODE_BADSTRUCTUREMISSING, "BadStructureMissing"}, |
| 25445 | {UA_STATUSCODE_BADEVENTFILTERINVALID, "BadEventFilterInvalid"}, |
| 25446 | {UA_STATUSCODE_BADCONTENTFILTERINVALID, "BadContentFilterInvalid"}, |
| 25447 | {UA_STATUSCODE_BADFILTEROPERATORINVALID, "BadFilterOperatorInvalid"}, |
| 25448 | {UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED, "BadFilterOperatorUnsupported"}, |
| 25449 | {UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH, "BadFilterOperandCountMismatch"}, |
| 25450 | {UA_STATUSCODE_BADFILTEROPERANDINVALID, "BadFilterOperandInvalid"}, |
| 25451 | {UA_STATUSCODE_BADFILTERELEMENTINVALID, "BadFilterElementInvalid"}, |
| 25452 | {UA_STATUSCODE_BADFILTERLITERALINVALID, "BadFilterLiteralInvalid"}, |
| 25453 | {UA_STATUSCODE_BADCONTINUATIONPOINTINVALID, "BadContinuationPointInvalid"}, |
| 25454 | {UA_STATUSCODE_BADNOCONTINUATIONPOINTS, "BadNoContinuationPoints"}, |
| 25455 | {UA_STATUSCODE_BADREFERENCETYPEIDINVALID, "BadReferenceTypeIdInvalid"}, |
| 25456 | {UA_STATUSCODE_BADBROWSEDIRECTIONINVALID, "BadBrowseDirectionInvalid"}, |
| 25457 | {UA_STATUSCODE_BADNODENOTINVIEW, "BadNodeNotInView"}, |
| 25458 | {UA_STATUSCODE_BADNUMERICOVERFLOW, "BadNumericOverflow"}, |
| 25459 | {UA_STATUSCODE_BADSERVERURIINVALID, "BadServerUriInvalid"}, |
| 25460 | {UA_STATUSCODE_BADSERVERNAMEMISSING, "BadServerNameMissing"}, |
| 25461 | {UA_STATUSCODE_BADDISCOVERYURLMISSING, "BadDiscoveryUrlMissing"}, |
| 25462 | {UA_STATUSCODE_BADSEMPAHOREFILEMISSING, "BadSempahoreFileMissing"}, |
| 25463 | {UA_STATUSCODE_BADREQUESTTYPEINVALID, "BadRequestTypeInvalid"}, |
| 25464 | {UA_STATUSCODE_BADSECURITYMODEREJECTED, "BadSecurityModeRejected"}, |
| 25465 | {UA_STATUSCODE_BADSECURITYPOLICYREJECTED, "BadSecurityPolicyRejected"}, |
| 25466 | {UA_STATUSCODE_BADTOOMANYSESSIONS, "BadTooManySessions"}, |
| 25467 | {UA_STATUSCODE_BADUSERSIGNATUREINVALID, "BadUserSignatureInvalid"}, |
| 25468 | {UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID, "BadApplicationSignatureInvalid"}, |
| 25469 | {UA_STATUSCODE_BADNOVALIDCERTIFICATES, "BadNoValidCertificates"}, |
| 25470 | {UA_STATUSCODE_BADIDENTITYCHANGENOTSUPPORTED, "BadIdentityChangeNotSupported"}, |
| 25471 | {UA_STATUSCODE_BADREQUESTCANCELLEDBYREQUEST, "BadRequestCancelledByRequest"}, |
| 25472 | {UA_STATUSCODE_BADPARENTNODEIDINVALID, "BadParentNodeIdInvalid"}, |
| 25473 | {UA_STATUSCODE_BADREFERENCENOTALLOWED, "BadReferenceNotAllowed"}, |
| 25474 | {UA_STATUSCODE_BADNODEIDREJECTED, "BadNodeIdRejected"}, |
| 25475 | {UA_STATUSCODE_BADNODEIDEXISTS, "BadNodeIdExists"}, |
| 25476 | {UA_STATUSCODE_BADNODECLASSINVALID, "BadNodeClassInvalid"}, |
| 25477 | {UA_STATUSCODE_BADBROWSENAMEINVALID, "BadBrowseNameInvalid"}, |
| 25478 | {UA_STATUSCODE_BADBROWSENAMEDUPLICATED, "BadBrowseNameDuplicated"}, |
| 25479 | {UA_STATUSCODE_BADNODEATTRIBUTESINVALID, "BadNodeAttributesInvalid"}, |
| 25480 | {UA_STATUSCODE_BADTYPEDEFINITIONINVALID, "BadTypeDefinitionInvalid"}, |
| 25481 | {UA_STATUSCODE_BADSOURCENODEIDINVALID, "BadSourceNodeIdInvalid"}, |
| 25482 | {UA_STATUSCODE_BADTARGETNODEIDINVALID, "BadTargetNodeIdInvalid"}, |
| 25483 | {UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED, "BadDuplicateReferenceNotAllowed"}, |
| 25484 | {UA_STATUSCODE_BADINVALIDSELFREFERENCE, "BadInvalidSelfReference"}, |
| 25485 | {UA_STATUSCODE_BADREFERENCELOCALONLY, "BadReferenceLocalOnly"}, |
| 25486 | {UA_STATUSCODE_BADNODELETERIGHTS, "BadNoDeleteRights"}, |
| 25487 | {UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED, "UncertainReferenceNotDeleted"}, |
| 25488 | {UA_STATUSCODE_BADSERVERINDEXINVALID, "BadServerIndexInvalid"}, |
| 25489 | {UA_STATUSCODE_BADVIEWIDUNKNOWN, "BadViewIdUnknown"}, |
| 25490 | {UA_STATUSCODE_BADVIEWTIMESTAMPINVALID, "BadViewTimestampInvalid"}, |
| 25491 | {UA_STATUSCODE_BADVIEWPARAMETERMISMATCH, "BadViewParameterMismatch"}, |
| 25492 | {UA_STATUSCODE_BADVIEWVERSIONINVALID, "BadViewVersionInvalid"}, |
| 25493 | {UA_STATUSCODE_UNCERTAINNOTALLNODESAVAILABLE, "UncertainNotAllNodesAvailable"}, |
| 25494 | {UA_STATUSCODE_GOODRESULTSMAYBEINCOMPLETE, "GoodResultsMayBeIncomplete"}, |
| 25495 | {UA_STATUSCODE_BADNOTTYPEDEFINITION, "BadNotTypeDefinition"}, |
| 25496 | {UA_STATUSCODE_UNCERTAINREFERENCEOUTOFSERVER, "UncertainReferenceOutOfServer"}, |
| 25497 | {UA_STATUSCODE_BADTOOMANYMATCHES, "BadTooManyMatches"}, |
| 25498 | {UA_STATUSCODE_BADQUERYTOOCOMPLEX, "BadQueryTooComplex"}, |
| 25499 | {UA_STATUSCODE_BADNOMATCH, "BadNoMatch"}, |
| 25500 | {UA_STATUSCODE_BADMAXAGEINVALID, "BadMaxAgeInvalid"}, |
| 25501 | {UA_STATUSCODE_BADSECURITYMODEINSUFFICIENT, "BadSecurityModeInsufficient"}, |
| 25502 | {UA_STATUSCODE_BADHISTORYOPERATIONINVALID, "BadHistoryOperationInvalid"}, |
| 25503 | {UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED, "BadHistoryOperationUnsupported"}, |
| 25504 | {UA_STATUSCODE_BADINVALIDTIMESTAMPARGUMENT, "BadInvalidTimestampArgument"}, |
| 25505 | {UA_STATUSCODE_BADWRITENOTSUPPORTED, "BadWriteNotSupported"}, |
| 25506 | {UA_STATUSCODE_BADTYPEMISMATCH, "BadTypeMismatch"}, |
| 25507 | {UA_STATUSCODE_BADMETHODINVALID, "BadMethodInvalid"}, |
| 25508 | {UA_STATUSCODE_BADARGUMENTSMISSING, "BadArgumentsMissing"}, |
| 25509 | {UA_STATUSCODE_BADNOTEXECUTABLE, "BadNotExecutable"}, |
| 25510 | {UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS, "BadTooManySubscriptions"}, |
| 25511 | {UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS, "BadTooManyPublishRequests"}, |
| 25512 | {UA_STATUSCODE_BADNOSUBSCRIPTION, "BadNoSubscription"}, |
| 25513 | {UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN, "BadSequenceNumberUnknown"}, |
| 25514 | {UA_STATUSCODE_GOODRETRANSMISSIONQUEUENOTSUPPORTED, "GoodRetransmissionQueueNotSupported"}, |
| 25515 | {UA_STATUSCODE_BADMESSAGENOTAVAILABLE, "BadMessageNotAvailable"}, |
| 25516 | {UA_STATUSCODE_BADINSUFFICIENTCLIENTPROFILE, "BadInsufficientClientProfile"}, |
| 25517 | {UA_STATUSCODE_BADSTATENOTACTIVE, "BadStateNotActive"}, |
| 25518 | {UA_STATUSCODE_BADALREADYEXISTS, "BadAlreadyExists"}, |
| 25519 | {UA_STATUSCODE_BADTCPSERVERTOOBUSY, "BadTcpServerTooBusy"}, |
| 25520 | {UA_STATUSCODE_BADTCPMESSAGETYPEINVALID, "BadTcpMessageTypeInvalid"}, |
| 25521 | {UA_STATUSCODE_BADTCPSECURECHANNELUNKNOWN, "BadTcpSecureChannelUnknown"}, |
| 25522 | {UA_STATUSCODE_BADTCPMESSAGETOOLARGE, "BadTcpMessageTooLarge"}, |
| 25523 | {UA_STATUSCODE_BADTCPNOTENOUGHRESOURCES, "BadTcpNotEnoughResources"}, |
| 25524 | {UA_STATUSCODE_BADTCPINTERNALERROR, "BadTcpInternalError"}, |
| 25525 | {UA_STATUSCODE_BADTCPENDPOINTURLINVALID, "BadTcpEndpointUrlInvalid"}, |
| 25526 | {UA_STATUSCODE_BADREQUESTINTERRUPTED, "BadRequestInterrupted"}, |
| 25527 | {UA_STATUSCODE_BADREQUESTTIMEOUT, "BadRequestTimeout"}, |
| 25528 | {UA_STATUSCODE_BADSECURECHANNELCLOSED, "BadSecureChannelClosed"}, |
| 25529 | {UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN, "BadSecureChannelTokenUnknown"}, |
| 25530 | {UA_STATUSCODE_BADSEQUENCENUMBERINVALID, "BadSequenceNumberInvalid"}, |
| 25531 | {UA_STATUSCODE_BADPROTOCOLVERSIONUNSUPPORTED, "BadProtocolVersionUnsupported"}, |
| 25532 | {UA_STATUSCODE_BADCONFIGURATIONERROR, "BadConfigurationError"}, |
| 25533 | {UA_STATUSCODE_BADNOTCONNECTED, "BadNotConnected"}, |
| 25534 | {UA_STATUSCODE_BADDEVICEFAILURE, "BadDeviceFailure"}, |
| 25535 | {UA_STATUSCODE_BADSENSORFAILURE, "BadSensorFailure"}, |
| 25536 | {UA_STATUSCODE_BADOUTOFSERVICE, "BadOutOfService"}, |
| 25537 | {UA_STATUSCODE_BADDEADBANDFILTERINVALID, "BadDeadbandFilterInvalid"}, |
| 25538 | {UA_STATUSCODE_UNCERTAINNOCOMMUNICATIONLASTUSABLEVALUE, "UncertainNoCommunicationLastUsableValue"}, |
| 25539 | {UA_STATUSCODE_UNCERTAINLASTUSABLEVALUE, "UncertainLastUsableValue"}, |
| 25540 | {UA_STATUSCODE_UNCERTAINSUBSTITUTEVALUE, "UncertainSubstituteValue"}, |
| 25541 | {UA_STATUSCODE_UNCERTAININITIALVALUE, "UncertainInitialValue"}, |
| 25542 | {UA_STATUSCODE_UNCERTAINSENSORNOTACCURATE, "UncertainSensorNotAccurate"}, |
| 25543 | {UA_STATUSCODE_UNCERTAINENGINEERINGUNITSEXCEEDED, "UncertainEngineeringUnitsExceeded"}, |
| 25544 | {UA_STATUSCODE_UNCERTAINSUBNORMAL, "UncertainSubNormal"}, |
| 25545 | {UA_STATUSCODE_GOODLOCALOVERRIDE, "GoodLocalOverride"}, |
| 25546 | {UA_STATUSCODE_BADREFRESHINPROGRESS, "BadRefreshInProgress"}, |
| 25547 | {UA_STATUSCODE_BADCONDITIONALREADYDISABLED, "BadConditionAlreadyDisabled"}, |
| 25548 | {UA_STATUSCODE_BADCONDITIONALREADYENABLED, "BadConditionAlreadyEnabled"}, |
| 25549 | {UA_STATUSCODE_BADCONDITIONDISABLED, "BadConditionDisabled"}, |
| 25550 | {UA_STATUSCODE_BADEVENTIDUNKNOWN, "BadEventIdUnknown"}, |
| 25551 | {UA_STATUSCODE_BADEVENTNOTACKNOWLEDGEABLE, "BadEventNotAcknowledgeable"}, |
| 25552 | {UA_STATUSCODE_BADDIALOGNOTACTIVE, "BadDialogNotActive"}, |
| 25553 | {UA_STATUSCODE_BADDIALOGRESPONSEINVALID, "BadDialogResponseInvalid"}, |
| 25554 | {UA_STATUSCODE_BADCONDITIONBRANCHALREADYACKED, "BadConditionBranchAlreadyAcked"}, |
| 25555 | {UA_STATUSCODE_BADCONDITIONBRANCHALREADYCONFIRMED, "BadConditionBranchAlreadyConfirmed"}, |
| 25556 | {UA_STATUSCODE_BADCONDITIONALREADYSHELVED, "BadConditionAlreadyShelved"}, |
| 25557 | {UA_STATUSCODE_BADCONDITIONNOTSHELVED, "BadConditionNotShelved"}, |
| 25558 | {UA_STATUSCODE_BADSHELVINGTIMEOUTOFRANGE, "BadShelvingTimeOutOfRange"}, |
| 25559 | {UA_STATUSCODE_BADNODATA, "BadNoData"}, |
| 25560 | {UA_STATUSCODE_BADBOUNDNOTFOUND, "BadBoundNotFound"}, |
| 25561 | {UA_STATUSCODE_BADBOUNDNOTSUPPORTED, "BadBoundNotSupported"}, |
| 25562 | {UA_STATUSCODE_BADDATALOST, "BadDataLost"}, |
| 25563 | {UA_STATUSCODE_BADDATAUNAVAILABLE, "BadDataUnavailable"}, |
| 25564 | {UA_STATUSCODE_BADENTRYEXISTS, "BadEntryExists"}, |
| 25565 | {UA_STATUSCODE_BADNOENTRYEXISTS, "BadNoEntryExists"}, |
| 25566 | {UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED, "BadTimestampNotSupported"}, |
| 25567 | {UA_STATUSCODE_GOODENTRYINSERTED, "GoodEntryInserted"}, |
| 25568 | {UA_STATUSCODE_GOODENTRYREPLACED, "GoodEntryReplaced"}, |
| 25569 | {UA_STATUSCODE_UNCERTAINDATASUBNORMAL, "UncertainDataSubNormal"}, |
| 25570 | {UA_STATUSCODE_GOODNODATA, "GoodNoData"}, |
| 25571 | {UA_STATUSCODE_GOODMOREDATA, "GoodMoreData"}, |
| 25572 | {UA_STATUSCODE_BADAGGREGATELISTMISMATCH, "BadAggregateListMismatch"}, |
| 25573 | {UA_STATUSCODE_BADAGGREGATENOTSUPPORTED, "BadAggregateNotSupported"}, |
| 25574 | {UA_STATUSCODE_BADAGGREGATEINVALIDINPUTS, "BadAggregateInvalidInputs"}, |
| 25575 | {UA_STATUSCODE_BADAGGREGATECONFIGURATIONREJECTED, "BadAggregateConfigurationRejected"}, |
| 25576 | {UA_STATUSCODE_GOODDATAIGNORED, "GoodDataIgnored"}, |
| 25577 | {UA_STATUSCODE_BADREQUESTNOTALLOWED, "BadRequestNotAllowed"}, |
| 25578 | {UA_STATUSCODE_BADREQUESTNOTCOMPLETE, "BadRequestNotComplete"}, |
| 25579 | {UA_STATUSCODE_BADTICKETREQUIRED, "BadTicketRequired"}, |
| 25580 | {UA_STATUSCODE_BADTICKETINVALID, "BadTicketInvalid"}, |
| 25581 | {UA_STATUSCODE_GOODEDITED, "GoodEdited"}, |
| 25582 | {UA_STATUSCODE_GOODPOSTACTIONFAILED, "GoodPostActionFailed"}, |
| 25583 | {UA_STATUSCODE_UNCERTAINDOMINANTVALUECHANGED, "UncertainDominantValueChanged"}, |
| 25584 | {UA_STATUSCODE_GOODDEPENDENTVALUECHANGED, "GoodDependentValueChanged"}, |
| 25585 | {UA_STATUSCODE_BADDOMINANTVALUECHANGED, "BadDominantValueChanged"}, |
| 25586 | {UA_STATUSCODE_UNCERTAINDEPENDENTVALUECHANGED, "UncertainDependentValueChanged"}, |
| 25587 | {UA_STATUSCODE_BADDEPENDENTVALUECHANGED, "BadDependentValueChanged"}, |
| 25588 | {UA_STATUSCODE_GOODEDITED_DEPENDENTVALUECHANGED, "GoodEdited_DependentValueChanged"}, |
| 25589 | {UA_STATUSCODE_GOODEDITED_DOMINANTVALUECHANGED, "GoodEdited_DominantValueChanged"}, |
| 25590 | {UA_STATUSCODE_GOODEDITED_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "GoodEdited_DominantValueChanged_DependentValueChanged"}, |
| 25591 | {UA_STATUSCODE_BADEDITED_OUTOFRANGE, "BadEdited_OutOfRange"}, |
| 25592 | {UA_STATUSCODE_BADINITIALVALUE_OUTOFRANGE, "BadInitialValue_OutOfRange"}, |
| 25593 | {UA_STATUSCODE_BADOUTOFRANGE_DOMINANTVALUECHANGED, "BadOutOfRange_DominantValueChanged"}, |
| 25594 | {UA_STATUSCODE_BADEDITED_OUTOFRANGE_DOMINANTVALUECHANGED, "BadEdited_OutOfRange_DominantValueChanged"}, |
| 25595 | {UA_STATUSCODE_BADOUTOFRANGE_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "BadOutOfRange_DominantValueChanged_DependentValueChanged"}, |
| 25596 | {UA_STATUSCODE_BADEDITED_OUTOFRANGE_DOMINANTVALUECHANGED_DEPENDENTVALUECHANGED, "BadEdited_OutOfRange_DominantValueChanged_DependentValueChanged"}, |
| 25597 | {UA_STATUSCODE_GOODCOMMUNICATIONEVENT, "GoodCommunicationEvent"}, |
| 25598 | {UA_STATUSCODE_GOODSHUTDOWNEVENT, "GoodShutdownEvent"}, |
| 25599 | {UA_STATUSCODE_GOODCALLAGAIN, "GoodCallAgain"}, |
| 25600 | {UA_STATUSCODE_GOODNONCRITICALTIMEOUT, "GoodNonCriticalTimeout"}, |
| 25601 | {UA_STATUSCODE_BADINVALIDARGUMENT, "BadInvalidArgument"}, |
| 25602 | {UA_STATUSCODE_BADCONNECTIONREJECTED, "BadConnectionRejected"}, |
| 25603 | {UA_STATUSCODE_BADDISCONNECT, "BadDisconnect"}, |
| 25604 | {UA_STATUSCODE_BADCONNECTIONCLOSED, "BadConnectionClosed"}, |
| 25605 | {UA_STATUSCODE_BADINVALIDSTATE, "BadInvalidState"}, |
| 25606 | {UA_STATUSCODE_BADENDOFSTREAM, "BadEndOfStream"}, |
| 25607 | {UA_STATUSCODE_BADNODATAAVAILABLE, "BadNoDataAvailable"}, |
| 25608 | {UA_STATUSCODE_BADWAITINGFORRESPONSE, "BadWaitingForResponse"}, |
| 25609 | {UA_STATUSCODE_BADOPERATIONABANDONED, "BadOperationAbandoned"}, |
| 25610 | {UA_STATUSCODE_BADEXPECTEDSTREAMTOBLOCK, "BadExpectedStreamToBlock"}, |
| 25611 | {UA_STATUSCODE_BADWOULDBLOCK, "BadWouldBlock"}, |
| 25612 | {UA_STATUSCODE_BADSYNTAXERROR, "BadSyntaxError"}, |
| 25613 | {UA_STATUSCODE_BADMAXCONNECTIONSREACHED, "BadMaxConnectionsReached"}, |
| 25614 | {0xffffffff, "Unknown StatusCode"} |
| 25615 | }; |
| 25616 | |
| 25617 | const char * UA_StatusCode_name(UA_StatusCode code) { |
| 25618 | for (size_t i = 0; i < statusCodeDescriptionsSize; ++i) { |
| 25619 | if (UA_StatusCode_isEqualTop(s1: statusCodeDescriptions[i].code,s2: code)) |
| 25620 | return statusCodeDescriptions[i].name; |
| 25621 | } |
| 25622 | return statusCodeDescriptions[statusCodeDescriptionsSize-1].name; |
| 25623 | } |
| 25624 | |
| 25625 | #endif |
| 25626 | |
| 25627 | /**** amalgamated original file "/src/ua_util.c" ****/ |
| 25628 | |
| 25629 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 25630 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 25631 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 25632 | * |
| 25633 | * Copyright 2014, 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 25634 | * Copyright 2014 (c) Florian Palm |
| 25635 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 25636 | */ |
| 25637 | |
| 25638 | /* If UA_ENABLE_INLINABLE_EXPORT is enabled, then this file is the compilation |
| 25639 | * unit for the generated code from UA_INLINABLE definitions. */ |
| 25640 | #define UA_INLINABLE_IMPL 1 |
| 25641 | |
| 25642 | |
| 25643 | |
| 25644 | static UA_DataTypeKind |
| 25645 | typeEquivalence(const UA_DataType *t) { |
| 25646 | UA_DataTypeKind k = (UA_DataTypeKind)t->typeKind; |
| 25647 | if(k == UA_DATATYPEKIND_ENUM) |
| 25648 | return UA_DATATYPEKIND_INT32; |
| 25649 | return k; |
| 25650 | } |
| 25651 | |
| 25652 | void |
| 25653 | adjustType(UA_Variant *value, const UA_DataType *targetType) { |
| 25654 | /* If the value is empty, there is nothing we can do here */ |
| 25655 | const UA_DataType *type = value->type; |
| 25656 | if(!type || !targetType) |
| 25657 | return; |
| 25658 | |
| 25659 | /* A string is written to a byte array. the valuerank and array dimensions |
| 25660 | * are checked later */ |
| 25661 | if(targetType == &UA_TYPES[UA_TYPES_BYTE] && |
| 25662 | type == &UA_TYPES[UA_TYPES_BYTESTRING] && |
| 25663 | UA_Variant_isScalar(v: value)) { |
| 25664 | UA_ByteString *str = (UA_ByteString*)value->data; |
| 25665 | value->type = &UA_TYPES[UA_TYPES_BYTE]; |
| 25666 | value->arrayLength = str->length; |
| 25667 | value->data = str->data; |
| 25668 | return; |
| 25669 | } |
| 25670 | |
| 25671 | /* An enum was sent as an int32, or an opaque type as a bytestring. This |
| 25672 | * is detected with the typeKind indicating the "true" datatype. */ |
| 25673 | UA_DataTypeKind te1 = typeEquivalence(t: targetType); |
| 25674 | UA_DataTypeKind te2 = typeEquivalence(t: type); |
| 25675 | if(te1 == te2 && te1 <= UA_DATATYPEKIND_ENUM) { |
| 25676 | value->type = targetType; |
| 25677 | return; |
| 25678 | } |
| 25679 | |
| 25680 | /* Add more possible type adjustments here. What are they? */ |
| 25681 | } |
| 25682 | |
| 25683 | size_t |
| 25684 | UA_readNumberWithBase(const UA_Byte *buf, size_t buflen, UA_UInt32 *number, UA_Byte base) { |
| 25685 | UA_assert(buf); |
| 25686 | UA_assert(number); |
| 25687 | u32 n = 0; |
| 25688 | size_t progress = 0; |
| 25689 | /* read numbers until the end or a non-number character appears */ |
| 25690 | while(progress < buflen) { |
| 25691 | u8 c = buf[progress]; |
| 25692 | if(c >= '0' && c <= '9' && c <= '0' + (base-1)) |
| 25693 | n = (n * base) + c - '0'; |
| 25694 | else if(base > 9 && c >= 'a' && c <= 'z' && c <= 'a' + (base-11)) |
| 25695 | n = (n * base) + c-'a' + 10; |
| 25696 | else if(base > 9 && c >= 'A' && c <= 'Z' && c <= 'A' + (base-11)) |
| 25697 | n = (n * base) + c-'A' + 10; |
| 25698 | else |
| 25699 | break; |
| 25700 | ++progress; |
| 25701 | } |
| 25702 | *number = n; |
| 25703 | return progress; |
| 25704 | } |
| 25705 | |
| 25706 | size_t |
| 25707 | UA_readNumber(const UA_Byte *buf, size_t buflen, UA_UInt32 *number) { |
| 25708 | return UA_readNumberWithBase(buf, buflen, number, base: 10); |
| 25709 | } |
| 25710 | |
| 25711 | struct urlSchema { |
| 25712 | const char *schema; |
| 25713 | }; |
| 25714 | |
| 25715 | static const struct urlSchema schemas[] = { |
| 25716 | {"opc.tcp://"}, |
| 25717 | {"opc.udp://"}, |
| 25718 | {"opc.eth://"}, |
| 25719 | {"opc.mqtt://"} |
| 25720 | }; |
| 25721 | |
| 25722 | static const unsigned scNumSchemas = sizeof(schemas) / sizeof(schemas[0]); |
| 25723 | static const unsigned scEthSchemaIdx = 2; |
| 25724 | |
| 25725 | UA_StatusCode |
| 25726 | UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname, |
| 25727 | UA_UInt16 *outPort, UA_String *outPath) { |
| 25728 | /* Url must begin with "opc.tcp://" or opc.udp:// (if pubsub enabled) */ |
| 25729 | if(endpointUrl->length < 11) { |
| 25730 | return UA_STATUSCODE_BADTCPENDPOINTURLINVALID; |
| 25731 | } |
| 25732 | |
| 25733 | /* Which type of schema is this? */ |
| 25734 | unsigned schemaType = 0; |
| 25735 | for(; schemaType < scNumSchemas; schemaType++) { |
| 25736 | if(strncmp(s1: (char*)endpointUrl->data, |
| 25737 | s2: schemas[schemaType].schema, |
| 25738 | n: strlen(s: schemas[schemaType].schema)) == 0) |
| 25739 | break; |
| 25740 | } |
| 25741 | if(schemaType == scNumSchemas) |
| 25742 | return UA_STATUSCODE_BADTCPENDPOINTURLINVALID; |
| 25743 | |
| 25744 | /* Forward the current position until the first colon or slash */ |
| 25745 | size_t start = strlen(s: schemas[schemaType].schema); |
| 25746 | size_t curr = start; |
| 25747 | UA_Boolean ipv6 = false; |
| 25748 | if(endpointUrl->length > curr && endpointUrl->data[curr] == '[') { |
| 25749 | /* IPv6: opc.tcp://[2001:0db8:85a3::8a2e:0370:7334]:1234/path */ |
| 25750 | for(; curr < endpointUrl->length; ++curr) { |
| 25751 | if(endpointUrl->data[curr] == ']') |
| 25752 | break; |
| 25753 | } |
| 25754 | if(curr == endpointUrl->length) |
| 25755 | return UA_STATUSCODE_BADTCPENDPOINTURLINVALID; |
| 25756 | curr++; |
| 25757 | ipv6 = true; |
| 25758 | } else { |
| 25759 | /* IPv4 or hostname: opc.tcp://something.something:1234/path */ |
| 25760 | for(; curr < endpointUrl->length; ++curr) { |
| 25761 | if(endpointUrl->data[curr] == ':' || endpointUrl->data[curr] == '/') |
| 25762 | break; |
| 25763 | } |
| 25764 | } |
| 25765 | |
| 25766 | /* Set the hostname */ |
| 25767 | if(ipv6) { |
| 25768 | /* Skip the ipv6 '[]' container for getaddrinfo() later */ |
| 25769 | outHostname->data = &endpointUrl->data[start+1]; |
| 25770 | outHostname->length = curr - (start+2); |
| 25771 | } else { |
| 25772 | outHostname->data = &endpointUrl->data[start]; |
| 25773 | outHostname->length = curr - start; |
| 25774 | } |
| 25775 | |
| 25776 | /* Empty string? */ |
| 25777 | if(outHostname->length == 0) |
| 25778 | outHostname->data = NULL; |
| 25779 | |
| 25780 | /* Already at the end */ |
| 25781 | if(curr == endpointUrl->length) |
| 25782 | return UA_STATUSCODE_GOOD; |
| 25783 | |
| 25784 | /* Set the port - and for ETH set the VID.PCP postfix in the outpath string. |
| 25785 | * We have to parse that externally. */ |
| 25786 | if(endpointUrl->data[curr] == ':') { |
| 25787 | if(++curr == endpointUrl->length) |
| 25788 | return UA_STATUSCODE_BADTCPENDPOINTURLINVALID; |
| 25789 | |
| 25790 | /* ETH schema */ |
| 25791 | if(schemaType == scEthSchemaIdx) { |
| 25792 | if(outPath != NULL) { |
| 25793 | outPath->data = &endpointUrl->data[curr]; |
| 25794 | outPath->length = endpointUrl->length - curr; |
| 25795 | } |
| 25796 | return UA_STATUSCODE_GOOD; |
| 25797 | } |
| 25798 | |
| 25799 | u32 largeNum; |
| 25800 | size_t progress = UA_readNumber(buf: &endpointUrl->data[curr], |
| 25801 | buflen: endpointUrl->length - curr, number: &largeNum); |
| 25802 | if(progress == 0 || largeNum > 65535) |
| 25803 | return UA_STATUSCODE_BADTCPENDPOINTURLINVALID; |
| 25804 | /* Test if the end of a valid port was reached */ |
| 25805 | curr += progress; |
| 25806 | if(curr == endpointUrl->length || endpointUrl->data[curr] == '/') |
| 25807 | *outPort = (u16)largeNum; |
| 25808 | if(curr == endpointUrl->length) |
| 25809 | return UA_STATUSCODE_GOOD; |
| 25810 | } |
| 25811 | |
| 25812 | /* Set the path */ |
| 25813 | UA_assert(curr < endpointUrl->length); |
| 25814 | if(endpointUrl->data[curr] != '/') |
| 25815 | return UA_STATUSCODE_BADTCPENDPOINTURLINVALID; |
| 25816 | if(++curr == endpointUrl->length) |
| 25817 | return UA_STATUSCODE_GOOD; |
| 25818 | if(outPath != NULL) { |
| 25819 | outPath->data = &endpointUrl->data[curr]; |
| 25820 | outPath->length = endpointUrl->length - curr; |
| 25821 | |
| 25822 | /* Remove trailing slash from the path */ |
| 25823 | if(endpointUrl->data[endpointUrl->length - 1] == '/') |
| 25824 | outPath->length--; |
| 25825 | |
| 25826 | /* Empty string? */ |
| 25827 | if(outPath->length == 0) |
| 25828 | outPath->data = NULL; |
| 25829 | } |
| 25830 | |
| 25831 | return UA_STATUSCODE_GOOD; |
| 25832 | } |
| 25833 | |
| 25834 | UA_StatusCode |
| 25835 | UA_parseEndpointUrlEthernet(const UA_String *endpointUrl, UA_String *target, |
| 25836 | UA_UInt16 *vid, UA_Byte *pcp) { |
| 25837 | /* Url must begin with "opc.eth://" */ |
| 25838 | if(endpointUrl->length < 11) { |
| 25839 | return UA_STATUSCODE_BADINTERNALERROR; |
| 25840 | } |
| 25841 | if(strncmp(s1: (char*) endpointUrl->data, s2: "opc.eth://", n: 10) != 0) { |
| 25842 | return UA_STATUSCODE_BADINTERNALERROR; |
| 25843 | } |
| 25844 | |
| 25845 | /* Where does the host address end? */ |
| 25846 | size_t curr = 10; |
| 25847 | for(; curr < endpointUrl->length; ++curr) { |
| 25848 | if(endpointUrl->data[curr] == ':') { |
| 25849 | break; |
| 25850 | } |
| 25851 | } |
| 25852 | |
| 25853 | /* set host address */ |
| 25854 | target->data = &endpointUrl->data[10]; |
| 25855 | target->length = curr - 10; |
| 25856 | if(curr == endpointUrl->length) { |
| 25857 | return UA_STATUSCODE_GOOD; |
| 25858 | } |
| 25859 | |
| 25860 | /* Set VLAN */ |
| 25861 | u32 value = 0; |
| 25862 | curr++; /* skip ':' */ |
| 25863 | size_t progress = UA_readNumber(buf: &endpointUrl->data[curr], |
| 25864 | buflen: endpointUrl->length - curr, number: &value); |
| 25865 | if(progress == 0 || value > 4096) { |
| 25866 | return UA_STATUSCODE_BADINTERNALERROR; |
| 25867 | } |
| 25868 | curr += progress; |
| 25869 | if(curr == endpointUrl->length || endpointUrl->data[curr] == '.') { |
| 25870 | *vid = (UA_UInt16) value; |
| 25871 | } |
| 25872 | if(curr == endpointUrl->length) { |
| 25873 | return UA_STATUSCODE_GOOD; |
| 25874 | } |
| 25875 | |
| 25876 | /* Set priority */ |
| 25877 | if(endpointUrl->data[curr] != '.') { |
| 25878 | return UA_STATUSCODE_BADINTERNALERROR; |
| 25879 | } |
| 25880 | curr++; /* skip '.' */ |
| 25881 | progress = UA_readNumber(buf: &endpointUrl->data[curr], |
| 25882 | buflen: endpointUrl->length - curr, number: &value); |
| 25883 | if(progress == 0 || value > 7) { |
| 25884 | return UA_STATUSCODE_BADINTERNALERROR; |
| 25885 | } |
| 25886 | curr += progress; |
| 25887 | if(curr != endpointUrl->length) { |
| 25888 | return UA_STATUSCODE_BADINTERNALERROR; |
| 25889 | } |
| 25890 | *pcp = (UA_Byte) value; |
| 25891 | |
| 25892 | return UA_STATUSCODE_GOOD; |
| 25893 | } |
| 25894 | |
| 25895 | UA_StatusCode |
| 25896 | UA_ByteString_toBase64(const UA_ByteString *byteString, |
| 25897 | UA_String *str) { |
| 25898 | UA_String_init(p: str); |
| 25899 | if(!byteString || !byteString->data) |
| 25900 | return UA_STATUSCODE_GOOD; |
| 25901 | |
| 25902 | str->data = (UA_Byte*) |
| 25903 | UA_base64(src: byteString->data, len: byteString->length, out_len: &str->length); |
| 25904 | if(!str->data) |
| 25905 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 25906 | |
| 25907 | return UA_STATUSCODE_GOOD; |
| 25908 | } |
| 25909 | |
| 25910 | UA_StatusCode |
| 25911 | UA_ByteString_fromBase64(UA_ByteString *bs, |
| 25912 | const UA_String *input) { |
| 25913 | UA_ByteString_init(p: bs); |
| 25914 | if(input->length == 0) |
| 25915 | return UA_STATUSCODE_GOOD; |
| 25916 | bs->data = UA_unbase64(src: (const unsigned char*)input->data, |
| 25917 | len: input->length, out_len: &bs->length); |
| 25918 | /* TODO: Differentiate between encoding and memory errors */ |
| 25919 | if(!bs->data) |
| 25920 | return UA_STATUSCODE_BADINTERNALERROR; |
| 25921 | return UA_STATUSCODE_GOOD; |
| 25922 | } |
| 25923 | |
| 25924 | /* Key Value Map */ |
| 25925 | |
| 25926 | const UA_KeyValueMap UA_KEYVALUEMAP_NULL = {0, NULL}; |
| 25927 | |
| 25928 | UA_KeyValueMap * |
| 25929 | UA_KeyValueMap_new(void) { |
| 25930 | return (UA_KeyValueMap*)UA_calloc(nmemb: 1, size: sizeof(UA_KeyValueMap)); |
| 25931 | } |
| 25932 | |
| 25933 | UA_StatusCode |
| 25934 | UA_KeyValueMap_set(UA_KeyValueMap *map, |
| 25935 | const UA_QualifiedName key, |
| 25936 | const UA_Variant *value) { |
| 25937 | if(map == NULL || value == NULL) |
| 25938 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 25939 | |
| 25940 | /* Key exists already */ |
| 25941 | const UA_Variant *v = UA_KeyValueMap_get(map, key); |
| 25942 | if(v) { |
| 25943 | UA_Variant copyV; |
| 25944 | UA_StatusCode res = UA_Variant_copy(src: value, dst: ©V); |
| 25945 | if(res != UA_STATUSCODE_GOOD) |
| 25946 | return res; |
| 25947 | UA_Variant *target = (UA_Variant*)(uintptr_t)v; |
| 25948 | UA_Variant_clear(p: target); |
| 25949 | *target = copyV; |
| 25950 | return UA_STATUSCODE_GOOD; |
| 25951 | } |
| 25952 | |
| 25953 | /* Append to the array */ |
| 25954 | UA_KeyValuePair pair; |
| 25955 | pair.key = key; |
| 25956 | pair.value = *value; |
| 25957 | return UA_Array_appendCopy(p: (void**)&map->map, size: &map->mapSize, newElem: &pair, |
| 25958 | type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]); |
| 25959 | } |
| 25960 | |
| 25961 | UA_StatusCode |
| 25962 | UA_KeyValueMap_setScalar(UA_KeyValueMap *map, |
| 25963 | const UA_QualifiedName key, |
| 25964 | void * UA_RESTRICT p, |
| 25965 | const UA_DataType *type) { |
| 25966 | if(p == NULL || type == NULL) |
| 25967 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 25968 | UA_Variant v; |
| 25969 | UA_Variant_init(p: &v); |
| 25970 | v.type = type; |
| 25971 | v.arrayLength = 0; |
| 25972 | v.data = p; |
| 25973 | return UA_KeyValueMap_set(map, key, value: &v); |
| 25974 | } |
| 25975 | |
| 25976 | const UA_Variant * |
| 25977 | UA_KeyValueMap_get(const UA_KeyValueMap *map, |
| 25978 | const UA_QualifiedName key) { |
| 25979 | if(!map) |
| 25980 | return NULL; |
| 25981 | for(size_t i = 0; i < map->mapSize; i++) { |
| 25982 | if(map->map[i].key.namespaceIndex == key.namespaceIndex && |
| 25983 | UA_String_equal(p1: &map->map[i].key.name, p2: &key.name)) |
| 25984 | return &map->map[i].value; |
| 25985 | |
| 25986 | } |
| 25987 | return NULL; |
| 25988 | } |
| 25989 | |
| 25990 | UA_Boolean |
| 25991 | UA_KeyValueMap_isEmpty(const UA_KeyValueMap *map) { |
| 25992 | if(!map) |
| 25993 | return true; |
| 25994 | return map->mapSize == 0; |
| 25995 | } |
| 25996 | |
| 25997 | const void * |
| 25998 | UA_KeyValueMap_getScalar(const UA_KeyValueMap *map, |
| 25999 | const UA_QualifiedName key, |
| 26000 | const UA_DataType *type) { |
| 26001 | const UA_Variant *v = UA_KeyValueMap_get(map, key); |
| 26002 | if(!v || !UA_Variant_hasScalarType(v, type)) |
| 26003 | return NULL; |
| 26004 | return v->data; |
| 26005 | } |
| 26006 | |
| 26007 | void |
| 26008 | UA_KeyValueMap_clear(UA_KeyValueMap *map) { |
| 26009 | if(!map) |
| 26010 | return; |
| 26011 | if(map->mapSize > 0) { |
| 26012 | UA_Array_delete(p: map->map, size: map->mapSize, type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]); |
| 26013 | map->mapSize = 0; |
| 26014 | } |
| 26015 | } |
| 26016 | |
| 26017 | void |
| 26018 | UA_KeyValueMap_delete(UA_KeyValueMap *map) { |
| 26019 | UA_KeyValueMap_clear(map); |
| 26020 | UA_free(ptr: map); |
| 26021 | } |
| 26022 | |
| 26023 | UA_StatusCode |
| 26024 | UA_KeyValueMap_remove(UA_KeyValueMap *map, |
| 26025 | const UA_QualifiedName key) { |
| 26026 | if(!map) |
| 26027 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 26028 | |
| 26029 | UA_KeyValuePair *m = map->map; |
| 26030 | size_t s = map->mapSize; |
| 26031 | size_t i = 0; |
| 26032 | for(; i < s; i++) { |
| 26033 | if(m[i].key.namespaceIndex == key.namespaceIndex && |
| 26034 | UA_String_equal(p1: &m[i].key.name, p2: &key.name)) |
| 26035 | break; |
| 26036 | } |
| 26037 | if(i == s) |
| 26038 | return UA_STATUSCODE_BADNOTFOUND; |
| 26039 | |
| 26040 | /* Clean the slot and move the last entry to fill the slot */ |
| 26041 | UA_KeyValuePair_clear(p: &m[i]); |
| 26042 | if(s > 1 && i < s - 1) { |
| 26043 | m[i] = m[s-1]; |
| 26044 | UA_KeyValuePair_init(p: &m[s-1]); |
| 26045 | } |
| 26046 | |
| 26047 | /* Ignore the result. In case resize fails, keep the longer original array |
| 26048 | * around. Resize never fails when reducing the size to zero. */ |
| 26049 | UA_StatusCode res = |
| 26050 | UA_Array_resize(p: (void**)&map->map, size: &map->mapSize, newSize: map->mapSize - 1, |
| 26051 | type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]); |
| 26052 | /* Adjust map->mapSize only when UA_Array_resize() failed. On success, the |
| 26053 | * value has already been decremented by UA_Array_resize(). */ |
| 26054 | if(res != UA_STATUSCODE_GOOD) |
| 26055 | map->mapSize--; |
| 26056 | return UA_STATUSCODE_GOOD; |
| 26057 | } |
| 26058 | |
| 26059 | UA_StatusCode |
| 26060 | UA_KeyValueMap_copy(const UA_KeyValueMap *src, UA_KeyValueMap *dst) { |
| 26061 | if(!dst) |
| 26062 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 26063 | if(!src) { |
| 26064 | dst->map = NULL; |
| 26065 | dst->mapSize = 0; |
| 26066 | return UA_STATUSCODE_GOOD; |
| 26067 | } |
| 26068 | UA_StatusCode res = UA_Array_copy(src: src->map, size: src->mapSize, dst: (void**)&dst->map, |
| 26069 | type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]); |
| 26070 | if(res == UA_STATUSCODE_GOOD) |
| 26071 | dst->mapSize = src->mapSize; |
| 26072 | return res; |
| 26073 | } |
| 26074 | |
| 26075 | UA_Boolean |
| 26076 | UA_KeyValueMap_contains(const UA_KeyValueMap *map, const UA_QualifiedName key) { |
| 26077 | if(!map) |
| 26078 | return false; |
| 26079 | for(size_t i = 0; i < map->mapSize; ++i) { |
| 26080 | if(UA_QualifiedName_equal(p1: &map->map[i].key, p2: &key)) |
| 26081 | return true; |
| 26082 | } |
| 26083 | return false; |
| 26084 | } |
| 26085 | |
| 26086 | UA_StatusCode |
| 26087 | UA_KeyValueMap_merge(UA_KeyValueMap *lhs, const UA_KeyValueMap *rhs) { |
| 26088 | if(!lhs) |
| 26089 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 26090 | if(!rhs) |
| 26091 | return UA_STATUSCODE_GOOD; |
| 26092 | |
| 26093 | UA_KeyValueMap merge; |
| 26094 | UA_StatusCode res = UA_KeyValueMap_copy(src: lhs, dst: &merge); |
| 26095 | if(res != UA_STATUSCODE_GOOD) |
| 26096 | return res; |
| 26097 | |
| 26098 | for(size_t i = 0; i < rhs->mapSize; ++i) { |
| 26099 | res = UA_KeyValueMap_set(map: &merge, key: rhs->map[i].key, value: &rhs->map[i].value); |
| 26100 | if(res != UA_STATUSCODE_GOOD) { |
| 26101 | UA_KeyValueMap_clear(map: &merge); |
| 26102 | return res; |
| 26103 | } |
| 26104 | } |
| 26105 | |
| 26106 | UA_KeyValueMap_clear(map: lhs); |
| 26107 | *lhs = merge; |
| 26108 | return UA_STATUSCODE_GOOD; |
| 26109 | } |
| 26110 | |
| 26111 | /***************************/ |
| 26112 | /* Random Number Generator */ |
| 26113 | /***************************/ |
| 26114 | |
| 26115 | /* TODO is this safe for multithreading? */ |
| 26116 | static pcg32_random_t UA_rng = PCG32_INITIALIZER; |
| 26117 | |
| 26118 | void |
| 26119 | UA_random_seed(u64 seed) { |
| 26120 | pcg32_srandom_r(rng: &UA_rng, initial_state: seed, initseq: (u64)UA_DateTime_now()); |
| 26121 | } |
| 26122 | |
| 26123 | u32 |
| 26124 | UA_UInt32_random(void) { |
| 26125 | return (u32)pcg32_random_r(rng: &UA_rng); |
| 26126 | } |
| 26127 | |
| 26128 | UA_Guid |
| 26129 | UA_Guid_random(void) { |
| 26130 | UA_Guid result; |
| 26131 | result.data1 = (u32)pcg32_random_r(rng: &UA_rng); |
| 26132 | u32 r = (u32)pcg32_random_r(rng: &UA_rng); |
| 26133 | result.data2 = (u16) r; |
| 26134 | result.data3 = (u16) (r >> 16); |
| 26135 | r = (u32)pcg32_random_r(rng: &UA_rng); |
| 26136 | result.data4[0] = (u8)r; |
| 26137 | result.data4[1] = (u8)(r >> 4); |
| 26138 | result.data4[2] = (u8)(r >> 8); |
| 26139 | result.data4[3] = (u8)(r >> 12); |
| 26140 | r = (u32)pcg32_random_r(rng: &UA_rng); |
| 26141 | result.data4[4] = (u8)r; |
| 26142 | result.data4[5] = (u8)(r >> 4); |
| 26143 | result.data4[6] = (u8)(r >> 8); |
| 26144 | result.data4[7] = (u8)(r >> 12); |
| 26145 | return result; |
| 26146 | } |
| 26147 | |
| 26148 | /********************/ |
| 26149 | /* Malloc Singleton */ |
| 26150 | /********************/ |
| 26151 | |
| 26152 | #ifdef UA_ENABLE_MALLOC_SINGLETON |
| 26153 | # include <stdlib.h> |
| 26154 | UA_EXPORT UA_THREAD_LOCAL void * (*UA_mallocSingleton)(size_t size) = malloc; |
| 26155 | UA_EXPORT UA_THREAD_LOCAL void (*UA_freeSingleton)(void *ptr) = free; |
| 26156 | UA_EXPORT UA_THREAD_LOCAL void * (*UA_callocSingleton)(size_t nelem, size_t elsize) = calloc; |
| 26157 | UA_EXPORT UA_THREAD_LOCAL void * (*UA_reallocSingleton)(void *ptr, size_t size) = realloc; |
| 26158 | #endif |
| 26159 | |
| 26160 | /************************/ |
| 26161 | /* Cryptography Helpers */ |
| 26162 | /************************/ |
| 26163 | |
| 26164 | UA_ByteString |
| 26165 | getLeafCertificate(UA_ByteString chain) { |
| 26166 | /* Detect DER encoded X.509 v3 certificate. If the DER detection fails, |
| 26167 | * return the entire chain. |
| 26168 | * |
| 26169 | * The OPC UA standard requires this to be DER. But we also allow other |
| 26170 | * formats like PEM. Afterwards it depends on the crypto backend to parse |
| 26171 | * it. mbedTLS and OpenSSL detect the format automatically. */ |
| 26172 | if(chain.length < 4 || chain.data[0] != 0x30 || chain.data[1] != 0x82) |
| 26173 | return chain; |
| 26174 | |
| 26175 | /* The certificate length is encoded in the next 2 bytes. */ |
| 26176 | size_t leafLen = 4; /* Magic numbers + length bytes */ |
| 26177 | leafLen += (size_t)(((uint16_t)chain.data[2]) << 8); |
| 26178 | leafLen += chain.data[3]; |
| 26179 | |
| 26180 | /* Consistency check */ |
| 26181 | if(leafLen > chain.length) |
| 26182 | return UA_BYTESTRING_NULL; |
| 26183 | |
| 26184 | /* Adjust the length and return */ |
| 26185 | chain.length = leafLen; |
| 26186 | return chain; |
| 26187 | } |
| 26188 | |
| 26189 | UA_Boolean |
| 26190 | UA_constantTimeEqual(const void *ptr1, const void *ptr2, size_t length) { |
| 26191 | volatile const UA_Byte *a = (volatile const UA_Byte *)ptr1; |
| 26192 | volatile const UA_Byte *b = (volatile const UA_Byte *)ptr2; |
| 26193 | volatile UA_Byte c = 0; |
| 26194 | for(size_t i = 0; i < length; ++i) { |
| 26195 | UA_Byte x = a[i], y = b[i]; |
| 26196 | c = c | (x ^ y); |
| 26197 | } |
| 26198 | return !c; |
| 26199 | } |
| 26200 | |
| 26201 | void |
| 26202 | UA_ByteString_memZero(UA_ByteString *bs) { |
| 26203 | #if defined(__STDC_LIB_EXT1__) |
| 26204 | memset_s(bs->data, bs->length, 0, bs->length); |
| 26205 | #elif defined(UA_ARCHITECTURE_WIN32) |
| 26206 | SecureZeroMemory(bs->data, bs->length); |
| 26207 | #else |
| 26208 | volatile unsigned char *volatile ptr = |
| 26209 | (volatile unsigned char *)bs->data; |
| 26210 | size_t i = 0; |
| 26211 | size_t maxLen = bs->length; |
| 26212 | while(i < maxLen) { |
| 26213 | ptr[i++] = 0; |
| 26214 | } |
| 26215 | #endif |
| 26216 | } |
| 26217 | |
| 26218 | /**** amalgamated original file "/src/ua_securechannel.c" ****/ |
| 26219 | |
| 26220 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 26221 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 26222 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 26223 | * |
| 26224 | * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 26225 | * Copyright 2014, 2016-2017 (c) Florian Palm |
| 26226 | * Copyright 2015-2016 (c) Sten Grüner |
| 26227 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 26228 | * Copyright 2016 (c) TorbenD |
| 26229 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 26230 | * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB |
| 26231 | * Copyright 2018-2019 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 26232 | */ |
| 26233 | |
| 26234 | |
| 26235 | |
| 26236 | #define UA_BITMASK_MESSAGETYPE 0x00ffffffu |
| 26237 | #define UA_BITMASK_CHUNKTYPE 0xff000000u |
| 26238 | |
| 26239 | const UA_String UA_SECURITY_POLICY_NONE_URI = |
| 26240 | {47, (UA_Byte *)"http://opcfoundation.org/UA/SecurityPolicy#None"}; |
| 26241 | |
| 26242 | void |
| 26243 | UA_SecureChannel_init(UA_SecureChannel *channel) { |
| 26244 | /* Normal linked lists are initialized by zeroing out */ |
| 26245 | memset(s: channel, c: 0, n: sizeof(UA_SecureChannel)); |
| 26246 | TAILQ_INIT(&channel->chunks); |
| 26247 | } |
| 26248 | |
| 26249 | UA_StatusCode |
| 26250 | UA_SecureChannel_setSecurityPolicy(UA_SecureChannel *channel, |
| 26251 | UA_SecurityPolicy *securityPolicy, |
| 26252 | const UA_ByteString *remoteCertificate) { |
| 26253 | /* Is a policy already configured? */ |
| 26254 | UA_CHECK_ERROR(!channel->securityPolicy, return UA_STATUSCODE_BADINTERNALERROR, |
| 26255 | securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 26256 | "Security policy already configured"); |
| 26257 | |
| 26258 | /* Create the context */ |
| 26259 | UA_StatusCode res = securityPolicy->channelModule. |
| 26260 | newContext(securityPolicy, remoteCertificate, &channel->channelContext); |
| 26261 | res |= UA_ByteString_copy(src: remoteCertificate, dst: &channel->remoteCertificate); |
| 26262 | UA_CHECK_STATUS_WARN(res, return res, securityPolicy->logger, |
| 26263 | UA_LOGCATEGORY_SECURITYPOLICY, |
| 26264 | "Could not set up the SecureChannel context"); |
| 26265 | |
| 26266 | /* Compute the certificate thumbprint */ |
| 26267 | UA_ByteString remoteCertificateThumbprint = |
| 26268 | {20, channel->remoteCertificateThumbprint}; |
| 26269 | res = securityPolicy->asymmetricModule. |
| 26270 | makeCertificateThumbprint(securityPolicy, &channel->remoteCertificate, |
| 26271 | &remoteCertificateThumbprint); |
| 26272 | UA_CHECK_STATUS_WARN(res, return res, securityPolicy->logger, |
| 26273 | UA_LOGCATEGORY_SECURITYPOLICY, |
| 26274 | "Could not create the certificate thumbprint"); |
| 26275 | |
| 26276 | /* Set the policy */ |
| 26277 | channel->securityPolicy = securityPolicy; |
| 26278 | return UA_STATUSCODE_GOOD; |
| 26279 | } |
| 26280 | |
| 26281 | /* Hides some errors before sending them to a client according to the |
| 26282 | * standard. */ |
| 26283 | static void |
| 26284 | hideErrors(UA_TcpErrorMessage *const error) { |
| 26285 | switch(error->error) { |
| 26286 | case UA_STATUSCODE_BADCERTIFICATEUNTRUSTED: |
| 26287 | case UA_STATUSCODE_BADCERTIFICATEREVOKED: |
| 26288 | case UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED: |
| 26289 | case UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE: |
| 26290 | case UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED: |
| 26291 | error->error = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 26292 | error->reason = UA_STRING_NULL; |
| 26293 | break; |
| 26294 | // TODO: Check if these are all cases that need to be covered. |
| 26295 | default: |
| 26296 | break; |
| 26297 | } |
| 26298 | } |
| 26299 | |
| 26300 | UA_Boolean |
| 26301 | UA_SecureChannel_isConnected(UA_SecureChannel *channel) { |
| 26302 | return (channel->state > UA_SECURECHANNELSTATE_CLOSED && |
| 26303 | channel->state < UA_SECURECHANNELSTATE_CLOSING); |
| 26304 | } |
| 26305 | |
| 26306 | void |
| 26307 | UA_SecureChannel_sendError(UA_SecureChannel *channel, UA_TcpErrorMessage *error) { |
| 26308 | if(!UA_SecureChannel_isConnected(channel)) |
| 26309 | return; |
| 26310 | |
| 26311 | hideErrors(error); |
| 26312 | |
| 26313 | UA_TcpMessageHeader header; |
| 26314 | header.messageTypeAndChunkType = UA_MESSAGETYPE_ERR + UA_CHUNKTYPE_FINAL; |
| 26315 | /* Header + ErrorMessage (error + reasonLength_field + length) */ |
| 26316 | header.messageSize = 8 + (4 + 4 + (UA_UInt32)error->reason.length); |
| 26317 | |
| 26318 | /* Get the send buffer from the network layer */ |
| 26319 | UA_ConnectionManager *cm = channel->connectionManager; |
| 26320 | UA_ByteString msg = UA_BYTESTRING_NULL; |
| 26321 | UA_StatusCode retval = cm->allocNetworkBuffer(cm, channel->connectionId, |
| 26322 | &msg, header.messageSize); |
| 26323 | if(retval != UA_STATUSCODE_GOOD) |
| 26324 | return; |
| 26325 | |
| 26326 | /* Encode and send the response */ |
| 26327 | UA_Byte *bufPos = msg.data; |
| 26328 | const UA_Byte *bufEnd = &msg.data[msg.length]; |
| 26329 | retval |= UA_encodeBinaryInternal(src: &header, |
| 26330 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], |
| 26331 | bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 26332 | retval |= UA_encodeBinaryInternal(src: error, |
| 26333 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE], |
| 26334 | bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 26335 | (void)retval; /* Encoding of these cannot fail */ |
| 26336 | msg.length = header.messageSize; |
| 26337 | cm->sendWithConnection(cm, channel->connectionId, &UA_KEYVALUEMAP_NULL, &msg); |
| 26338 | } |
| 26339 | |
| 26340 | static void |
| 26341 | UA_Chunk_delete(UA_Chunk *chunk) { |
| 26342 | if(chunk->copied) |
| 26343 | UA_ByteString_clear(p: &chunk->bytes); |
| 26344 | UA_free(ptr: chunk); |
| 26345 | } |
| 26346 | |
| 26347 | static void |
| 26348 | deleteChunks(UA_SecureChannel *channel) { |
| 26349 | UA_Chunk *chunk, *chunk_tmp; |
| 26350 | TAILQ_FOREACH_SAFE(chunk, &channel->chunks, pointers, chunk_tmp) { |
| 26351 | TAILQ_REMOVE(&channel->chunks, chunk, pointers); |
| 26352 | UA_Chunk_delete(chunk); |
| 26353 | } |
| 26354 | channel->chunksCount = 0; |
| 26355 | channel->chunksLength = 0; |
| 26356 | } |
| 26357 | |
| 26358 | void |
| 26359 | UA_SecureChannel_deleteBuffered(UA_SecureChannel *channel) { |
| 26360 | deleteChunks(channel); |
| 26361 | if(channel->unprocessedCopied) |
| 26362 | UA_ByteString_clear(p: &channel->unprocessed); |
| 26363 | } |
| 26364 | |
| 26365 | void |
| 26366 | UA_SecureChannel_shutdown(UA_SecureChannel *channel, |
| 26367 | UA_ShutdownReason shutdownReason) { |
| 26368 | /* No open socket or already closing -> nothing to do */ |
| 26369 | if(!UA_SecureChannel_isConnected(channel)) |
| 26370 | return; |
| 26371 | |
| 26372 | /* Set the shutdown event for diagnostics */ |
| 26373 | channel->shutdownReason= shutdownReason; |
| 26374 | |
| 26375 | /* Trigger the async closing of the connection */ |
| 26376 | UA_ConnectionManager *cm = channel->connectionManager; |
| 26377 | cm->closeConnection(cm, channel->connectionId); |
| 26378 | channel->state = UA_SECURECHANNELSTATE_CLOSING; |
| 26379 | } |
| 26380 | |
| 26381 | void |
| 26382 | UA_SecureChannel_clear(UA_SecureChannel *channel) { |
| 26383 | /* Detach Sessions from the SecureChannel. This also removes outstanding |
| 26384 | * Publish requests whose RequestId is valid only for the SecureChannel. */ |
| 26385 | UA_SessionHeader *sh, *sh_tmp; |
| 26386 | SLIST_FOREACH_SAFE(sh, &channel->sessions, next, sh_tmp) { |
| 26387 | if(sh->serverSession) { |
| 26388 | UA_Session_detachFromSecureChannel(session: (UA_Session *)sh); |
| 26389 | } else { |
| 26390 | sh->channel = NULL; |
| 26391 | SLIST_REMOVE_HEAD(&channel->sessions, next); |
| 26392 | } |
| 26393 | } |
| 26394 | |
| 26395 | /* Delete the channel context for the security policy */ |
| 26396 | if(channel->securityPolicy) { |
| 26397 | channel->securityPolicy->channelModule.deleteContext(channel->channelContext); |
| 26398 | channel->securityPolicy = NULL; |
| 26399 | channel->channelContext = NULL; |
| 26400 | } |
| 26401 | |
| 26402 | /* Remove remaining delayed callback */ |
| 26403 | if(channel->connectionManager && |
| 26404 | channel->connectionManager->eventSource.eventLoop) { |
| 26405 | UA_EventLoop *el = channel->connectionManager->eventSource.eventLoop; |
| 26406 | el->removeDelayedCallback(el, &channel->unprocessedDelayed); |
| 26407 | } |
| 26408 | |
| 26409 | /* The EventLoop connection is no longer valid */ |
| 26410 | channel->connectionId = 0; |
| 26411 | channel->connectionManager = NULL; |
| 26412 | |
| 26413 | /* Clean up the SecurityToken */ |
| 26414 | UA_ChannelSecurityToken_clear(p: &channel->securityToken); |
| 26415 | UA_ChannelSecurityToken_clear(p: &channel->altSecurityToken); |
| 26416 | |
| 26417 | /* Clean up certificate and nonces */ |
| 26418 | UA_ByteString_clear(p: &channel->remoteCertificate); |
| 26419 | UA_ByteString_clear(p: &channel->localNonce); |
| 26420 | UA_ByteString_clear(p: &channel->remoteNonce); |
| 26421 | |
| 26422 | /* Clean up endpointUrl */ |
| 26423 | UA_String_clear(p: &channel->endpointUrl); |
| 26424 | |
| 26425 | /* Delete remaining chunks */ |
| 26426 | UA_SecureChannel_deleteBuffered(channel); |
| 26427 | |
| 26428 | /* Reset the SecureChannel for reuse (in the client) */ |
| 26429 | channel->securityMode = UA_MESSAGESECURITYMODE_INVALID; |
| 26430 | channel->shutdownReason = UA_SHUTDOWNREASON_CLOSE; |
| 26431 | memset(s: &channel->config, c: 0, n: sizeof(UA_ConnectionConfig)); |
| 26432 | channel->receiveSequenceNumber = 0; |
| 26433 | channel->sendSequenceNumber = 0; |
| 26434 | |
| 26435 | /* Set the state to closed */ |
| 26436 | channel->state = UA_SECURECHANNELSTATE_CLOSED; |
| 26437 | channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL; |
| 26438 | } |
| 26439 | |
| 26440 | UA_StatusCode |
| 26441 | UA_SecureChannel_processHELACK(UA_SecureChannel *channel, |
| 26442 | const UA_TcpAcknowledgeMessage *remoteConfig) { |
| 26443 | /* The lowest common version is used by both sides */ |
| 26444 | if(channel->config.protocolVersion > remoteConfig->protocolVersion) |
| 26445 | channel->config.protocolVersion = remoteConfig->protocolVersion; |
| 26446 | |
| 26447 | /* Can we receive the max send size? */ |
| 26448 | if(channel->config.sendBufferSize > remoteConfig->receiveBufferSize) |
| 26449 | channel->config.sendBufferSize = remoteConfig->receiveBufferSize; |
| 26450 | |
| 26451 | /* Can we send the max receive size? */ |
| 26452 | if(channel->config.recvBufferSize > remoteConfig->sendBufferSize) |
| 26453 | channel->config.recvBufferSize = remoteConfig->sendBufferSize; |
| 26454 | |
| 26455 | channel->config.remoteMaxMessageSize = remoteConfig->maxMessageSize; |
| 26456 | channel->config.remoteMaxChunkCount = remoteConfig->maxChunkCount; |
| 26457 | |
| 26458 | /* Chunks of at least 8192 bytes must be permissible. |
| 26459 | * See Part 6, Clause 6.7.1 */ |
| 26460 | if(channel->config.recvBufferSize < 8192 || |
| 26461 | channel->config.sendBufferSize < 8192 || |
| 26462 | (channel->config.remoteMaxMessageSize != 0 && |
| 26463 | channel->config.remoteMaxMessageSize < 8192)) |
| 26464 | return UA_STATUSCODE_BADINTERNALERROR; |
| 26465 | |
| 26466 | return UA_STATUSCODE_GOOD; |
| 26467 | } |
| 26468 | |
| 26469 | /* Sends an OPN message using asymmetric encryption if defined */ |
| 26470 | UA_StatusCode |
| 26471 | UA_SecureChannel_sendAsymmetricOPNMessage(UA_SecureChannel *channel, |
| 26472 | UA_UInt32 requestId, const void *content, |
| 26473 | const UA_DataType *contentType) { |
| 26474 | UA_CHECK(channel->securityMode != UA_MESSAGESECURITYMODE_INVALID, |
| 26475 | return UA_STATUSCODE_BADSECURITYMODEREJECTED); |
| 26476 | |
| 26477 | /* Can we use the connection manager? */ |
| 26478 | UA_ConnectionManager *cm = channel->connectionManager; |
| 26479 | if(!UA_SecureChannel_isConnected(channel)) |
| 26480 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 26481 | |
| 26482 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 26483 | UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR); |
| 26484 | |
| 26485 | /* Allocate the message buffer */ |
| 26486 | UA_ByteString buf = UA_BYTESTRING_NULL; |
| 26487 | UA_StatusCode res = cm->allocNetworkBuffer(cm, channel->connectionId, &buf, |
| 26488 | channel->config.sendBufferSize); |
| 26489 | UA_CHECK_STATUS(res, return res); |
| 26490 | |
| 26491 | /* Restrict buffer to the available space for the payload */ |
| 26492 | UA_Byte *buf_pos = buf.data; |
| 26493 | const UA_Byte *buf_end = &buf.data[buf.length]; |
| 26494 | hideBytesAsym(channel, buf_start: &buf_pos, buf_end: &buf_end); |
| 26495 | |
| 26496 | /* Define variables here to pacify some compilers wrt goto */ |
| 26497 | size_t securityHeaderLength, pre_sig_length, total_length, encryptedLength; |
| 26498 | |
| 26499 | /* Encode the message type and content */ |
| 26500 | res |= UA_NodeId_encodeBinary(src: &contentType->binaryEncodingId, bufPos: &buf_pos, bufEnd: buf_end); |
| 26501 | res |= UA_encodeBinaryInternal(src: content, type: contentType, bufPos: &buf_pos, bufEnd: &buf_end, NULL, NULL); |
| 26502 | UA_CHECK_STATUS(res, goto error); |
| 26503 | |
| 26504 | /* Compute the header length */ |
| 26505 | securityHeaderLength = calculateAsymAlgSecurityHeaderLength(channel); |
| 26506 | |
| 26507 | /* Add padding to the chunk. Also pad if the securityMode is SIGN_ONLY, |
| 26508 | * since we are using asymmetric communication to exchange keys and thus |
| 26509 | * need to encrypt. */ |
| 26510 | #ifdef UA_ENABLE_ENCRYPTION |
| 26511 | if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE) |
| 26512 | padChunk(channel, cm: &channel->securityPolicy->asymmetricModule.cryptoModule, |
| 26513 | start: &buf.data[UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength], |
| 26514 | pos: &buf_pos); |
| 26515 | #endif |
| 26516 | |
| 26517 | /* The total message length */ |
| 26518 | pre_sig_length = (uintptr_t)buf_pos - (uintptr_t)buf.data; |
| 26519 | total_length = pre_sig_length; |
| 26520 | if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 26521 | channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 26522 | total_length += sp->asymmetricModule.cryptoModule.signatureAlgorithm. |
| 26523 | getLocalSignatureSize(channel->channelContext); |
| 26524 | |
| 26525 | /* The total message length is known here which is why we encode the headers |
| 26526 | * at this step and not earlier. */ |
| 26527 | res = prependHeadersAsym(channel, header_pos: buf.data, buf_end, totalLength: total_length, |
| 26528 | securityHeaderLength, requestId, finalLength: &encryptedLength); |
| 26529 | UA_CHECK_STATUS(res, goto error); |
| 26530 | |
| 26531 | #ifdef UA_ENABLE_ENCRYPTION |
| 26532 | res = signAndEncryptAsym(channel, preSignLength: pre_sig_length, buf: &buf, |
| 26533 | securityHeaderLength, totalLength: total_length); |
| 26534 | UA_CHECK_STATUS(res, goto error); |
| 26535 | #endif |
| 26536 | |
| 26537 | /* Send the message, the buffer is freed in the network layer */ |
| 26538 | buf.length = encryptedLength; |
| 26539 | return cm->sendWithConnection(cm, channel->connectionId, &UA_KEYVALUEMAP_NULL, &buf); |
| 26540 | |
| 26541 | error: |
| 26542 | cm->freeNetworkBuffer(cm, channel->connectionId, &buf); |
| 26543 | return res; |
| 26544 | } |
| 26545 | |
| 26546 | /* Will this chunk surpass the capacity of the SecureChannel for the message? */ |
| 26547 | static UA_StatusCode |
| 26548 | adjustCheckMessageLimitsSym(UA_MessageContext *mc, size_t bodyLength) { |
| 26549 | mc->messageSizeSoFar += bodyLength; |
| 26550 | mc->chunksSoFar++; |
| 26551 | |
| 26552 | UA_SecureChannel *channel = mc->channel; |
| 26553 | if(mc->messageSizeSoFar > channel->config.localMaxMessageSize && |
| 26554 | channel->config.localMaxMessageSize != 0) |
| 26555 | return UA_STATUSCODE_BADRESPONSETOOLARGE; |
| 26556 | |
| 26557 | if(mc->chunksSoFar > channel->config.localMaxChunkCount && |
| 26558 | channel->config.localMaxChunkCount != 0) |
| 26559 | return UA_STATUSCODE_BADRESPONSETOOLARGE; |
| 26560 | |
| 26561 | return UA_STATUSCODE_GOOD; |
| 26562 | } |
| 26563 | |
| 26564 | static UA_StatusCode |
| 26565 | encodeHeadersSym(UA_MessageContext *mc, size_t totalLength) { |
| 26566 | UA_SecureChannel *channel = mc->channel; |
| 26567 | UA_Byte *header_pos = mc->messageBuffer.data; |
| 26568 | |
| 26569 | UA_TcpMessageHeader header; |
| 26570 | header.messageTypeAndChunkType = mc->messageType; |
| 26571 | header.messageSize = (UA_UInt32)totalLength; |
| 26572 | if(mc->final) |
| 26573 | header.messageTypeAndChunkType += UA_CHUNKTYPE_FINAL; |
| 26574 | else |
| 26575 | header.messageTypeAndChunkType += UA_CHUNKTYPE_INTERMEDIATE; |
| 26576 | |
| 26577 | /* Increase the sequence number in the channel */ |
| 26578 | channel->sendSequenceNumber++; |
| 26579 | |
| 26580 | UA_SequenceHeader seqHeader; |
| 26581 | seqHeader.requestId = mc->requestId; |
| 26582 | seqHeader.sequenceNumber = channel->sendSequenceNumber; |
| 26583 | |
| 26584 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 26585 | res |= UA_encodeBinaryInternal(src: &header, type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], |
| 26586 | bufPos: &header_pos, bufEnd: &mc->buf_end, NULL, NULL); |
| 26587 | res |= UA_UInt32_encodeBinary(src: &channel->securityToken.channelId, |
| 26588 | bufPos: &header_pos, bufEnd: mc->buf_end); |
| 26589 | res |= UA_UInt32_encodeBinary(src: &channel->securityToken.tokenId, |
| 26590 | bufPos: &header_pos, bufEnd: mc->buf_end); |
| 26591 | res |= UA_encodeBinaryInternal(src: &seqHeader, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], |
| 26592 | bufPos: &header_pos, bufEnd: &mc->buf_end, NULL, NULL); |
| 26593 | return res; |
| 26594 | } |
| 26595 | |
| 26596 | static UA_StatusCode |
| 26597 | sendSymmetricChunk(UA_MessageContext *mc) { |
| 26598 | UA_SecureChannel *channel = mc->channel; |
| 26599 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 26600 | UA_ConnectionManager *cm = channel->connectionManager; |
| 26601 | if(!UA_SecureChannel_isConnected(channel)) |
| 26602 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 26603 | |
| 26604 | /* The size of the message payload */ |
| 26605 | size_t bodyLength = (uintptr_t)mc->buf_pos - |
| 26606 | (uintptr_t)&mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]; |
| 26607 | |
| 26608 | /* Early-declare variables so we can use a goto in the error case */ |
| 26609 | size_t total_length = 0; |
| 26610 | size_t pre_sig_length = 0; |
| 26611 | |
| 26612 | /* Check if chunk exceeds the limits for the overall message */ |
| 26613 | UA_StatusCode res = adjustCheckMessageLimitsSym(mc, bodyLength); |
| 26614 | UA_CHECK_STATUS(res, goto error); |
| 26615 | |
| 26616 | UA_LOG_TRACE_CHANNEL(sp->logger, channel, |
| 26617 | "Send from a symmetric message buffer of length %lu " |
| 26618 | "a message of header+payload length of %lu", |
| 26619 | (long unsigned int)mc->messageBuffer.length, |
| 26620 | (long unsigned int) |
| 26621 | ((uintptr_t)mc->buf_pos - (uintptr_t)mc->messageBuffer.data)); |
| 26622 | |
| 26623 | #ifdef UA_ENABLE_ENCRYPTION |
| 26624 | /* Add padding if the message is encrypted */ |
| 26625 | if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 26626 | padChunk(channel, cm: &sp->symmetricModule.cryptoModule, |
| 26627 | start: &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_UNENCRYPTEDLENGTH], |
| 26628 | pos: &mc->buf_pos); |
| 26629 | #endif |
| 26630 | |
| 26631 | /* Compute the total message length */ |
| 26632 | pre_sig_length = (uintptr_t)mc->buf_pos - (uintptr_t)mc->messageBuffer.data; |
| 26633 | total_length = pre_sig_length; |
| 26634 | if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 26635 | channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 26636 | total_length += sp->symmetricModule.cryptoModule.signatureAlgorithm. |
| 26637 | getLocalSignatureSize(channel->channelContext); |
| 26638 | |
| 26639 | UA_LOG_TRACE_CHANNEL(sp->logger, channel, |
| 26640 | "Send from a symmetric message buffer of length %lu " |
| 26641 | "a message of length %lu", |
| 26642 | (long unsigned int)mc->messageBuffer.length, |
| 26643 | (long unsigned int)total_length); |
| 26644 | |
| 26645 | /* Space for the padding and the signature have been reserved in setBufPos() */ |
| 26646 | UA_assert(total_length <= channel->config.sendBufferSize); |
| 26647 | |
| 26648 | /* Adjust the buffer size of the network layer */ |
| 26649 | mc->messageBuffer.length = total_length; |
| 26650 | |
| 26651 | /* Generate and encode the header for symmetric messages */ |
| 26652 | res = encodeHeadersSym(mc, totalLength: total_length); |
| 26653 | UA_CHECK_STATUS(res, goto error); |
| 26654 | |
| 26655 | #ifdef UA_ENABLE_ENCRYPTION |
| 26656 | /* Sign and encrypt the messge */ |
| 26657 | res = signAndEncryptSym(messageContext: mc, preSigLength: pre_sig_length, totalLength: total_length); |
| 26658 | UA_CHECK_STATUS(res, goto error); |
| 26659 | #endif |
| 26660 | |
| 26661 | /* Send the chunk. The buffer is freed in the network layer. If sending goes |
| 26662 | * wrong, the connection is removed in the next iteration of the |
| 26663 | * SecureChannel. Set the SecureChannel to closing already. */ |
| 26664 | res = cm->sendWithConnection(cm, channel->connectionId, |
| 26665 | &UA_KEYVALUEMAP_NULL, &mc->messageBuffer); |
| 26666 | if(res != UA_STATUSCODE_GOOD && UA_SecureChannel_isConnected(channel)) |
| 26667 | channel->state = UA_SECURECHANNELSTATE_CLOSING; |
| 26668 | |
| 26669 | error: |
| 26670 | /* Free the unused message buffer */ |
| 26671 | cm->freeNetworkBuffer(cm, channel->connectionId, &mc->messageBuffer); |
| 26672 | return res; |
| 26673 | } |
| 26674 | |
| 26675 | /* Callback from the encoding layer. Send the chunk and replace the buffer. */ |
| 26676 | static UA_StatusCode |
| 26677 | sendSymmetricEncodingCallback(void *data, UA_Byte **buf_pos, |
| 26678 | const UA_Byte **buf_end) { |
| 26679 | /* Set buf values from encoding in the messagecontext */ |
| 26680 | UA_MessageContext *mc = (UA_MessageContext *)data; |
| 26681 | mc->buf_pos = *buf_pos; |
| 26682 | mc->buf_end = *buf_end; |
| 26683 | |
| 26684 | /* Send out */ |
| 26685 | UA_StatusCode res = sendSymmetricChunk(mc); |
| 26686 | UA_CHECK_STATUS(res, return res); |
| 26687 | |
| 26688 | /* Set a new buffer for the next chunk */ |
| 26689 | UA_ConnectionManager *cm = mc->channel->connectionManager; |
| 26690 | if(!UA_SecureChannel_isConnected(channel: mc->channel)) |
| 26691 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 26692 | |
| 26693 | res = cm->allocNetworkBuffer(cm, mc->channel->connectionId, |
| 26694 | &mc->messageBuffer, |
| 26695 | mc->channel->config.sendBufferSize); |
| 26696 | UA_CHECK_STATUS(res, return res); |
| 26697 | |
| 26698 | /* Hide bytes for header, padding and signature */ |
| 26699 | setBufPos(mc); |
| 26700 | *buf_pos = mc->buf_pos; |
| 26701 | *buf_end = mc->buf_end; |
| 26702 | return UA_STATUSCODE_GOOD; |
| 26703 | } |
| 26704 | |
| 26705 | UA_StatusCode |
| 26706 | UA_MessageContext_begin(UA_MessageContext *mc, UA_SecureChannel *channel, |
| 26707 | UA_UInt32 requestId, UA_MessageType messageType) { |
| 26708 | UA_CHECK(messageType == UA_MESSAGETYPE_MSG || messageType == UA_MESSAGETYPE_CLO, |
| 26709 | return UA_STATUSCODE_BADINTERNALERROR); |
| 26710 | |
| 26711 | UA_ConnectionManager *cm = channel->connectionManager; |
| 26712 | if(!UA_SecureChannel_isConnected(channel)) |
| 26713 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 26714 | |
| 26715 | /* Create the chunking info structure */ |
| 26716 | mc->channel = channel; |
| 26717 | mc->requestId = requestId; |
| 26718 | mc->chunksSoFar = 0; |
| 26719 | mc->messageSizeSoFar = 0; |
| 26720 | mc->final = false; |
| 26721 | mc->messageBuffer = UA_BYTESTRING_NULL; |
| 26722 | mc->messageType = messageType; |
| 26723 | |
| 26724 | /* Allocate the message buffer */ |
| 26725 | UA_StatusCode res = |
| 26726 | cm->allocNetworkBuffer(cm, channel->connectionId, |
| 26727 | &mc->messageBuffer, |
| 26728 | channel->config.sendBufferSize); |
| 26729 | UA_CHECK_STATUS(res, return res); |
| 26730 | |
| 26731 | /* Hide bytes for header, padding and signature */ |
| 26732 | setBufPos(mc); |
| 26733 | return UA_STATUSCODE_GOOD; |
| 26734 | } |
| 26735 | |
| 26736 | UA_StatusCode |
| 26737 | UA_MessageContext_encode(UA_MessageContext *mc, const void *content, |
| 26738 | const UA_DataType *contentType) { |
| 26739 | UA_StatusCode res = |
| 26740 | UA_encodeBinaryInternal(src: content, type: contentType, bufPos: &mc->buf_pos, bufEnd: &mc->buf_end, |
| 26741 | exchangeCallback: sendSymmetricEncodingCallback, exchangeHandle: mc); |
| 26742 | if(res != UA_STATUSCODE_GOOD && mc->messageBuffer.length > 0) |
| 26743 | UA_MessageContext_abort(mc); |
| 26744 | return res; |
| 26745 | } |
| 26746 | |
| 26747 | UA_StatusCode |
| 26748 | UA_MessageContext_finish(UA_MessageContext *mc) { |
| 26749 | mc->final = true; |
| 26750 | return sendSymmetricChunk(mc); |
| 26751 | } |
| 26752 | |
| 26753 | void |
| 26754 | UA_MessageContext_abort(UA_MessageContext *mc) { |
| 26755 | UA_ConnectionManager *cm = mc->channel->connectionManager; |
| 26756 | if(!UA_SecureChannel_isConnected(channel: mc->channel)) |
| 26757 | return; |
| 26758 | cm->freeNetworkBuffer(cm, mc->channel->connectionId, &mc->messageBuffer); |
| 26759 | } |
| 26760 | |
| 26761 | UA_StatusCode |
| 26762 | UA_SecureChannel_sendSymmetricMessage(UA_SecureChannel *channel, UA_UInt32 requestId, |
| 26763 | UA_MessageType messageType, void *payload, |
| 26764 | const UA_DataType *payloadType) { |
| 26765 | if(!channel || !payload || !payloadType) |
| 26766 | return UA_STATUSCODE_BADINTERNALERROR; |
| 26767 | |
| 26768 | if(channel->state != UA_SECURECHANNELSTATE_OPEN) |
| 26769 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 26770 | |
| 26771 | UA_MessageContext mc; |
| 26772 | UA_StatusCode res = UA_MessageContext_begin(mc: &mc, channel, requestId, messageType); |
| 26773 | UA_CHECK_STATUS(res, return res); |
| 26774 | |
| 26775 | /* Assert's required for clang-analyzer */ |
| 26776 | UA_assert(mc.buf_pos == |
| 26777 | &mc.messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]); |
| 26778 | UA_assert(mc.buf_end <= &mc.messageBuffer.data[mc.messageBuffer.length]); |
| 26779 | |
| 26780 | res = UA_MessageContext_encode(mc: &mc, content: &payloadType->binaryEncodingId, |
| 26781 | contentType: &UA_TYPES[UA_TYPES_NODEID]); |
| 26782 | UA_CHECK_STATUS(res, return res); |
| 26783 | |
| 26784 | res = UA_MessageContext_encode(mc: &mc, content: payload, contentType: payloadType); |
| 26785 | UA_CHECK_STATUS(res, return res); |
| 26786 | |
| 26787 | return UA_MessageContext_finish(mc: &mc); |
| 26788 | } |
| 26789 | |
| 26790 | /********************************/ |
| 26791 | /* Receive and Process Messages */ |
| 26792 | /********************************/ |
| 26793 | |
| 26794 | /* Does the sequence number match? Otherwise try to rollover. See Part 6, |
| 26795 | * Section 6.7.2.4 of the standard. */ |
| 26796 | #define UA_SEQUENCENUMBER_ROLLOVER 4294966271 |
| 26797 | |
| 26798 | #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| 26799 | static UA_StatusCode |
| 26800 | processSequenceNumberSym(UA_SecureChannel *channel, UA_UInt32 sequenceNumber) { |
| 26801 | if(sequenceNumber != channel->receiveSequenceNumber + 1) { |
| 26802 | if(channel->receiveSequenceNumber + 1 <= UA_SEQUENCENUMBER_ROLLOVER || |
| 26803 | sequenceNumber >= 1024) |
| 26804 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 26805 | channel->receiveSequenceNumber = sequenceNumber - 1; /* Roll over */ |
| 26806 | } |
| 26807 | ++channel->receiveSequenceNumber; |
| 26808 | return UA_STATUSCODE_GOOD; |
| 26809 | } |
| 26810 | #endif |
| 26811 | |
| 26812 | static UA_StatusCode |
| 26813 | unpackPayloadOPN(UA_SecureChannel *channel, UA_Chunk *chunk) { |
| 26814 | UA_assert(chunk->bytes.length >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH); |
| 26815 | size_t offset = UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; /* Skip the message header */ |
| 26816 | UA_UInt32 secureChannelId; |
| 26817 | UA_StatusCode res = UA_UInt32_decodeBinary(src: &chunk->bytes, offset: &offset, dst: &secureChannelId); |
| 26818 | UA_assert(res == UA_STATUSCODE_GOOD); |
| 26819 | |
| 26820 | UA_AsymmetricAlgorithmSecurityHeader asymHeader; |
| 26821 | res = UA_decodeBinaryInternal(src: &chunk->bytes, offset: &offset, dst: &asymHeader, |
| 26822 | type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER], NULL); |
| 26823 | UA_CHECK_STATUS(res, return res); |
| 26824 | |
| 26825 | if(asymHeader.senderCertificate.length > 0) { |
| 26826 | if(channel->certificateVerification && channel->certificateVerification->verifyCertificate) |
| 26827 | res = channel->certificateVerification-> |
| 26828 | verifyCertificate(channel->certificateVerification, |
| 26829 | &asymHeader.senderCertificate); |
| 26830 | else |
| 26831 | res = UA_STATUSCODE_BADINTERNALERROR; |
| 26832 | UA_CHECK_STATUS(res, goto error); |
| 26833 | } |
| 26834 | |
| 26835 | /* New channel, create a security policy context and attach */ |
| 26836 | UA_assert(channel->processOPNHeader); |
| 26837 | res = channel->processOPNHeader(channel->processOPNHeaderApplication, |
| 26838 | channel, &asymHeader); |
| 26839 | UA_CHECK_STATUS(res, goto error); |
| 26840 | |
| 26841 | /* On the client side, take the SecureChannelId from the first response */ |
| 26842 | if(secureChannelId != 0 && channel->securityToken.channelId == 0) |
| 26843 | channel->securityToken.channelId = secureChannelId; |
| 26844 | |
| 26845 | /* Check the ChannelId */ |
| 26846 | #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) |
| 26847 | if(secureChannelId != channel->securityToken.channelId) { |
| 26848 | /* Allow the channel id to be different if the sent channel id is zero |
| 26849 | * and the SecurityToken is not initialized. This only happens on the |
| 26850 | * server side before we had a chance to tell the client which ChannelId |
| 26851 | * to use. */ |
| 26852 | if(secureChannelId != 0 || channel->securityToken.tokenId != 0) { |
| 26853 | res = UA_STATUSCODE_BADSECURECHANNELIDINVALID; |
| 26854 | goto error; |
| 26855 | } |
| 26856 | } |
| 26857 | #endif |
| 26858 | |
| 26859 | /* Check the header for the channel's security policy */ |
| 26860 | res = checkAsymHeader(channel, asymHeader: &asymHeader); |
| 26861 | UA_AsymmetricAlgorithmSecurityHeader_clear(p: &asymHeader); |
| 26862 | UA_CHECK_STATUS(res, return res); |
| 26863 | |
| 26864 | /* Decrypt the chunk payload */ |
| 26865 | res = decryptAndVerifyChunk(channel, |
| 26866 | cryptoModule: &channel->securityPolicy->asymmetricModule.cryptoModule, |
| 26867 | messageType: chunk->messageType, chunk: &chunk->bytes, offset); |
| 26868 | UA_CHECK_STATUS(res, return res); |
| 26869 | |
| 26870 | /* Decode the SequenceHeader */ |
| 26871 | UA_SequenceHeader sequenceHeader; |
| 26872 | res = UA_decodeBinaryInternal(src: &chunk->bytes, offset: &offset, dst: &sequenceHeader, |
| 26873 | type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL); |
| 26874 | UA_CHECK_STATUS(res, return res); |
| 26875 | |
| 26876 | /* Set the sequence number for the channel from which to count up */ |
| 26877 | channel->receiveSequenceNumber = sequenceHeader.sequenceNumber; |
| 26878 | chunk->requestId = sequenceHeader.requestId; /* Set the RequestId of the chunk */ |
| 26879 | |
| 26880 | /* Use only the payload */ |
| 26881 | chunk->bytes.data += offset; |
| 26882 | chunk->bytes.length -= offset; |
| 26883 | return UA_STATUSCODE_GOOD; |
| 26884 | |
| 26885 | error: |
| 26886 | UA_AsymmetricAlgorithmSecurityHeader_clear(p: &asymHeader); |
| 26887 | return res; |
| 26888 | } |
| 26889 | |
| 26890 | static UA_StatusCode |
| 26891 | unpackPayloadMSG(UA_SecureChannel *channel, UA_Chunk *chunk) { |
| 26892 | UA_CHECK_MEM(channel->securityPolicy, return UA_STATUSCODE_BADINTERNALERROR); |
| 26893 | |
| 26894 | UA_assert(chunk->bytes.length >= UA_SECURECHANNEL_MESSAGE_MIN_LENGTH); |
| 26895 | size_t offset = UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; /* Skip the message header */ |
| 26896 | UA_UInt32 secureChannelId; |
| 26897 | UA_UInt32 tokenId; /* SymmetricAlgorithmSecurityHeader */ |
| 26898 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 26899 | res |= UA_UInt32_decodeBinary(src: &chunk->bytes, offset: &offset, dst: &secureChannelId); |
| 26900 | res |= UA_UInt32_decodeBinary(src: &chunk->bytes, offset: &offset, dst: &tokenId); |
| 26901 | UA_assert(offset == UA_SECURECHANNEL_MESSAGE_MIN_LENGTH); |
| 26902 | UA_assert(res == UA_STATUSCODE_GOOD); |
| 26903 | |
| 26904 | #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) |
| 26905 | /* Check the ChannelId. Non-opened channels have the id zero. */ |
| 26906 | if(secureChannelId != channel->securityToken.channelId) |
| 26907 | return UA_STATUSCODE_BADSECURECHANNELIDINVALID; |
| 26908 | #endif |
| 26909 | |
| 26910 | /* Check (and revolve) the SecurityToken */ |
| 26911 | res = checkSymHeader(channel, tokenId); |
| 26912 | UA_CHECK_STATUS(res, return res); |
| 26913 | |
| 26914 | /* Decrypt the chunk payload */ |
| 26915 | res = decryptAndVerifyChunk(channel, |
| 26916 | cryptoModule: &channel->securityPolicy->symmetricModule.cryptoModule, |
| 26917 | messageType: chunk->messageType, chunk: &chunk->bytes, offset); |
| 26918 | UA_CHECK_STATUS(res, return res); |
| 26919 | |
| 26920 | /* Check the sequence number. Skip sequence number checking for fuzzer to |
| 26921 | * improve coverage */ |
| 26922 | UA_SequenceHeader sequenceHeader; |
| 26923 | res = UA_decodeBinaryInternal(src: &chunk->bytes, offset: &offset, dst: &sequenceHeader, |
| 26924 | type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], NULL); |
| 26925 | #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| 26926 | res |= processSequenceNumberSym(channel, sequenceNumber: sequenceHeader.sequenceNumber); |
| 26927 | #endif |
| 26928 | UA_CHECK_STATUS(res, return res); |
| 26929 | |
| 26930 | chunk->requestId = sequenceHeader.requestId; /* Set the RequestId of the chunk */ |
| 26931 | |
| 26932 | /* Use only the payload */ |
| 26933 | chunk->bytes.data += offset; |
| 26934 | chunk->bytes.length -= offset; |
| 26935 | return UA_STATUSCODE_GOOD; |
| 26936 | } |
| 26937 | |
| 26938 | static UA_StatusCode |
| 26939 | extractCompleteChunk(UA_SecureChannel *channel, UA_Chunk *chunk) { |
| 26940 | /* At least 8 byte needed for the header */ |
| 26941 | size_t offset = channel->unprocessedOffset; |
| 26942 | size_t remaining = channel->unprocessed.length - offset; |
| 26943 | if(remaining < UA_SECURECHANNEL_MESSAGEHEADER_LENGTH) |
| 26944 | return UA_STATUSCODE_GOOD; |
| 26945 | |
| 26946 | /* Decoding the header cannot fail */ |
| 26947 | UA_TcpMessageHeader hdr; |
| 26948 | UA_StatusCode res = |
| 26949 | UA_decodeBinaryInternal(src: &channel->unprocessed, offset: &offset, dst: &hdr, |
| 26950 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], NULL); |
| 26951 | UA_assert(res == UA_STATUSCODE_GOOD); |
| 26952 | (void)res; /* pacify compilers if assert is ignored */ |
| 26953 | UA_MessageType msgType = (UA_MessageType) |
| 26954 | (hdr.messageTypeAndChunkType & UA_BITMASK_MESSAGETYPE); |
| 26955 | UA_ChunkType chunkType = (UA_ChunkType) |
| 26956 | (hdr.messageTypeAndChunkType & UA_BITMASK_CHUNKTYPE); |
| 26957 | |
| 26958 | /* The message size is not allowed */ |
| 26959 | if(hdr.messageSize < UA_SECURECHANNEL_MESSAGE_MIN_LENGTH) |
| 26960 | return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID; |
| 26961 | if(hdr.messageSize > channel->config.recvBufferSize) |
| 26962 | return UA_STATUSCODE_BADTCPMESSAGETOOLARGE; |
| 26963 | |
| 26964 | /* Incomplete chunk. Continue processing later. */ |
| 26965 | if(hdr.messageSize > remaining) |
| 26966 | return UA_STATUSCODE_GOOD; |
| 26967 | |
| 26968 | /* Set the chunk information */ |
| 26969 | chunk->bytes.data = channel->unprocessed.data + channel->unprocessedOffset; |
| 26970 | chunk->bytes.length = hdr.messageSize; |
| 26971 | chunk->messageType = msgType; |
| 26972 | chunk->chunkType = chunkType; |
| 26973 | chunk->requestId = 0; |
| 26974 | chunk->copied = false; |
| 26975 | |
| 26976 | /* Increase the unprocessed offset */ |
| 26977 | channel->unprocessedOffset += hdr.messageSize; |
| 26978 | |
| 26979 | /* Validate, decrypt and unpack the chunk payload */ |
| 26980 | switch(msgType) { |
| 26981 | case UA_MESSAGETYPE_OPN: |
| 26982 | if(chunkType != UA_CHUNKTYPE_FINAL) |
| 26983 | return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID; |
| 26984 | if(channel->state != UA_SECURECHANNELSTATE_OPEN && |
| 26985 | channel->state != UA_SECURECHANNELSTATE_OPN_SENT && |
| 26986 | channel->state != UA_SECURECHANNELSTATE_ACK_SENT) |
| 26987 | return UA_STATUSCODE_BADINVALIDSTATE; |
| 26988 | res = unpackPayloadOPN(channel, chunk); |
| 26989 | break; |
| 26990 | |
| 26991 | case UA_MESSAGETYPE_MSG: |
| 26992 | case UA_MESSAGETYPE_CLO: |
| 26993 | if(chunkType != UA_CHUNKTYPE_FINAL && |
| 26994 | chunkType != UA_CHUNKTYPE_INTERMEDIATE && |
| 26995 | chunkType != UA_CHUNKTYPE_ABORT) |
| 26996 | return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID; |
| 26997 | if(channel->state != UA_SECURECHANNELSTATE_OPEN) |
| 26998 | return UA_STATUSCODE_BADINVALIDSTATE; |
| 26999 | res = unpackPayloadMSG(channel, chunk); |
| 27000 | break; |
| 27001 | |
| 27002 | case UA_MESSAGETYPE_RHE: |
| 27003 | case UA_MESSAGETYPE_HEL: |
| 27004 | case UA_MESSAGETYPE_ACK: |
| 27005 | case UA_MESSAGETYPE_ERR: |
| 27006 | if(chunkType != UA_CHUNKTYPE_FINAL) |
| 27007 | return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID; |
| 27008 | /* Hide the message header */ |
| 27009 | chunk->bytes.data += UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; |
| 27010 | chunk->bytes.length -= UA_SECURECHANNEL_MESSAGEHEADER_LENGTH; |
| 27011 | break; |
| 27012 | |
| 27013 | default: |
| 27014 | res = UA_STATUSCODE_BADTCPMESSAGETYPEINVALID; |
| 27015 | break; |
| 27016 | } |
| 27017 | return res; |
| 27018 | } |
| 27019 | |
| 27020 | UA_StatusCode |
| 27021 | UA_SecureChannel_loadBuffer(UA_SecureChannel *channel, const UA_ByteString buffer) { |
| 27022 | /* Append to the previous unprocessed buffer */ |
| 27023 | if(channel->unprocessed.length > 0) { |
| 27024 | UA_assert(channel->unprocessedCopied == true); |
| 27025 | |
| 27026 | UA_Byte *t = (UA_Byte*) |
| 27027 | UA_realloc(ptr: channel->unprocessed.data, |
| 27028 | size: channel->unprocessed.length + buffer.length); |
| 27029 | if(!t) |
| 27030 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 27031 | |
| 27032 | memcpy(dest: t + channel->unprocessed.length, src: buffer.data, n: buffer.length); |
| 27033 | channel->unprocessed.data = t; |
| 27034 | channel->unprocessed.length += buffer.length; |
| 27035 | return UA_STATUSCODE_GOOD; |
| 27036 | } |
| 27037 | |
| 27038 | /* Use the new buffer directly */ |
| 27039 | channel->unprocessed = buffer; |
| 27040 | channel->unprocessedCopied = false; |
| 27041 | return UA_STATUSCODE_GOOD; |
| 27042 | } |
| 27043 | |
| 27044 | UA_StatusCode |
| 27045 | UA_SecureChannel_getCompleteMessage(UA_SecureChannel *channel, |
| 27046 | UA_MessageType *messageType, UA_UInt32 *requestId, |
| 27047 | UA_ByteString *payload, UA_Boolean *copied) { |
| 27048 | UA_Chunk chunk, *pchunk; |
| 27049 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 27050 | |
| 27051 | extract_chunk: |
| 27052 | /* Extract+decode the next chunk from the buffer */ |
| 27053 | memset(s: &chunk, c: 0, n: sizeof(UA_Chunk)); |
| 27054 | res = extractCompleteChunk(channel, chunk: &chunk); |
| 27055 | if(chunk.bytes.length == 0 || res != UA_STATUSCODE_GOOD) |
| 27056 | return res; /* Error or no complete chunk could be extracted */ |
| 27057 | |
| 27058 | /* Process the chunk */ |
| 27059 | switch(chunk.chunkType) { |
| 27060 | case UA_CHUNKTYPE_ABORT: |
| 27061 | /* Remove all chunks received so far. Then continue extracting chunks. */ |
| 27062 | deleteChunks(channel); |
| 27063 | if(chunk.copied) |
| 27064 | UA_ByteString_clear(p: &chunk.bytes); |
| 27065 | goto extract_chunk; |
| 27066 | |
| 27067 | case UA_CHUNKTYPE_INTERMEDIATE: |
| 27068 | /* Validate the resource limits */ |
| 27069 | if((channel->config.localMaxChunkCount != 0 && |
| 27070 | channel->chunksCount >= channel->config.localMaxChunkCount) || |
| 27071 | (channel->config.localMaxMessageSize != 0 && |
| 27072 | channel->chunksLength + chunk.bytes.length > channel->config.localMaxMessageSize)) { |
| 27073 | if(chunk.copied) |
| 27074 | UA_ByteString_clear(p: &chunk.bytes); |
| 27075 | return UA_STATUSCODE_BADTCPMESSAGETOOLARGE; |
| 27076 | } |
| 27077 | |
| 27078 | /* Add the chunk to the queue. Then continue extracting more chunks. */ |
| 27079 | pchunk = (UA_Chunk*)UA_malloc(size: sizeof(UA_Chunk)); |
| 27080 | if(!pchunk) { |
| 27081 | if(chunk.copied) |
| 27082 | UA_ByteString_clear(p: &chunk.bytes); |
| 27083 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 27084 | } |
| 27085 | *pchunk = chunk; |
| 27086 | TAILQ_INSERT_TAIL(&channel->chunks, pchunk, pointers); |
| 27087 | channel->chunksCount++; |
| 27088 | channel->chunksLength += pchunk->bytes.length; |
| 27089 | goto extract_chunk; |
| 27090 | |
| 27091 | case UA_CHUNKTYPE_FINAL: |
| 27092 | default: |
| 27093 | UA_assert(chunk.chunkType == UA_CHUNKTYPE_FINAL); /* Was checked before */ |
| 27094 | break; /* A final chunk was received -- assemble the message */ |
| 27095 | } |
| 27096 | |
| 27097 | /* Compute the message size */ |
| 27098 | size_t messageSize = chunk.bytes.length; |
| 27099 | UA_Chunk *first = NULL; |
| 27100 | TAILQ_FOREACH(pchunk, &channel->chunks, pointers) { |
| 27101 | if(chunk.requestId != pchunk->requestId) |
| 27102 | continue; |
| 27103 | if(chunk.messageType != pchunk->messageType) { |
| 27104 | if(chunk.copied) |
| 27105 | UA_ByteString_clear(p: &chunk.bytes); |
| 27106 | return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID; |
| 27107 | } |
| 27108 | if(!first) |
| 27109 | first = pchunk; |
| 27110 | messageSize += pchunk->bytes.length; |
| 27111 | } |
| 27112 | |
| 27113 | /* Validate the assembled message size */ |
| 27114 | if(channel->config.localMaxMessageSize != 0 && |
| 27115 | channel->chunksLength > channel->config.localMaxMessageSize) { |
| 27116 | if(chunk.copied) |
| 27117 | UA_ByteString_clear(p: &chunk.bytes); |
| 27118 | return UA_STATUSCODE_BADTCPMESSAGETOOLARGE; |
| 27119 | } |
| 27120 | |
| 27121 | /* Assemble the full payload and store it in chunk.bytes */ |
| 27122 | if(messageSize > chunk.bytes.length) { |
| 27123 | UA_assert(first != NULL); |
| 27124 | |
| 27125 | /* Allocate the full memory and initialize with the first chunk content. |
| 27126 | * Use realloc to speed up. */ |
| 27127 | UA_ByteString message; |
| 27128 | if(first->copied) { |
| 27129 | message.data = (UA_Byte*)UA_realloc(ptr: first->bytes.data, size: messageSize); |
| 27130 | } else { |
| 27131 | message.data = (UA_Byte*)UA_malloc(size: messageSize); |
| 27132 | if(message.data) |
| 27133 | memcpy(dest: message.data, src: first->bytes.data, n: first->bytes.length); |
| 27134 | } |
| 27135 | if(!message.data) { |
| 27136 | if(chunk.copied) |
| 27137 | UA_ByteString_clear(p: &chunk.bytes); |
| 27138 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 27139 | } |
| 27140 | message.length = first->bytes.length; |
| 27141 | |
| 27142 | /* Remove the the first chunk */ |
| 27143 | pchunk = TAILQ_NEXT(first, pointers); |
| 27144 | first->copied = false; |
| 27145 | channel->chunksCount--; |
| 27146 | channel->chunksLength -= first->bytes.length; |
| 27147 | TAILQ_REMOVE(&channel->chunks, first, pointers); |
| 27148 | UA_Chunk_delete(chunk: first); |
| 27149 | |
| 27150 | /* Copy over the content from the remaining intermediate chunks. |
| 27151 | * And remove them right away. */ |
| 27152 | UA_Chunk *next; |
| 27153 | for(; pchunk; pchunk = next) { |
| 27154 | next = TAILQ_NEXT(pchunk, pointers); |
| 27155 | if(chunk.requestId != pchunk->requestId) |
| 27156 | continue; |
| 27157 | memcpy(dest: message.data + message.length, src: pchunk->bytes.data, n: pchunk->bytes.length); |
| 27158 | message.length += pchunk->bytes.length; |
| 27159 | channel->chunksCount--; |
| 27160 | channel->chunksLength -= pchunk->bytes.length; |
| 27161 | TAILQ_REMOVE(&channel->chunks, pchunk, pointers); |
| 27162 | UA_Chunk_delete(chunk: pchunk); |
| 27163 | } |
| 27164 | |
| 27165 | /* Copy over the content from the final chunk */ |
| 27166 | memcpy(dest: message.data + message.length, src: chunk.bytes.data, n: chunk.bytes.length); |
| 27167 | message.length += chunk.bytes.length; |
| 27168 | UA_assert(message.length == messageSize); |
| 27169 | |
| 27170 | /* Set assembled message as the content of the final chunk */ |
| 27171 | if(chunk.copied) |
| 27172 | UA_ByteString_clear(p: &chunk.bytes); |
| 27173 | chunk.bytes = message; |
| 27174 | chunk.copied = true; |
| 27175 | } |
| 27176 | |
| 27177 | /* Return the assembled message */ |
| 27178 | *requestId = chunk.requestId; |
| 27179 | *messageType = chunk.messageType; |
| 27180 | *payload = chunk.bytes; |
| 27181 | *copied = chunk.copied; |
| 27182 | return UA_STATUSCODE_GOOD; |
| 27183 | } |
| 27184 | |
| 27185 | UA_StatusCode |
| 27186 | UA_SecureChannel_persistBuffer(UA_SecureChannel *channel) { |
| 27187 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 27188 | |
| 27189 | /* Persist the chunks */ |
| 27190 | UA_Chunk *chunk; |
| 27191 | TAILQ_FOREACH(chunk, &channel->chunks, pointers) { |
| 27192 | if(chunk->copied) |
| 27193 | continue; |
| 27194 | UA_ByteString tmp = UA_BYTESTRING_NULL; |
| 27195 | res |= UA_ByteString_copy(src: &chunk->bytes, dst: &tmp); |
| 27196 | chunk->bytes = tmp; |
| 27197 | chunk->copied = true; |
| 27198 | } |
| 27199 | |
| 27200 | /* No unprocessed bytes remaining */ |
| 27201 | UA_assert(channel->unprocessed.length >= channel->unprocessedOffset); |
| 27202 | if(channel->unprocessed.length == channel->unprocessedOffset) { |
| 27203 | if(channel->unprocessedCopied) |
| 27204 | UA_ByteString_clear(p: &channel->unprocessed); |
| 27205 | else |
| 27206 | UA_ByteString_init(p: &channel->unprocessed); |
| 27207 | channel->unprocessedOffset = 0; |
| 27208 | return res; |
| 27209 | } |
| 27210 | |
| 27211 | /* Allocate a new unprocessed ByteString. |
| 27212 | * tmp is the empty string if malloc fails. */ |
| 27213 | UA_ByteString tmp = UA_BYTESTRING_NULL; |
| 27214 | UA_ByteString remaining = channel->unprocessed; |
| 27215 | remaining.data += channel->unprocessedOffset; |
| 27216 | remaining.length -= channel->unprocessedOffset; |
| 27217 | res |= UA_ByteString_copy(src: &remaining, dst: &tmp); |
| 27218 | if(channel->unprocessedCopied) |
| 27219 | UA_ByteString_clear(p: &channel->unprocessed); |
| 27220 | channel->unprocessed = tmp; |
| 27221 | channel->unprocessedOffset = 0; |
| 27222 | channel->unprocessedCopied = true; |
| 27223 | return res; |
| 27224 | } |
| 27225 | |
| 27226 | /**** amalgamated original file "/src/ua_securechannel_crypto.c" ****/ |
| 27227 | |
| 27228 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 27229 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 27230 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 27231 | * |
| 27232 | * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 27233 | * Copyright 2014, 2016-2017 (c) Florian Palm |
| 27234 | * Copyright 2015-2016 (c) Sten Grüner |
| 27235 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 27236 | * Copyright 2016 (c) TorbenD |
| 27237 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 27238 | * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB |
| 27239 | */ |
| 27240 | |
| 27241 | |
| 27242 | |
| 27243 | UA_StatusCode |
| 27244 | UA_SecureChannel_generateLocalNonce(UA_SecureChannel *channel) { |
| 27245 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 27246 | UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR); |
| 27247 | UA_LOG_DEBUG_CHANNEL(sp->logger, channel, "Generating new local nonce"); |
| 27248 | |
| 27249 | /* Is the length of the previous nonce correct? */ |
| 27250 | size_t nonceLength = sp->symmetricModule.secureChannelNonceLength; |
| 27251 | if(channel->localNonce.length != nonceLength) { |
| 27252 | UA_ByteString_clear(p: &channel->localNonce); |
| 27253 | UA_StatusCode res = UA_ByteString_allocBuffer(bs: &channel->localNonce, length: nonceLength); |
| 27254 | UA_CHECK_STATUS(res, return res); |
| 27255 | } |
| 27256 | |
| 27257 | /* Generate the nonce */ |
| 27258 | return sp->symmetricModule.generateNonce(sp->policyContext, &channel->localNonce); |
| 27259 | } |
| 27260 | |
| 27261 | UA_StatusCode |
| 27262 | UA_SecureChannel_generateLocalKeys(const UA_SecureChannel *channel) { |
| 27263 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 27264 | UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR); |
| 27265 | UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Generating new local keys"); |
| 27266 | |
| 27267 | void *cc = channel->channelContext; |
| 27268 | const UA_SecurityPolicyChannelModule *cm = &sp->channelModule; |
| 27269 | const UA_SecurityPolicySymmetricModule *sm = &sp->symmetricModule; |
| 27270 | const UA_SecurityPolicyCryptoModule *crm = &sm->cryptoModule; |
| 27271 | |
| 27272 | /* Generate symmetric key buffer of the required length. The block size is |
| 27273 | * identical for local/remote. */ |
| 27274 | UA_ByteString buf; |
| 27275 | size_t encrKL = crm->encryptionAlgorithm.getLocalKeyLength(cc); |
| 27276 | size_t encrBS = crm->encryptionAlgorithm.getRemoteBlockSize(cc); |
| 27277 | size_t signKL = crm->signatureAlgorithm.getLocalKeyLength(cc); |
| 27278 | if(encrBS + signKL + encrKL == 0) |
| 27279 | return UA_STATUSCODE_GOOD; /* No keys to generate */ |
| 27280 | |
| 27281 | UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &buf, length: encrBS + signKL + encrKL); |
| 27282 | UA_CHECK_STATUS(retval, return retval); |
| 27283 | UA_ByteString localSigningKey = {signKL, buf.data}; |
| 27284 | UA_ByteString localEncryptingKey = {encrKL, &buf.data[signKL]}; |
| 27285 | UA_ByteString localIv = {encrBS, &buf.data[signKL + encrKL]}; |
| 27286 | |
| 27287 | /* Generate key */ |
| 27288 | retval = sm->generateKey(sp->policyContext, &channel->remoteNonce, |
| 27289 | &channel->localNonce, &buf); |
| 27290 | UA_CHECK_STATUS(retval, goto error); |
| 27291 | |
| 27292 | /* Set the channel context */ |
| 27293 | retval |= cm->setLocalSymSigningKey(cc, &localSigningKey); |
| 27294 | retval |= cm->setLocalSymEncryptingKey(cc, &localEncryptingKey); |
| 27295 | retval |= cm->setLocalSymIv(cc, &localIv); |
| 27296 | |
| 27297 | error: |
| 27298 | UA_CHECK_STATUS(retval, UA_LOG_WARNING_CHANNEL(sp->logger, channel, |
| 27299 | "Could not generate local keys (statuscode: %s)", |
| 27300 | UA_StatusCode_name(retval))); |
| 27301 | UA_ByteString_clear(p: &buf); |
| 27302 | return retval; |
| 27303 | } |
| 27304 | |
| 27305 | UA_StatusCode |
| 27306 | generateRemoteKeys(const UA_SecureChannel *channel) { |
| 27307 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 27308 | UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR); |
| 27309 | UA_LOG_TRACE_CHANNEL(sp->logger, channel, "Generating new remote keys"); |
| 27310 | |
| 27311 | void *cc = channel->channelContext; |
| 27312 | const UA_SecurityPolicyChannelModule *cm = &sp->channelModule; |
| 27313 | const UA_SecurityPolicySymmetricModule *sm = &sp->symmetricModule; |
| 27314 | const UA_SecurityPolicyCryptoModule *crm = &sm->cryptoModule; |
| 27315 | |
| 27316 | /* Generate symmetric key buffer of the required length */ |
| 27317 | UA_ByteString buf; |
| 27318 | size_t encrKL = crm->encryptionAlgorithm.getRemoteKeyLength(cc); |
| 27319 | size_t encrBS = crm->encryptionAlgorithm.getRemoteBlockSize(cc); |
| 27320 | size_t signKL = crm->signatureAlgorithm.getRemoteKeyLength(cc); |
| 27321 | if(encrBS + signKL + encrKL == 0) |
| 27322 | return UA_STATUSCODE_GOOD; /* No keys to generate */ |
| 27323 | |
| 27324 | UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &buf, length: encrBS + signKL + encrKL); |
| 27325 | UA_CHECK_STATUS(retval, return retval); |
| 27326 | UA_ByteString remoteSigningKey = {signKL, buf.data}; |
| 27327 | UA_ByteString remoteEncryptingKey = {encrKL, &buf.data[signKL]}; |
| 27328 | UA_ByteString remoteIv = {encrBS, &buf.data[signKL + encrKL]}; |
| 27329 | |
| 27330 | /* Generate key */ |
| 27331 | retval = sm->generateKey(sp->policyContext, &channel->localNonce, |
| 27332 | &channel->remoteNonce, &buf); |
| 27333 | UA_CHECK_STATUS(retval, goto error); |
| 27334 | |
| 27335 | /* Set the channel context */ |
| 27336 | retval |= cm->setRemoteSymSigningKey(cc, &remoteSigningKey); |
| 27337 | retval |= cm->setRemoteSymEncryptingKey(cc, &remoteEncryptingKey); |
| 27338 | retval |= cm->setRemoteSymIv(cc, &remoteIv); |
| 27339 | |
| 27340 | error: |
| 27341 | UA_CHECK_STATUS(retval, UA_LOG_WARNING_CHANNEL(sp->logger, channel, |
| 27342 | "Could not generate remote keys (statuscode: %s)", |
| 27343 | UA_StatusCode_name(retval))); |
| 27344 | UA_ByteString_clear(p: &buf); |
| 27345 | return retval; |
| 27346 | } |
| 27347 | |
| 27348 | /***************************/ |
| 27349 | /* Send Asymmetric Message */ |
| 27350 | /***************************/ |
| 27351 | |
| 27352 | /* The length of the static header content */ |
| 27353 | #define UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH 12 |
| 27354 | |
| 27355 | size_t |
| 27356 | calculateAsymAlgSecurityHeaderLength(const UA_SecureChannel *channel) { |
| 27357 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 27358 | UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR); |
| 27359 | |
| 27360 | size_t asymHeaderLength = UA_SECURECHANNEL_ASYMMETRIC_SECURITYHEADER_FIXED_LENGTH + |
| 27361 | sp->policyUri.length; |
| 27362 | if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE) |
| 27363 | return asymHeaderLength; |
| 27364 | |
| 27365 | /* OPN is always encrypted even if the mode is sign only */ |
| 27366 | asymHeaderLength += 20; /* Thumbprints are always 20 byte long */ |
| 27367 | asymHeaderLength += sp->localCertificate.length; |
| 27368 | return asymHeaderLength; |
| 27369 | } |
| 27370 | |
| 27371 | UA_StatusCode |
| 27372 | prependHeadersAsym(UA_SecureChannel *const channel, UA_Byte *header_pos, |
| 27373 | const UA_Byte *buf_end, size_t totalLength, |
| 27374 | size_t securityHeaderLength, UA_UInt32 requestId, |
| 27375 | size_t *const encryptedLength) { |
| 27376 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 27377 | UA_CHECK_MEM(sp, return UA_STATUSCODE_BADINTERNALERROR); |
| 27378 | |
| 27379 | if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE) { |
| 27380 | *encryptedLength = totalLength; |
| 27381 | } else { |
| 27382 | size_t dataToEncryptLength = totalLength - |
| 27383 | (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength); |
| 27384 | size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule. |
| 27385 | encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext); |
| 27386 | size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule. |
| 27387 | encryptionAlgorithm.getRemoteBlockSize(channel->channelContext); |
| 27388 | |
| 27389 | /* Padding always fills up the last block */ |
| 27390 | UA_assert(dataToEncryptLength % plainTextBlockSize == 0); |
| 27391 | size_t blocks = dataToEncryptLength / plainTextBlockSize; |
| 27392 | *encryptedLength = totalLength + blocks * (encryptedBlockSize - plainTextBlockSize); |
| 27393 | } |
| 27394 | |
| 27395 | UA_TcpMessageHeader messageHeader; |
| 27396 | messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL; |
| 27397 | messageHeader.messageSize = (UA_UInt32)*encryptedLength; |
| 27398 | UA_UInt32 secureChannelId = channel->securityToken.channelId; |
| 27399 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 27400 | retval |= UA_encodeBinaryInternal(src: &messageHeader, |
| 27401 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], |
| 27402 | bufPos: &header_pos, bufEnd: &buf_end, NULL, NULL); |
| 27403 | retval |= UA_UInt32_encodeBinary(src: &secureChannelId, bufPos: &header_pos, bufEnd: buf_end); |
| 27404 | UA_CHECK_STATUS(retval, return retval); |
| 27405 | |
| 27406 | UA_AsymmetricAlgorithmSecurityHeader asymHeader; |
| 27407 | UA_AsymmetricAlgorithmSecurityHeader_init(p: &asymHeader); |
| 27408 | asymHeader.securityPolicyUri = sp->policyUri; |
| 27409 | if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 27410 | channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 27411 | asymHeader.senderCertificate = sp->localCertificate; |
| 27412 | asymHeader.receiverCertificateThumbprint.length = 20; |
| 27413 | asymHeader.receiverCertificateThumbprint.data = channel->remoteCertificateThumbprint; |
| 27414 | } |
| 27415 | retval = UA_encodeBinaryInternal(src: &asymHeader, |
| 27416 | type: &UA_TRANSPORT[UA_TRANSPORT_ASYMMETRICALGORITHMSECURITYHEADER], |
| 27417 | bufPos: &header_pos, bufEnd: &buf_end, NULL, NULL); |
| 27418 | UA_CHECK_STATUS(retval, return retval); |
| 27419 | |
| 27420 | /* Increase the sequence number in the channel */ |
| 27421 | channel->sendSequenceNumber++; |
| 27422 | |
| 27423 | UA_SequenceHeader seqHeader; |
| 27424 | seqHeader.requestId = requestId; |
| 27425 | seqHeader.sequenceNumber = channel->sendSequenceNumber; |
| 27426 | retval = UA_encodeBinaryInternal(src: &seqHeader, type: &UA_TRANSPORT[UA_TRANSPORT_SEQUENCEHEADER], |
| 27427 | bufPos: &header_pos, bufEnd: &buf_end, NULL, NULL); |
| 27428 | return retval; |
| 27429 | } |
| 27430 | |
| 27431 | void |
| 27432 | hideBytesAsym(const UA_SecureChannel *channel, UA_Byte **buf_start, |
| 27433 | const UA_Byte **buf_end) { |
| 27434 | /* Set buf_start to the beginning of the payload body */ |
| 27435 | *buf_start += UA_SECURECHANNEL_CHANNELHEADER_LENGTH; |
| 27436 | *buf_start += calculateAsymAlgSecurityHeaderLength(channel); |
| 27437 | *buf_start += UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH; |
| 27438 | |
| 27439 | #ifdef UA_ENABLE_ENCRYPTION |
| 27440 | if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE) |
| 27441 | return; |
| 27442 | |
| 27443 | /* Make space for the certificate */ |
| 27444 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 27445 | *buf_end -= sp->asymmetricModule.cryptoModule.signatureAlgorithm. |
| 27446 | getLocalSignatureSize(channel->channelContext); |
| 27447 | |
| 27448 | /* Block sizes depend on the remote key (certificate) */ |
| 27449 | size_t plainTextBlockSize = sp->asymmetricModule.cryptoModule. |
| 27450 | encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext); |
| 27451 | size_t encryptedBlockSize = sp->asymmetricModule.cryptoModule. |
| 27452 | encryptionAlgorithm.getRemoteBlockSize(channel->channelContext); |
| 27453 | UA_Boolean extraPadding = (sp->asymmetricModule.cryptoModule.encryptionAlgorithm. |
| 27454 | getRemoteKeyLength(channel->channelContext) > 2048); |
| 27455 | |
| 27456 | /* Compute the maximum number of encrypted blocks that can fit entirely |
| 27457 | * before the signature. From that compute the maximum usable plaintext |
| 27458 | * size. */ |
| 27459 | size_t maxEncrypted = (size_t)(*buf_end - *buf_start) + |
| 27460 | UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH; |
| 27461 | size_t max_blocks = maxEncrypted / encryptedBlockSize; |
| 27462 | size_t paddingBytes = (UA_LIKELY(!extraPadding)) ? 1u : 2u; |
| 27463 | *buf_end = *buf_start + (max_blocks * plainTextBlockSize) - |
| 27464 | UA_SECURECHANNEL_SEQUENCEHEADER_LENGTH - paddingBytes; |
| 27465 | #endif |
| 27466 | } |
| 27467 | |
| 27468 | #ifdef UA_ENABLE_ENCRYPTION |
| 27469 | |
| 27470 | /* Assumes that pos can be advanced to the end of the current block */ |
| 27471 | void |
| 27472 | padChunk(UA_SecureChannel *channel, const UA_SecurityPolicyCryptoModule *cm, |
| 27473 | const UA_Byte *start, UA_Byte **pos) { |
| 27474 | const size_t bytesToWrite = (uintptr_t)*pos - (uintptr_t)start; |
| 27475 | size_t signatureSize = cm->signatureAlgorithm. |
| 27476 | getLocalSignatureSize(channel->channelContext); |
| 27477 | size_t plainTextBlockSize = cm->encryptionAlgorithm. |
| 27478 | getRemotePlainTextBlockSize(channel->channelContext); |
| 27479 | UA_Boolean extraPadding = (cm->encryptionAlgorithm. |
| 27480 | getRemoteKeyLength(channel->channelContext) > 2048); |
| 27481 | size_t paddingBytes = (UA_LIKELY(!extraPadding)) ? 1u : 2u; |
| 27482 | |
| 27483 | size_t lastBlock = ((bytesToWrite + signatureSize + paddingBytes) % plainTextBlockSize); |
| 27484 | size_t paddingLength = (lastBlock != 0) ? plainTextBlockSize - lastBlock : 0; |
| 27485 | |
| 27486 | UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel, |
| 27487 | "Add %lu bytes of padding plus %lu padding size bytes", |
| 27488 | (long unsigned int)paddingLength, |
| 27489 | (long unsigned int)paddingBytes); |
| 27490 | |
| 27491 | /* Write the padding. This is <= because the paddingSize byte also has to be |
| 27492 | * written */ |
| 27493 | UA_Byte paddingByte = (UA_Byte)paddingLength; |
| 27494 | for(UA_UInt16 i = 0; i <= paddingLength; ++i) { |
| 27495 | **pos = paddingByte; |
| 27496 | ++*pos; |
| 27497 | } |
| 27498 | |
| 27499 | /* Write the extra padding byte if required */ |
| 27500 | if(extraPadding) { |
| 27501 | **pos = (UA_Byte)(paddingLength >> 8u); |
| 27502 | ++*pos; |
| 27503 | } |
| 27504 | } |
| 27505 | |
| 27506 | UA_StatusCode |
| 27507 | signAndEncryptAsym(UA_SecureChannel *channel, size_t preSignLength, |
| 27508 | UA_ByteString *buf, size_t securityHeaderLength, |
| 27509 | size_t totalLength) { |
| 27510 | if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN && |
| 27511 | channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 27512 | return UA_STATUSCODE_GOOD; |
| 27513 | |
| 27514 | /* Sign message */ |
| 27515 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 27516 | const UA_ByteString dataToSign = {preSignLength, buf->data}; |
| 27517 | size_t sigsize = sp->asymmetricModule.cryptoModule.signatureAlgorithm. |
| 27518 | getLocalSignatureSize(channel->channelContext); |
| 27519 | UA_ByteString signature = {sigsize, buf->data + preSignLength}; |
| 27520 | UA_StatusCode retval = sp->asymmetricModule.cryptoModule.signatureAlgorithm. |
| 27521 | sign(channel->channelContext, &dataToSign, &signature); |
| 27522 | UA_CHECK_STATUS(retval, return retval); |
| 27523 | |
| 27524 | /* Specification part 6, 6.7.4: The OpenSecureChannel Messages are |
| 27525 | * signed and encrypted if the SecurityMode is not None (even if the |
| 27526 | * SecurityMode is SignOnly). */ |
| 27527 | size_t unencrypted_length = |
| 27528 | UA_SECURECHANNEL_CHANNELHEADER_LENGTH + securityHeaderLength; |
| 27529 | UA_ByteString dataToEncrypt = {totalLength - unencrypted_length, |
| 27530 | &buf->data[unencrypted_length]}; |
| 27531 | return sp->asymmetricModule.cryptoModule.encryptionAlgorithm. |
| 27532 | encrypt(channel->channelContext, &dataToEncrypt); |
| 27533 | } |
| 27534 | |
| 27535 | /**************************/ |
| 27536 | /* Send Symmetric Message */ |
| 27537 | /**************************/ |
| 27538 | |
| 27539 | UA_StatusCode |
| 27540 | signAndEncryptSym(UA_MessageContext *messageContext, |
| 27541 | size_t preSigLength, size_t totalLength) { |
| 27542 | const UA_SecureChannel *channel = messageContext->channel; |
| 27543 | if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE) |
| 27544 | return UA_STATUSCODE_GOOD; |
| 27545 | |
| 27546 | /* Sign */ |
| 27547 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 27548 | UA_ByteString dataToSign = messageContext->messageBuffer; |
| 27549 | dataToSign.length = preSigLength; |
| 27550 | UA_ByteString signature; |
| 27551 | signature.length = sp->symmetricModule.cryptoModule.signatureAlgorithm. |
| 27552 | getLocalSignatureSize(channel->channelContext); |
| 27553 | signature.data = messageContext->buf_pos; |
| 27554 | UA_StatusCode res = sp->symmetricModule.cryptoModule.signatureAlgorithm. |
| 27555 | sign(channel->channelContext, &dataToSign, &signature); |
| 27556 | UA_CHECK_STATUS(res, return res); |
| 27557 | |
| 27558 | if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 27559 | return UA_STATUSCODE_GOOD; |
| 27560 | |
| 27561 | /* Encrypt */ |
| 27562 | UA_ByteString dataToEncrypt; |
| 27563 | dataToEncrypt.data = messageContext->messageBuffer.data + |
| 27564 | UA_SECURECHANNEL_CHANNELHEADER_LENGTH + |
| 27565 | UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH; |
| 27566 | dataToEncrypt.length = totalLength - |
| 27567 | (UA_SECURECHANNEL_CHANNELHEADER_LENGTH + |
| 27568 | UA_SECURECHANNEL_SYMMETRIC_SECURITYHEADER_LENGTH); |
| 27569 | return sp->symmetricModule.cryptoModule.encryptionAlgorithm. |
| 27570 | encrypt(channel->channelContext, &dataToEncrypt); |
| 27571 | } |
| 27572 | |
| 27573 | #endif /* UA_ENABLE_ENCRYPTION */ |
| 27574 | |
| 27575 | void |
| 27576 | setBufPos(UA_MessageContext *mc) { |
| 27577 | /* Forward the data pointer so that the payload is encoded after the message |
| 27578 | * header. This has to be a symmetric message because OPN (with asymmetric |
| 27579 | * encryption) does not support chunking. */ |
| 27580 | mc->buf_pos = &mc->messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]; |
| 27581 | mc->buf_end = &mc->messageBuffer.data[mc->messageBuffer.length]; |
| 27582 | |
| 27583 | #ifdef UA_ENABLE_ENCRYPTION |
| 27584 | if(mc->channel->securityMode == UA_MESSAGESECURITYMODE_NONE) |
| 27585 | return; |
| 27586 | |
| 27587 | const UA_SecureChannel *channel = mc->channel; |
| 27588 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 27589 | size_t sigsize = sp->symmetricModule.cryptoModule.signatureAlgorithm. |
| 27590 | getLocalSignatureSize(channel->channelContext); |
| 27591 | size_t plainBlockSize = sp->symmetricModule.cryptoModule. |
| 27592 | encryptionAlgorithm.getRemotePlainTextBlockSize(channel->channelContext); |
| 27593 | |
| 27594 | /* Assuming that for symmetric encryption the plainTextBlockSize == |
| 27595 | * cypherTextBlockSize. For symmetric encryption the remote/local block |
| 27596 | * sizes are identical. */ |
| 27597 | UA_assert(sp->symmetricModule.cryptoModule.encryptionAlgorithm. |
| 27598 | getRemoteBlockSize(channel->channelContext) == plainBlockSize); |
| 27599 | |
| 27600 | /* Leave enough space for the signature and padding */ |
| 27601 | mc->buf_end -= sigsize; |
| 27602 | mc->buf_end -= mc->messageBuffer.length % plainBlockSize; |
| 27603 | |
| 27604 | if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 27605 | /* Reserve space for the padding bytes */ |
| 27606 | UA_Boolean extraPadding = |
| 27607 | (sp->symmetricModule.cryptoModule.encryptionAlgorithm. |
| 27608 | getRemoteKeyLength(channel->channelContext) > 2048); |
| 27609 | mc->buf_end -= (UA_LIKELY(!extraPadding)) ? 1 : 2; |
| 27610 | } |
| 27611 | |
| 27612 | UA_LOG_TRACE_CHANNEL(sp->logger, channel, |
| 27613 | "Prepare a symmetric message buffer of length %lu " |
| 27614 | "with a usable maximum payload length of %lu", |
| 27615 | (long unsigned)mc->messageBuffer.length, |
| 27616 | (long unsigned)((uintptr_t)mc->buf_end - |
| 27617 | (uintptr_t)mc->messageBuffer.data)); |
| 27618 | #endif |
| 27619 | } |
| 27620 | |
| 27621 | /****************************/ |
| 27622 | /* Process a received Chunk */ |
| 27623 | /****************************/ |
| 27624 | |
| 27625 | static size_t |
| 27626 | decodePadding(const UA_SecureChannel *channel, |
| 27627 | const UA_SecurityPolicyCryptoModule *cryptoModule, |
| 27628 | const UA_ByteString *chunk, size_t sigsize) { |
| 27629 | /* Read the byte with the padding size */ |
| 27630 | size_t paddingSize = chunk->data[chunk->length - sigsize - 1]; |
| 27631 | |
| 27632 | /* Extra padding size */ |
| 27633 | if(cryptoModule->encryptionAlgorithm. |
| 27634 | getLocalKeyLength(channel->channelContext) > 2048) { |
| 27635 | paddingSize <<= 8u; |
| 27636 | paddingSize += chunk->data[chunk->length - sigsize - 2]; |
| 27637 | paddingSize += 1; /* Extra padding byte itself */ |
| 27638 | } |
| 27639 | |
| 27640 | /* Add one since the paddingSize byte itself needs to be removed as well */ |
| 27641 | return paddingSize + 1; |
| 27642 | } |
| 27643 | |
| 27644 | static UA_StatusCode |
| 27645 | verifySignature(const UA_SecureChannel *channel, |
| 27646 | const UA_SecurityPolicyCryptoModule *cryptoModule, |
| 27647 | const UA_ByteString *chunk, size_t sigsize) { |
| 27648 | UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel, |
| 27649 | "Verifying chunk signature"); |
| 27650 | UA_CHECK(sigsize < chunk->length, return UA_STATUSCODE_BADSECURITYCHECKSFAILED); |
| 27651 | const UA_ByteString content = {chunk->length - sigsize, chunk->data}; |
| 27652 | const UA_ByteString sig = {sigsize, chunk->data + chunk->length - sigsize}; |
| 27653 | UA_StatusCode retval = cryptoModule->signatureAlgorithm. |
| 27654 | verify(channel->channelContext, &content, &sig); |
| 27655 | return retval; |
| 27656 | } |
| 27657 | |
| 27658 | /* Sets the payload to a pointer inside the chunk buffer. Returns the requestId |
| 27659 | * and the sequenceNumber */ |
| 27660 | UA_StatusCode |
| 27661 | decryptAndVerifyChunk(const UA_SecureChannel *channel, |
| 27662 | const UA_SecurityPolicyCryptoModule *cryptoModule, |
| 27663 | UA_MessageType messageType, UA_ByteString *chunk, |
| 27664 | size_t offset) { |
| 27665 | /* Decrypt the chunk */ |
| 27666 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 27667 | if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT || |
| 27668 | messageType == UA_MESSAGETYPE_OPN) { |
| 27669 | UA_ByteString cipher = {chunk->length - offset, chunk->data + offset}; |
| 27670 | res = cryptoModule->encryptionAlgorithm.decrypt(channel->channelContext, &cipher); |
| 27671 | UA_CHECK_STATUS(res, return res); |
| 27672 | chunk->length = cipher.length + offset; |
| 27673 | } |
| 27674 | |
| 27675 | /* Does the message have a signature? */ |
| 27676 | if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN && |
| 27677 | channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT && |
| 27678 | messageType != UA_MESSAGETYPE_OPN) |
| 27679 | return UA_STATUSCODE_GOOD; |
| 27680 | |
| 27681 | /* Verify the chunk signature */ |
| 27682 | size_t sigsize = cryptoModule->signatureAlgorithm. |
| 27683 | getRemoteSignatureSize(channel->channelContext); |
| 27684 | res = verifySignature(channel, cryptoModule, chunk, sigsize); |
| 27685 | UA_CHECK_STATUS(res, |
| 27686 | UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel, |
| 27687 | "Could not verify the signature"); return res); |
| 27688 | |
| 27689 | /* Compute the padding if the payload as encrypted */ |
| 27690 | size_t padSize = 0; |
| 27691 | if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT || |
| 27692 | (messageType == UA_MESSAGETYPE_OPN && |
| 27693 | cryptoModule->encryptionAlgorithm.uri.length > 0)) { |
| 27694 | padSize = decodePadding(channel, cryptoModule, chunk, sigsize); |
| 27695 | UA_LOG_TRACE_CHANNEL(channel->securityPolicy->logger, channel, |
| 27696 | "Calculated padding size to be %lu", |
| 27697 | (long unsigned)padSize); |
| 27698 | } |
| 27699 | |
| 27700 | /* Verify the content length. The encrypted payload has to be at least 9 |
| 27701 | * bytes long: 8 byte for the SequenceHeader and one byte for the actual |
| 27702 | * message */ |
| 27703 | UA_CHECK(offset + padSize + sigsize + 9 < chunk->length, |
| 27704 | UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel, |
| 27705 | "Impossible padding value"); |
| 27706 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED); |
| 27707 | |
| 27708 | /* Hide the signature and padding */ |
| 27709 | chunk->length -= (sigsize + padSize); |
| 27710 | return UA_STATUSCODE_GOOD; |
| 27711 | } |
| 27712 | |
| 27713 | UA_StatusCode |
| 27714 | checkAsymHeader(UA_SecureChannel *channel, |
| 27715 | const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) { |
| 27716 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 27717 | if(!UA_ByteString_equal(p1: &sp->policyUri, p2: &asymHeader->securityPolicyUri)) |
| 27718 | return UA_STATUSCODE_BADSECURITYPOLICYREJECTED; |
| 27719 | |
| 27720 | return sp->asymmetricModule. |
| 27721 | compareCertificateThumbprint(sp, &asymHeader->receiverCertificateThumbprint); |
| 27722 | |
| 27723 | /* The certificate in the header is verified via the configured PKI plugin |
| 27724 | * as certificateVerification.verifyCertificate(...). We cannot do it here |
| 27725 | * because the client/server context is needed. */ |
| 27726 | } |
| 27727 | |
| 27728 | UA_StatusCode |
| 27729 | checkSymHeader(UA_SecureChannel *channel, const UA_UInt32 tokenId) { |
| 27730 | /* If no match, try to revolve to the next token after a |
| 27731 | * RenewSecureChannel */ |
| 27732 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 27733 | UA_ChannelSecurityToken *token = &channel->securityToken; |
| 27734 | switch(channel->renewState) { |
| 27735 | case UA_SECURECHANNELRENEWSTATE_NORMAL: |
| 27736 | case UA_SECURECHANNELRENEWSTATE_SENT: |
| 27737 | default: |
| 27738 | break; |
| 27739 | |
| 27740 | case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER: |
| 27741 | /* Old token still in use */ |
| 27742 | if(tokenId == channel->securityToken.tokenId) |
| 27743 | break; |
| 27744 | |
| 27745 | /* Not the new token */ |
| 27746 | UA_CHECK(tokenId == channel->altSecurityToken.tokenId, |
| 27747 | UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel, |
| 27748 | "Unknown SecurityToken"); |
| 27749 | return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN); |
| 27750 | |
| 27751 | /* Roll over to the new token, generate new local and remote keys */ |
| 27752 | channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL; |
| 27753 | channel->securityToken = channel->altSecurityToken; |
| 27754 | UA_ChannelSecurityToken_init(p: &channel->altSecurityToken); |
| 27755 | retval |= UA_SecureChannel_generateLocalKeys(channel); |
| 27756 | retval |= generateRemoteKeys(channel); |
| 27757 | UA_CHECK_STATUS(retval, return retval); |
| 27758 | break; |
| 27759 | |
| 27760 | case UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT: |
| 27761 | /* The server is still using the old token. That's okay. */ |
| 27762 | if(tokenId == channel->altSecurityToken.tokenId) { |
| 27763 | token = &channel->altSecurityToken; |
| 27764 | break; |
| 27765 | } |
| 27766 | |
| 27767 | /* Not the new token */ |
| 27768 | UA_CHECK(tokenId == channel->securityToken.tokenId, |
| 27769 | UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel, |
| 27770 | "Unknown SecurityToken"); |
| 27771 | return UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN); |
| 27772 | |
| 27773 | /* The remote server uses the new token for the first time. Delete the |
| 27774 | * old token and roll the remote key over. The local key already uses |
| 27775 | * the nonce pair from the last OPN exchange. */ |
| 27776 | channel->renewState = UA_SECURECHANNELRENEWSTATE_NORMAL; |
| 27777 | UA_ChannelSecurityToken_init(p: &channel->altSecurityToken); |
| 27778 | retval = generateRemoteKeys(channel); |
| 27779 | UA_CHECK_STATUS(retval, return retval); |
| 27780 | } |
| 27781 | |
| 27782 | UA_DateTime timeout = token->createdAt + (token->revisedLifetime * UA_DATETIME_MSEC); |
| 27783 | if(channel->state == UA_SECURECHANNELSTATE_OPEN && |
| 27784 | timeout < UA_DateTime_nowMonotonic()) { |
| 27785 | UA_LOG_WARNING_CHANNEL(channel->securityPolicy->logger, channel, |
| 27786 | "SecurityToken timed out"); |
| 27787 | UA_SecureChannel_shutdown(channel, shutdownReason: UA_SHUTDOWNREASON_TIMEOUT); |
| 27788 | return UA_STATUSCODE_BADSECURECHANNELCLOSED; |
| 27789 | } |
| 27790 | |
| 27791 | return UA_STATUSCODE_GOOD; |
| 27792 | } |
| 27793 | |
| 27794 | /**** amalgamated original file "/src/server/ua_session.c" ****/ |
| 27795 | |
| 27796 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 27797 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 27798 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 27799 | * |
| 27800 | * Copyright 2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 27801 | * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA |
| 27802 | * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 27803 | */ |
| 27804 | |
| 27805 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 27806 | #endif |
| 27807 | |
| 27808 | #define UA_SESSION_NONCELENTH 32 |
| 27809 | |
| 27810 | void UA_Session_init(UA_Session *session) { |
| 27811 | memset(s: session, c: 0, n: sizeof(UA_Session)); |
| 27812 | session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS; |
| 27813 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 27814 | SIMPLEQ_INIT(&session->responseQueue); |
| 27815 | TAILQ_INIT(&session->subscriptions); |
| 27816 | #endif |
| 27817 | } |
| 27818 | |
| 27819 | void UA_Session_clear(UA_Session *session, UA_Server* server) { |
| 27820 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 27821 | |
| 27822 | /* Remove all Subscriptions. This may send out remaining publish |
| 27823 | * responses. */ |
| 27824 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 27825 | UA_Subscription *sub, *tempsub; |
| 27826 | TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, tempsub) { |
| 27827 | UA_Subscription_delete(server, sub); |
| 27828 | } |
| 27829 | #endif |
| 27830 | |
| 27831 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 27832 | deleteNode(server, nodeId: session->sessionId, true); |
| 27833 | #endif |
| 27834 | |
| 27835 | UA_Session_detachFromSecureChannel(session); |
| 27836 | UA_ApplicationDescription_clear(p: &session->clientDescription); |
| 27837 | UA_NodeId_clear(p: &session->header.authenticationToken); |
| 27838 | UA_String_clear(p: &session->clientUserIdOfSession); |
| 27839 | UA_NodeId_clear(p: &session->sessionId); |
| 27840 | UA_String_clear(p: &session->sessionName); |
| 27841 | UA_ByteString_clear(p: &session->serverNonce); |
| 27842 | struct ContinuationPoint *cp, *next = session->continuationPoints; |
| 27843 | while((cp = next)) { |
| 27844 | next = ContinuationPoint_clear(cp); |
| 27845 | UA_free(ptr: cp); |
| 27846 | } |
| 27847 | session->continuationPoints = NULL; |
| 27848 | session->availableContinuationPoints = UA_MAXCONTINUATIONPOINTS; |
| 27849 | |
| 27850 | UA_KeyValueMap_delete(map: session->attributes); |
| 27851 | session->attributes = NULL; |
| 27852 | |
| 27853 | UA_Array_delete(p: session->localeIds, size: session->localeIdsSize, |
| 27854 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 27855 | session->localeIds = NULL; |
| 27856 | session->localeIdsSize = 0; |
| 27857 | |
| 27858 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 27859 | UA_SessionDiagnosticsDataType_clear(p: &session->diagnostics); |
| 27860 | UA_SessionSecurityDiagnosticsDataType_clear(p: &session->securityDiagnostics); |
| 27861 | #endif |
| 27862 | } |
| 27863 | |
| 27864 | void |
| 27865 | UA_Session_attachToSecureChannel(UA_Session *session, UA_SecureChannel *channel) { |
| 27866 | UA_Session_detachFromSecureChannel(session); |
| 27867 | session->header.channel = channel; |
| 27868 | session->header.serverSession = true; |
| 27869 | SLIST_INSERT_HEAD(&channel->sessions, &session->header, next); |
| 27870 | } |
| 27871 | |
| 27872 | void |
| 27873 | UA_Session_detachFromSecureChannel(UA_Session *session) { |
| 27874 | UA_SecureChannel *channel = session->header.channel; |
| 27875 | if(!channel) |
| 27876 | return; |
| 27877 | session->header.channel = NULL; |
| 27878 | UA_SessionHeader *sh; |
| 27879 | SLIST_FOREACH(sh, &channel->sessions, next) { |
| 27880 | if((UA_Session*)sh != session) |
| 27881 | continue; |
| 27882 | SLIST_REMOVE(&channel->sessions, sh, UA_SessionHeader, next); |
| 27883 | break; |
| 27884 | } |
| 27885 | |
| 27886 | /* Clean up the response queue. Their RequestId is bound to the |
| 27887 | * SecureChannel so they cannot be reused. */ |
| 27888 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 27889 | UA_PublishResponseEntry *pre; |
| 27890 | while((pre = UA_Session_dequeuePublishReq(session))) { |
| 27891 | UA_PublishResponse_clear(p: &pre->response); |
| 27892 | UA_free(ptr: pre); |
| 27893 | } |
| 27894 | #endif |
| 27895 | } |
| 27896 | |
| 27897 | UA_StatusCode |
| 27898 | UA_Session_generateNonce(UA_Session *session) { |
| 27899 | UA_SecureChannel *channel = session->header.channel; |
| 27900 | if(!channel || !channel->securityPolicy) |
| 27901 | return UA_STATUSCODE_BADINTERNALERROR; |
| 27902 | |
| 27903 | /* Is the length of the previous nonce correct? */ |
| 27904 | if(session->serverNonce.length != UA_SESSION_NONCELENTH) { |
| 27905 | UA_ByteString_clear(p: &session->serverNonce); |
| 27906 | UA_StatusCode retval = |
| 27907 | UA_ByteString_allocBuffer(bs: &session->serverNonce, UA_SESSION_NONCELENTH); |
| 27908 | if(retval != UA_STATUSCODE_GOOD) |
| 27909 | return retval; |
| 27910 | } |
| 27911 | |
| 27912 | return channel->securityPolicy->symmetricModule. |
| 27913 | generateNonce(channel->securityPolicy->policyContext, &session->serverNonce); |
| 27914 | } |
| 27915 | |
| 27916 | void UA_Session_updateLifetime(UA_Session *session) { |
| 27917 | session->validTill = UA_DateTime_nowMonotonic() + |
| 27918 | (UA_DateTime)(session->timeout * UA_DATETIME_MSEC); |
| 27919 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 27920 | session->diagnostics.clientLastContactTime = UA_DateTime_now(); |
| 27921 | #endif |
| 27922 | } |
| 27923 | |
| 27924 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 27925 | |
| 27926 | void |
| 27927 | UA_Session_attachSubscription(UA_Session *session, UA_Subscription *sub) { |
| 27928 | /* Attach to the session */ |
| 27929 | sub->session = session; |
| 27930 | |
| 27931 | /* Increase the count */ |
| 27932 | session->subscriptionsSize++; |
| 27933 | |
| 27934 | /* Increase the number of outstanding retransmissions */ |
| 27935 | session->totalRetransmissionQueueSize += sub->retransmissionQueueSize; |
| 27936 | |
| 27937 | /* Insert at the end of the subscriptions of the same priority / just before |
| 27938 | * the subscriptions with the next lower priority. */ |
| 27939 | UA_Subscription *after = NULL; |
| 27940 | TAILQ_FOREACH(after, &session->subscriptions, sessionListEntry) { |
| 27941 | if(after->priority < sub->priority) { |
| 27942 | TAILQ_INSERT_BEFORE(after, sub, sessionListEntry); |
| 27943 | return; |
| 27944 | } |
| 27945 | } |
| 27946 | TAILQ_INSERT_TAIL(&session->subscriptions, sub, sessionListEntry); |
| 27947 | } |
| 27948 | |
| 27949 | void |
| 27950 | UA_Session_detachSubscription(UA_Server *server, UA_Session *session, |
| 27951 | UA_Subscription *sub, UA_Boolean releasePublishResponses) { |
| 27952 | /* Detach from the session */ |
| 27953 | sub->session = NULL; |
| 27954 | TAILQ_REMOVE(&session->subscriptions, sub, sessionListEntry); |
| 27955 | |
| 27956 | /* Reduce the count */ |
| 27957 | UA_assert(session->subscriptionsSize > 0); |
| 27958 | session->subscriptionsSize--; |
| 27959 | |
| 27960 | /* Reduce the number of outstanding retransmissions */ |
| 27961 | session->totalRetransmissionQueueSize -= sub->retransmissionQueueSize; |
| 27962 | |
| 27963 | /* Send remaining publish responses if the last subscription was removed */ |
| 27964 | if(!releasePublishResponses || !TAILQ_EMPTY(&session->subscriptions)) |
| 27965 | return; |
| 27966 | UA_PublishResponseEntry *pre; |
| 27967 | while((pre = UA_Session_dequeuePublishReq(session))) { |
| 27968 | UA_PublishResponse *response = &pre->response; |
| 27969 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION; |
| 27970 | sendResponse(server, session, channel: session->header.channel, requestId: pre->requestId, |
| 27971 | response: (UA_Response*)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]); |
| 27972 | UA_PublishResponse_clear(p: response); |
| 27973 | UA_free(ptr: pre); |
| 27974 | } |
| 27975 | } |
| 27976 | |
| 27977 | UA_Subscription * |
| 27978 | UA_Session_getSubscriptionById(UA_Session *session, UA_UInt32 subscriptionId) { |
| 27979 | UA_Subscription *sub; |
| 27980 | TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) { |
| 27981 | /* Prevent lookup of subscriptions that are to be deleted with a statuschange */ |
| 27982 | if(sub->statusChange != UA_STATUSCODE_GOOD) |
| 27983 | continue; |
| 27984 | if(sub->subscriptionId == subscriptionId) |
| 27985 | break; |
| 27986 | } |
| 27987 | return sub; |
| 27988 | } |
| 27989 | |
| 27990 | UA_Subscription * |
| 27991 | getSubscriptionById(UA_Server *server, UA_UInt32 subscriptionId) { |
| 27992 | UA_Subscription *sub; |
| 27993 | LIST_FOREACH(sub, &server->subscriptions, serverListEntry) { |
| 27994 | /* Prevent lookup of subscriptions that are to be deleted with a statuschange */ |
| 27995 | if(sub->statusChange != UA_STATUSCODE_GOOD) |
| 27996 | continue; |
| 27997 | if(sub->subscriptionId == subscriptionId) |
| 27998 | break; |
| 27999 | } |
| 28000 | return sub; |
| 28001 | } |
| 28002 | |
| 28003 | UA_PublishResponseEntry* |
| 28004 | UA_Session_dequeuePublishReq(UA_Session *session) { |
| 28005 | UA_PublishResponseEntry *entry = SIMPLEQ_FIRST(&session->responseQueue); |
| 28006 | if(entry) { |
| 28007 | SIMPLEQ_REMOVE_HEAD(&session->responseQueue, listEntry); |
| 28008 | session->responseQueueSize--; |
| 28009 | } |
| 28010 | return entry; |
| 28011 | } |
| 28012 | |
| 28013 | void |
| 28014 | UA_Session_queuePublishReq(UA_Session *session, UA_PublishResponseEntry* entry, |
| 28015 | UA_Boolean head) { |
| 28016 | if(!head) |
| 28017 | SIMPLEQ_INSERT_TAIL(&session->responseQueue, entry, listEntry); |
| 28018 | else |
| 28019 | SIMPLEQ_INSERT_HEAD(&session->responseQueue, entry, listEntry); |
| 28020 | session->responseQueueSize++; |
| 28021 | } |
| 28022 | |
| 28023 | #endif |
| 28024 | |
| 28025 | /* Session Handling */ |
| 28026 | |
| 28027 | UA_StatusCode |
| 28028 | UA_Server_closeSession(UA_Server *server, const UA_NodeId *sessionId) { |
| 28029 | lockServer(server); |
| 28030 | session_list_entry *entry; |
| 28031 | UA_StatusCode res = UA_STATUSCODE_BADSESSIONIDINVALID; |
| 28032 | LIST_FOREACH(entry, &server->sessions, pointers) { |
| 28033 | if(UA_NodeId_equal(p1: &entry->session.sessionId, p2: sessionId)) { |
| 28034 | UA_Server_removeSession(server, sentry: entry, shutdownReason: UA_SHUTDOWNREASON_CLOSE); |
| 28035 | res = UA_STATUSCODE_GOOD; |
| 28036 | break; |
| 28037 | } |
| 28038 | } |
| 28039 | unlockServer(server); |
| 28040 | return res; |
| 28041 | } |
| 28042 | |
| 28043 | /* Session Attributes */ |
| 28044 | |
| 28045 | #define UA_PROTECTEDATTRIBUTESSIZE 4 |
| 28046 | static const UA_QualifiedName protectedAttributes[UA_PROTECTEDATTRIBUTESSIZE] = { |
| 28047 | {0, UA_STRING_STATIC("localeIds")}, |
| 28048 | {0, UA_STRING_STATIC("clientDescription")}, |
| 28049 | {0, UA_STRING_STATIC("sessionName")}, |
| 28050 | {0, UA_STRING_STATIC("clientUserId")} |
| 28051 | }; |
| 28052 | |
| 28053 | static UA_Boolean |
| 28054 | protectedAttribute(const UA_QualifiedName key) { |
| 28055 | for(size_t i = 0; i < UA_PROTECTEDATTRIBUTESSIZE; i++) { |
| 28056 | if(UA_QualifiedName_equal(p1: &key, p2: &protectedAttributes[i])) |
| 28057 | return true; |
| 28058 | } |
| 28059 | return false; |
| 28060 | } |
| 28061 | |
| 28062 | UA_StatusCode |
| 28063 | UA_Server_setSessionAttribute(UA_Server *server, const UA_NodeId *sessionId, |
| 28064 | const UA_QualifiedName key, const UA_Variant *value) { |
| 28065 | if(protectedAttribute(key)) |
| 28066 | return UA_STATUSCODE_BADNOTWRITABLE; |
| 28067 | lockServer(server); |
| 28068 | UA_Session *session = getSessionById(server, sessionId); |
| 28069 | UA_StatusCode res = UA_STATUSCODE_BADSESSIONIDINVALID; |
| 28070 | if(session) |
| 28071 | res = UA_KeyValueMap_set(map: session->attributes, |
| 28072 | key, value); |
| 28073 | unlockServer(server); |
| 28074 | return res; |
| 28075 | } |
| 28076 | |
| 28077 | UA_StatusCode |
| 28078 | UA_Server_deleteSessionAttribute(UA_Server *server, const UA_NodeId *sessionId, |
| 28079 | const UA_QualifiedName key) { |
| 28080 | if(protectedAttribute(key)) |
| 28081 | return UA_STATUSCODE_BADNOTWRITABLE; |
| 28082 | lockServer(server); |
| 28083 | UA_Session *session = getSessionById(server, sessionId); |
| 28084 | if(!session) { |
| 28085 | unlockServer(server); |
| 28086 | return UA_STATUSCODE_BADSESSIONIDINVALID; |
| 28087 | } |
| 28088 | UA_StatusCode res = |
| 28089 | UA_KeyValueMap_remove(map: session->attributes, key); |
| 28090 | unlockServer(server); |
| 28091 | return res; |
| 28092 | } |
| 28093 | |
| 28094 | static UA_StatusCode |
| 28095 | getSessionAttribute(UA_Server *server, const UA_NodeId *sessionId, |
| 28096 | const UA_QualifiedName key, UA_Variant *outValue, |
| 28097 | UA_Boolean copy) { |
| 28098 | if(!outValue) |
| 28099 | return UA_STATUSCODE_BADINTERNALERROR; |
| 28100 | |
| 28101 | UA_Session *session = getSessionById(server, sessionId); |
| 28102 | if(!session) |
| 28103 | return UA_STATUSCODE_BADSESSIONIDINVALID; |
| 28104 | |
| 28105 | const UA_Variant *attr; |
| 28106 | UA_Variant localAttr; |
| 28107 | |
| 28108 | if(UA_QualifiedName_equal(p1: &key, p2: &protectedAttributes[0])) { |
| 28109 | /* Return LocaleIds */ |
| 28110 | UA_Variant_setArray(v: &localAttr, array: session->localeIds, |
| 28111 | arraySize: session->localeIdsSize, type: &UA_TYPES[UA_TYPES_STRING]); |
| 28112 | attr = &localAttr; |
| 28113 | } else if(UA_QualifiedName_equal(p1: &key, p2: &protectedAttributes[1])) { |
| 28114 | /* Return client description */ |
| 28115 | UA_Variant_setScalar(v: &localAttr, p: &session->clientDescription, |
| 28116 | type: &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]); |
| 28117 | attr = &localAttr; |
| 28118 | } else if(UA_QualifiedName_equal(p1: &key, p2: &protectedAttributes[2])) { |
| 28119 | /* Return session name */ |
| 28120 | UA_Variant_setScalar(v: &localAttr, p: &session->sessionName, |
| 28121 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 28122 | attr = &localAttr; |
| 28123 | } else if(UA_QualifiedName_equal(p1: &key, p2: &protectedAttributes[3])) { |
| 28124 | /* Return client user id */ |
| 28125 | UA_Variant_setScalar(v: &localAttr, p: &session->clientUserIdOfSession, |
| 28126 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 28127 | attr = &localAttr; |
| 28128 | } else { |
| 28129 | /* Get from the actual key-value list */ |
| 28130 | attr = UA_KeyValueMap_get(map: session->attributes, key); |
| 28131 | if(!attr) |
| 28132 | return UA_STATUSCODE_BADNOTFOUND; |
| 28133 | } |
| 28134 | |
| 28135 | if(copy) |
| 28136 | return UA_Variant_copy(src: attr, dst: outValue); |
| 28137 | |
| 28138 | *outValue = *attr; |
| 28139 | outValue->storageType = UA_VARIANT_DATA_NODELETE; |
| 28140 | return UA_STATUSCODE_GOOD; |
| 28141 | } |
| 28142 | |
| 28143 | UA_StatusCode |
| 28144 | UA_Server_getSessionAttribute(UA_Server *server, const UA_NodeId *sessionId, |
| 28145 | const UA_QualifiedName key, UA_Variant *outValue) { |
| 28146 | lockServer(server); |
| 28147 | UA_StatusCode res = getSessionAttribute(server, sessionId, key, outValue, false); |
| 28148 | unlockServer(server); |
| 28149 | return res; |
| 28150 | } |
| 28151 | |
| 28152 | UA_StatusCode |
| 28153 | UA_Server_getSessionAttributeCopy(UA_Server *server, const UA_NodeId *sessionId, |
| 28154 | const UA_QualifiedName key, UA_Variant *outValue) { |
| 28155 | lockServer(server); |
| 28156 | UA_StatusCode res = getSessionAttribute(server, sessionId, key, outValue, true); |
| 28157 | unlockServer(server); |
| 28158 | return res; |
| 28159 | } |
| 28160 | |
| 28161 | UA_StatusCode |
| 28162 | UA_Server_getSessionAttribute_scalar(UA_Server *server, |
| 28163 | const UA_NodeId *sessionId, |
| 28164 | const UA_QualifiedName key, |
| 28165 | const UA_DataType *type, |
| 28166 | void *outValue) { |
| 28167 | lockServer(server); |
| 28168 | |
| 28169 | UA_Variant attr; |
| 28170 | UA_StatusCode res = getSessionAttribute(server, sessionId, key, outValue: &attr, false); |
| 28171 | if(res != UA_STATUSCODE_GOOD) { |
| 28172 | unlockServer(server); |
| 28173 | return res; |
| 28174 | } |
| 28175 | |
| 28176 | if(!UA_Variant_hasScalarType(v: &attr, type)) { |
| 28177 | unlockServer(server); |
| 28178 | return UA_STATUSCODE_BADNOTFOUND; |
| 28179 | } |
| 28180 | |
| 28181 | memcpy(dest: outValue, src: attr.data, n: type->memSize); |
| 28182 | |
| 28183 | unlockServer(server); |
| 28184 | return UA_STATUSCODE_GOOD; |
| 28185 | } |
| 28186 | |
| 28187 | /**** amalgamated original file "/src/server/ua_nodes.c" ****/ |
| 28188 | |
| 28189 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 28190 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 28191 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 28192 | * |
| 28193 | * Copyright 2015-2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 28194 | * Copyright 2015-2016 (c) Sten Grüner |
| 28195 | * Copyright 2015 (c) Chris Iatrou |
| 28196 | * Copyright 2015, 2017 (c) Florian Palm |
| 28197 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 28198 | * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH |
| 28199 | * Copyright 2017 (c) Julian Grothoff |
| 28200 | */ |
| 28201 | |
| 28202 | |
| 28203 | /*********************/ |
| 28204 | /* ReferenceType Set */ |
| 28205 | /*********************/ |
| 28206 | |
| 28207 | #define UA_REFTYPES_ALL_MASK (~(UA_UInt32)0) |
| 28208 | #define UA_REFTYPES_ALL_MASK2 UA_REFTYPES_ALL_MASK, UA_REFTYPES_ALL_MASK |
| 28209 | #define UA_REFTYPES_ALL_MASK4 UA_REFTYPES_ALL_MASK2, UA_REFTYPES_ALL_MASK2 |
| 28210 | #if (UA_REFERENCETYPESET_MAX) / 32 > 8 |
| 28211 | # error Adjust macros to support than 256 reference types |
| 28212 | #elif (UA_REFERENCETYPESET_MAX) / 32 == 8 |
| 28213 | # define UA_REFTYPES_ALL_ARRAY UA_REFTYPES_ALL_MASK4, UA_REFTYPES_ALL_MASK4 |
| 28214 | #elif (UA_REFERENCETYPESET_MAX) / 32 == 7 |
| 28215 | # define UA_REFTYPES_ALL_ARRAY \ |
| 28216 | UA_REFTYPES_ALL_MASK4, UA_REFTYPES_ALL_MASK2, UA_REFTYPES_ALL_MASK |
| 28217 | #elif (UA_REFERENCETYPESET_MAX) / 32 == 6 |
| 28218 | # define UA_REFTYPES_ALL_ARRAY UA_REFTYPES_ALL_MASK4, UA_REFTYPES_ALL_MASK2 |
| 28219 | #elif (UA_REFERENCETYPESET_MAX) / 32 == 5 |
| 28220 | # define UA_REFTYPES_ALL_ARRAY UA_REFTYPES_ALL_MASK4, UA_REFTYPES_ALL_MASK |
| 28221 | #elif (UA_REFERENCETYPESET_MAX) / 32 == 4 |
| 28222 | # define UA_REFTYPES_ALL_ARRAY UA_REFTYPES_ALL_MASK4 |
| 28223 | #elif (UA_REFERENCETYPESET_MAX) / 32 == 3 |
| 28224 | # define UA_REFTYPES_ALL_ARRAY UA_REFTYPES_ALL_MASK2, UA_REFTYPES_ALL_MASK |
| 28225 | #elif (UA_REFERENCETYPESET_MAX) / 32 == 2 |
| 28226 | # define UA_REFTYPES_ALL_ARRAY UA_REFTYPES_ALL_MASK2 |
| 28227 | #else |
| 28228 | # define UA_REFTYPES_ALL_ARRAY UA_REFTYPES_ALL_MASK |
| 28229 | #endif |
| 28230 | |
| 28231 | const UA_ReferenceTypeSet UA_REFERENCETYPESET_NONE = {{0}}; |
| 28232 | const UA_ReferenceTypeSet UA_REFERENCETYPESET_ALL = {{UA_REFTYPES_ALL_ARRAY}}; |
| 28233 | |
| 28234 | /*****************/ |
| 28235 | /* Node Pointers */ |
| 28236 | /*****************/ |
| 28237 | |
| 28238 | #define UA_NODEPOINTER_MASK 0x03 |
| 28239 | #define UA_NODEPOINTER_TAG_IMMEDIATE 0x00 |
| 28240 | #define UA_NODEPOINTER_TAG_NODEID 0x01 |
| 28241 | #define UA_NODEPOINTER_TAG_EXPANDEDNODEID 0x02 |
| 28242 | #define UA_NODEPOINTER_TAG_NODE 0x03 |
| 28243 | |
| 28244 | void |
| 28245 | UA_NodePointer_clear(UA_NodePointer *np) { |
| 28246 | switch(np->immediate & UA_NODEPOINTER_MASK) { |
| 28247 | case UA_NODEPOINTER_TAG_NODEID: |
| 28248 | np->immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK; |
| 28249 | UA_NodeId_delete(p: (UA_NodeId*)(uintptr_t)np->id); |
| 28250 | break; |
| 28251 | case UA_NODEPOINTER_TAG_EXPANDEDNODEID: |
| 28252 | np->immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK; |
| 28253 | UA_ExpandedNodeId_delete(p: (UA_ExpandedNodeId*)(uintptr_t) |
| 28254 | np->expandedId); |
| 28255 | break; |
| 28256 | default: |
| 28257 | break; |
| 28258 | } |
| 28259 | UA_NodePointer_init(np); |
| 28260 | } |
| 28261 | |
| 28262 | UA_StatusCode |
| 28263 | UA_NodePointer_copy(UA_NodePointer in, UA_NodePointer *out) { |
| 28264 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 28265 | UA_Byte tag = in.immediate & UA_NODEPOINTER_MASK; |
| 28266 | in.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK; |
| 28267 | switch(tag) { |
| 28268 | case UA_NODEPOINTER_TAG_NODE: |
| 28269 | in.id = &in.node->nodeId; |
| 28270 | goto nodeid; /* fallthrough */ |
| 28271 | case UA_NODEPOINTER_TAG_NODEID: |
| 28272 | nodeid: |
| 28273 | out->id = UA_NodeId_new(); |
| 28274 | if(!out->id) |
| 28275 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 28276 | res = UA_NodeId_copy(src: in.id, dst: (UA_NodeId*)(uintptr_t)out->id); |
| 28277 | if(res != UA_STATUSCODE_GOOD) { |
| 28278 | UA_free(ptr: (void*)out->immediate); |
| 28279 | out->immediate = 0; |
| 28280 | break; |
| 28281 | } |
| 28282 | out->immediate |= UA_NODEPOINTER_TAG_NODEID; |
| 28283 | break; |
| 28284 | case UA_NODEPOINTER_TAG_EXPANDEDNODEID: |
| 28285 | out->expandedId = UA_ExpandedNodeId_new(); |
| 28286 | if(!out->expandedId) |
| 28287 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 28288 | res = UA_ExpandedNodeId_copy(src: in.expandedId, |
| 28289 | dst: (UA_ExpandedNodeId*)(uintptr_t) |
| 28290 | out->expandedId); |
| 28291 | if(res != UA_STATUSCODE_GOOD) { |
| 28292 | UA_free(ptr: (void*)out->immediate); |
| 28293 | out->immediate = 0; |
| 28294 | break; |
| 28295 | } |
| 28296 | out->immediate |= UA_NODEPOINTER_TAG_EXPANDEDNODEID; |
| 28297 | break; |
| 28298 | default: |
| 28299 | case UA_NODEPOINTER_TAG_IMMEDIATE: |
| 28300 | *out = in; |
| 28301 | break; |
| 28302 | } |
| 28303 | return res; |
| 28304 | } |
| 28305 | |
| 28306 | UA_Boolean |
| 28307 | UA_NodePointer_isLocal(UA_NodePointer np) { |
| 28308 | UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK; |
| 28309 | return (tag != UA_NODEPOINTER_TAG_EXPANDEDNODEID); |
| 28310 | } |
| 28311 | |
| 28312 | UA_Order |
| 28313 | UA_NodePointer_order(UA_NodePointer p1, UA_NodePointer p2) { |
| 28314 | if(p1.immediate == p2.immediate) |
| 28315 | return UA_ORDER_EQ; |
| 28316 | |
| 28317 | /* Extract the tag and resolve pointers to nodes */ |
| 28318 | UA_Byte tag1 = p1.immediate & UA_NODEPOINTER_MASK; |
| 28319 | if(tag1 == UA_NODEPOINTER_TAG_NODE) { |
| 28320 | p1 = UA_NodePointer_fromNodeId(id: &p1.node->nodeId); |
| 28321 | tag1 = p1.immediate & UA_NODEPOINTER_MASK; |
| 28322 | } |
| 28323 | UA_Byte tag2 = p2.immediate & UA_NODEPOINTER_MASK; |
| 28324 | if(tag2 == UA_NODEPOINTER_TAG_NODE) { |
| 28325 | p2 = UA_NodePointer_fromNodeId(id: &p2.node->nodeId); |
| 28326 | tag2 = p2.immediate & UA_NODEPOINTER_MASK; |
| 28327 | } |
| 28328 | |
| 28329 | /* Different tags, cannot be identical */ |
| 28330 | if(tag1 != tag2) |
| 28331 | return (tag1 > tag2) ? UA_ORDER_MORE : UA_ORDER_LESS; |
| 28332 | |
| 28333 | /* Immediate */ |
| 28334 | if(UA_LIKELY(tag1 == UA_NODEPOINTER_TAG_IMMEDIATE)) |
| 28335 | return (p1.immediate > p2.immediate) ? |
| 28336 | UA_ORDER_MORE : UA_ORDER_LESS; |
| 28337 | |
| 28338 | /* Compare from pointers */ |
| 28339 | p1.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK; |
| 28340 | p2.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK; |
| 28341 | if(tag1 == UA_NODEPOINTER_TAG_EXPANDEDNODEID) |
| 28342 | return UA_ExpandedNodeId_order(n1: p1.expandedId, n2: p2.expandedId); |
| 28343 | return UA_NodeId_order(n1: p1.id, n2: p2.id); |
| 28344 | } |
| 28345 | |
| 28346 | UA_NodePointer |
| 28347 | UA_NodePointer_fromNodeId(const UA_NodeId *id) { |
| 28348 | UA_NodePointer np; |
| 28349 | if(id->identifierType != UA_NODEIDTYPE_NUMERIC) { |
| 28350 | np.id = id; |
| 28351 | np.immediate |= UA_NODEPOINTER_TAG_NODEID; |
| 28352 | return np; |
| 28353 | } |
| 28354 | |
| 28355 | #if SIZE_MAX > UA_UINT32_MAX |
| 28356 | /* 64bit: 4 Byte for the numeric identifier + 2 Byte for the namespaceIndex |
| 28357 | * + 1 Byte for the tagging bit (zero) */ |
| 28358 | np.immediate = ((uintptr_t)id->identifier.numeric) << 32; |
| 28359 | np.immediate |= ((uintptr_t)id->namespaceIndex) << 8; |
| 28360 | #else |
| 28361 | /* 32bit: 3 Byte for the numeric identifier + 6 Bit for the namespaceIndex |
| 28362 | * + 2 Bit for the tagging bit (zero) */ |
| 28363 | if(id->namespaceIndex < (0x01 << 6) && |
| 28364 | id->identifier.numeric < (0x01 << 24)) { |
| 28365 | np.immediate = ((uintptr_t)id->identifier.numeric) << 8; |
| 28366 | np.immediate |= ((uintptr_t)id->namespaceIndex) << 2; |
| 28367 | } else { |
| 28368 | np.id = id; |
| 28369 | np.immediate |= UA_NODEPOINTER_TAG_NODEID; |
| 28370 | } |
| 28371 | #endif |
| 28372 | return np; |
| 28373 | } |
| 28374 | |
| 28375 | UA_NodeId |
| 28376 | UA_NodePointer_toNodeId(UA_NodePointer np) { |
| 28377 | UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK; |
| 28378 | np.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK; |
| 28379 | switch(tag) { |
| 28380 | case UA_NODEPOINTER_TAG_NODE: |
| 28381 | return np.node->nodeId; |
| 28382 | case UA_NODEPOINTER_TAG_NODEID: |
| 28383 | return *np.id; |
| 28384 | case UA_NODEPOINTER_TAG_EXPANDEDNODEID: |
| 28385 | return np.expandedId->nodeId; |
| 28386 | default: |
| 28387 | case UA_NODEPOINTER_TAG_IMMEDIATE: |
| 28388 | break; |
| 28389 | } |
| 28390 | |
| 28391 | UA_NodeId id; |
| 28392 | id.identifierType = UA_NODEIDTYPE_NUMERIC; |
| 28393 | #if SIZE_MAX > UA_UINT32_MAX /* 64bit */ |
| 28394 | id.namespaceIndex = (UA_UInt16)(np.immediate >> 8); |
| 28395 | id.identifier.numeric = (UA_UInt32)(np.immediate >> 32); |
| 28396 | #else /* 32bit */ |
| 28397 | id.namespaceIndex = ((UA_Byte)np.immediate) >> 2; |
| 28398 | id.identifier.numeric = np.immediate >> 8; |
| 28399 | #endif |
| 28400 | return id; |
| 28401 | } |
| 28402 | |
| 28403 | UA_NodePointer |
| 28404 | UA_NodePointer_fromExpandedNodeId(const UA_ExpandedNodeId *id) { |
| 28405 | if(!UA_ExpandedNodeId_isLocal(n: id)) { |
| 28406 | UA_NodePointer np; |
| 28407 | np.expandedId = id; |
| 28408 | np.immediate |= UA_NODEPOINTER_TAG_EXPANDEDNODEID; |
| 28409 | return np; |
| 28410 | } |
| 28411 | return UA_NodePointer_fromNodeId(id: &id->nodeId); |
| 28412 | } |
| 28413 | |
| 28414 | UA_ExpandedNodeId |
| 28415 | UA_NodePointer_toExpandedNodeId(UA_NodePointer np) { |
| 28416 | /* Resolve node pointer to get the NodeId */ |
| 28417 | UA_Byte tag = np.immediate & UA_NODEPOINTER_MASK; |
| 28418 | if(tag == UA_NODEPOINTER_TAG_NODE) { |
| 28419 | np = UA_NodePointer_fromNodeId(id: &np.node->nodeId); |
| 28420 | tag = np.immediate & UA_NODEPOINTER_MASK; |
| 28421 | } |
| 28422 | |
| 28423 | /* ExpandedNodeId, make a shallow copy */ |
| 28424 | if(tag == UA_NODEPOINTER_TAG_EXPANDEDNODEID) { |
| 28425 | np.immediate &= ~(uintptr_t)UA_NODEPOINTER_MASK; |
| 28426 | return *np.expandedId; |
| 28427 | } |
| 28428 | |
| 28429 | /* NodeId, either immediate or via a pointer */ |
| 28430 | UA_ExpandedNodeId en; |
| 28431 | UA_ExpandedNodeId_init(p: &en); |
| 28432 | en.nodeId = UA_NodePointer_toNodeId(np); |
| 28433 | return en; |
| 28434 | } |
| 28435 | |
| 28436 | /**************/ |
| 28437 | /* References */ |
| 28438 | /**************/ |
| 28439 | |
| 28440 | static UA_StatusCode |
| 28441 | addReferenceTarget(UA_NodeReferenceKind *refs, UA_NodePointer target, |
| 28442 | UA_UInt32 targetNameHash); |
| 28443 | |
| 28444 | static UA_StatusCode |
| 28445 | addReferenceTargetToTree(UA_NodeReferenceKind *rk, UA_NodePointer targetId, |
| 28446 | UA_UInt32 targetIdHash, UA_UInt32 targetNameHash); |
| 28447 | |
| 28448 | enum ZIP_CMP |
| 28449 | cmpRefTargetId(const void *a, const void *b) { |
| 28450 | const UA_ReferenceTargetTreeElem *aa = (const UA_ReferenceTargetTreeElem*)a; |
| 28451 | const UA_ReferenceTargetTreeElem *bb = (const UA_ReferenceTargetTreeElem*)b; |
| 28452 | if(aa->targetIdHash < bb->targetIdHash) |
| 28453 | return ZIP_CMP_LESS; |
| 28454 | if(aa->targetIdHash > bb->targetIdHash) |
| 28455 | return ZIP_CMP_MORE; |
| 28456 | return (enum ZIP_CMP)UA_NodePointer_order(p1: aa->target.targetId, |
| 28457 | p2: bb->target.targetId); |
| 28458 | } |
| 28459 | |
| 28460 | enum ZIP_CMP |
| 28461 | cmpRefTargetName(const void *a, const void *b) { |
| 28462 | const UA_ReferenceTargetTreeElem *aa = (const UA_ReferenceTargetTreeElem*)a; |
| 28463 | const UA_ReferenceTargetTreeElem *bb = (const UA_ReferenceTargetTreeElem*)b; |
| 28464 | if(aa->target.targetNameHash == bb->target.targetNameHash) |
| 28465 | return ZIP_CMP_EQ; |
| 28466 | return (aa->target.targetNameHash < bb->target.targetNameHash) ? |
| 28467 | ZIP_CMP_LESS : ZIP_CMP_MORE; |
| 28468 | } |
| 28469 | |
| 28470 | /* Move to the array in-order, also deletes the tree elements */ |
| 28471 | static void |
| 28472 | moveTreeToArray(UA_ReferenceTarget *array, size_t *pos, |
| 28473 | UA_ReferenceTargetTreeElem *elem) { |
| 28474 | if(!elem) |
| 28475 | return; |
| 28476 | moveTreeToArray(array, pos, elem: elem->idTreeEntry.left); |
| 28477 | array[*pos] = elem->target; |
| 28478 | (*pos)++; |
| 28479 | moveTreeToArray(array, pos, elem: elem->idTreeEntry.right); |
| 28480 | UA_free(ptr: elem); |
| 28481 | } |
| 28482 | |
| 28483 | static void * |
| 28484 | removeTreeEntry(void *context, UA_ReferenceTargetTreeElem *elem) { |
| 28485 | (void)context; |
| 28486 | UA_NodePointer_clear(np: &elem->target.targetId); |
| 28487 | UA_free(ptr: elem); |
| 28488 | return NULL; |
| 28489 | } |
| 28490 | |
| 28491 | UA_StatusCode |
| 28492 | UA_NodeReferenceKind_switch(UA_NodeReferenceKind *rk) { |
| 28493 | UA_assert(rk->targetsSize > 0); |
| 28494 | |
| 28495 | if(rk->hasRefTree) { |
| 28496 | /* From tree to array */ |
| 28497 | UA_ReferenceTarget *array = (UA_ReferenceTarget*) |
| 28498 | UA_malloc(size: sizeof(UA_ReferenceTarget) * rk->targetsSize); |
| 28499 | if(!array) |
| 28500 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 28501 | size_t pos = 0; |
| 28502 | moveTreeToArray(array, pos: &pos, elem: rk->targets.tree.idRoot); |
| 28503 | rk->targets.array = array; |
| 28504 | rk->hasRefTree = false; |
| 28505 | return UA_STATUSCODE_GOOD; |
| 28506 | } |
| 28507 | |
| 28508 | /* From array to tree */ |
| 28509 | UA_NodeReferenceKind newRk = *rk; |
| 28510 | newRk.hasRefTree = true; |
| 28511 | newRk.targets.tree.idRoot = NULL; |
| 28512 | newRk.targets.tree.nameRoot = NULL; |
| 28513 | newRk.targetsSize = 0; |
| 28514 | for(size_t i = 0; i < rk->targetsSize; i++) { |
| 28515 | UA_StatusCode res = |
| 28516 | addReferenceTarget(refs: &newRk, target: rk->targets.array[i].targetId, |
| 28517 | targetNameHash: rk->targets.array[i].targetNameHash); |
| 28518 | if(res != UA_STATUSCODE_GOOD) { |
| 28519 | ZIP_ITER(UA_ReferenceIdTree, |
| 28520 | (UA_ReferenceIdTree*)&newRk.targets.tree.idRoot, |
| 28521 | removeTreeEntry, NULL); |
| 28522 | return res; |
| 28523 | } |
| 28524 | } |
| 28525 | for(size_t i = 0; i < rk->targetsSize; i++) |
| 28526 | UA_NodePointer_clear(np: &rk->targets.array[i].targetId); |
| 28527 | UA_free(ptr: rk->targets.array); |
| 28528 | *rk = newRk; |
| 28529 | return UA_STATUSCODE_GOOD; |
| 28530 | } |
| 28531 | |
| 28532 | void * |
| 28533 | UA_NodeReferenceKind_iterate(UA_NodeReferenceKind *rk, |
| 28534 | UA_NodeReferenceKind_iterateCallback callback, |
| 28535 | void *context) { |
| 28536 | if(rk->hasRefTree) |
| 28537 | return ZIP_ITER(UA_ReferenceIdTree, |
| 28538 | (UA_ReferenceIdTree*)&rk->targets.tree.idRoot, |
| 28539 | (UA_ReferenceIdTree_cb)callback, context); |
| 28540 | for(size_t i = 0; i < rk->targetsSize; i++) { |
| 28541 | void *res = callback(context, &rk->targets.array[i]); |
| 28542 | if(res) |
| 28543 | return res; |
| 28544 | } |
| 28545 | return NULL; |
| 28546 | } |
| 28547 | |
| 28548 | const UA_ReferenceTarget * |
| 28549 | UA_NodeReferenceKind_findTarget(const UA_NodeReferenceKind *rk, |
| 28550 | const UA_ExpandedNodeId *targetId) { |
| 28551 | UA_NodePointer targetP = UA_NodePointer_fromExpandedNodeId(id: targetId); |
| 28552 | if(rk->hasRefTree) { |
| 28553 | /* Return from the tree */ |
| 28554 | UA_ReferenceTargetTreeElem tmpTarget; |
| 28555 | tmpTarget.target.targetId = targetP; |
| 28556 | tmpTarget.targetIdHash = UA_ExpandedNodeId_hash(n: targetId); |
| 28557 | UA_ReferenceTargetTreeElem *result = |
| 28558 | ZIP_FIND(UA_ReferenceIdTree, (UA_ReferenceIdTree*) |
| 28559 | (uintptr_t)&rk->targets.tree.idRoot, &tmpTarget); |
| 28560 | if(result) |
| 28561 | return &result->target; |
| 28562 | } else { |
| 28563 | /* Return from the array */ |
| 28564 | for(size_t i = 0; i < rk->targetsSize; i++) { |
| 28565 | if(UA_NodePointer_equal(p1: targetP, p2: rk->targets.array[i].targetId)) |
| 28566 | return &rk->targets.array[i]; |
| 28567 | } |
| 28568 | } |
| 28569 | return NULL; |
| 28570 | } |
| 28571 | |
| 28572 | /* General node handling methods. There is no UA_Node_new() method here. |
| 28573 | * Creating nodes is part of the Nodestore layer */ |
| 28574 | |
| 28575 | void UA_Node_clear(UA_Node *node) { |
| 28576 | /* Delete references */ |
| 28577 | UA_Node_deleteReferences(node); |
| 28578 | |
| 28579 | /* Delete other head content */ |
| 28580 | UA_NodeHead *head = &node->head; |
| 28581 | UA_NodeId_clear(p: &head->nodeId); |
| 28582 | UA_QualifiedName_clear(p: &head->browseName); |
| 28583 | |
| 28584 | UA_LocalizedTextListEntry *lt; |
| 28585 | |
| 28586 | while((lt = head->displayName)) { |
| 28587 | head->displayName = lt->next; |
| 28588 | UA_LocalizedText_clear(p: <->localizedText); |
| 28589 | UA_free(ptr: lt); |
| 28590 | } |
| 28591 | |
| 28592 | while((lt = head->description)) { |
| 28593 | head->description = lt->next; |
| 28594 | UA_LocalizedText_clear(p: <->localizedText); |
| 28595 | UA_free(ptr: lt); |
| 28596 | } |
| 28597 | |
| 28598 | /* Delete unique content of the nodeclass */ |
| 28599 | switch(head->nodeClass) { |
| 28600 | case UA_NODECLASS_OBJECT: |
| 28601 | break; |
| 28602 | case UA_NODECLASS_METHOD: |
| 28603 | break; |
| 28604 | case UA_NODECLASS_OBJECTTYPE: |
| 28605 | break; |
| 28606 | case UA_NODECLASS_VARIABLE: |
| 28607 | case UA_NODECLASS_VARIABLETYPE: { |
| 28608 | UA_VariableNode *p = &node->variableNode; |
| 28609 | UA_NodeId_clear(p: &p->dataType); |
| 28610 | UA_Array_delete(p: p->arrayDimensions, size: p->arrayDimensionsSize, |
| 28611 | type: &UA_TYPES[UA_TYPES_INT32]); |
| 28612 | p->arrayDimensions = NULL; |
| 28613 | p->arrayDimensionsSize = 0; |
| 28614 | if(p->valueSource == UA_VALUESOURCE_DATA) |
| 28615 | UA_DataValue_clear(p: &p->value.data.value); |
| 28616 | break; |
| 28617 | } |
| 28618 | case UA_NODECLASS_REFERENCETYPE: { |
| 28619 | UA_ReferenceTypeNode *p = &node->referenceTypeNode; |
| 28620 | UA_LocalizedText_clear(p: &p->inverseName); |
| 28621 | break; |
| 28622 | } |
| 28623 | case UA_NODECLASS_DATATYPE: |
| 28624 | break; |
| 28625 | case UA_NODECLASS_VIEW: |
| 28626 | break; |
| 28627 | default: |
| 28628 | break; |
| 28629 | } |
| 28630 | } |
| 28631 | |
| 28632 | static UA_StatusCode |
| 28633 | UA_ObjectNode_copy(const UA_ObjectNode *src, UA_ObjectNode *dst) { |
| 28634 | dst->eventNotifier = src->eventNotifier; |
| 28635 | return UA_STATUSCODE_GOOD; |
| 28636 | } |
| 28637 | |
| 28638 | static UA_StatusCode |
| 28639 | UA_CommonVariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) { |
| 28640 | UA_StatusCode retval = |
| 28641 | UA_Array_copy(src: src->arrayDimensions, size: src->arrayDimensionsSize, |
| 28642 | dst: (void**)&dst->arrayDimensions, type: &UA_TYPES[UA_TYPES_INT32]); |
| 28643 | if(retval != UA_STATUSCODE_GOOD) |
| 28644 | return retval; |
| 28645 | dst->arrayDimensionsSize = src->arrayDimensionsSize; |
| 28646 | retval = UA_NodeId_copy(src: &src->dataType, dst: &dst->dataType); |
| 28647 | dst->valueRank = src->valueRank; |
| 28648 | dst->valueBackend = src->valueBackend; |
| 28649 | dst->valueSource = src->valueSource; |
| 28650 | if(src->valueSource == UA_VALUESOURCE_DATA) { |
| 28651 | retval |= UA_DataValue_copy(src: &src->value.data.value, |
| 28652 | dst: &dst->value.data.value); |
| 28653 | dst->value.data.callback = src->value.data.callback; |
| 28654 | } else { |
| 28655 | dst->value.dataSource = src->value.dataSource; |
| 28656 | } |
| 28657 | return retval; |
| 28658 | } |
| 28659 | |
| 28660 | static UA_StatusCode |
| 28661 | UA_VariableNode_copy(const UA_VariableNode *src, UA_VariableNode *dst) { |
| 28662 | dst->accessLevel = src->accessLevel; |
| 28663 | dst->minimumSamplingInterval = src->minimumSamplingInterval; |
| 28664 | dst->historizing = src->historizing; |
| 28665 | dst->isDynamic = src->isDynamic; |
| 28666 | return UA_CommonVariableNode_copy(src, dst); |
| 28667 | } |
| 28668 | |
| 28669 | static UA_StatusCode |
| 28670 | UA_VariableTypeNode_copy(const UA_VariableTypeNode *src, |
| 28671 | UA_VariableTypeNode *dst) { |
| 28672 | dst->isAbstract = src->isAbstract; |
| 28673 | return UA_CommonVariableNode_copy(src: (const UA_VariableNode*)src, dst: (UA_VariableNode*)dst); |
| 28674 | } |
| 28675 | |
| 28676 | static UA_StatusCode |
| 28677 | UA_MethodNode_copy(const UA_MethodNode *src, UA_MethodNode *dst) { |
| 28678 | dst->executable = src->executable; |
| 28679 | dst->method = src->method; |
| 28680 | #if UA_MULTITHREADING >= 100 |
| 28681 | dst->async = src->async; |
| 28682 | #endif |
| 28683 | return UA_STATUSCODE_GOOD; |
| 28684 | } |
| 28685 | |
| 28686 | static UA_StatusCode |
| 28687 | UA_ObjectTypeNode_copy(const UA_ObjectTypeNode *src, UA_ObjectTypeNode *dst) { |
| 28688 | dst->isAbstract = src->isAbstract; |
| 28689 | dst->lifecycle = src->lifecycle; |
| 28690 | return UA_STATUSCODE_GOOD; |
| 28691 | } |
| 28692 | |
| 28693 | static UA_StatusCode |
| 28694 | UA_ReferenceTypeNode_copy(const UA_ReferenceTypeNode *src, |
| 28695 | UA_ReferenceTypeNode *dst) { |
| 28696 | dst->isAbstract = src->isAbstract; |
| 28697 | dst->symmetric = src->symmetric; |
| 28698 | dst->referenceTypeIndex = src->referenceTypeIndex; |
| 28699 | dst->subTypes = src->subTypes; |
| 28700 | return UA_LocalizedText_copy(src: &src->inverseName, dst: &dst->inverseName); |
| 28701 | } |
| 28702 | |
| 28703 | static UA_StatusCode |
| 28704 | UA_DataTypeNode_copy(const UA_DataTypeNode *src, UA_DataTypeNode *dst) { |
| 28705 | dst->isAbstract = src->isAbstract; |
| 28706 | return UA_STATUSCODE_GOOD; |
| 28707 | } |
| 28708 | |
| 28709 | static UA_StatusCode |
| 28710 | UA_ViewNode_copy(const UA_ViewNode *src, UA_ViewNode *dst) { |
| 28711 | dst->containsNoLoops = src->containsNoLoops; |
| 28712 | dst->eventNotifier = src->eventNotifier; |
| 28713 | return UA_STATUSCODE_GOOD; |
| 28714 | } |
| 28715 | |
| 28716 | static void * |
| 28717 | copyTarget(void *context, UA_ReferenceTargetTreeElem *elm) { |
| 28718 | UA_NodeReferenceKind *drefs = (UA_NodeReferenceKind*)context; |
| 28719 | return (void*)(uintptr_t) |
| 28720 | addReferenceTargetToTree(rk: drefs, targetId: elm->target.targetId, |
| 28721 | targetIdHash: elm->targetIdHash, |
| 28722 | targetNameHash: elm->target.targetNameHash); |
| 28723 | } |
| 28724 | |
| 28725 | UA_StatusCode |
| 28726 | UA_Node_copy(const UA_Node *src, UA_Node *dst) { |
| 28727 | const UA_NodeHead *srchead = &src->head; |
| 28728 | UA_NodeHead *dsthead = &dst->head; |
| 28729 | if(srchead->nodeClass != dsthead->nodeClass) |
| 28730 | return UA_STATUSCODE_BADINTERNALERROR; |
| 28731 | |
| 28732 | /* Copy standard content */ |
| 28733 | UA_StatusCode retval = UA_NodeId_copy(src: &srchead->nodeId, dst: &dsthead->nodeId); |
| 28734 | retval |= UA_QualifiedName_copy(src: &srchead->browseName, dst: &dsthead->browseName); |
| 28735 | |
| 28736 | /* Copy the display name in several languages */ |
| 28737 | for(UA_LocalizedTextListEntry *lt = srchead->displayName; lt != NULL; lt = lt->next) { |
| 28738 | UA_LocalizedTextListEntry *newEntry = (UA_LocalizedTextListEntry *) |
| 28739 | UA_calloc(nmemb: 1, size: sizeof(UA_LocalizedTextListEntry)); |
| 28740 | if(!newEntry) { |
| 28741 | retval |= UA_STATUSCODE_BADOUTOFMEMORY; |
| 28742 | break; |
| 28743 | } |
| 28744 | retval |= UA_LocalizedText_copy(src: <->localizedText, dst: &newEntry->localizedText); |
| 28745 | |
| 28746 | /* Add to the linked list possibly in reverse order */ |
| 28747 | newEntry->next = dsthead->displayName; |
| 28748 | dsthead->displayName = newEntry; |
| 28749 | } |
| 28750 | |
| 28751 | /* Copy the description in several languages */ |
| 28752 | for(UA_LocalizedTextListEntry *lt = srchead->description; lt != NULL; lt = lt->next) { |
| 28753 | UA_LocalizedTextListEntry *newEntry = (UA_LocalizedTextListEntry *) |
| 28754 | UA_calloc(nmemb: 1, size: sizeof(UA_LocalizedTextListEntry)); |
| 28755 | if(!newEntry) { |
| 28756 | retval |= UA_STATUSCODE_BADOUTOFMEMORY; |
| 28757 | break; |
| 28758 | } |
| 28759 | retval |= UA_LocalizedText_copy(src: <->localizedText, dst: &newEntry->localizedText); |
| 28760 | |
| 28761 | /* Add to the linked list possibly in reverse order */ |
| 28762 | newEntry->next = dsthead->description; |
| 28763 | dsthead->description= newEntry; |
| 28764 | } |
| 28765 | |
| 28766 | dsthead->writeMask = srchead->writeMask; |
| 28767 | dsthead->context = srchead->context; |
| 28768 | dsthead->constructed = srchead->constructed; |
| 28769 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 28770 | dsthead->monitoredItems = srchead->monitoredItems; |
| 28771 | #endif |
| 28772 | if(retval != UA_STATUSCODE_GOOD) { |
| 28773 | UA_Node_clear(node: dst); |
| 28774 | return retval; |
| 28775 | } |
| 28776 | |
| 28777 | /* Copy the references */ |
| 28778 | dsthead->references = NULL; |
| 28779 | if(srchead->referencesSize > 0) { |
| 28780 | dsthead->references = (UA_NodeReferenceKind*) |
| 28781 | UA_calloc(nmemb: srchead->referencesSize, size: sizeof(UA_NodeReferenceKind)); |
| 28782 | if(!dsthead->references) { |
| 28783 | UA_Node_clear(node: dst); |
| 28784 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 28785 | } |
| 28786 | dsthead->referencesSize = srchead->referencesSize; |
| 28787 | |
| 28788 | for(size_t i = 0; i < srchead->referencesSize; ++i) { |
| 28789 | UA_NodeReferenceKind *srefs = &srchead->references[i]; |
| 28790 | UA_NodeReferenceKind *drefs = &dsthead->references[i]; |
| 28791 | drefs->referenceTypeIndex = srefs->referenceTypeIndex; |
| 28792 | drefs->isInverse = srefs->isInverse; |
| 28793 | drefs->hasRefTree = srefs->hasRefTree; /* initially empty */ |
| 28794 | |
| 28795 | /* Copy all the targets */ |
| 28796 | if(!srefs->hasRefTree) { |
| 28797 | drefs->targets.array = (UA_ReferenceTarget*) |
| 28798 | UA_malloc(size: sizeof(UA_ReferenceTarget) * srefs->targetsSize); |
| 28799 | if(!drefs->targets.array) { |
| 28800 | UA_Node_clear(node: dst); |
| 28801 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 28802 | } |
| 28803 | for(size_t j = 0; j < srefs->targetsSize; j++) { |
| 28804 | drefs->targets.array[j].targetNameHash = |
| 28805 | srefs->targets.array[j].targetNameHash; |
| 28806 | retval = UA_NodePointer_copy(in: srefs->targets.array[j].targetId, |
| 28807 | out: &drefs->targets.array[j].targetId); |
| 28808 | drefs->targetsSize++; /* avoid that targetsSize == 0 in error case */ |
| 28809 | if(retval != UA_STATUSCODE_GOOD) { |
| 28810 | UA_Node_clear(node: dst); |
| 28811 | return retval; |
| 28812 | } |
| 28813 | } |
| 28814 | } else { |
| 28815 | void *res = ZIP_ITER(UA_ReferenceIdTree, |
| 28816 | (UA_ReferenceIdTree*)&srefs->targets.tree.idRoot, |
| 28817 | copyTarget, drefs); |
| 28818 | if(res != NULL) { |
| 28819 | UA_Node_clear(node: dst); |
| 28820 | return (UA_StatusCode)(uintptr_t)res; |
| 28821 | } |
| 28822 | } |
| 28823 | |
| 28824 | UA_assert(srefs->targetsSize > 0); |
| 28825 | UA_assert(srefs->targetsSize == drefs->targetsSize); |
| 28826 | } |
| 28827 | } |
| 28828 | |
| 28829 | /* Copy unique content of the nodeclass */ |
| 28830 | switch(src->head.nodeClass) { |
| 28831 | case UA_NODECLASS_OBJECT: |
| 28832 | retval = UA_ObjectNode_copy(src: &src->objectNode, dst: &dst->objectNode); |
| 28833 | break; |
| 28834 | case UA_NODECLASS_VARIABLE: |
| 28835 | retval = UA_VariableNode_copy(src: &src->variableNode, dst: &dst->variableNode); |
| 28836 | break; |
| 28837 | case UA_NODECLASS_METHOD: |
| 28838 | retval = UA_MethodNode_copy(src: &src->methodNode, dst: &dst->methodNode); |
| 28839 | break; |
| 28840 | case UA_NODECLASS_OBJECTTYPE: |
| 28841 | retval = UA_ObjectTypeNode_copy(src: &src->objectTypeNode, dst: &dst->objectTypeNode); |
| 28842 | break; |
| 28843 | case UA_NODECLASS_VARIABLETYPE: |
| 28844 | retval = UA_VariableTypeNode_copy(src: &src->variableTypeNode, dst: &dst->variableTypeNode); |
| 28845 | break; |
| 28846 | case UA_NODECLASS_REFERENCETYPE: |
| 28847 | retval = UA_ReferenceTypeNode_copy(src: &src->referenceTypeNode, dst: &dst->referenceTypeNode); |
| 28848 | break; |
| 28849 | case UA_NODECLASS_DATATYPE: |
| 28850 | retval = UA_DataTypeNode_copy(src: &src->dataTypeNode, dst: &dst->dataTypeNode); |
| 28851 | break; |
| 28852 | case UA_NODECLASS_VIEW: |
| 28853 | retval = UA_ViewNode_copy(src: &src->viewNode, dst: &dst->viewNode); |
| 28854 | break; |
| 28855 | default: |
| 28856 | break; |
| 28857 | } |
| 28858 | |
| 28859 | if(retval != UA_STATUSCODE_GOOD) |
| 28860 | UA_Node_clear(node: dst); |
| 28861 | |
| 28862 | return retval; |
| 28863 | } |
| 28864 | |
| 28865 | UA_Node * |
| 28866 | UA_Node_copy_alloc(const UA_Node *src) { |
| 28867 | size_t nodesize = 0; |
| 28868 | switch(src->head.nodeClass) { |
| 28869 | case UA_NODECLASS_OBJECT: |
| 28870 | nodesize = sizeof(UA_ObjectNode); |
| 28871 | break; |
| 28872 | case UA_NODECLASS_VARIABLE: |
| 28873 | nodesize = sizeof(UA_VariableNode); |
| 28874 | break; |
| 28875 | case UA_NODECLASS_METHOD: |
| 28876 | nodesize = sizeof(UA_MethodNode); |
| 28877 | break; |
| 28878 | case UA_NODECLASS_OBJECTTYPE: |
| 28879 | nodesize = sizeof(UA_ObjectTypeNode); |
| 28880 | break; |
| 28881 | case UA_NODECLASS_VARIABLETYPE: |
| 28882 | nodesize = sizeof(UA_VariableTypeNode); |
| 28883 | break; |
| 28884 | case UA_NODECLASS_REFERENCETYPE: |
| 28885 | nodesize = sizeof(UA_ReferenceTypeNode); |
| 28886 | break; |
| 28887 | case UA_NODECLASS_DATATYPE: |
| 28888 | nodesize = sizeof(UA_DataTypeNode); |
| 28889 | break; |
| 28890 | case UA_NODECLASS_VIEW: |
| 28891 | nodesize = sizeof(UA_ViewNode); |
| 28892 | break; |
| 28893 | default: |
| 28894 | return NULL; |
| 28895 | } |
| 28896 | |
| 28897 | UA_Node *dst = (UA_Node*)UA_calloc(nmemb: 1, size: nodesize); |
| 28898 | if(!dst) |
| 28899 | return NULL; |
| 28900 | |
| 28901 | dst->head.nodeClass = src->head.nodeClass; |
| 28902 | |
| 28903 | UA_StatusCode retval = UA_Node_copy(src, dst); |
| 28904 | if(retval != UA_STATUSCODE_GOOD) { |
| 28905 | UA_free(ptr: dst); |
| 28906 | return NULL; |
| 28907 | } |
| 28908 | return dst; |
| 28909 | } |
| 28910 | /******************************/ |
| 28911 | /* Copy Attributes into Nodes */ |
| 28912 | /******************************/ |
| 28913 | |
| 28914 | static UA_StatusCode |
| 28915 | copyStandardAttributes(UA_NodeHead *head, const UA_NodeAttributes *attr) { |
| 28916 | /* UA_NodeId_copy(&item->requestedNewNodeId.nodeId, &node->nodeId); */ |
| 28917 | /* UA_QualifiedName_copy(&item->browseName, &node->browseName); */ |
| 28918 | |
| 28919 | head->writeMask = attr->writeMask; |
| 28920 | UA_StatusCode retval = UA_Node_insertOrUpdateDescription(head, value: &attr->description); |
| 28921 | /* The new nodeset format has optional display names: |
| 28922 | * https://github.com/open62541/open62541/issues/2627. If the display name |
| 28923 | * is NULL, take the name part of the browse name */ |
| 28924 | if(attr->displayName.text.length == 0) { |
| 28925 | UA_LocalizedText lt; |
| 28926 | UA_LocalizedText_init(p: <); |
| 28927 | lt.text = head->browseName.name; |
| 28928 | retval |= UA_Node_insertOrUpdateDisplayName(head, value: <); |
| 28929 | } else |
| 28930 | retval |= UA_Node_insertOrUpdateDisplayName(head, value: &attr->displayName); |
| 28931 | return retval; |
| 28932 | } |
| 28933 | |
| 28934 | static UA_StatusCode |
| 28935 | copyCommonVariableAttributes(UA_VariableNode *node, |
| 28936 | const UA_VariableAttributes *attr) { |
| 28937 | /* Copy the array dimensions */ |
| 28938 | UA_StatusCode retval = |
| 28939 | UA_Array_copy(src: attr->arrayDimensions, size: attr->arrayDimensionsSize, |
| 28940 | dst: (void**)&node->arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 28941 | if(retval != UA_STATUSCODE_GOOD) |
| 28942 | return retval; |
| 28943 | node->arrayDimensionsSize = attr->arrayDimensionsSize; |
| 28944 | |
| 28945 | /* Data type and value rank */ |
| 28946 | retval = UA_NodeId_copy(src: &attr->dataType, dst: &node->dataType); |
| 28947 | if(retval != UA_STATUSCODE_GOOD) |
| 28948 | return retval; |
| 28949 | node->valueRank = attr->valueRank; |
| 28950 | |
| 28951 | /* Copy the value */ |
| 28952 | retval = UA_Variant_copy(src: &attr->value, dst: &node->value.data.value.value); |
| 28953 | node->valueSource = UA_VALUESOURCE_DATA; |
| 28954 | node->value.data.value.hasValue = (node->value.data.value.value.type != NULL); |
| 28955 | |
| 28956 | return retval; |
| 28957 | } |
| 28958 | |
| 28959 | static UA_StatusCode |
| 28960 | copyVariableNodeAttributes(UA_VariableNode *vnode, |
| 28961 | const UA_VariableAttributes *attr) { |
| 28962 | vnode->accessLevel = attr->accessLevel; |
| 28963 | vnode->historizing = attr->historizing; |
| 28964 | vnode->minimumSamplingInterval = attr->minimumSamplingInterval; |
| 28965 | return copyCommonVariableAttributes(node: vnode, attr); |
| 28966 | } |
| 28967 | |
| 28968 | static UA_StatusCode |
| 28969 | copyVariableTypeNodeAttributes(UA_VariableTypeNode *vtnode, |
| 28970 | const UA_VariableTypeAttributes *attr) { |
| 28971 | vtnode->isAbstract = attr->isAbstract; |
| 28972 | return copyCommonVariableAttributes(node: (UA_VariableNode*)vtnode, |
| 28973 | attr: (const UA_VariableAttributes*)attr); |
| 28974 | } |
| 28975 | |
| 28976 | static UA_StatusCode |
| 28977 | copyObjectNodeAttributes(UA_ObjectNode *onode, const UA_ObjectAttributes *attr) { |
| 28978 | onode->eventNotifier = attr->eventNotifier; |
| 28979 | return UA_STATUSCODE_GOOD; |
| 28980 | } |
| 28981 | |
| 28982 | static UA_StatusCode |
| 28983 | copyReferenceTypeNodeAttributes(UA_ReferenceTypeNode *rtnode, |
| 28984 | const UA_ReferenceTypeAttributes *attr) { |
| 28985 | rtnode->isAbstract = attr->isAbstract; |
| 28986 | rtnode->symmetric = attr->symmetric; |
| 28987 | return UA_LocalizedText_copy(src: &attr->inverseName, dst: &rtnode->inverseName); |
| 28988 | } |
| 28989 | |
| 28990 | static UA_StatusCode |
| 28991 | copyObjectTypeNodeAttributes(UA_ObjectTypeNode *otnode, |
| 28992 | const UA_ObjectTypeAttributes *attr) { |
| 28993 | otnode->isAbstract = attr->isAbstract; |
| 28994 | return UA_STATUSCODE_GOOD; |
| 28995 | } |
| 28996 | |
| 28997 | static UA_StatusCode |
| 28998 | copyViewNodeAttributes(UA_ViewNode *vnode, const UA_ViewAttributes *attr) { |
| 28999 | vnode->containsNoLoops = attr->containsNoLoops; |
| 29000 | vnode->eventNotifier = attr->eventNotifier; |
| 29001 | return UA_STATUSCODE_GOOD; |
| 29002 | } |
| 29003 | |
| 29004 | static UA_StatusCode |
| 29005 | copyDataTypeNodeAttributes(UA_DataTypeNode *dtnode, |
| 29006 | const UA_DataTypeAttributes *attr) { |
| 29007 | dtnode->isAbstract = attr->isAbstract; |
| 29008 | return UA_STATUSCODE_GOOD; |
| 29009 | } |
| 29010 | |
| 29011 | static UA_StatusCode |
| 29012 | copyMethodNodeAttributes(UA_MethodNode *mnode, |
| 29013 | const UA_MethodAttributes *attr) { |
| 29014 | mnode->executable = attr->executable; |
| 29015 | return UA_STATUSCODE_GOOD; |
| 29016 | } |
| 29017 | |
| 29018 | #define CHECK_ATTRIBUTES(TYPE) \ |
| 29019 | if(attributeType != &UA_TYPES[UA_TYPES_##TYPE]) { \ |
| 29020 | retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID; \ |
| 29021 | break; \ |
| 29022 | } |
| 29023 | |
| 29024 | UA_StatusCode |
| 29025 | UA_Node_setAttributes(UA_Node *node, const void *attributes, const UA_DataType *attributeType) { |
| 29026 | /* Copy the attributes into the node */ |
| 29027 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 29028 | switch(node->head.nodeClass) { |
| 29029 | case UA_NODECLASS_OBJECT: |
| 29030 | CHECK_ATTRIBUTES(OBJECTATTRIBUTES); |
| 29031 | retval = copyObjectNodeAttributes(onode: &node->objectNode, |
| 29032 | attr: (const UA_ObjectAttributes*)attributes); |
| 29033 | break; |
| 29034 | case UA_NODECLASS_VARIABLE: |
| 29035 | CHECK_ATTRIBUTES(VARIABLEATTRIBUTES); |
| 29036 | retval = copyVariableNodeAttributes(vnode: &node->variableNode, |
| 29037 | attr: (const UA_VariableAttributes*)attributes); |
| 29038 | break; |
| 29039 | case UA_NODECLASS_OBJECTTYPE: |
| 29040 | CHECK_ATTRIBUTES(OBJECTTYPEATTRIBUTES); |
| 29041 | retval = copyObjectTypeNodeAttributes(otnode: &node->objectTypeNode, |
| 29042 | attr: (const UA_ObjectTypeAttributes*)attributes); |
| 29043 | break; |
| 29044 | case UA_NODECLASS_VARIABLETYPE: |
| 29045 | CHECK_ATTRIBUTES(VARIABLETYPEATTRIBUTES); |
| 29046 | retval = copyVariableTypeNodeAttributes(vtnode: &node->variableTypeNode, |
| 29047 | attr: (const UA_VariableTypeAttributes*)attributes); |
| 29048 | break; |
| 29049 | case UA_NODECLASS_REFERENCETYPE: |
| 29050 | CHECK_ATTRIBUTES(REFERENCETYPEATTRIBUTES); |
| 29051 | retval = copyReferenceTypeNodeAttributes(rtnode: &node->referenceTypeNode, |
| 29052 | attr: (const UA_ReferenceTypeAttributes*)attributes); |
| 29053 | break; |
| 29054 | case UA_NODECLASS_DATATYPE: |
| 29055 | CHECK_ATTRIBUTES(DATATYPEATTRIBUTES); |
| 29056 | retval = copyDataTypeNodeAttributes(dtnode: &node->dataTypeNode, |
| 29057 | attr: (const UA_DataTypeAttributes*)attributes); |
| 29058 | break; |
| 29059 | case UA_NODECLASS_VIEW: |
| 29060 | CHECK_ATTRIBUTES(VIEWATTRIBUTES); |
| 29061 | retval = copyViewNodeAttributes(vnode: &node->viewNode, attr: (const UA_ViewAttributes*)attributes); |
| 29062 | break; |
| 29063 | case UA_NODECLASS_METHOD: |
| 29064 | CHECK_ATTRIBUTES(METHODATTRIBUTES); |
| 29065 | retval = copyMethodNodeAttributes(mnode: &node->methodNode, attr: (const UA_MethodAttributes*)attributes); |
| 29066 | break; |
| 29067 | case UA_NODECLASS_UNSPECIFIED: |
| 29068 | default: |
| 29069 | retval = UA_STATUSCODE_BADNODECLASSINVALID; |
| 29070 | } |
| 29071 | |
| 29072 | if(retval == UA_STATUSCODE_GOOD) |
| 29073 | retval = copyStandardAttributes(head: &node->head, attr: (const UA_NodeAttributes*)attributes); |
| 29074 | if(retval != UA_STATUSCODE_GOOD) |
| 29075 | UA_Node_clear(node); |
| 29076 | return retval; |
| 29077 | } |
| 29078 | |
| 29079 | /*********************/ |
| 29080 | /* Manage References */ |
| 29081 | /*********************/ |
| 29082 | |
| 29083 | static UA_StatusCode |
| 29084 | addReferenceTargetToTree(UA_NodeReferenceKind *rk, UA_NodePointer targetId, |
| 29085 | UA_UInt32 targetIdHash, UA_UInt32 targetNameHash) { |
| 29086 | UA_ReferenceTargetTreeElem *entry = (UA_ReferenceTargetTreeElem*) |
| 29087 | UA_malloc(size: sizeof(UA_ReferenceTargetTreeElem)); |
| 29088 | if(!entry) |
| 29089 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 29090 | |
| 29091 | UA_StatusCode res = UA_NodePointer_copy(in: targetId, out: &entry->target.targetId); |
| 29092 | if(res != UA_STATUSCODE_GOOD) { |
| 29093 | UA_free(ptr: entry); |
| 29094 | return res; |
| 29095 | } |
| 29096 | |
| 29097 | entry->targetIdHash = targetIdHash; |
| 29098 | entry->target.targetNameHash = targetNameHash; |
| 29099 | |
| 29100 | ZIP_INSERT(UA_ReferenceIdTree, |
| 29101 | (UA_ReferenceIdTree*)&rk->targets.tree.idRoot, entry); |
| 29102 | ZIP_INSERT(UA_ReferenceNameTree, |
| 29103 | (UA_ReferenceNameTree*)&rk->targets.tree.nameRoot, entry); |
| 29104 | |
| 29105 | rk->targetsSize++; |
| 29106 | return UA_STATUSCODE_GOOD; |
| 29107 | } |
| 29108 | |
| 29109 | static UA_StatusCode |
| 29110 | addReferenceTarget(UA_NodeReferenceKind *rk, UA_NodePointer targetId, |
| 29111 | UA_UInt32 targetNameHash) { |
| 29112 | /* Insert into tree */ |
| 29113 | if(rk->hasRefTree) { |
| 29114 | UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(np: targetId); |
| 29115 | return addReferenceTargetToTree(rk, targetId, targetIdHash: UA_ExpandedNodeId_hash(n: &en), |
| 29116 | targetNameHash); |
| 29117 | } |
| 29118 | |
| 29119 | /* Insert to the array */ |
| 29120 | UA_ReferenceTarget *newRefs = (UA_ReferenceTarget*) |
| 29121 | UA_realloc(ptr: rk->targets.array, |
| 29122 | size: sizeof(UA_ReferenceTarget) * (rk->targetsSize + 1)); |
| 29123 | if(!newRefs) |
| 29124 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 29125 | rk->targets.array = newRefs; |
| 29126 | |
| 29127 | UA_StatusCode retval = |
| 29128 | UA_NodePointer_copy(in: targetId, |
| 29129 | out: &rk->targets.array[rk->targetsSize].targetId); |
| 29130 | rk->targets.array[rk->targetsSize].targetNameHash = targetNameHash; |
| 29131 | if(retval != UA_STATUSCODE_GOOD) { |
| 29132 | if(rk->targetsSize == 0) { |
| 29133 | UA_free(ptr: rk->targets.array); |
| 29134 | rk->targets.array = NULL; |
| 29135 | } |
| 29136 | return retval; |
| 29137 | } |
| 29138 | |
| 29139 | rk->targetsSize++; |
| 29140 | return UA_STATUSCODE_GOOD; |
| 29141 | } |
| 29142 | |
| 29143 | static UA_StatusCode |
| 29144 | addReferenceKind(UA_NodeHead *head, UA_Byte refTypeIndex, UA_Boolean isForward, |
| 29145 | const UA_NodePointer target, UA_UInt32 targetBrowseNameHash) { |
| 29146 | UA_NodeReferenceKind *refs = (UA_NodeReferenceKind*) |
| 29147 | UA_realloc(ptr: head->references, |
| 29148 | size: sizeof(UA_NodeReferenceKind) * (head->referencesSize+1)); |
| 29149 | if(!refs) |
| 29150 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 29151 | head->references = refs; |
| 29152 | |
| 29153 | UA_NodeReferenceKind *newRef = &refs[head->referencesSize]; |
| 29154 | memset(s: newRef, c: 0, n: sizeof(UA_NodeReferenceKind)); |
| 29155 | newRef->referenceTypeIndex = refTypeIndex; |
| 29156 | newRef->isInverse = !isForward; |
| 29157 | UA_StatusCode res = addReferenceTarget(rk: newRef, targetId: target, targetNameHash: targetBrowseNameHash); |
| 29158 | if(res != UA_STATUSCODE_GOOD) { |
| 29159 | if(head->referencesSize == 0) { |
| 29160 | UA_free(ptr: head->references); |
| 29161 | head->references = NULL; |
| 29162 | } |
| 29163 | return res; |
| 29164 | } |
| 29165 | |
| 29166 | head->referencesSize++; |
| 29167 | return UA_STATUSCODE_GOOD; |
| 29168 | } |
| 29169 | |
| 29170 | UA_StatusCode |
| 29171 | UA_Node_addReference(UA_Node *node, UA_Byte refTypeIndex, UA_Boolean isForward, |
| 29172 | const UA_ExpandedNodeId *targetNodeId, |
| 29173 | UA_UInt32 targetBrowseNameHash) { |
| 29174 | /* Find the matching reference kind */ |
| 29175 | for(size_t i = 0; i < node->head.referencesSize; ++i) { |
| 29176 | UA_NodeReferenceKind *refs = &node->head.references[i]; |
| 29177 | |
| 29178 | /* Reference direction does not match */ |
| 29179 | if(refs->isInverse == isForward) |
| 29180 | continue; |
| 29181 | |
| 29182 | /* Reference type does not match */ |
| 29183 | if(refs->referenceTypeIndex != refTypeIndex) |
| 29184 | continue; |
| 29185 | |
| 29186 | /* Does an identical reference already exist? */ |
| 29187 | const UA_ReferenceTarget *found = |
| 29188 | UA_NodeReferenceKind_findTarget(rk: refs, targetId: targetNodeId); |
| 29189 | if(found) |
| 29190 | return UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED; |
| 29191 | |
| 29192 | /* Add to existing ReferenceKind */ |
| 29193 | return addReferenceTarget(rk: refs, targetId: UA_NodePointer_fromExpandedNodeId(id: targetNodeId), |
| 29194 | targetNameHash: targetBrowseNameHash); |
| 29195 | } |
| 29196 | |
| 29197 | /* Add new ReferenceKind for the target */ |
| 29198 | return addReferenceKind(head: &node->head, refTypeIndex, isForward, |
| 29199 | target: UA_NodePointer_fromExpandedNodeId(id: targetNodeId), |
| 29200 | targetBrowseNameHash); |
| 29201 | |
| 29202 | } |
| 29203 | |
| 29204 | UA_StatusCode |
| 29205 | UA_Node_deleteReference(UA_Node *node, UA_Byte refTypeIndex, UA_Boolean isForward, |
| 29206 | const UA_ExpandedNodeId *targetNodeId) { |
| 29207 | UA_NodeHead *head = &node->head; |
| 29208 | for(size_t i = 0; i < head->referencesSize; i++) { |
| 29209 | UA_NodeReferenceKind *refs = &head->references[i]; |
| 29210 | if(isForward == refs->isInverse) |
| 29211 | continue; |
| 29212 | if(refTypeIndex != refs->referenceTypeIndex) |
| 29213 | continue; |
| 29214 | |
| 29215 | /* Cast out the const qualifier (hack!) */ |
| 29216 | UA_ReferenceTarget *target = (UA_ReferenceTarget*)(uintptr_t) |
| 29217 | UA_NodeReferenceKind_findTarget(rk: refs, targetId: targetNodeId); |
| 29218 | if(!target) |
| 29219 | continue; |
| 29220 | |
| 29221 | /* Ok, delete the reference. Cannot fail */ |
| 29222 | refs->targetsSize--; |
| 29223 | |
| 29224 | if(!refs->hasRefTree) { |
| 29225 | /* Remove from array */ |
| 29226 | UA_NodePointer_clear(np: &target->targetId); |
| 29227 | |
| 29228 | /* Elements remaining. Realloc. */ |
| 29229 | if(refs->targetsSize > 0) { |
| 29230 | if(target != &refs->targets.array[refs->targetsSize]) |
| 29231 | *target = refs->targets.array[refs->targetsSize]; |
| 29232 | UA_ReferenceTarget *newRefs = (UA_ReferenceTarget*) |
| 29233 | UA_realloc(ptr: refs->targets.array, |
| 29234 | size: sizeof(UA_ReferenceTarget) * refs->targetsSize); |
| 29235 | if(newRefs) |
| 29236 | refs->targets.array = newRefs; |
| 29237 | return UA_STATUSCODE_GOOD; /* Realloc allowed to fail */ |
| 29238 | } |
| 29239 | |
| 29240 | /* Remove the last target. Remove the ReferenceKind below */ |
| 29241 | UA_free(ptr: refs->targets.array); |
| 29242 | } else { |
| 29243 | UA_ReferenceTargetTreeElem *elem = (UA_ReferenceTargetTreeElem*)target; |
| 29244 | ZIP_REMOVE(UA_ReferenceIdTree, |
| 29245 | (UA_ReferenceIdTree*)&refs->targets.tree.idRoot, elem); |
| 29246 | ZIP_REMOVE(UA_ReferenceNameTree, |
| 29247 | (UA_ReferenceNameTree*)&refs->targets.tree.nameRoot, elem); |
| 29248 | UA_NodePointer_clear(np: &target->targetId); |
| 29249 | UA_free(ptr: target); |
| 29250 | if(refs->targetsSize > 0) |
| 29251 | return UA_STATUSCODE_GOOD; |
| 29252 | } |
| 29253 | |
| 29254 | /* No targets remaining. Remove the ReferenceKind. */ |
| 29255 | head->referencesSize--; |
| 29256 | if(head->referencesSize > 0) { |
| 29257 | /* No target for the ReferenceType remaining. Remove and shrink down |
| 29258 | * allocated buffer. Ignore errors in case memory buffer could not |
| 29259 | * be shrinked down. */ |
| 29260 | if(i != head->referencesSize) |
| 29261 | head->references[i] = head->references[node->head.referencesSize]; |
| 29262 | UA_NodeReferenceKind *newRefs = (UA_NodeReferenceKind*) |
| 29263 | UA_realloc(ptr: head->references, |
| 29264 | size: sizeof(UA_NodeReferenceKind) * head->referencesSize); |
| 29265 | if(newRefs) |
| 29266 | head->references = newRefs; |
| 29267 | } else { |
| 29268 | /* No remaining references of any ReferenceType */ |
| 29269 | UA_free(ptr: head->references); |
| 29270 | head->references = NULL; |
| 29271 | } |
| 29272 | return UA_STATUSCODE_GOOD; |
| 29273 | } |
| 29274 | return UA_STATUSCODE_UNCERTAINREFERENCENOTDELETED; |
| 29275 | } |
| 29276 | |
| 29277 | void |
| 29278 | UA_Node_deleteReferencesSubset(UA_Node *node, const UA_ReferenceTypeSet *keepSet) { |
| 29279 | UA_NodeHead *head = &node->head; |
| 29280 | for(size_t i = 0; i < head->referencesSize; i++) { |
| 29281 | /* Keep the references of this type? */ |
| 29282 | UA_NodeReferenceKind *refs = &head->references[i]; |
| 29283 | if(UA_ReferenceTypeSet_contains(set: keepSet, index: refs->referenceTypeIndex)) |
| 29284 | continue; |
| 29285 | |
| 29286 | /* Remove all target entries. Don't remove entries from browseName tree. |
| 29287 | * The entire ReferenceKind will be removed anyway. */ |
| 29288 | if(!refs->hasRefTree) { |
| 29289 | for(size_t j = 0; j < refs->targetsSize; j++) |
| 29290 | UA_NodePointer_clear(np: &refs->targets.array[j].targetId); |
| 29291 | UA_free(ptr: refs->targets.array); |
| 29292 | } else { |
| 29293 | ZIP_ITER(UA_ReferenceIdTree, |
| 29294 | (UA_ReferenceIdTree*)&refs->targets.tree.idRoot, |
| 29295 | removeTreeEntry, NULL); |
| 29296 | } |
| 29297 | |
| 29298 | /* Move last references-kind entry to this position. Don't memcpy over |
| 29299 | * the same position. Decrease i to repeat at this location. */ |
| 29300 | head->referencesSize--; |
| 29301 | if(i != head->referencesSize) { |
| 29302 | head->references[i] = head->references[head->referencesSize]; |
| 29303 | i--; |
| 29304 | } |
| 29305 | } |
| 29306 | |
| 29307 | if(head->referencesSize > 0) { |
| 29308 | /* Realloc to save memory. Ignore if realloc fails. */ |
| 29309 | UA_NodeReferenceKind *refs = (UA_NodeReferenceKind*) |
| 29310 | UA_realloc(ptr: head->references, |
| 29311 | size: sizeof(UA_NodeReferenceKind) * head->referencesSize); |
| 29312 | if(refs) |
| 29313 | head->references = refs; |
| 29314 | } else { |
| 29315 | /* The array is empty. Remove. */ |
| 29316 | UA_free(ptr: head->references); |
| 29317 | head->references = NULL; |
| 29318 | } |
| 29319 | } |
| 29320 | |
| 29321 | void UA_Node_deleteReferences(UA_Node *node) { |
| 29322 | UA_ReferenceTypeSet noRefs; |
| 29323 | UA_ReferenceTypeSet_init(set: &noRefs); |
| 29324 | UA_Node_deleteReferencesSubset(node, keepSet: &noRefs); |
| 29325 | } |
| 29326 | |
| 29327 | static UA_StatusCode |
| 29328 | UA_Node_insertOrUpdateLocale(UA_LocalizedTextListEntry **root, |
| 29329 | const UA_LocalizedText *value) { |
| 29330 | UA_StatusCode res; |
| 29331 | UA_LocalizedTextListEntry *lt, *prev = NULL; |
| 29332 | for(lt = *root; lt != NULL; prev = lt, lt = lt->next) { |
| 29333 | if(!UA_String_equal(p1: &value->locale, p2: <->localizedText.locale)) |
| 29334 | continue; |
| 29335 | |
| 29336 | /* No text -> remove the entry for this locale */ |
| 29337 | if(value->text.length == 0) { |
| 29338 | if(prev == NULL) |
| 29339 | *root = lt->next; |
| 29340 | else |
| 29341 | prev->next = lt->next; |
| 29342 | UA_LocalizedText_clear(p: <->localizedText); |
| 29343 | UA_free(ptr: lt); |
| 29344 | return UA_STATUSCODE_GOOD; |
| 29345 | } |
| 29346 | |
| 29347 | /* First make a copy of the text, if this succeeds replace the old |
| 29348 | * version */ |
| 29349 | UA_String tmp; |
| 29350 | res = UA_String_copy(src: &value->text, dst: &tmp); |
| 29351 | if(res != UA_STATUSCODE_GOOD) |
| 29352 | return res; |
| 29353 | |
| 29354 | UA_String_clear(p: <->localizedText.text); |
| 29355 | lt->localizedText.text = tmp; |
| 29356 | return UA_STATUSCODE_GOOD; |
| 29357 | } |
| 29358 | |
| 29359 | /* The locale does not exist so far */ |
| 29360 | |
| 29361 | /* Do nothing if a non-existing locale should be removed */ |
| 29362 | if(value->text.length == 0) |
| 29363 | return UA_STATUSCODE_GOOD; |
| 29364 | |
| 29365 | /* Add a new localized text */ |
| 29366 | lt = (UA_LocalizedTextListEntry *)UA_malloc(size: sizeof(UA_LocalizedTextListEntry)); |
| 29367 | if(!lt) |
| 29368 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 29369 | |
| 29370 | res = UA_LocalizedText_copy(src: value, dst: <->localizedText); |
| 29371 | if(res != UA_STATUSCODE_GOOD) { |
| 29372 | UA_free(ptr: lt); |
| 29373 | return res; |
| 29374 | } |
| 29375 | |
| 29376 | lt->next = *root; |
| 29377 | *root = lt; |
| 29378 | return UA_STATUSCODE_GOOD; |
| 29379 | } |
| 29380 | |
| 29381 | UA_StatusCode |
| 29382 | UA_Node_insertOrUpdateDisplayName(UA_NodeHead *head, |
| 29383 | const UA_LocalizedText *value) { |
| 29384 | return UA_Node_insertOrUpdateLocale(root: &head->displayName, value); |
| 29385 | } |
| 29386 | |
| 29387 | UA_StatusCode |
| 29388 | UA_Node_insertOrUpdateDescription(UA_NodeHead *head, |
| 29389 | const UA_LocalizedText *value) { |
| 29390 | return UA_Node_insertOrUpdateLocale(root: &head->description, value); |
| 29391 | } |
| 29392 | |
| 29393 | /**** amalgamated original file "/src/server/ua_server.c" ****/ |
| 29394 | |
| 29395 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 29396 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 29397 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 29398 | * |
| 29399 | * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 29400 | * Copyright 2014-2017 (c) Florian Palm |
| 29401 | * Copyright 2015-2016 (c) Sten Grüner |
| 29402 | * Copyright 2015-2016 (c) Chris Iatrou |
| 29403 | * Copyright 2015 (c) LEvertz |
| 29404 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 29405 | * Copyright 2016 (c) Julian Grothoff |
| 29406 | * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH |
| 29407 | * Copyright 2016 (c) Lorenz Haas |
| 29408 | * Copyright 2017 (c) frax2222 |
| 29409 | * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB |
| 29410 | * Copyright 2018 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang) |
| 29411 | * Copyright 2019 (c) Kalycito Infotech Private Limited |
| 29412 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes) |
| 29413 | * Copyright 2022 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
| 29414 | */ |
| 29415 | |
| 29416 | |
| 29417 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 29418 | #endif |
| 29419 | |
| 29420 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 29421 | #endif |
| 29422 | |
| 29423 | #ifdef UA_ENABLE_NODESET_INJECTOR |
| 29424 | #endif |
| 29425 | |
| 29426 | /**********************/ |
| 29427 | /* Namespace Handling */ |
| 29428 | /**********************/ |
| 29429 | |
| 29430 | /* The NS1 Uri can be changed by the user to some custom string. This method is |
| 29431 | * called to initialize the NS1 Uri if it is not set before to the default |
| 29432 | * Application URI. |
| 29433 | * |
| 29434 | * This is done as soon as the Namespace Array is read or written via node value |
| 29435 | * read / write services, or UA_Server_addNamespace, or UA_Server_getNamespaceByIndex |
| 29436 | * UA_Server_getNamespaceByName or UA_Server_run_startup is called. |
| 29437 | * |
| 29438 | * Therefore one has to set the custom NS1 URI before one of the previously |
| 29439 | * mentioned steps. */ |
| 29440 | |
| 29441 | void |
| 29442 | setupNs1Uri(UA_Server *server) { |
| 29443 | if(!server->namespaces[1].data) { |
| 29444 | UA_String_copy(src: &server->config.applicationDescription.applicationUri, |
| 29445 | dst: &server->namespaces[1]); |
| 29446 | } |
| 29447 | } |
| 29448 | |
| 29449 | UA_UInt16 addNamespace(UA_Server *server, const UA_String name) { |
| 29450 | /* ensure that the uri for ns1 is set up from the app description */ |
| 29451 | setupNs1Uri(server); |
| 29452 | |
| 29453 | /* Check if the namespace already exists in the server's namespace array */ |
| 29454 | for(size_t i = 0; i < server->namespacesSize; ++i) { |
| 29455 | if(UA_String_equal(p1: &name, p2: &server->namespaces[i])) |
| 29456 | return (UA_UInt16) i; |
| 29457 | } |
| 29458 | |
| 29459 | /* Make the array bigger */ |
| 29460 | UA_String *newNS = (UA_String*)UA_realloc(ptr: server->namespaces, |
| 29461 | size: sizeof(UA_String) * (server->namespacesSize + 1)); |
| 29462 | UA_CHECK_MEM(newNS, return 0); |
| 29463 | |
| 29464 | server->namespaces = newNS; |
| 29465 | |
| 29466 | /* Copy the namespace string */ |
| 29467 | UA_StatusCode retval = UA_String_copy(src: &name, dst: &server->namespaces[server->namespacesSize]); |
| 29468 | UA_CHECK_STATUS(retval, return 0); |
| 29469 | |
| 29470 | /* Announce the change (otherwise, the array appears unchanged) */ |
| 29471 | ++server->namespacesSize; |
| 29472 | return (UA_UInt16)(server->namespacesSize - 1); |
| 29473 | } |
| 29474 | |
| 29475 | UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) { |
| 29476 | /* Override const attribute to get string (dirty hack) */ |
| 29477 | UA_String nameString; |
| 29478 | nameString.length = strlen(s: name); |
| 29479 | nameString.data = (UA_Byte*)(uintptr_t)name; |
| 29480 | lockServer(server); |
| 29481 | UA_UInt16 retVal = addNamespace(server, name: nameString); |
| 29482 | unlockServer(server); |
| 29483 | return retVal; |
| 29484 | } |
| 29485 | |
| 29486 | UA_ServerConfig* |
| 29487 | UA_Server_getConfig(UA_Server *server) { |
| 29488 | UA_CHECK_MEM(server, return NULL); |
| 29489 | return &server->config; |
| 29490 | } |
| 29491 | |
| 29492 | UA_StatusCode |
| 29493 | getNamespaceByName(UA_Server *server, const UA_String namespaceUri, |
| 29494 | size_t *foundIndex) { |
| 29495 | /* ensure that the uri for ns1 is set up from the app description */ |
| 29496 | setupNs1Uri(server); |
| 29497 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 29498 | for(size_t idx = 0; idx < server->namespacesSize; idx++) { |
| 29499 | if(UA_String_equal(p1: &server->namespaces[idx], p2: &namespaceUri)) { |
| 29500 | (*foundIndex) = idx; |
| 29501 | res = UA_STATUSCODE_GOOD; |
| 29502 | break; |
| 29503 | } |
| 29504 | } |
| 29505 | return res; |
| 29506 | } |
| 29507 | |
| 29508 | UA_StatusCode |
| 29509 | getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex, |
| 29510 | UA_String *foundUri) { |
| 29511 | /* ensure that the uri for ns1 is set up from the app description */ |
| 29512 | setupNs1Uri(server); |
| 29513 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 29514 | if(namespaceIndex >= server->namespacesSize) |
| 29515 | return res; |
| 29516 | res = UA_String_copy(src: &server->namespaces[namespaceIndex], dst: foundUri); |
| 29517 | return res; |
| 29518 | } |
| 29519 | |
| 29520 | UA_StatusCode |
| 29521 | UA_Server_getNamespaceByName(UA_Server *server, const UA_String namespaceUri, |
| 29522 | size_t *foundIndex) { |
| 29523 | lockServer(server); |
| 29524 | UA_StatusCode res = getNamespaceByName(server, namespaceUri, foundIndex); |
| 29525 | unlockServer(server); |
| 29526 | return res; |
| 29527 | } |
| 29528 | |
| 29529 | UA_StatusCode |
| 29530 | UA_Server_getNamespaceByIndex(UA_Server *server, const size_t namespaceIndex, |
| 29531 | UA_String *foundUri) { |
| 29532 | lockServer(server); |
| 29533 | UA_StatusCode res = getNamespaceByIndex(server, namespaceIndex, foundUri); |
| 29534 | unlockServer(server); |
| 29535 | return res; |
| 29536 | } |
| 29537 | |
| 29538 | UA_StatusCode |
| 29539 | UA_Server_forEachChildNodeCall(UA_Server *server, UA_NodeId parentNodeId, |
| 29540 | UA_NodeIteratorCallback callback, void *handle) { |
| 29541 | UA_BrowseDescription bd; |
| 29542 | UA_BrowseDescription_init(p: &bd); |
| 29543 | bd.nodeId = parentNodeId; |
| 29544 | bd.browseDirection = UA_BROWSEDIRECTION_BOTH; |
| 29545 | bd.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_ISFORWARD; |
| 29546 | |
| 29547 | UA_BrowseResult br = UA_Server_browse(server, maxReferences: 0, bd: &bd); |
| 29548 | UA_StatusCode res = br.statusCode; |
| 29549 | UA_CHECK_STATUS(res, goto cleanup); |
| 29550 | |
| 29551 | for(size_t i = 0; i < br.referencesSize; i++) { |
| 29552 | if(!UA_ExpandedNodeId_isLocal(n: &br.references[i].nodeId)) |
| 29553 | continue; |
| 29554 | res = callback(br.references[i].nodeId.nodeId, !br.references[i].isForward, |
| 29555 | br.references[i].referenceTypeId, handle); |
| 29556 | UA_CHECK_STATUS(res, goto cleanup); |
| 29557 | } |
| 29558 | cleanup: |
| 29559 | UA_BrowseResult_clear(p: &br); |
| 29560 | return res; |
| 29561 | } |
| 29562 | |
| 29563 | /*********************/ |
| 29564 | /* Server Components */ |
| 29565 | /*********************/ |
| 29566 | |
| 29567 | enum ZIP_CMP |
| 29568 | cmpServerComponent(const UA_UInt64 *a, const UA_UInt64 *b) { |
| 29569 | if(*a == *b) |
| 29570 | return ZIP_CMP_EQ; |
| 29571 | return (*a < *b) ? ZIP_CMP_LESS : ZIP_CMP_MORE; |
| 29572 | } |
| 29573 | |
| 29574 | void |
| 29575 | addServerComponent(UA_Server *server, UA_ServerComponent *sc, |
| 29576 | UA_UInt64 *identifier) { |
| 29577 | if(!sc) |
| 29578 | return; |
| 29579 | |
| 29580 | sc->identifier = ++server->serverComponentIds; |
| 29581 | ZIP_INSERT(UA_ServerComponentTree, &server->serverComponents, sc); |
| 29582 | |
| 29583 | /* Start the component if the server is started */ |
| 29584 | if(server->state == UA_LIFECYCLESTATE_STARTED && sc->start) |
| 29585 | sc->start(server, sc); |
| 29586 | |
| 29587 | if(identifier) |
| 29588 | *identifier = sc->identifier; |
| 29589 | } |
| 29590 | |
| 29591 | static void * |
| 29592 | findServerComponent(void *context, UA_ServerComponent *sc) { |
| 29593 | UA_String *name = (UA_String*)context; |
| 29594 | return (UA_String_equal(p1: &sc->name, p2: name)) ? sc : NULL; |
| 29595 | } |
| 29596 | |
| 29597 | UA_ServerComponent * |
| 29598 | getServerComponentByName(UA_Server *server, UA_String name) { |
| 29599 | return (UA_ServerComponent*) |
| 29600 | ZIP_ITER(UA_ServerComponentTree, &server->serverComponents, |
| 29601 | findServerComponent, &name); |
| 29602 | } |
| 29603 | |
| 29604 | static void * |
| 29605 | removeServerComponent(void *application, UA_ServerComponent *sc) { |
| 29606 | UA_assert(sc->state == UA_LIFECYCLESTATE_STOPPED); |
| 29607 | sc->free((UA_Server*)application, sc); |
| 29608 | return NULL; |
| 29609 | } |
| 29610 | |
| 29611 | static void * |
| 29612 | startServerComponent(void *application, UA_ServerComponent *sc) { |
| 29613 | sc->start((UA_Server*)application, sc); |
| 29614 | return NULL; |
| 29615 | } |
| 29616 | |
| 29617 | static void * |
| 29618 | stopServerComponent(void *application, UA_ServerComponent *sc) { |
| 29619 | sc->stop((UA_Server*)application, sc); |
| 29620 | return NULL; |
| 29621 | } |
| 29622 | |
| 29623 | /* ZIP_ITER returns NULL only if all components are stopped */ |
| 29624 | static void * |
| 29625 | checkServerComponent(void *application, UA_ServerComponent *sc) { |
| 29626 | return (sc->state == UA_LIFECYCLESTATE_STOPPED) ? NULL : (void*)0x01; |
| 29627 | } |
| 29628 | |
| 29629 | /********************/ |
| 29630 | /* Server Lifecycle */ |
| 29631 | /********************/ |
| 29632 | |
| 29633 | /* The server needs to be stopped before it can be deleted */ |
| 29634 | UA_StatusCode |
| 29635 | UA_Server_delete(UA_Server *server) { |
| 29636 | if(server == NULL) { |
| 29637 | return UA_STATUSCODE_BADINTERNALERROR; |
| 29638 | } |
| 29639 | |
| 29640 | if(server->state != UA_LIFECYCLESTATE_STOPPED) { |
| 29641 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 29642 | msg: "The server must be fully stopped before it can be deleted"); |
| 29643 | return UA_STATUSCODE_BADINTERNALERROR; |
| 29644 | } |
| 29645 | |
| 29646 | lockServer(server); |
| 29647 | |
| 29648 | session_list_entry *current, *temp; |
| 29649 | LIST_FOREACH_SAFE(current, &server->sessions, pointers, temp) { |
| 29650 | UA_Server_removeSession(server, sentry: current, shutdownReason: UA_SHUTDOWNREASON_CLOSE); |
| 29651 | } |
| 29652 | UA_Array_delete(p: server->namespaces, size: server->namespacesSize, type: &UA_TYPES[UA_TYPES_STRING]); |
| 29653 | |
| 29654 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 29655 | UA_MonitoredItem *mon, *mon_tmp; |
| 29656 | LIST_FOREACH_SAFE(mon, &server->localMonitoredItems, listEntry, mon_tmp) { |
| 29657 | LIST_REMOVE(mon, listEntry); |
| 29658 | UA_MonitoredItem_delete(server, mon); |
| 29659 | } |
| 29660 | |
| 29661 | /* Remove subscriptions without a session */ |
| 29662 | UA_Subscription *sub, *sub_tmp; |
| 29663 | LIST_FOREACH_SAFE(sub, &server->subscriptions, serverListEntry, sub_tmp) { |
| 29664 | UA_Subscription_delete(server, sub); |
| 29665 | } |
| 29666 | UA_assert(server->monitoredItemsSize == 0); |
| 29667 | UA_assert(server->subscriptionsSize == 0); |
| 29668 | |
| 29669 | #ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS |
| 29670 | UA_ConditionList_delete(server); |
| 29671 | #endif |
| 29672 | |
| 29673 | #endif |
| 29674 | |
| 29675 | #ifdef UA_ENABLE_PUBSUB |
| 29676 | UA_PubSubManager_delete(server, pubSubManager: &server->pubSubManager); |
| 29677 | #endif |
| 29678 | |
| 29679 | #if UA_MULTITHREADING >= 100 |
| 29680 | UA_AsyncManager_clear(&server->asyncManager, server); |
| 29681 | #endif |
| 29682 | |
| 29683 | /* Clean up the Admin Session */ |
| 29684 | UA_Session_clear(session: &server->adminSession, server); |
| 29685 | |
| 29686 | /* Remove all remaining server components (must be all stopped) */ |
| 29687 | ZIP_ITER(UA_ServerComponentTree, &server->serverComponents, |
| 29688 | removeServerComponent, server); |
| 29689 | |
| 29690 | unlockServer(server); /* The timer has its own mutex */ |
| 29691 | |
| 29692 | /* Clean up the config */ |
| 29693 | UA_ServerConfig_clean(config: &server->config); |
| 29694 | |
| 29695 | #if UA_MULTITHREADING >= 100 |
| 29696 | UA_LOCK_DESTROY(&server->serviceMutex); |
| 29697 | #endif |
| 29698 | |
| 29699 | /* Delete the server itself and return */ |
| 29700 | UA_free(ptr: server); |
| 29701 | return UA_STATUSCODE_GOOD; |
| 29702 | } |
| 29703 | |
| 29704 | /* Regular house-keeping tasks. Removing unused and timed-out channels and |
| 29705 | * sessions. */ |
| 29706 | static void |
| 29707 | serverHouseKeeping(UA_Server *server, void *_) { |
| 29708 | lockServer(server); |
| 29709 | UA_DateTime nowMonotonic = UA_DateTime_nowMonotonic(); |
| 29710 | UA_Server_cleanupSessions(server, nowMonotonic); |
| 29711 | unlockServer(server); |
| 29712 | } |
| 29713 | |
| 29714 | /********************/ |
| 29715 | /* Server Lifecycle */ |
| 29716 | /********************/ |
| 29717 | |
| 29718 | static |
| 29719 | UA_INLINE |
| 29720 | UA_Boolean UA_Server_NodestoreIsConfigured(UA_Server *server) { |
| 29721 | return server->config.nodestore.getNode != NULL; |
| 29722 | } |
| 29723 | |
| 29724 | static UA_Server * |
| 29725 | UA_Server_init(UA_Server *server) { |
| 29726 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 29727 | UA_CHECK_FATAL(UA_Server_NodestoreIsConfigured(server), goto cleanup, |
| 29728 | server->config.logging, UA_LOGCATEGORY_SERVER, |
| 29729 | "No Nodestore configured in the server"); |
| 29730 | |
| 29731 | /* Init start time to zero, the actual start time will be sampled in |
| 29732 | * UA_Server_run_startup() */ |
| 29733 | server->startTime = 0; |
| 29734 | |
| 29735 | /* Set a seed for non-cyptographic randomness */ |
| 29736 | #ifndef UA_ENABLE_DETERMINISTIC_RNG |
| 29737 | UA_random_seed(seed: (UA_UInt64)UA_DateTime_now()); |
| 29738 | #endif |
| 29739 | |
| 29740 | UA_LOCK_INIT(&server->serviceMutex); |
| 29741 | lockServer(server); |
| 29742 | |
| 29743 | /* Initialize the adminSession */ |
| 29744 | UA_Session_init(session: &server->adminSession); |
| 29745 | server->adminSession.sessionId.identifierType = UA_NODEIDTYPE_GUID; |
| 29746 | server->adminSession.sessionId.identifier.guid.data1 = 1; |
| 29747 | server->adminSession.validTill = UA_INT64_MAX; |
| 29748 | server->adminSession.sessionName = UA_STRING_ALLOC("Administrator"); |
| 29749 | |
| 29750 | /* Create Namespaces 0 and 1 |
| 29751 | * Ns1 will be filled later with the uri from the app description */ |
| 29752 | server->namespaces = (UA_String *)UA_Array_new(size: 2, type: &UA_TYPES[UA_TYPES_STRING]); |
| 29753 | UA_CHECK_MEM(server->namespaces, goto cleanup); |
| 29754 | |
| 29755 | server->namespaces[0] = UA_STRING_ALLOC("http://opcfoundation.org/UA/"); |
| 29756 | server->namespaces[1] = UA_STRING_NULL; |
| 29757 | server->namespacesSize = 2; |
| 29758 | |
| 29759 | /* Initialize Session Management */ |
| 29760 | LIST_INIT(&server->sessions); |
| 29761 | server->sessionCount = 0; |
| 29762 | |
| 29763 | #if UA_MULTITHREADING >= 100 |
| 29764 | UA_AsyncManager_init(&server->asyncManager, server); |
| 29765 | #endif |
| 29766 | |
| 29767 | /* Initialize the binay protocol support */ |
| 29768 | addServerComponent(server, sc: UA_BinaryProtocolManager_new(server), NULL); |
| 29769 | |
| 29770 | /* Initialized discovery */ |
| 29771 | #ifdef UA_ENABLE_DISCOVERY |
| 29772 | addServerComponent(server, sc: UA_DiscoveryManager_new(server), NULL); |
| 29773 | #endif |
| 29774 | |
| 29775 | /* Initialize namespace 0*/ |
| 29776 | res = initNS0(server); |
| 29777 | UA_CHECK_STATUS(res, goto cleanup); |
| 29778 | |
| 29779 | #ifdef UA_ENABLE_NODESET_INJECTOR |
| 29780 | res = UA_Server_injectNodesets(server); |
| 29781 | UA_CHECK_STATUS(res, goto cleanup); |
| 29782 | #endif |
| 29783 | |
| 29784 | #ifdef UA_ENABLE_PUBSUB |
| 29785 | /* Initialized PubSubManager */ |
| 29786 | UA_PubSubManager_init(server, pubSubManager: &server->pubSubManager); |
| 29787 | |
| 29788 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 29789 | /* Build PubSub information model */ |
| 29790 | initPubSubNS0(server); |
| 29791 | #endif |
| 29792 | |
| 29793 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 29794 | /* setup default PubSub monitoring callbacks */ |
| 29795 | res = UA_PubSubManager_setDefaultMonitoringCallbacks(&server->config.pubSubConfig.monitoringInterface); |
| 29796 | UA_CHECK_STATUS(res, goto cleanup); |
| 29797 | #endif /* UA_ENABLE_PUBSUB_MONITORING */ |
| 29798 | #endif /* UA_ENABLE_PUBSUB */ |
| 29799 | |
| 29800 | unlockServer(server); |
| 29801 | return server; |
| 29802 | |
| 29803 | cleanup: |
| 29804 | unlockServer(server); |
| 29805 | UA_Server_delete(server); |
| 29806 | return NULL; |
| 29807 | } |
| 29808 | |
| 29809 | UA_Server * |
| 29810 | UA_Server_newWithConfig(UA_ServerConfig *config) { |
| 29811 | UA_CHECK_MEM(config, return NULL); |
| 29812 | |
| 29813 | UA_CHECK_LOG(config->eventLoop != NULL, return NULL, ERROR, |
| 29814 | config->logging, UA_LOGCATEGORY_SERVER, "No EventLoop configured"); |
| 29815 | |
| 29816 | UA_Server *server = (UA_Server *)UA_calloc(nmemb: 1, size: sizeof(UA_Server)); |
| 29817 | UA_CHECK_MEM(server, UA_ServerConfig_clean(config); return NULL); |
| 29818 | |
| 29819 | server->config = *config; |
| 29820 | |
| 29821 | /* If not defined, set logging to what the server has */ |
| 29822 | if(!server->config.secureChannelPKI.logging) |
| 29823 | server->config.secureChannelPKI.logging = server->config.logging; |
| 29824 | if(!server->config.sessionPKI.logging) |
| 29825 | server->config.sessionPKI.logging = server->config.logging; |
| 29826 | |
| 29827 | /* Reset the old config */ |
| 29828 | memset(s: config, c: 0, n: sizeof(UA_ServerConfig)); |
| 29829 | return UA_Server_init(server); |
| 29830 | } |
| 29831 | |
| 29832 | /* Returns if the server should be shut down immediately */ |
| 29833 | static UA_Boolean |
| 29834 | setServerShutdown(UA_Server *server) { |
| 29835 | if(server->endTime != 0) |
| 29836 | return false; |
| 29837 | if(server->config.shutdownDelay == 0) |
| 29838 | return true; |
| 29839 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 29840 | msg: "Shutting down the server with a delay of %i ms", (int)server->config.shutdownDelay); |
| 29841 | server->endTime = UA_DateTime_now() + (UA_DateTime)(server->config.shutdownDelay * UA_DATETIME_MSEC); |
| 29842 | return false; |
| 29843 | } |
| 29844 | |
| 29845 | /*******************/ |
| 29846 | /* Timed Callbacks */ |
| 29847 | /*******************/ |
| 29848 | |
| 29849 | UA_StatusCode |
| 29850 | UA_Server_addTimedCallback(UA_Server *server, UA_ServerCallback callback, |
| 29851 | void *data, UA_DateTime date, UA_UInt64 *callbackId) { |
| 29852 | lockServer(server); |
| 29853 | UA_StatusCode retval = server->config.eventLoop-> |
| 29854 | addTimedCallback(server->config.eventLoop, (UA_Callback)callback, |
| 29855 | server, data, date, callbackId); |
| 29856 | unlockServer(server); |
| 29857 | return retval; |
| 29858 | } |
| 29859 | |
| 29860 | UA_StatusCode |
| 29861 | addRepeatedCallback(UA_Server *server, UA_ServerCallback callback, |
| 29862 | void *data, UA_Double interval_ms, UA_UInt64 *callbackId) { |
| 29863 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 29864 | return server->config.eventLoop-> |
| 29865 | addCyclicCallback(server->config.eventLoop, (UA_Callback) callback, |
| 29866 | server, data, interval_ms, NULL, |
| 29867 | UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, callbackId); |
| 29868 | } |
| 29869 | |
| 29870 | UA_StatusCode |
| 29871 | UA_Server_addRepeatedCallback(UA_Server *server, UA_ServerCallback callback, |
| 29872 | void *data, UA_Double interval_ms, |
| 29873 | UA_UInt64 *callbackId) { |
| 29874 | lockServer(server); |
| 29875 | UA_StatusCode res = addRepeatedCallback(server, callback, data, interval_ms, callbackId); |
| 29876 | unlockServer(server); |
| 29877 | return res; |
| 29878 | } |
| 29879 | |
| 29880 | UA_StatusCode |
| 29881 | changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId, |
| 29882 | UA_Double interval_ms) { |
| 29883 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 29884 | return server->config.eventLoop-> |
| 29885 | modifyCyclicCallback(server->config.eventLoop, callbackId, interval_ms, |
| 29886 | NULL, UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME); |
| 29887 | } |
| 29888 | |
| 29889 | UA_StatusCode |
| 29890 | UA_Server_changeRepeatedCallbackInterval(UA_Server *server, UA_UInt64 callbackId, |
| 29891 | UA_Double interval_ms) { |
| 29892 | lockServer(server); |
| 29893 | UA_StatusCode retval = |
| 29894 | changeRepeatedCallbackInterval(server, callbackId, interval_ms); |
| 29895 | unlockServer(server); |
| 29896 | return retval; |
| 29897 | } |
| 29898 | |
| 29899 | void |
| 29900 | removeCallback(UA_Server *server, UA_UInt64 callbackId) { |
| 29901 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 29902 | UA_EventLoop *el = server->config.eventLoop; |
| 29903 | if(el) { |
| 29904 | el->removeCyclicCallback(el, callbackId); |
| 29905 | } |
| 29906 | } |
| 29907 | |
| 29908 | void |
| 29909 | UA_Server_removeCallback(UA_Server *server, UA_UInt64 callbackId) { |
| 29910 | lockServer(server); |
| 29911 | removeCallback(server, callbackId); |
| 29912 | unlockServer(server); |
| 29913 | } |
| 29914 | |
| 29915 | static void |
| 29916 | notifySecureChannelsStopped(UA_Server *server, struct UA_ServerComponent *sc, |
| 29917 | UA_LifecycleState state) { |
| 29918 | if(sc->state == UA_LIFECYCLESTATE_STOPPED && |
| 29919 | server->state == UA_LIFECYCLESTATE_STARTED) { |
| 29920 | sc->notifyState = NULL; /* remove the callback */ |
| 29921 | sc->start(server, sc); |
| 29922 | } |
| 29923 | } |
| 29924 | |
| 29925 | UA_StatusCode |
| 29926 | UA_Server_updateCertificate(UA_Server *server, |
| 29927 | const UA_ByteString *oldCertificate, |
| 29928 | const UA_ByteString *newCertificate, |
| 29929 | const UA_ByteString *newPrivateKey, |
| 29930 | UA_Boolean closeSessions, |
| 29931 | UA_Boolean closeSecureChannels) { |
| 29932 | UA_CHECK(server && oldCertificate && newCertificate && newPrivateKey, |
| 29933 | return UA_STATUSCODE_BADINTERNALERROR); |
| 29934 | |
| 29935 | lockServer(server); |
| 29936 | |
| 29937 | if(closeSessions) { |
| 29938 | session_list_entry *current; |
| 29939 | LIST_FOREACH(current, &server->sessions, pointers) { |
| 29940 | UA_SessionHeader *header = ¤t->session.header; |
| 29941 | if(UA_ByteString_equal(p1: oldCertificate, p2: &header->channel->securityPolicy->localCertificate)) |
| 29942 | UA_Server_removeSessionByToken(server, token: &header->authenticationToken, |
| 29943 | shutdownReason: UA_SHUTDOWNREASON_CLOSE); |
| 29944 | } |
| 29945 | } |
| 29946 | |
| 29947 | /* Gracefully close all SecureChannels. And restart the |
| 29948 | * BinaryProtocolManager once it has fully stopped. */ |
| 29949 | if(closeSecureChannels) { |
| 29950 | UA_ServerComponent *binaryProtocolManager = |
| 29951 | getServerComponentByName(server, name: UA_STRING(chars: "binary")); |
| 29952 | if(binaryProtocolManager) { |
| 29953 | binaryProtocolManager->notifyState = notifySecureChannelsStopped; |
| 29954 | binaryProtocolManager->stop(server, binaryProtocolManager); |
| 29955 | } |
| 29956 | } |
| 29957 | |
| 29958 | size_t i = 0; |
| 29959 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 29960 | while(i < server->config.endpointsSize) { |
| 29961 | UA_EndpointDescription *ed = &server->config.endpoints[i]; |
| 29962 | if(UA_ByteString_equal(p1: &ed->serverCertificate, p2: oldCertificate)) { |
| 29963 | UA_String_clear(p: &ed->serverCertificate); |
| 29964 | UA_String_copy(src: newCertificate, dst: &ed->serverCertificate); |
| 29965 | UA_SecurityPolicy *sp = getSecurityPolicyByUri(server, |
| 29966 | securityPolicyUri: &server->config.endpoints[i].securityPolicyUri); |
| 29967 | if(!sp) { |
| 29968 | res = UA_STATUSCODE_BADINTERNALERROR; |
| 29969 | break; |
| 29970 | } |
| 29971 | sp->updateCertificateAndPrivateKey(sp, *newCertificate, *newPrivateKey); |
| 29972 | } |
| 29973 | i++; |
| 29974 | } |
| 29975 | |
| 29976 | unlockServer(server); |
| 29977 | |
| 29978 | return res; |
| 29979 | } |
| 29980 | |
| 29981 | /***************************/ |
| 29982 | /* Server lookup functions */ |
| 29983 | /***************************/ |
| 29984 | |
| 29985 | UA_SecurityPolicy * |
| 29986 | getSecurityPolicyByUri(const UA_Server *server, const UA_ByteString *securityPolicyUri) { |
| 29987 | for(size_t i = 0; i < server->config.securityPoliciesSize; i++) { |
| 29988 | UA_SecurityPolicy *securityPolicyCandidate = &server->config.securityPolicies[i]; |
| 29989 | if(UA_ByteString_equal(p1: securityPolicyUri, p2: &securityPolicyCandidate->policyUri)) |
| 29990 | return securityPolicyCandidate; |
| 29991 | } |
| 29992 | return NULL; |
| 29993 | } |
| 29994 | |
| 29995 | #ifdef UA_ENABLE_ENCRYPTION |
| 29996 | /* The local ApplicationURI has to match the certificates of the |
| 29997 | * SecurityPolicies */ |
| 29998 | static UA_StatusCode |
| 29999 | verifyServerApplicationURI(const UA_Server *server) { |
| 30000 | const UA_String securityPolicyNoneUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None"); |
| 30001 | for(size_t i = 0; i < server->config.securityPoliciesSize; i++) { |
| 30002 | UA_SecurityPolicy *sp = &server->config.securityPolicies[i]; |
| 30003 | if(UA_String_equal(p1: &sp->policyUri, p2: &securityPolicyNoneUri) && (sp->localCertificate.length == 0)) |
| 30004 | continue; |
| 30005 | UA_StatusCode retval = server->config.secureChannelPKI. |
| 30006 | verifyApplicationURI(&server->config.secureChannelPKI, |
| 30007 | &sp->localCertificate, |
| 30008 | &server->config.applicationDescription.applicationUri); |
| 30009 | |
| 30010 | UA_CHECK_STATUS_ERROR(retval, return retval, server->config.logging, UA_LOGCATEGORY_SERVER, |
| 30011 | "The configured ApplicationURI \"%.*s\"does not match the " |
| 30012 | "ApplicationURI specified in the certificate for the " |
| 30013 | "SecurityPolicy %.*s", |
| 30014 | (int)server->config.applicationDescription.applicationUri.length, |
| 30015 | server->config.applicationDescription.applicationUri.data, |
| 30016 | (int)sp->policyUri.length, sp->policyUri.data); |
| 30017 | } |
| 30018 | return UA_STATUSCODE_GOOD; |
| 30019 | } |
| 30020 | #endif |
| 30021 | |
| 30022 | UA_ServerStatistics |
| 30023 | UA_Server_getStatistics(UA_Server *server) { |
| 30024 | UA_ServerStatistics stat; |
| 30025 | lockServer(server); |
| 30026 | stat.scs = server->secureChannelStatistics; |
| 30027 | UA_ServerDiagnosticsSummaryDataType *sds = &server->serverDiagnosticsSummary; |
| 30028 | stat.ss.currentSessionCount = server->activeSessionCount; |
| 30029 | stat.ss.cumulatedSessionCount = sds->cumulatedSessionCount; |
| 30030 | stat.ss.securityRejectedSessionCount = sds->securityRejectedSessionCount; |
| 30031 | stat.ss.rejectedSessionCount = sds->rejectedSessionCount; |
| 30032 | stat.ss.sessionTimeoutCount = sds->sessionTimeoutCount; |
| 30033 | stat.ss.sessionAbortCount = sds->sessionAbortCount; |
| 30034 | unlockServer(server); |
| 30035 | return stat; |
| 30036 | } |
| 30037 | |
| 30038 | /********************/ |
| 30039 | /* Main Server Loop */ |
| 30040 | /********************/ |
| 30041 | |
| 30042 | #define UA_MAXTIMEOUT 500 /* Max timeout in ms between main-loop iterations */ |
| 30043 | |
| 30044 | void |
| 30045 | setServerLifecycleState(UA_Server *server, UA_LifecycleState state) { |
| 30046 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 30047 | if(server->state == state) |
| 30048 | return; |
| 30049 | server->state = state; |
| 30050 | if(server->config.notifyLifecycleState) |
| 30051 | server->config.notifyLifecycleState(server, server->state); |
| 30052 | } |
| 30053 | |
| 30054 | UA_LifecycleState |
| 30055 | UA_Server_getLifecycleState(UA_Server *server) { |
| 30056 | return server->state; |
| 30057 | } |
| 30058 | |
| 30059 | /* Start: Spin up the workers and the network layer and sample the server's |
| 30060 | * start time. |
| 30061 | * Iterate: Process repeated callbacks and events in the network layer. This |
| 30062 | * part can be driven from an external main-loop in an event-driven |
| 30063 | * single-threaded architecture. |
| 30064 | * Stop: Stop workers, finish all callbacks, stop the network layer, clean up */ |
| 30065 | |
| 30066 | UA_StatusCode |
| 30067 | UA_Server_run_startup(UA_Server *server) { |
| 30068 | if(server == NULL) { |
| 30069 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 30070 | } |
| 30071 | UA_ServerConfig *config = &server->config; |
| 30072 | |
| 30073 | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| 30074 | /* Prominently warn user that fuzzing build is enabled. This will tamper |
| 30075 | * with authentication tokens and other important variables E.g. if fuzzing |
| 30076 | * is enabled, and two clients are connected, subscriptions do not work |
| 30077 | * properly, since the tokens will be overridden to allow easier fuzzing. */ |
| 30078 | UA_LOG_FATAL(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 30079 | "Server was built with unsafe fuzzing mode. " |
| 30080 | "This should only be used for specific fuzzing builds."); |
| 30081 | #endif |
| 30082 | |
| 30083 | if(server->state != UA_LIFECYCLESTATE_STOPPED) { |
| 30084 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 30085 | msg: "The server has already been started"); |
| 30086 | return UA_STATUSCODE_BADINTERNALERROR; |
| 30087 | } |
| 30088 | |
| 30089 | /* Check if UserIdentityTokens are defined */ |
| 30090 | bool hasUserIdentityTokens = false; |
| 30091 | for(size_t i = 0; i < config->endpointsSize; i++) { |
| 30092 | if(config->endpoints[i].userIdentityTokensSize > 0) { |
| 30093 | hasUserIdentityTokens = true; |
| 30094 | break; |
| 30095 | } |
| 30096 | } |
| 30097 | if(config->accessControl.userTokenPoliciesSize == 0 && hasUserIdentityTokens == false) { |
| 30098 | UA_LOG_ERROR(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 30099 | msg: "The server has no userIdentificationPolicies defined."); |
| 30100 | return UA_STATUSCODE_BADINTERNALERROR; |
| 30101 | } |
| 30102 | |
| 30103 | /* Start the EventLoop if not already started */ |
| 30104 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 30105 | UA_EventLoop *el = config->eventLoop; |
| 30106 | UA_CHECK_MEM_ERROR(el, return UA_STATUSCODE_BADINTERNALERROR, |
| 30107 | config->logging, UA_LOGCATEGORY_SERVER, |
| 30108 | "An EventLoop must be configured"); |
| 30109 | |
| 30110 | if(el->state != UA_EVENTLOOPSTATE_STARTED) { |
| 30111 | retVal = el->start(el); |
| 30112 | UA_CHECK_STATUS(retVal, return retVal); /* Errors are logged internally */ |
| 30113 | } |
| 30114 | |
| 30115 | /* Take the server lock */ |
| 30116 | lockServer(server); |
| 30117 | |
| 30118 | /* Does the ApplicationURI match the local certificates? */ |
| 30119 | #ifdef UA_ENABLE_ENCRYPTION |
| 30120 | retVal = verifyServerApplicationURI(server); |
| 30121 | UA_CHECK_STATUS(retVal, unlockServer(server); return retVal); |
| 30122 | #endif |
| 30123 | |
| 30124 | /* Are there enough SecureChannels possible for the max number of sessions? */ |
| 30125 | if(config->maxSecureChannels != 0 && |
| 30126 | (config->maxSessions == 0 || config->maxSessions > config->maxSecureChannels)) { |
| 30127 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 30128 | msg: "Maximum SecureChannels count not enough for the " |
| 30129 | "maximum Sessions count"); |
| 30130 | } |
| 30131 | |
| 30132 | /* Add a regular callback for housekeeping tasks. With a 1s interval. */ |
| 30133 | retVal = addRepeatedCallback(server, callback: serverHouseKeeping, |
| 30134 | NULL, interval_ms: 1000.0, callbackId: &server->houseKeepingCallbackId); |
| 30135 | UA_CHECK_STATUS_ERROR(retVal, unlockServer(server); return retVal, |
| 30136 | config->logging, UA_LOGCATEGORY_SERVER, |
| 30137 | "Could not create the server housekeeping task"); |
| 30138 | |
| 30139 | /* Ensure that the uri for ns1 is set up from the app description */ |
| 30140 | UA_String_clear(p: &server->namespaces[1]); |
| 30141 | setupNs1Uri(server); |
| 30142 | |
| 30143 | /* At least one endpoint has to be configured */ |
| 30144 | if(config->endpointsSize == 0) { |
| 30145 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 30146 | msg: "There has to be at least one endpoint."); |
| 30147 | } |
| 30148 | |
| 30149 | /* Update Endpoint description */ |
| 30150 | for(size_t i = 0; i < config->endpointsSize; ++i) { |
| 30151 | UA_ApplicationDescription_clear(p: &config->endpoints[i].server); |
| 30152 | UA_ApplicationDescription_copy(src: &config->applicationDescription, |
| 30153 | dst: &config->endpoints[i].server); |
| 30154 | } |
| 30155 | |
| 30156 | /* Write ServerArray with same ApplicationUri value as NamespaceArray */ |
| 30157 | UA_Variant var; |
| 30158 | UA_Variant_init(p: &var); |
| 30159 | UA_Variant_setArray(v: &var, array: &config->applicationDescription.applicationUri, |
| 30160 | arraySize: 1, type: &UA_TYPES[UA_TYPES_STRING]); |
| 30161 | UA_NodeId serverArray = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERARRAY); |
| 30162 | writeValueAttribute(server, nodeId: serverArray, value: &var); |
| 30163 | |
| 30164 | /* Sample the start time and set it to the Server object */ |
| 30165 | server->startTime = UA_DateTime_now(); |
| 30166 | UA_Variant_init(p: &var); |
| 30167 | UA_Variant_setScalar(v: &var, p: &server->startTime, type: &UA_TYPES[UA_TYPES_DATETIME]); |
| 30168 | UA_NodeId startTime = |
| 30169 | UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME); |
| 30170 | writeValueAttribute(server, nodeId: startTime, value: &var); |
| 30171 | |
| 30172 | /* Start all ServerComponents */ |
| 30173 | ZIP_ITER(UA_ServerComponentTree, &server->serverComponents, |
| 30174 | startServerComponent, server); |
| 30175 | |
| 30176 | /* Check that the binary protocol support component have been started */ |
| 30177 | UA_ServerComponent *binaryProtocolManager = |
| 30178 | getServerComponentByName(server, name: UA_STRING(chars: "binary")); |
| 30179 | if(binaryProtocolManager->state != UA_LIFECYCLESTATE_STARTED) { |
| 30180 | UA_LOG_ERROR(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 30181 | msg: "The binary protocol support component could not been started."); |
| 30182 | /* Stop all server components that have already been started */ |
| 30183 | ZIP_ITER(UA_ServerComponentTree, &server->serverComponents, |
| 30184 | stopServerComponent, server); |
| 30185 | unlockServer(server); |
| 30186 | return UA_STATUSCODE_BADINTERNALERROR; |
| 30187 | } |
| 30188 | |
| 30189 | /* Set the server to STARTED. From here on, only use |
| 30190 | * UA_Server_run_shutdown(server) to stop the server. */ |
| 30191 | setServerLifecycleState(server, state: UA_LIFECYCLESTATE_STARTED); |
| 30192 | |
| 30193 | unlockServer(server); |
| 30194 | return UA_STATUSCODE_GOOD; |
| 30195 | } |
| 30196 | |
| 30197 | UA_UInt16 |
| 30198 | UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) { |
| 30199 | /* Make sure an EventLoop is configured */ |
| 30200 | UA_EventLoop *el = server->config.eventLoop; |
| 30201 | if(!el) |
| 30202 | return 0; |
| 30203 | |
| 30204 | /* Process timed and network events in the EventLoop */ |
| 30205 | UA_UInt32 timeout = (waitInternal) ? UA_MAXTIMEOUT : 0; |
| 30206 | el->run(el, timeout); |
| 30207 | |
| 30208 | /* Return the time until the next scheduled callback */ |
| 30209 | UA_DateTime now = el->dateTime_nowMonotonic(el); |
| 30210 | UA_DateTime nextTimeout = (el->nextCyclicTime(el) - now) / UA_DATETIME_MSEC; |
| 30211 | if(nextTimeout < 0) |
| 30212 | nextTimeout = 0; |
| 30213 | if(nextTimeout > UA_UINT16_MAX) |
| 30214 | nextTimeout = UA_UINT16_MAX; |
| 30215 | return (UA_UInt16)nextTimeout; |
| 30216 | } |
| 30217 | |
| 30218 | static UA_Boolean |
| 30219 | testShutdownCondition(UA_Server *server) { |
| 30220 | /* Was there a wait time until the shutdown configured? */ |
| 30221 | if(server->endTime == 0) |
| 30222 | return false; |
| 30223 | return (UA_DateTime_now() > server->endTime); |
| 30224 | } |
| 30225 | |
| 30226 | static UA_Boolean |
| 30227 | testStoppedCondition(UA_Server *server) { |
| 30228 | /* Check if there are remaining server components that did not fully stop */ |
| 30229 | if(ZIP_ITER(UA_ServerComponentTree, &server->serverComponents, |
| 30230 | checkServerComponent, server) != NULL) |
| 30231 | return false; |
| 30232 | return true; |
| 30233 | } |
| 30234 | |
| 30235 | UA_StatusCode |
| 30236 | UA_Server_run_shutdown(UA_Server *server) { |
| 30237 | if(server == NULL) |
| 30238 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 30239 | |
| 30240 | lockServer(server); |
| 30241 | |
| 30242 | if(server->state != UA_LIFECYCLESTATE_STARTED) { |
| 30243 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 30244 | msg: "The server is not started, cannot be shut down"); |
| 30245 | unlockServer(server); |
| 30246 | return UA_STATUSCODE_BADINTERNALERROR; |
| 30247 | } |
| 30248 | |
| 30249 | /* Set to stopping and notify the application */ |
| 30250 | setServerLifecycleState(server, state: UA_LIFECYCLESTATE_STOPPING); |
| 30251 | |
| 30252 | /* Stop the regular housekeeping tasks */ |
| 30253 | if(server->houseKeepingCallbackId != 0) { |
| 30254 | removeCallback(server, callbackId: server->houseKeepingCallbackId); |
| 30255 | server->houseKeepingCallbackId = 0; |
| 30256 | } |
| 30257 | |
| 30258 | /* Stop PubSub */ |
| 30259 | #ifdef UA_ENABLE_PUBSUB |
| 30260 | UA_PubSubManager_shutdown(server, pubSubManager: &server->pubSubManager); |
| 30261 | #endif |
| 30262 | |
| 30263 | /* Stop all ServerComponents */ |
| 30264 | ZIP_ITER(UA_ServerComponentTree, &server->serverComponents, |
| 30265 | stopServerComponent, server); |
| 30266 | |
| 30267 | /* Are we already stopped? */ |
| 30268 | if(testStoppedCondition(server)) { |
| 30269 | setServerLifecycleState(server, state: UA_LIFECYCLESTATE_STOPPED); |
| 30270 | } |
| 30271 | |
| 30272 | /* Only stop the EventLoop if it is coupled to the server lifecycle */ |
| 30273 | if(server->config.externalEventLoop) { |
| 30274 | unlockServer(server); |
| 30275 | return UA_STATUSCODE_GOOD; |
| 30276 | } |
| 30277 | |
| 30278 | /* Iterate the EventLoop until the server is stopped */ |
| 30279 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 30280 | UA_EventLoop *el = server->config.eventLoop; |
| 30281 | while(!testStoppedCondition(server) && |
| 30282 | res == UA_STATUSCODE_GOOD) { |
| 30283 | res = el->run(el, 100); |
| 30284 | } |
| 30285 | |
| 30286 | /* Stop the EventLoop. Iterate until stopped. */ |
| 30287 | el->stop(el); |
| 30288 | while(el->state != UA_EVENTLOOPSTATE_STOPPED && |
| 30289 | el->state != UA_EVENTLOOPSTATE_FRESH && |
| 30290 | res == UA_STATUSCODE_GOOD) { |
| 30291 | res = el->run(el, 100); |
| 30292 | } |
| 30293 | |
| 30294 | /* Set server lifecycle state to stopped if not already the case */ |
| 30295 | setServerLifecycleState(server, state: UA_LIFECYCLESTATE_STOPPED); |
| 30296 | |
| 30297 | unlockServer(server); |
| 30298 | return res; |
| 30299 | } |
| 30300 | |
| 30301 | UA_StatusCode |
| 30302 | UA_Server_run(UA_Server *server, const volatile UA_Boolean *running) { |
| 30303 | UA_StatusCode retval = UA_Server_run_startup(server); |
| 30304 | UA_CHECK_STATUS(retval, return retval); |
| 30305 | |
| 30306 | while(!testShutdownCondition(server)) { |
| 30307 | UA_Server_run_iterate(server, true); |
| 30308 | if(!*running) { |
| 30309 | if(setServerShutdown(server)) |
| 30310 | break; |
| 30311 | } |
| 30312 | } |
| 30313 | return UA_Server_run_shutdown(server); |
| 30314 | } |
| 30315 | |
| 30316 | void lockServer(UA_Server *server) { |
| 30317 | if(UA_LIKELY(server->config.eventLoop && server->config.eventLoop->lock)) |
| 30318 | server->config.eventLoop->lock(server->config.eventLoop); |
| 30319 | UA_LOCK(&server->serviceMutex); |
| 30320 | } |
| 30321 | |
| 30322 | void unlockServer(UA_Server *server) { |
| 30323 | if(UA_LIKELY(server->config.eventLoop && server->config.eventLoop->unlock)) |
| 30324 | server->config.eventLoop->unlock(server->config.eventLoop); |
| 30325 | UA_UNLOCK(&server->serviceMutex); |
| 30326 | } |
| 30327 | |
| 30328 | /**** amalgamated original file "/src/server/ua_server_ns0.c" ****/ |
| 30329 | |
| 30330 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 30331 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 30332 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 30333 | * |
| 30334 | * Copyright 2017-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 30335 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 30336 | * Copyright 2017 (c) Thomas Bender |
| 30337 | * Copyright 2017 (c) Julian Grothoff |
| 30338 | * Copyright 2017 (c) Henrik Norrman |
| 30339 | * Copyright 2018 (c) Fabian Arndt, Root-Core |
| 30340 | * Copyright 2019 (c) Kalycito Infotech Private Limited |
| 30341 | * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 30342 | * Copyright 2023 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
| 30343 | */ |
| 30344 | |
| 30345 | |
| 30346 | |
| 30347 | static UA_StatusCode |
| 30348 | ns0_addNode_raw(UA_Server *server, UA_NodeClass nodeClass, |
| 30349 | UA_UInt32 nodeId, char *name, void *attributes, |
| 30350 | const UA_DataType *attributesType) { |
| 30351 | UA_AddNodesItem item; |
| 30352 | UA_AddNodesItem_init(p: &item); |
| 30353 | item.nodeClass = nodeClass; |
| 30354 | item.requestedNewNodeId.nodeId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: nodeId); |
| 30355 | item.browseName = UA_QUALIFIEDNAME(nsIndex: 0, chars: name); |
| 30356 | UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes, |
| 30357 | p: attributes, type: attributesType); |
| 30358 | return addNode_raw(server, session: &server->adminSession, NULL, item: &item, NULL); |
| 30359 | } |
| 30360 | |
| 30361 | static UA_StatusCode |
| 30362 | ns0_addNode_finish(UA_Server *server, UA_UInt32 nodeId, |
| 30363 | UA_UInt32 parentNodeId, UA_UInt32 referenceTypeId) { |
| 30364 | const UA_NodeId sourceId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: nodeId); |
| 30365 | const UA_NodeId refTypeId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: referenceTypeId); |
| 30366 | const UA_NodeId targetId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: parentNodeId); |
| 30367 | UA_StatusCode retval = addRef(server, sourceId, referenceTypeId: refTypeId, targetId, false); |
| 30368 | if(retval != UA_STATUSCODE_GOOD) |
| 30369 | return retval; |
| 30370 | return addNode_finish(server, session: &server->adminSession, nodeId: &sourceId); |
| 30371 | } |
| 30372 | |
| 30373 | static UA_StatusCode |
| 30374 | addObjectNode(UA_Server *server, char* name, UA_UInt32 objectid, |
| 30375 | UA_UInt32 parentid, UA_UInt32 referenceid, UA_UInt32 type_id) { |
| 30376 | UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; |
| 30377 | object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name); |
| 30378 | return addNode(server, nodeClass: UA_NODECLASS_OBJECT, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: objectid), |
| 30379 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: parentid), referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: referenceid), |
| 30380 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name), typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, identifier: type_id), |
| 30381 | attr: &object_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 30382 | NULL, NULL); |
| 30383 | } |
| 30384 | |
| 30385 | static UA_StatusCode |
| 30386 | addReferenceTypeNode(UA_Server *server, char* name, char *inverseName, UA_UInt32 referencetypeid, |
| 30387 | UA_Boolean isabstract, UA_Boolean symmetric, UA_UInt32 parentid) { |
| 30388 | UA_ReferenceTypeAttributes reference_attr = UA_ReferenceTypeAttributes_default; |
| 30389 | reference_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name); |
| 30390 | reference_attr.isAbstract = isabstract; |
| 30391 | reference_attr.symmetric = symmetric; |
| 30392 | if(inverseName) |
| 30393 | reference_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: inverseName); |
| 30394 | return addNode(server, nodeClass: UA_NODECLASS_REFERENCETYPE, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: referencetypeid), |
| 30395 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: parentid), referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name), |
| 30396 | typeDefinition: UA_NODEID_NULL, attr: &reference_attr, |
| 30397 | attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES], NULL, NULL); |
| 30398 | } |
| 30399 | |
| 30400 | /***************************/ |
| 30401 | /* Bootstrap NS0 hierarchy */ |
| 30402 | /***************************/ |
| 30403 | |
| 30404 | /* Creates the basic nodes which are expected by the nodeset compiler to be |
| 30405 | * already created. This is necessary to reduce the dependencies for the nodeset |
| 30406 | * compiler. */ |
| 30407 | static UA_StatusCode |
| 30408 | createNS0_base(UA_Server *server) { |
| 30409 | /* Bootstrap ReferenceTypes. The order of these is important for the |
| 30410 | * ReferenceTypeIndex. The ReferenceTypeIndex is created with the raw node. |
| 30411 | * The ReferenceTypeSet of subtypes for every ReferenceType is created |
| 30412 | * during the call to AddNode_finish. */ |
| 30413 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 30414 | UA_ReferenceTypeAttributes references_attr = UA_ReferenceTypeAttributes_default; |
| 30415 | references_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "References"); |
| 30416 | references_attr.isAbstract = true; |
| 30417 | references_attr.symmetric = true; |
| 30418 | references_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "References"); |
| 30419 | ret |= ns0_addNode_raw(server, nodeClass: UA_NODECLASS_REFERENCETYPE, UA_NS0ID_REFERENCES, name: "References", |
| 30420 | attributes: &references_attr, attributesType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]); |
| 30421 | |
| 30422 | UA_ReferenceTypeAttributes hassubtype_attr = UA_ReferenceTypeAttributes_default; |
| 30423 | hassubtype_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasSubtype"); |
| 30424 | hassubtype_attr.isAbstract = false; |
| 30425 | hassubtype_attr.symmetric = false; |
| 30426 | hassubtype_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "SubtypeOf"); |
| 30427 | ret |= ns0_addNode_raw(server, nodeClass: UA_NODECLASS_REFERENCETYPE, UA_NS0ID_HASSUBTYPE, name: "HasSubtype", |
| 30428 | attributes: &hassubtype_attr, attributesType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]); |
| 30429 | |
| 30430 | UA_ReferenceTypeAttributes aggregates_attr = UA_ReferenceTypeAttributes_default; |
| 30431 | aggregates_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Aggregates"); |
| 30432 | aggregates_attr.isAbstract = true; |
| 30433 | aggregates_attr.symmetric = false; |
| 30434 | aggregates_attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "AggregatedBy"); |
| 30435 | ret |= ns0_addNode_raw(server, nodeClass: UA_NODECLASS_REFERENCETYPE, UA_NS0ID_AGGREGATES, name: "Aggregates", |
| 30436 | attributes: &aggregates_attr, attributesType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES]); |
| 30437 | |
| 30438 | ret |= addReferenceTypeNode(server, name: "HierarchicalReferences", NULL, |
| 30439 | UA_NS0ID_HIERARCHICALREFERENCES, true, false, UA_NS0ID_REFERENCES); |
| 30440 | |
| 30441 | ret |= addReferenceTypeNode(server, name: "NonHierarchicalReferences", NULL, |
| 30442 | UA_NS0ID_NONHIERARCHICALREFERENCES, true, true, UA_NS0ID_REFERENCES); |
| 30443 | |
| 30444 | ret |= addReferenceTypeNode(server, name: "HasChild", NULL, UA_NS0ID_HASCHILD, |
| 30445 | true, false, UA_NS0ID_HIERARCHICALREFERENCES); |
| 30446 | |
| 30447 | ret |= addReferenceTypeNode(server, name: "Organizes", inverseName: "OrganizedBy", UA_NS0ID_ORGANIZES, |
| 30448 | false, false, UA_NS0ID_HIERARCHICALREFERENCES); |
| 30449 | |
| 30450 | ret |= addReferenceTypeNode(server, name: "HasEventSource", inverseName: "EventSourceOf", UA_NS0ID_HASEVENTSOURCE, |
| 30451 | false, false, UA_NS0ID_HIERARCHICALREFERENCES); |
| 30452 | |
| 30453 | ret |= addReferenceTypeNode(server, name: "HasModellingRule", inverseName: "ModellingRuleOf", UA_NS0ID_HASMODELLINGRULE, |
| 30454 | false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
| 30455 | |
| 30456 | ret |= addReferenceTypeNode(server, name: "HasEncoding", inverseName: "EncodingOf", UA_NS0ID_HASENCODING, |
| 30457 | false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
| 30458 | |
| 30459 | ret |= addReferenceTypeNode(server, name: "HasDescription", inverseName: "DescriptionOf", UA_NS0ID_HASDESCRIPTION, |
| 30460 | false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
| 30461 | |
| 30462 | ret |= addReferenceTypeNode(server, name: "HasTypeDefinition", inverseName: "TypeDefinitionOf", UA_NS0ID_HASTYPEDEFINITION, |
| 30463 | false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
| 30464 | |
| 30465 | ret |= addReferenceTypeNode(server, name: "GeneratesEvent", inverseName: "GeneratedBy", UA_NS0ID_GENERATESEVENT, |
| 30466 | false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
| 30467 | |
| 30468 | /* Complete bootstrap of Aggregates */ |
| 30469 | ret |= ns0_addNode_finish(server, UA_NS0ID_AGGREGATES, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE); |
| 30470 | |
| 30471 | /* Complete bootstrap of HasSubtype */ |
| 30472 | ret |= ns0_addNode_finish(server, UA_NS0ID_HASSUBTYPE, UA_NS0ID_HASCHILD, UA_NS0ID_HASSUBTYPE); |
| 30473 | |
| 30474 | ret |= addReferenceTypeNode(server, name: "HasProperty", inverseName: "PropertyOf", UA_NS0ID_HASPROPERTY, |
| 30475 | false, false, UA_NS0ID_AGGREGATES); |
| 30476 | |
| 30477 | ret |= addReferenceTypeNode(server, name: "HasComponent", inverseName: "ComponentOf", UA_NS0ID_HASCOMPONENT, |
| 30478 | false, false, UA_NS0ID_AGGREGATES); |
| 30479 | |
| 30480 | ret |= addReferenceTypeNode(server, name: "HasNotifier", inverseName: "NotifierOf", UA_NS0ID_HASNOTIFIER, |
| 30481 | false, false, UA_NS0ID_HASEVENTSOURCE); |
| 30482 | |
| 30483 | ret |= addReferenceTypeNode(server, name: "HasOrderedComponent", inverseName: "OrderedComponentOf", |
| 30484 | UA_NS0ID_HASORDEREDCOMPONENT, false, false, UA_NS0ID_HASCOMPONENT); |
| 30485 | |
| 30486 | ret |= addReferenceTypeNode(server, name: "HasInterface", inverseName: "InterfaceOf", |
| 30487 | UA_NS0ID_HASINTERFACE, false, false, UA_NS0ID_NONHIERARCHICALREFERENCES); |
| 30488 | |
| 30489 | /**************/ |
| 30490 | /* Data Types */ |
| 30491 | /**************/ |
| 30492 | |
| 30493 | /* Bootstrap BaseDataType */ |
| 30494 | UA_DataTypeAttributes basedatatype_attr = UA_DataTypeAttributes_default; |
| 30495 | basedatatype_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseDataType"); |
| 30496 | basedatatype_attr.isAbstract = true; |
| 30497 | ret |= ns0_addNode_raw(server, nodeClass: UA_NODECLASS_DATATYPE, UA_NS0ID_BASEDATATYPE, name: "BaseDataType", |
| 30498 | attributes: &basedatatype_attr, attributesType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES]); |
| 30499 | |
| 30500 | /*****************/ |
| 30501 | /* VariableTypes */ |
| 30502 | /*****************/ |
| 30503 | |
| 30504 | UA_VariableTypeAttributes basevar_attr = UA_VariableTypeAttributes_default; |
| 30505 | basevar_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseVariableType"); |
| 30506 | basevar_attr.isAbstract = true; |
| 30507 | basevar_attr.valueRank = UA_VALUERANK_ANY; |
| 30508 | basevar_attr.dataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATATYPE); |
| 30509 | ret |= ns0_addNode_raw(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 30510 | UA_NS0ID_BASEVARIABLETYPE, name: "BaseVariableType", |
| 30511 | attributes: &basevar_attr, attributesType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES]); |
| 30512 | |
| 30513 | UA_VariableTypeAttributes bdv_attr = UA_VariableTypeAttributes_default; |
| 30514 | bdv_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseDataVariableType"); |
| 30515 | bdv_attr.dataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATATYPE); |
| 30516 | bdv_attr.valueRank = UA_VALUERANK_ANY; |
| 30517 | ret |= addNode(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 30518 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATAVARIABLETYPE), |
| 30519 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEVARIABLETYPE), |
| 30520 | referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "BaseDataVariableType"), |
| 30521 | typeDefinition: UA_NODEID_NULL, attr: &bdv_attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], |
| 30522 | NULL, NULL); |
| 30523 | |
| 30524 | UA_VariableTypeAttributes prop_attr = UA_VariableTypeAttributes_default; |
| 30525 | prop_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PropertyType"); |
| 30526 | prop_attr.dataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATATYPE); |
| 30527 | prop_attr.valueRank = UA_VALUERANK_ANY; |
| 30528 | ret |= addNode(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 30529 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PROPERTYTYPE), |
| 30530 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEVARIABLETYPE), |
| 30531 | referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PropertyType"), |
| 30532 | typeDefinition: UA_NODEID_NULL, attr: &prop_attr, |
| 30533 | attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES], NULL, NULL); |
| 30534 | |
| 30535 | /***************/ |
| 30536 | /* ObjectTypes */ |
| 30537 | /***************/ |
| 30538 | |
| 30539 | UA_ObjectTypeAttributes baseobj_attr = UA_ObjectTypeAttributes_default; |
| 30540 | baseobj_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseObjectType"); |
| 30541 | ret |= ns0_addNode_raw(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 30542 | UA_NS0ID_BASEOBJECTTYPE, name: "BaseObjectType", |
| 30543 | attributes: &baseobj_attr, attributesType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES]); |
| 30544 | |
| 30545 | UA_ObjectTypeAttributes folder_attr = UA_ObjectTypeAttributes_default; |
| 30546 | folder_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FolderType"); |
| 30547 | ret |= addNode(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 30548 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_FOLDERTYPE), |
| 30549 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE), |
| 30550 | referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "FolderType"), |
| 30551 | typeDefinition: UA_NODEID_NULL, |
| 30552 | attr: &folder_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], NULL, NULL); |
| 30553 | |
| 30554 | /******************/ |
| 30555 | /* Root and below */ |
| 30556 | /******************/ |
| 30557 | |
| 30558 | ret |= addObjectNode(server, name: "Root", UA_NS0ID_ROOTFOLDER, parentid: 0, referenceid: 0, UA_NS0ID_FOLDERTYPE); |
| 30559 | |
| 30560 | ret |= addObjectNode(server, name: "Objects", UA_NS0ID_OBJECTSFOLDER, UA_NS0ID_ROOTFOLDER, |
| 30561 | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
| 30562 | |
| 30563 | ret |= addObjectNode(server, name: "Types", UA_NS0ID_TYPESFOLDER, UA_NS0ID_ROOTFOLDER, |
| 30564 | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
| 30565 | |
| 30566 | ret |= addObjectNode(server, name: "ReferenceTypes", UA_NS0ID_REFERENCETYPESFOLDER, UA_NS0ID_TYPESFOLDER, |
| 30567 | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
| 30568 | ret |= ns0_addNode_finish(server, UA_NS0ID_REFERENCES, |
| 30569 | UA_NS0ID_REFERENCETYPESFOLDER, UA_NS0ID_ORGANIZES); |
| 30570 | |
| 30571 | ret |= addObjectNode(server, name: "DataTypes", UA_NS0ID_DATATYPESFOLDER, UA_NS0ID_TYPESFOLDER, |
| 30572 | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
| 30573 | ret |= ns0_addNode_finish(server, UA_NS0ID_BASEDATATYPE, |
| 30574 | UA_NS0ID_DATATYPESFOLDER, UA_NS0ID_ORGANIZES); |
| 30575 | |
| 30576 | ret |= addObjectNode(server, name: "VariableTypes", UA_NS0ID_VARIABLETYPESFOLDER, UA_NS0ID_TYPESFOLDER, |
| 30577 | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
| 30578 | ret |= ns0_addNode_finish(server, UA_NS0ID_BASEVARIABLETYPE, |
| 30579 | UA_NS0ID_VARIABLETYPESFOLDER, UA_NS0ID_ORGANIZES); |
| 30580 | |
| 30581 | ret |= addObjectNode(server, name: "ObjectTypes", UA_NS0ID_OBJECTTYPESFOLDER, UA_NS0ID_TYPESFOLDER, |
| 30582 | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
| 30583 | ret |= ns0_addNode_finish(server, UA_NS0ID_BASEOBJECTTYPE, |
| 30584 | UA_NS0ID_OBJECTTYPESFOLDER, UA_NS0ID_ORGANIZES); |
| 30585 | |
| 30586 | ret |= addObjectNode(server, name: "EventTypes", UA_NS0ID_EVENTTYPESFOLDER, UA_NS0ID_TYPESFOLDER, |
| 30587 | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
| 30588 | |
| 30589 | ret |= addObjectNode(server, name: "Views", UA_NS0ID_VIEWSFOLDER, UA_NS0ID_ROOTFOLDER, |
| 30590 | UA_NS0ID_ORGANIZES, UA_NS0ID_FOLDERTYPE); |
| 30591 | |
| 30592 | /* Add BaseEventType */ |
| 30593 | UA_ObjectTypeAttributes eventtype_attr = UA_ObjectTypeAttributes_default; |
| 30594 | eventtype_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseEventType"); |
| 30595 | ret |= addNode(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 30596 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE), |
| 30597 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE), |
| 30598 | referenceTypeId: UA_NODEID_NULL, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "BaseEventType"), |
| 30599 | typeDefinition: UA_NODEID_NULL, |
| 30600 | attr: &eventtype_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES], NULL, NULL); |
| 30601 | ret |= addRef(server, |
| 30602 | sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_EVENTTYPESFOLDER), |
| 30603 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_ORGANIZES), |
| 30604 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE), true); |
| 30605 | |
| 30606 | if(ret != UA_STATUSCODE_GOOD) |
| 30607 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 30608 | |
| 30609 | return ret; |
| 30610 | } |
| 30611 | |
| 30612 | /****************/ |
| 30613 | /* Data Sources */ |
| 30614 | /****************/ |
| 30615 | |
| 30616 | static UA_StatusCode |
| 30617 | writeStatus(UA_Server *server, const UA_NodeId *sessionId, |
| 30618 | void *sessionContext, const UA_NodeId *nodeId, |
| 30619 | void *nodeContext, const UA_NumericRange *range, |
| 30620 | const UA_DataValue *value) { |
| 30621 | if(range) |
| 30622 | return UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 30623 | |
| 30624 | if(nodeId->identifier.numeric != UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN) |
| 30625 | return UA_STATUSCODE_BADINTERNALERROR; |
| 30626 | |
| 30627 | /* Only the local user can write into this variable */ |
| 30628 | if(sessionId != &server->adminSession.sessionId) |
| 30629 | return UA_STATUSCODE_BADUSERACCESSDENIED; |
| 30630 | |
| 30631 | if(!UA_Variant_hasScalarType(v: &value->value, type: &UA_TYPES[UA_TYPES_UINT32])) |
| 30632 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 30633 | |
| 30634 | UA_UInt32 *endTime = (UA_UInt32*)value->value.data; |
| 30635 | server->endTime = UA_DateTime_now() + (UA_DateTime)(*endTime * UA_DATETIME_SEC); |
| 30636 | return UA_STATUSCODE_GOOD; |
| 30637 | } |
| 30638 | |
| 30639 | static UA_StatusCode |
| 30640 | readStatus(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 30641 | const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp, |
| 30642 | const UA_NumericRange *range, UA_DataValue *value) { |
| 30643 | if(range) { |
| 30644 | value->hasStatus = true; |
| 30645 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 30646 | return UA_STATUSCODE_GOOD; |
| 30647 | } |
| 30648 | |
| 30649 | if(sourceTimestamp) { |
| 30650 | value->hasSourceTimestamp = true; |
| 30651 | value->sourceTimestamp = UA_DateTime_now(); |
| 30652 | } |
| 30653 | |
| 30654 | void *data = NULL; |
| 30655 | |
| 30656 | UA_assert(nodeId->identifierType == UA_NODEIDTYPE_NUMERIC); |
| 30657 | |
| 30658 | switch(nodeId->identifier.numeric) { |
| 30659 | case UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN: { |
| 30660 | UA_UInt32 *shutdown = UA_UInt32_new(); |
| 30661 | if(!shutdown) |
| 30662 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 30663 | if(server->endTime != 0) |
| 30664 | *shutdown = (UA_UInt32)((server->endTime - UA_DateTime_now()) / UA_DATETIME_SEC); |
| 30665 | value->value.data = shutdown; |
| 30666 | value->value.type = &UA_TYPES[UA_TYPES_UINT32]; |
| 30667 | value->hasValue = true; |
| 30668 | return UA_STATUSCODE_GOOD; |
| 30669 | } |
| 30670 | |
| 30671 | case UA_NS0ID_SERVER_SERVERSTATUS_STATE: { |
| 30672 | UA_ServerState *state = UA_ServerState_new(); |
| 30673 | if(!state) |
| 30674 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 30675 | if(server->endTime != 0) |
| 30676 | *state = UA_SERVERSTATE_SHUTDOWN; |
| 30677 | value->value.data = state; |
| 30678 | value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATE]; |
| 30679 | value->hasValue = true; |
| 30680 | return UA_STATUSCODE_GOOD; |
| 30681 | } |
| 30682 | |
| 30683 | case UA_NS0ID_SERVER_SERVERSTATUS: { |
| 30684 | UA_ServerStatusDataType *statustype = UA_ServerStatusDataType_new(); |
| 30685 | if(!statustype) |
| 30686 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 30687 | statustype->startTime = server->startTime; |
| 30688 | statustype->currentTime = UA_DateTime_now(); |
| 30689 | |
| 30690 | statustype->state = UA_SERVERSTATE_RUNNING; |
| 30691 | statustype->secondsTillShutdown = 0; |
| 30692 | if(server->endTime != 0) { |
| 30693 | statustype->state = UA_SERVERSTATE_SHUTDOWN; |
| 30694 | statustype->secondsTillShutdown = (UA_UInt32) |
| 30695 | ((server->endTime - UA_DateTime_now()) / UA_DATETIME_SEC); |
| 30696 | } |
| 30697 | |
| 30698 | value->value.data = statustype; |
| 30699 | value->value.type = &UA_TYPES[UA_TYPES_SERVERSTATUSDATATYPE]; |
| 30700 | value->hasValue = true; |
| 30701 | return UA_BuildInfo_copy(src: &server->config.buildInfo, dst: &statustype->buildInfo); |
| 30702 | } |
| 30703 | |
| 30704 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO: |
| 30705 | value->value.type = &UA_TYPES[UA_TYPES_BUILDINFO]; |
| 30706 | data = &server->config.buildInfo; |
| 30707 | break; |
| 30708 | |
| 30709 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI: |
| 30710 | value->value.type = &UA_TYPES[UA_TYPES_STRING]; |
| 30711 | data = &server->config.buildInfo.productUri; |
| 30712 | break; |
| 30713 | |
| 30714 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME: |
| 30715 | value->value.type = &UA_TYPES[UA_TYPES_STRING]; |
| 30716 | data = &server->config.buildInfo.manufacturerName; |
| 30717 | break; |
| 30718 | |
| 30719 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME: |
| 30720 | value->value.type = &UA_TYPES[UA_TYPES_STRING]; |
| 30721 | data = &server->config.buildInfo.productName; |
| 30722 | break; |
| 30723 | |
| 30724 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION: |
| 30725 | value->value.type = &UA_TYPES[UA_TYPES_STRING]; |
| 30726 | data = &server->config.buildInfo.softwareVersion; |
| 30727 | break; |
| 30728 | |
| 30729 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER: |
| 30730 | value->value.type = &UA_TYPES[UA_TYPES_STRING]; |
| 30731 | data = &server->config.buildInfo.buildNumber; |
| 30732 | break; |
| 30733 | |
| 30734 | case UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE: |
| 30735 | value->value.type = &UA_TYPES[UA_TYPES_DATETIME]; |
| 30736 | data = &server->config.buildInfo.buildDate; |
| 30737 | break; |
| 30738 | |
| 30739 | default: |
| 30740 | value->hasStatus = true; |
| 30741 | value->status = UA_STATUSCODE_BADINTERNALERROR; |
| 30742 | return UA_STATUSCODE_GOOD; |
| 30743 | } |
| 30744 | |
| 30745 | value->value.data = UA_new(type: value->value.type); |
| 30746 | if(!value->value.data) { |
| 30747 | value->value.type = NULL; |
| 30748 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 30749 | } |
| 30750 | |
| 30751 | value->hasValue = true; |
| 30752 | return UA_copy(src: data, dst: value->value.data, type: value->value.type); |
| 30753 | } |
| 30754 | |
| 30755 | #ifdef UA_GENERATED_NAMESPACE_ZERO |
| 30756 | static UA_StatusCode |
| 30757 | readServiceLevel(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 30758 | const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp, |
| 30759 | const UA_NumericRange *range, UA_DataValue *value) { |
| 30760 | if(range) { |
| 30761 | value->hasStatus = true; |
| 30762 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 30763 | return UA_STATUSCODE_GOOD; |
| 30764 | } |
| 30765 | |
| 30766 | value->value.type = &UA_TYPES[UA_TYPES_BYTE]; |
| 30767 | value->value.arrayLength = 0; |
| 30768 | UA_Byte *byte = UA_Byte_new(); |
| 30769 | *byte = 255; |
| 30770 | value->value.data = byte; |
| 30771 | value->value.arrayDimensionsSize = 0; |
| 30772 | value->value.arrayDimensions = NULL; |
| 30773 | value->hasValue = true; |
| 30774 | if(includeSourceTimeStamp) { |
| 30775 | value->hasSourceTimestamp = true; |
| 30776 | value->sourceTimestamp = UA_DateTime_now(); |
| 30777 | } |
| 30778 | return UA_STATUSCODE_GOOD; |
| 30779 | } |
| 30780 | |
| 30781 | static UA_StatusCode |
| 30782 | readAuditing(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 30783 | const UA_NodeId *nodeId, void *nodeContext, UA_Boolean includeSourceTimeStamp, |
| 30784 | const UA_NumericRange *range, UA_DataValue *value) { |
| 30785 | if(range) { |
| 30786 | value->hasStatus = true; |
| 30787 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 30788 | return UA_STATUSCODE_GOOD; |
| 30789 | } |
| 30790 | |
| 30791 | value->value.type = &UA_TYPES[UA_TYPES_BOOLEAN]; |
| 30792 | value->value.arrayLength = 0; |
| 30793 | UA_Boolean *boolean = UA_Boolean_new(); |
| 30794 | *boolean = false; |
| 30795 | value->value.data = boolean; |
| 30796 | value->value.arrayDimensionsSize = 0; |
| 30797 | value->value.arrayDimensions = NULL; |
| 30798 | value->hasValue = true; |
| 30799 | if(includeSourceTimeStamp) { |
| 30800 | value->hasSourceTimestamp = true; |
| 30801 | value->sourceTimestamp = UA_DateTime_now(); |
| 30802 | } |
| 30803 | return UA_STATUSCODE_GOOD; |
| 30804 | } |
| 30805 | #endif |
| 30806 | |
| 30807 | static UA_StatusCode |
| 30808 | readNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 30809 | const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp, |
| 30810 | const UA_NumericRange *range, |
| 30811 | UA_DataValue *value) { |
| 30812 | /* ensure that the uri for ns1 is set up from the app description */ |
| 30813 | setupNs1Uri(server); |
| 30814 | |
| 30815 | if(range) { |
| 30816 | value->hasStatus = true; |
| 30817 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 30818 | return UA_STATUSCODE_GOOD; |
| 30819 | } |
| 30820 | UA_StatusCode retval; |
| 30821 | retval = UA_Variant_setArrayCopy(v: &value->value, array: server->namespaces, |
| 30822 | arraySize: server->namespacesSize, type: &UA_TYPES[UA_TYPES_STRING]); |
| 30823 | if(retval != UA_STATUSCODE_GOOD) |
| 30824 | return retval; |
| 30825 | value->hasValue = true; |
| 30826 | if(includeSourceTimeStamp) { |
| 30827 | value->hasSourceTimestamp = true; |
| 30828 | value->sourceTimestamp = UA_DateTime_now(); |
| 30829 | } |
| 30830 | return UA_STATUSCODE_GOOD; |
| 30831 | } |
| 30832 | |
| 30833 | static UA_StatusCode |
| 30834 | writeNamespaces(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 30835 | const UA_NodeId *nodeid, void *nodeContext, const UA_NumericRange *range, |
| 30836 | const UA_DataValue *value) { |
| 30837 | /* Check the data type */ |
| 30838 | if(!value->hasValue || |
| 30839 | value->value.type != &UA_TYPES[UA_TYPES_STRING]) |
| 30840 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 30841 | |
| 30842 | /* Check that the variant is not empty */ |
| 30843 | if(!value->value.data) |
| 30844 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 30845 | |
| 30846 | /* TODO: Writing with a range is not implemented */ |
| 30847 | if(range) |
| 30848 | return UA_STATUSCODE_BADINTERNALERROR; |
| 30849 | |
| 30850 | UA_String *newNamespaces = (UA_String*)value->value.data; |
| 30851 | size_t newNamespacesSize = value->value.arrayLength; |
| 30852 | |
| 30853 | /* Test if we append to the existing namespaces */ |
| 30854 | if(newNamespacesSize <= server->namespacesSize) |
| 30855 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 30856 | |
| 30857 | /* ensure that the uri for ns1 is set up from the app description */ |
| 30858 | setupNs1Uri(server); |
| 30859 | |
| 30860 | /* Test if the existing namespaces are unchanged */ |
| 30861 | for(size_t i = 0; i < server->namespacesSize; ++i) { |
| 30862 | if(!UA_String_equal(p1: &server->namespaces[i], p2: &newNamespaces[i])) |
| 30863 | return UA_STATUSCODE_BADINTERNALERROR; |
| 30864 | } |
| 30865 | |
| 30866 | /* Add namespaces */ |
| 30867 | for(size_t i = server->namespacesSize; i < newNamespacesSize; ++i) |
| 30868 | addNamespace(server, name: newNamespaces[i]); |
| 30869 | return UA_STATUSCODE_GOOD; |
| 30870 | } |
| 30871 | |
| 30872 | static UA_StatusCode |
| 30873 | readCurrentTime(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 30874 | const UA_NodeId *nodeid, void *nodeContext, UA_Boolean sourceTimeStamp, |
| 30875 | const UA_NumericRange *range, UA_DataValue *value) { |
| 30876 | if(range) { |
| 30877 | value->hasStatus = true; |
| 30878 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 30879 | return UA_STATUSCODE_GOOD; |
| 30880 | } |
| 30881 | UA_DateTime currentTime = UA_DateTime_now(); |
| 30882 | UA_StatusCode retval = UA_Variant_setScalarCopy(v: &value->value, p: ¤tTime, |
| 30883 | type: &UA_TYPES[UA_TYPES_DATETIME]); |
| 30884 | if(retval != UA_STATUSCODE_GOOD) |
| 30885 | return retval; |
| 30886 | value->hasValue = true; |
| 30887 | if(sourceTimeStamp) { |
| 30888 | value->hasSourceTimestamp = true; |
| 30889 | value->sourceTimestamp = currentTime; |
| 30890 | } |
| 30891 | return UA_STATUSCODE_GOOD; |
| 30892 | } |
| 30893 | |
| 30894 | #ifdef UA_GENERATED_NAMESPACE_ZERO |
| 30895 | static UA_StatusCode |
| 30896 | readOperationLimits(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 30897 | const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp, |
| 30898 | const UA_NumericRange *range, |
| 30899 | UA_DataValue *value) { |
| 30900 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 30901 | if(nodeid->identifierType != UA_NODEIDTYPE_NUMERIC) |
| 30902 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 30903 | switch(nodeid->identifier.numeric) { |
| 30904 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREAD: |
| 30905 | retval = UA_Variant_setScalarCopy(v: &value->value, p: &server->config.maxNodesPerRead, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 30906 | break; |
| 30907 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERWRITE: |
| 30908 | retval = UA_Variant_setScalarCopy(v: &value->value, p: &server->config.maxNodesPerWrite, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 30909 | break; |
| 30910 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERMETHODCALL: |
| 30911 | retval = UA_Variant_setScalarCopy(v: &value->value, p: &server->config.maxNodesPerMethodCall, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 30912 | break; |
| 30913 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERBROWSE: |
| 30914 | retval = UA_Variant_setScalarCopy(v: &value->value, p: &server->config.maxNodesPerBrowse, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 30915 | break; |
| 30916 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREGISTERNODES: |
| 30917 | retval = UA_Variant_setScalarCopy(v: &value->value, p: &server->config.maxNodesPerRegisterNodes, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 30918 | break; |
| 30919 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERTRANSLATEBROWSEPATHSTONODEIDS: |
| 30920 | retval = UA_Variant_setScalarCopy(v: &value->value, p: &server->config.maxNodesPerTranslateBrowsePathsToNodeIds, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 30921 | break; |
| 30922 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERNODEMANAGEMENT: |
| 30923 | retval = UA_Variant_setScalarCopy(v: &value->value, p: &server->config.maxNodesPerNodeManagement, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 30924 | break; |
| 30925 | case UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXMONITOREDITEMSPERCALL: |
| 30926 | retval = UA_Variant_setScalarCopy(v: &value->value, p: &server->config.maxMonitoredItemsPerCall, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 30927 | break; |
| 30928 | default: |
| 30929 | retval = UA_STATUSCODE_BADNOTSUPPORTED; |
| 30930 | } |
| 30931 | return retval; |
| 30932 | } |
| 30933 | |
| 30934 | static UA_StatusCode |
| 30935 | readMinSamplingInterval(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 30936 | const UA_NodeId *nodeid, void *nodeContext, UA_Boolean includeSourceTimeStamp, |
| 30937 | const UA_NumericRange *range, |
| 30938 | UA_DataValue *value) { |
| 30939 | if(range) { |
| 30940 | value->hasStatus = true; |
| 30941 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 30942 | return UA_STATUSCODE_GOOD; |
| 30943 | } |
| 30944 | |
| 30945 | UA_StatusCode retval; |
| 30946 | UA_Duration minInterval; |
| 30947 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 30948 | minInterval = server->config.samplingIntervalLimits.min; |
| 30949 | #else |
| 30950 | minInterval = 0.0; |
| 30951 | #endif |
| 30952 | retval = UA_Variant_setScalarCopy(v: &value->value, p: &minInterval, type: &UA_TYPES[UA_TYPES_DURATION]); |
| 30953 | if(retval != UA_STATUSCODE_GOOD) |
| 30954 | return retval; |
| 30955 | value->hasValue = true; |
| 30956 | if(includeSourceTimeStamp) { |
| 30957 | value->hasSourceTimestamp = true; |
| 30958 | value->sourceTimestamp = UA_DateTime_now(); |
| 30959 | } |
| 30960 | return UA_STATUSCODE_GOOD; |
| 30961 | } |
| 30962 | #endif |
| 30963 | |
| 30964 | #if defined(UA_GENERATED_NAMESPACE_ZERO) && defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS) |
| 30965 | static UA_StatusCode |
| 30966 | resendData(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 30967 | const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId, |
| 30968 | void *objectContext, size_t inputSize, const UA_Variant *input, |
| 30969 | size_t outputSize, UA_Variant *output) { |
| 30970 | /* Get the input argument */ |
| 30971 | if(inputSize != 1 || |
| 30972 | !UA_Variant_hasScalarType(v: input, type: &UA_TYPES[UA_TYPES_UINT32])) |
| 30973 | return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 30974 | UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data)); |
| 30975 | |
| 30976 | /* Get the Session */ |
| 30977 | lockServer(server); |
| 30978 | UA_Session *session = getSessionById(server, sessionId); |
| 30979 | if(!session) { |
| 30980 | unlockServer(server); |
| 30981 | return UA_STATUSCODE_BADINTERNALERROR; |
| 30982 | } |
| 30983 | |
| 30984 | /* Get the Subscription */ |
| 30985 | UA_Subscription *subscription = getSubscriptionById(server, subscriptionId); |
| 30986 | if(!subscription) { |
| 30987 | unlockServer(server); |
| 30988 | return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 30989 | } |
| 30990 | |
| 30991 | /* The Subscription is not attached to this Session */ |
| 30992 | if(subscription->session != session) { |
| 30993 | unlockServer(server); |
| 30994 | return UA_STATUSCODE_BADUSERACCESSDENIED; |
| 30995 | } |
| 30996 | |
| 30997 | UA_Subscription_resendData(server, sub: subscription); |
| 30998 | |
| 30999 | unlockServer(server); |
| 31000 | return UA_STATUSCODE_GOOD; |
| 31001 | } |
| 31002 | static UA_StatusCode |
| 31003 | readMonitoredItems(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 31004 | const UA_NodeId *methodId, void *methodContext, const UA_NodeId *objectId, |
| 31005 | void *objectContext, size_t inputSize, const UA_Variant *input, |
| 31006 | size_t outputSize, UA_Variant *output) { |
| 31007 | /* Return two empty arrays by default */ |
| 31008 | UA_Variant_setArray(v: &output[0], array: UA_Array_new(size: 0, type: &UA_TYPES[UA_TYPES_UINT32]), |
| 31009 | arraySize: 0, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 31010 | UA_Variant_setArray(v: &output[1], array: UA_Array_new(size: 0, type: &UA_TYPES[UA_TYPES_UINT32]), |
| 31011 | arraySize: 0, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 31012 | |
| 31013 | lockServer(server); |
| 31014 | |
| 31015 | /* Get the Session */ |
| 31016 | UA_Session *session = getSessionById(server, sessionId); |
| 31017 | if(!session) { |
| 31018 | unlockServer(server); |
| 31019 | return UA_STATUSCODE_BADINTERNALERROR; |
| 31020 | } |
| 31021 | if(inputSize == 0 || !input[0].data) { |
| 31022 | unlockServer(server); |
| 31023 | return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 31024 | } |
| 31025 | |
| 31026 | /* Get the Subscription */ |
| 31027 | UA_UInt32 subscriptionId = *((UA_UInt32*)(input[0].data)); |
| 31028 | UA_Subscription *subscription = getSubscriptionById(server, subscriptionId); |
| 31029 | if(!subscription) { |
| 31030 | unlockServer(server); |
| 31031 | return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 31032 | } |
| 31033 | |
| 31034 | /* The Subscription is not attached to this Session */ |
| 31035 | if(subscription->session != session) { |
| 31036 | unlockServer(server); |
| 31037 | return UA_STATUSCODE_BADUSERACCESSDENIED; |
| 31038 | } |
| 31039 | |
| 31040 | /* Count the MonitoredItems */ |
| 31041 | UA_UInt32 sizeOfOutput = 0; |
| 31042 | UA_MonitoredItem* monitoredItem; |
| 31043 | LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) { |
| 31044 | ++sizeOfOutput; |
| 31045 | } |
| 31046 | if(sizeOfOutput == 0) { |
| 31047 | unlockServer(server); |
| 31048 | return UA_STATUSCODE_GOOD; |
| 31049 | } |
| 31050 | |
| 31051 | /* Allocate the output arrays */ |
| 31052 | UA_UInt32 *clientHandles = (UA_UInt32*) |
| 31053 | UA_Array_new(size: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 31054 | if(!clientHandles) { |
| 31055 | unlockServer(server); |
| 31056 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 31057 | } |
| 31058 | UA_UInt32 *serverHandles = (UA_UInt32*) |
| 31059 | UA_Array_new(size: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 31060 | if(!serverHandles) { |
| 31061 | unlockServer(server); |
| 31062 | UA_free(ptr: clientHandles); |
| 31063 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 31064 | } |
| 31065 | |
| 31066 | /* Fill the array */ |
| 31067 | UA_UInt32 i = 0; |
| 31068 | LIST_FOREACH(monitoredItem, &subscription->monitoredItems, listEntry) { |
| 31069 | clientHandles[i] = monitoredItem->parameters.clientHandle; |
| 31070 | serverHandles[i] = monitoredItem->monitoredItemId; |
| 31071 | ++i; |
| 31072 | } |
| 31073 | UA_Variant_setArray(v: &output[0], array: serverHandles, arraySize: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 31074 | UA_Variant_setArray(v: &output[1], array: clientHandles, arraySize: sizeOfOutput, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 31075 | |
| 31076 | unlockServer(server); |
| 31077 | return UA_STATUSCODE_GOOD; |
| 31078 | } |
| 31079 | #endif /* defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS) */ |
| 31080 | |
| 31081 | static UA_StatusCode |
| 31082 | writeNs0VariableArray(UA_Server *server, UA_UInt32 id, void *v, |
| 31083 | size_t length, const UA_DataType *type) { |
| 31084 | UA_Variant var; |
| 31085 | UA_Variant_init(p: &var); |
| 31086 | UA_Variant_setArray(v: &var, array: v, arraySize: length, type); |
| 31087 | return writeValueAttribute(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: id), value: &var); |
| 31088 | } |
| 31089 | |
| 31090 | #ifdef UA_GENERATED_NAMESPACE_ZERO |
| 31091 | static UA_StatusCode |
| 31092 | writeNs0Variable(UA_Server *server, UA_UInt32 id, void *v, const UA_DataType *type) { |
| 31093 | UA_Variant var; |
| 31094 | UA_Variant_init(p: &var); |
| 31095 | UA_Variant_setScalar(v: &var, p: v, type); |
| 31096 | return writeValueAttribute(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, identifier: id), value: &var); |
| 31097 | } |
| 31098 | #endif |
| 31099 | |
| 31100 | #ifndef UA_GENERATED_NAMESPACE_ZERO |
| 31101 | static UA_StatusCode |
| 31102 | addVariableNode(UA_Server *server, char* name, UA_UInt32 variableid, |
| 31103 | UA_UInt32 parentid, UA_UInt32 referenceid, |
| 31104 | UA_Int32 valueRank, UA_UInt32 dataType) { |
| 31105 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 31106 | attr.displayName = UA_LOCALIZEDTEXT("", name); |
| 31107 | attr.dataType = UA_NODEID_NUMERIC(0, dataType); |
| 31108 | attr.valueRank = valueRank; |
| 31109 | attr.accessLevel = UA_ACCESSLEVELMASK_READ; |
| 31110 | return addNode(server, UA_NODECLASS_VARIABLE, UA_NODEID_NUMERIC(0, variableid), |
| 31111 | UA_NODEID_NUMERIC(0, parentid), UA_NODEID_NUMERIC(0, referenceid), |
| 31112 | UA_QUALIFIEDNAME(0, name), |
| 31113 | UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), |
| 31114 | &attr, &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL, NULL); |
| 31115 | } |
| 31116 | |
| 31117 | /* A minimal server object that is not complete and does not use the mandated |
| 31118 | * references to a server type. To be used on very constrained devices. */ |
| 31119 | static UA_StatusCode |
| 31120 | minimalServerObject(UA_Server *server) { |
| 31121 | /* Server */ |
| 31122 | UA_StatusCode retval = addObjectNode(server, "Server", UA_NS0ID_SERVER, UA_NS0ID_OBJECTSFOLDER, |
| 31123 | UA_NS0ID_ORGANIZES, UA_NS0ID_BASEOBJECTTYPE); |
| 31124 | |
| 31125 | /* Use a valuerank of -2 for now. The array is added later on and the valuerank set to 1. */ |
| 31126 | retval |= addVariableNode(server, "ServerArray", UA_NS0ID_SERVER_SERVERARRAY, |
| 31127 | UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY, |
| 31128 | UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE); |
| 31129 | |
| 31130 | retval |= addVariableNode(server, "NamespaceArray", UA_NS0ID_SERVER_NAMESPACEARRAY, |
| 31131 | UA_NS0ID_SERVER, UA_NS0ID_HASPROPERTY, |
| 31132 | UA_VALUERANK_ANY, UA_NS0ID_BASEDATATYPE); |
| 31133 | |
| 31134 | retval |= addVariableNode(server, "ServerStatus", UA_NS0ID_SERVER_SERVERSTATUS, |
| 31135 | UA_NS0ID_SERVER, UA_NS0ID_HASCOMPONENT, |
| 31136 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31137 | |
| 31138 | retval |= addVariableNode(server, "StartTime", UA_NS0ID_SERVER_SERVERSTATUS_STARTTIME, |
| 31139 | UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, |
| 31140 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31141 | |
| 31142 | retval |= addVariableNode(server, "CurrentTime", UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME, |
| 31143 | UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, |
| 31144 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31145 | |
| 31146 | retval |= addVariableNode(server, "State", UA_NS0ID_SERVER_SERVERSTATUS_STATE, |
| 31147 | UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, |
| 31148 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31149 | |
| 31150 | retval |= addVariableNode(server, "BuildInfo", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, |
| 31151 | UA_NS0ID_SERVER_SERVERSTATUS, UA_NS0ID_HASCOMPONENT, |
| 31152 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31153 | |
| 31154 | retval |= addVariableNode(server, "ProductUri", UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI, |
| 31155 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
| 31156 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31157 | |
| 31158 | retval |= addVariableNode(server, "ManufacturerName", |
| 31159 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME, |
| 31160 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
| 31161 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31162 | |
| 31163 | retval |= addVariableNode(server, "ProductName", |
| 31164 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME, |
| 31165 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
| 31166 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31167 | |
| 31168 | retval |= addVariableNode(server, "SoftwareVersion", |
| 31169 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION, |
| 31170 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
| 31171 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31172 | |
| 31173 | retval |= addVariableNode(server, "BuildNumber", |
| 31174 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER, |
| 31175 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
| 31176 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31177 | |
| 31178 | retval |= addVariableNode(server, "BuildDate", |
| 31179 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE, |
| 31180 | UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO, UA_NS0ID_HASCOMPONENT, |
| 31181 | UA_VALUERANK_SCALAR, UA_NS0ID_BASEDATATYPE); |
| 31182 | |
| 31183 | return retval; |
| 31184 | } |
| 31185 | |
| 31186 | #else |
| 31187 | |
| 31188 | static void |
| 31189 | addModellingRules(UA_Server *server) { |
| 31190 | /* Test if the ModellingRules folder was added. (Only for the full ns0.) */ |
| 31191 | UA_NodeId mrNodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES); |
| 31192 | const UA_Node *mrnode = UA_NODESTORE_GET(server, nodeId: &mrNodeId); |
| 31193 | if(!mrnode) |
| 31194 | return; |
| 31195 | UA_NODESTORE_RELEASE(server, mrnode); |
| 31196 | |
| 31197 | /* Add ExposesItsArray */ |
| 31198 | addRef(server, |
| 31199 | sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES), |
| 31200 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 31201 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_EXPOSESITSARRAY), true); |
| 31202 | |
| 31203 | /* Add Mandatory */ |
| 31204 | addRef(server, |
| 31205 | sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES), |
| 31206 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 31207 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_MANDATORY), true); |
| 31208 | |
| 31209 | |
| 31210 | /* Add MandatoryPlaceholder */ |
| 31211 | addRef(server, |
| 31212 | sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES), |
| 31213 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 31214 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_MANDATORYPLACEHOLDER), true); |
| 31215 | |
| 31216 | /* Add Optional */ |
| 31217 | addRef(server, |
| 31218 | sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES), |
| 31219 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 31220 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_OPTIONAL), true); |
| 31221 | |
| 31222 | /* Add OptionalPlaceholder */ |
| 31223 | addRef(server, |
| 31224 | sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MODELLINGRULES), |
| 31225 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 31226 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_MODELLINGRULE_OPTIONALPLACEHOLDER), true); |
| 31227 | } |
| 31228 | |
| 31229 | #endif |
| 31230 | |
| 31231 | /* Initialize the nodeset 0 by using the generated code of the nodeset compiler. |
| 31232 | * This also initialized the data sources for various variables, such as for |
| 31233 | * example server time. */ |
| 31234 | UA_StatusCode |
| 31235 | initNS0(UA_Server *server) { |
| 31236 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 31237 | |
| 31238 | /* Initialize base nodes which are always required an cannot be created |
| 31239 | * through the NS compiler */ |
| 31240 | server->bootstrapNS0 = true; |
| 31241 | UA_StatusCode retVal = createNS0_base(server); |
| 31242 | |
| 31243 | #ifdef UA_GENERATED_NAMESPACE_ZERO |
| 31244 | /* Load nodes and references generated from the XML ns0 definition */ |
| 31245 | retVal |= namespace0_generated(server); |
| 31246 | #else |
| 31247 | /* Create a minimal server object */ |
| 31248 | retVal |= minimalServerObject(server); |
| 31249 | #endif |
| 31250 | |
| 31251 | server->bootstrapNS0 = false; |
| 31252 | |
| 31253 | if(retVal != UA_STATUSCODE_GOOD) { |
| 31254 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 31255 | msg: "Initialization of Namespace 0 failed with %s. " |
| 31256 | "See previous outputs for any error messages.", |
| 31257 | UA_StatusCode_name(code: retVal)); |
| 31258 | return UA_STATUSCODE_BADINTERNALERROR; |
| 31259 | } |
| 31260 | |
| 31261 | /* NamespaceArray */ |
| 31262 | UA_DataSource namespaceDataSource = {readNamespaces, writeNamespaces}; |
| 31263 | retVal |= setVariableNode_dataSource(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_NAMESPACEARRAY), |
| 31264 | dataSource: namespaceDataSource); |
| 31265 | retVal |= writeValueRankAttribute(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_NAMESPACEARRAY), value: 1); |
| 31266 | |
| 31267 | /* ServerArray */ |
| 31268 | retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERARRAY, |
| 31269 | v: &server->config.applicationDescription.applicationUri, |
| 31270 | length: 1, type: &UA_TYPES[UA_TYPES_STRING]); |
| 31271 | retVal |= writeValueRankAttribute(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERARRAY), value: 1); |
| 31272 | |
| 31273 | /* ServerStatus */ |
| 31274 | UA_DataSource serverStatus = {readStatus, writeStatus}; |
| 31275 | retVal |= setVariableNode_dataSource(server, |
| 31276 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS), dataSource: serverStatus); |
| 31277 | |
| 31278 | /* StartTime will be sampled in UA_Server_run_startup()*/ |
| 31279 | |
| 31280 | /* CurrentTime */ |
| 31281 | UA_DataSource currentTime = {readCurrentTime, NULL}; |
| 31282 | UA_NodeId currTime = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME); |
| 31283 | retVal |= setVariableNode_dataSource(server, nodeId: currTime, dataSource: currentTime); |
| 31284 | retVal |= writeMinimumSamplingIntervalAttribute(server, nodeId: currTime, value: 100.0); |
| 31285 | |
| 31286 | /* State */ |
| 31287 | retVal |= setVariableNode_dataSource(server, |
| 31288 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_STATE), dataSource: serverStatus); |
| 31289 | |
| 31290 | /* BuildInfo */ |
| 31291 | retVal |= setVariableNode_dataSource(server, |
| 31292 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO), dataSource: serverStatus); |
| 31293 | |
| 31294 | /* BuildInfo - ProductUri */ |
| 31295 | retVal |= setVariableNode_dataSource(server, |
| 31296 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTURI), |
| 31297 | dataSource: serverStatus); |
| 31298 | |
| 31299 | /* BuildInfo - ManufacturerName */ |
| 31300 | retVal |= setVariableNode_dataSource(server, |
| 31301 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_MANUFACTURERNAME), |
| 31302 | dataSource: serverStatus); |
| 31303 | |
| 31304 | /* BuildInfo - ProductName */ |
| 31305 | retVal |= setVariableNode_dataSource(server, |
| 31306 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_PRODUCTNAME), |
| 31307 | dataSource: serverStatus); |
| 31308 | |
| 31309 | /* BuildInfo - SoftwareVersion */ |
| 31310 | retVal |= setVariableNode_dataSource(server, |
| 31311 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_SOFTWAREVERSION), |
| 31312 | dataSource: serverStatus); |
| 31313 | |
| 31314 | /* BuildInfo - BuildNumber */ |
| 31315 | retVal |= setVariableNode_dataSource(server, |
| 31316 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDNUMBER), |
| 31317 | dataSource: serverStatus); |
| 31318 | |
| 31319 | /* BuildInfo - BuildDate */ |
| 31320 | retVal |= setVariableNode_dataSource(server, |
| 31321 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_BUILDINFO_BUILDDATE), |
| 31322 | dataSource: serverStatus); |
| 31323 | |
| 31324 | #ifdef UA_GENERATED_NAMESPACE_ZERO |
| 31325 | |
| 31326 | /* SecondsTillShutdown */ |
| 31327 | retVal |= setVariableNode_dataSource(server, |
| 31328 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN), |
| 31329 | dataSource: serverStatus); |
| 31330 | |
| 31331 | /* ShutDownReason */ |
| 31332 | UA_LocalizedText shutdownReason; |
| 31333 | UA_LocalizedText_init(p: &shutdownReason); |
| 31334 | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERSTATUS_SHUTDOWNREASON, |
| 31335 | v: &shutdownReason, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 31336 | |
| 31337 | /* ServiceLevel */ |
| 31338 | UA_DataSource serviceLevel = {readServiceLevel, NULL}; |
| 31339 | retVal |= setVariableNode_dataSource(server, |
| 31340 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVICELEVEL), dataSource: serviceLevel); |
| 31341 | |
| 31342 | /* ServerDiagnostics - EnabledFlag */ |
| 31343 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 31344 | UA_Boolean enabledFlag = true; |
| 31345 | #else |
| 31346 | UA_Boolean enabledFlag = false; |
| 31347 | #endif |
| 31348 | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG, |
| 31349 | v: &enabledFlag, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31350 | |
| 31351 | /* According to Specification part-5 - pg.no-11(PDF pg.no-29), when the ServerDiagnostics is disabled the client |
| 31352 | * may modify the value of enabledFlag=true in the server. By default, this node have CurrentRead/Write access. |
| 31353 | * In CTT, Subscription_Minimum_1/002.js test will modify the above flag. This will not be a problem when build |
| 31354 | * configuration is set at UA_NAMESPACE_ZERO="REDUCED" as NodeIds will not be present. When UA_NAMESPACE_ZERO="FULL", |
| 31355 | * the test will fail. Hence made the NodeId as read only */ |
| 31356 | retVal |= writeAccessLevelAttribute(server, |
| 31357 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_ENABLEDFLAG), |
| 31358 | UA_ACCESSLEVELMASK_READ); |
| 31359 | |
| 31360 | /* Auditing */ |
| 31361 | UA_DataSource auditing = {readAuditing, NULL}; |
| 31362 | retVal |= setVariableNode_dataSource(server, |
| 31363 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_AUDITING), dataSource: auditing); |
| 31364 | |
| 31365 | /* Redundancy Support */ |
| 31366 | UA_RedundancySupport redundancySupport = UA_REDUNDANCYSUPPORT_NONE; |
| 31367 | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANCYSUPPORT, |
| 31368 | v: &redundancySupport, type: &UA_TYPES[UA_TYPES_REDUNDANCYSUPPORT]); |
| 31369 | /* Remove unused subtypes of ServerRedundancy */ |
| 31370 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_CURRENTSERVERID), true); |
| 31371 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_REDUNDANTSERVERARRAY), true); |
| 31372 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_SERVERURIARRAY), true); |
| 31373 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERREDUNDANCY_SERVERNETWORKGROUPS), true); |
| 31374 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_CONFORMANCEUNITS), true); |
| 31375 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_URISVERSION), true); |
| 31376 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_CONFORMANCEUNITS), true); |
| 31377 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMS), true); |
| 31378 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMSPERSUBSCRIPTION), true); |
| 31379 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXMONITOREDITEMSQUEUESIZE), true); |
| 31380 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXSELECTCLAUSEPARAMETERS), true); |
| 31381 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXSESSIONS), true); |
| 31382 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXSUBSCRIPTIONS), true); |
| 31383 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXSUBSCRIPTIONSPERSESSION), true); |
| 31384 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXWHERECLAUSEPARAMETERS), true); |
| 31385 | |
| 31386 | /* ServerCapabilities - LocaleIdArray */ |
| 31387 | UA_LocaleId locale_en = UA_STRING(chars: "en"); |
| 31388 | retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_LOCALEIDARRAY, |
| 31389 | v: &locale_en, length: 1, type: &UA_TYPES[UA_TYPES_LOCALEID]); |
| 31390 | |
| 31391 | /* ServerCapabilities - MaxBrowseContinuationPoints */ |
| 31392 | UA_UInt16 maxBrowseContinuationPoints = UA_MAXCONTINUATIONPOINTS; |
| 31393 | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBROWSECONTINUATIONPOINTS, |
| 31394 | v: &maxBrowseContinuationPoints, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 31395 | |
| 31396 | /* ServerProfileArray */ |
| 31397 | UA_String profileArray[3]; |
| 31398 | UA_UInt16 profileArraySize = 0; |
| 31399 | #define ADDPROFILEARRAY(x) profileArray[profileArraySize++] = UA_STRING(x) |
| 31400 | ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/StandardUA2017"); |
| 31401 | #ifdef UA_ENABLE_NODEMANAGEMENT |
| 31402 | ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/NodeManagement"); |
| 31403 | #endif |
| 31404 | #ifdef UA_ENABLE_METHODCALLS |
| 31405 | ADDPROFILEARRAY("http://opcfoundation.org/UA-Profile/Server/Methods"); |
| 31406 | #endif |
| 31407 | retVal |= writeNs0VariableArray(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_SERVERPROFILEARRAY, |
| 31408 | v: profileArray, length: profileArraySize, type: &UA_TYPES[UA_TYPES_STRING]); |
| 31409 | |
| 31410 | /* ServerCapabilities - MaxQueryContinuationPoints */ |
| 31411 | UA_UInt16 maxQueryContinuationPoints = 0; |
| 31412 | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXQUERYCONTINUATIONPOINTS, |
| 31413 | v: &maxQueryContinuationPoints, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 31414 | |
| 31415 | /* ServerCapabilities - MaxHistoryContinuationPoints */ |
| 31416 | UA_UInt16 maxHistoryContinuationPoints = 0; |
| 31417 | retVal |= writeNs0Variable(server, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXHISTORYCONTINUATIONPOINTS, |
| 31418 | v: &maxHistoryContinuationPoints, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 31419 | |
| 31420 | /* ServerCapabilities - MinSupportedSampleRate */ |
| 31421 | UA_DataSource samplingInterval = {readMinSamplingInterval, NULL}; |
| 31422 | retVal |= setVariableNode_dataSource(server, |
| 31423 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MINSUPPORTEDSAMPLERATE), |
| 31424 | dataSource: samplingInterval); |
| 31425 | |
| 31426 | /* ServerCapabilities - OperationLimits - MaxNodesPerRead */ |
| 31427 | UA_DataSource operationLimitRead = {readOperationLimits, NULL}; |
| 31428 | retVal |= setVariableNode_dataSource(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREAD), |
| 31429 | dataSource: operationLimitRead); |
| 31430 | |
| 31431 | /* ServerCapabilities - OperationLimits - maxNodesPerWrite */ |
| 31432 | retVal |= setVariableNode_dataSource(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERWRITE), |
| 31433 | dataSource: operationLimitRead); |
| 31434 | |
| 31435 | /* ServerCapabilities - OperationLimits - MaxNodesPerMethodCall */ |
| 31436 | retVal |= setVariableNode_dataSource(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERMETHODCALL), |
| 31437 | dataSource: operationLimitRead); |
| 31438 | |
| 31439 | /* ServerCapabilities - OperationLimits - MaxNodesPerBrowse */ |
| 31440 | retVal |= setVariableNode_dataSource(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERBROWSE), |
| 31441 | dataSource: operationLimitRead); |
| 31442 | |
| 31443 | /* ServerCapabilities - OperationLimits - MaxNodesPerRegisterNodes */ |
| 31444 | retVal |= setVariableNode_dataSource(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERREGISTERNODES), |
| 31445 | dataSource: operationLimitRead); |
| 31446 | |
| 31447 | /* ServerCapabilities - OperationLimits - MaxNodesPerTranslateBrowsePathsToNodeIds */ |
| 31448 | retVal |= setVariableNode_dataSource(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERTRANSLATEBROWSEPATHSTONODEIDS), |
| 31449 | dataSource: operationLimitRead); |
| 31450 | |
| 31451 | /* ServerCapabilities - OperationLimits - MaxNodesPerNodeManagement */ |
| 31452 | retVal |= setVariableNode_dataSource(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERNODEMANAGEMENT), |
| 31453 | dataSource: operationLimitRead); |
| 31454 | |
| 31455 | /* ServerCapabilities - OperationLimits - MaxMonitoredItemsPerCall */ |
| 31456 | retVal |= setVariableNode_dataSource(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXMONITOREDITEMSPERCALL), |
| 31457 | dataSource: operationLimitRead); |
| 31458 | |
| 31459 | /* Remove unused operation limit components */ |
| 31460 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADDATA), true); |
| 31461 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYREADEVENTS), true); |
| 31462 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYUPDATEDATA), true); |
| 31463 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_OPERATIONLIMITS_MAXNODESPERHISTORYUPDATEEVENTS), true); |
| 31464 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_ROLESET), true); |
| 31465 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXSTRINGLENGTH), true); |
| 31466 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXARRAYLENGTH), true); |
| 31467 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERCAPABILITIES_MAXBYTESTRINGLENGTH), true); |
| 31468 | |
| 31469 | /* Remove not supported server configurations */ |
| 31470 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_ESTIMATEDRETURNTIME), true); |
| 31471 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_LOCALTIME), true); |
| 31472 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_REQUESTSERVERSTATECHANGE), true); |
| 31473 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVERCONFIGURATION), true); |
| 31474 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SETSUBSCRIPTIONDURABLE), true); |
| 31475 | |
| 31476 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 31477 | /* ServerDiagnostics - ServerDiagnosticsSummary */ |
| 31478 | UA_DataSource serverDiagSummary = {readDiagnostics, NULL}; |
| 31479 | retVal |= setVariableNode_dataSource(server, |
| 31480 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), dataSource: serverDiagSummary); |
| 31481 | |
| 31482 | /* ServerDiagnostics - ServerDiagnosticsSummary - ServerViewCount */ |
| 31483 | retVal |= setVariableNode_dataSource(server, |
| 31484 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SERVERVIEWCOUNT), dataSource: serverDiagSummary); |
| 31485 | |
| 31486 | /* ServerDiagnostics - ServerDiagnosticsSummary - CurrentSessionCount */ |
| 31487 | retVal |= setVariableNode_dataSource(server, |
| 31488 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSESSIONCOUNT), dataSource: serverDiagSummary); |
| 31489 | |
| 31490 | /* ServerDiagnostics - ServerDiagnosticsSummary - CumulatedSessionCount */ |
| 31491 | retVal |= setVariableNode_dataSource(server, |
| 31492 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSESSIONCOUNT), dataSource: serverDiagSummary); |
| 31493 | |
| 31494 | /* ServerDiagnostics - ServerDiagnosticsSummary - SecurityRejectedSessionCount */ |
| 31495 | retVal |= setVariableNode_dataSource(server, |
| 31496 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDSESSIONCOUNT), dataSource: serverDiagSummary); |
| 31497 | |
| 31498 | /* ServerDiagnostics - ServerDiagnosticsSummary - RejectedSessionCount */ |
| 31499 | retVal |= setVariableNode_dataSource(server, |
| 31500 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDSESSIONCOUNT), dataSource: serverDiagSummary); |
| 31501 | |
| 31502 | /* ServerDiagnostics - ServerDiagnosticsSummary - SessionTimeoutCount */ |
| 31503 | retVal |= setVariableNode_dataSource(server, |
| 31504 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONTIMEOUTCOUNT), dataSource: serverDiagSummary); |
| 31505 | |
| 31506 | /* ServerDiagnostics - ServerDiagnosticsSummary - SessionAbortCount */ |
| 31507 | retVal |= setVariableNode_dataSource(server, |
| 31508 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONABORTCOUNT), dataSource: serverDiagSummary); |
| 31509 | |
| 31510 | /* ServerDiagnostics - ServerDiagnosticsSummary - CurrentSubscriptionCount */ |
| 31511 | retVal |= setVariableNode_dataSource(server, |
| 31512 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSUBSCRIPTIONCOUNT), dataSource: serverDiagSummary); |
| 31513 | |
| 31514 | /* ServerDiagnostics - ServerDiagnosticsSummary - CumulatedSubscriptionCount */ |
| 31515 | retVal |= setVariableNode_dataSource(server, |
| 31516 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSUBSCRIPTIONCOUNT), dataSource: serverDiagSummary); |
| 31517 | |
| 31518 | /* ServerDiagnostics - ServerDiagnosticsSummary - PublishingIntervalCount */ |
| 31519 | retVal |= setVariableNode_dataSource(server, |
| 31520 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_PUBLISHINGINTERVALCOUNT), dataSource: serverDiagSummary); |
| 31521 | |
| 31522 | /* ServerDiagnostics - ServerDiagnosticsSummary - SecurityRejectedRequestsCount */ |
| 31523 | retVal |= setVariableNode_dataSource(server, |
| 31524 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDREQUESTSCOUNT), dataSource: serverDiagSummary); |
| 31525 | |
| 31526 | /* ServerDiagnostics - ServerDiagnosticsSummary - RejectedRequestsCount */ |
| 31527 | retVal |= setVariableNode_dataSource(server, |
| 31528 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDREQUESTSCOUNT), dataSource: serverDiagSummary); |
| 31529 | |
| 31530 | /* ServerDiagnostics - SubscriptionDiagnosticsArray */ |
| 31531 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 31532 | UA_DataSource serverSubDiagSummary = {readSubscriptionDiagnosticsArray, NULL}; |
| 31533 | retVal |= setVariableNode_dataSource(server, |
| 31534 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), dataSource: serverSubDiagSummary); |
| 31535 | #endif |
| 31536 | |
| 31537 | /* ServerDiagnostics - SessionDiagnosticsSummary - SessionDiagnosticsArray */ |
| 31538 | UA_DataSource sessionDiagSummary = {readSessionDiagnosticsArray, NULL}; |
| 31539 | retVal |= setVariableNode_dataSource(server, |
| 31540 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONDIAGNOSTICSARRAY), dataSource: sessionDiagSummary); |
| 31541 | |
| 31542 | /* ServerDiagnostics - SessionDiagnosticsSummary - SessionSecurityDiagnosticsArray */ |
| 31543 | UA_DataSource sessionSecDiagSummary = {readSessionSecurityDiagnostics, NULL}; |
| 31544 | retVal |= setVariableNode_dataSource(server, |
| 31545 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY_SESSIONSECURITYDIAGNOSTICSARRAY), dataSource: sessionSecDiagSummary); |
| 31546 | |
| 31547 | #else |
| 31548 | /* Removing these NodeIds make Server Object to be non-complaint with UA |
| 31549 | * 1.03 in CTT (Base Inforamtion/Base Info Core Structure/ 001.js) In the |
| 31550 | * 1.04 specification this has been resolved by allowing to remove these |
| 31551 | * static nodes as well */ |
| 31552 | deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY), true); |
| 31553 | deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY), true); |
| 31554 | deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY), true); |
| 31555 | #endif |
| 31556 | |
| 31557 | /* The sampling diagnostics array is optional |
| 31558 | * TODO: Add support for this diagnostics */ |
| 31559 | deleteNode(server, nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SAMPLINGINTERVALDIAGNOSTICSARRAY), true); |
| 31560 | |
| 31561 | #ifndef UA_ENABLE_PUBSUB |
| 31562 | deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE), true); |
| 31563 | #endif |
| 31564 | |
| 31565 | #ifndef UA_ENABLE_HISTORIZING |
| 31566 | deleteNode(server, UA_NODEID_NUMERIC(0, UA_NS0ID_HISTORYSERVERCAPABILITIES), true); |
| 31567 | #else |
| 31568 | /* ServerCapabilities - HistoryServerCapabilities - AccessHistoryDataCapability */ |
| 31569 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_ACCESSHISTORYDATACAPABILITY, |
| 31570 | v: &server->config.accessHistoryDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31571 | |
| 31572 | /* ServerCapabilities - HistoryServerCapabilities - MaxReturnDataValues */ |
| 31573 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_MAXRETURNDATAVALUES, |
| 31574 | v: &server->config.maxReturnDataValues, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 31575 | |
| 31576 | /* ServerCapabilities - HistoryServerCapabilities - AccessHistoryEventsCapability */ |
| 31577 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_ACCESSHISTORYEVENTSCAPABILITY, |
| 31578 | v: &server->config.accessHistoryEventsCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31579 | |
| 31580 | /* ServerCapabilities - HistoryServerCapabilities - MaxReturnEventValues */ |
| 31581 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_MAXRETURNEVENTVALUES, |
| 31582 | v: &server->config.maxReturnEventValues, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 31583 | |
| 31584 | /* ServerCapabilities - HistoryServerCapabilities - InsertDataCapability */ |
| 31585 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTDATACAPABILITY, |
| 31586 | v: &server->config.insertDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31587 | |
| 31588 | /* ServerCapabilities - HistoryServerCapabilities - InsertEventCapability */ |
| 31589 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTEVENTCAPABILITY, |
| 31590 | v: &server->config.insertEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31591 | |
| 31592 | /* ServerCapabilities - HistoryServerCapabilities - InsertAnnotationsCapability */ |
| 31593 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_INSERTANNOTATIONCAPABILITY, |
| 31594 | v: &server->config.insertAnnotationsCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31595 | |
| 31596 | /* ServerCapabilities - HistoryServerCapabilities - ReplaceDataCapability */ |
| 31597 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_REPLACEDATACAPABILITY, |
| 31598 | v: &server->config.replaceDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31599 | |
| 31600 | /* ServerCapabilities - HistoryServerCapabilities - ReplaceEventCapability */ |
| 31601 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_REPLACEEVENTCAPABILITY, |
| 31602 | v: &server->config.replaceEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31603 | |
| 31604 | /* ServerCapabilities - HistoryServerCapabilities - UpdateDataCapability */ |
| 31605 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_UPDATEDATACAPABILITY, |
| 31606 | v: &server->config.updateDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31607 | |
| 31608 | /* ServerCapabilities - HistoryServerCapabilities - UpdateEventCapability */ |
| 31609 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_UPDATEEVENTCAPABILITY, |
| 31610 | v: &server->config.updateEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31611 | |
| 31612 | /* ServerCapabilities - HistoryServerCapabilities - DeleteRawCapability */ |
| 31613 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETERAWCAPABILITY, |
| 31614 | v: &server->config.deleteRawCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31615 | |
| 31616 | /* ServerCapabilities - HistoryServerCapabilities - DeleteEventCapability */ |
| 31617 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETEEVENTCAPABILITY, |
| 31618 | v: &server->config.deleteEventCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31619 | |
| 31620 | /* ServerCapabilities - HistoryServerCapabilities - DeleteAtTimeDataCapability */ |
| 31621 | retVal |= writeNs0Variable(server, UA_NS0ID_HISTORYSERVERCAPABILITIES_DELETEATTIMECAPABILITY, |
| 31622 | v: &server->config.deleteAtTimeDataCapability, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 31623 | #endif |
| 31624 | |
| 31625 | #if defined(UA_ENABLE_METHODCALLS) && defined(UA_ENABLE_SUBSCRIPTIONS) |
| 31626 | retVal |= setMethodNode_callback(server, |
| 31627 | methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_GETMONITOREDITEMS), |
| 31628 | methodCallback: readMonitoredItems); |
| 31629 | |
| 31630 | retVal |= setMethodNode_callback(server, |
| 31631 | methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_RESENDDATA), |
| 31632 | methodCallback: resendData); |
| 31633 | #endif |
| 31634 | |
| 31635 | /* The HasComponent references to the ModellingRules are not part of the |
| 31636 | * Nodeset2.xml. So we add the references manually. */ |
| 31637 | addModellingRules(server); |
| 31638 | |
| 31639 | #endif /* UA_GENERATED_NAMESPACE_ZERO */ |
| 31640 | |
| 31641 | if(retVal != UA_STATUSCODE_GOOD) { |
| 31642 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 31643 | msg: "Initialization of Namespace 0 (after bootstrapping) " |
| 31644 | "failed with %s. See previous outputs for any error messages.", |
| 31645 | UA_StatusCode_name(code: retVal)); |
| 31646 | return UA_STATUSCODE_BADINTERNALERROR; |
| 31647 | } |
| 31648 | return UA_STATUSCODE_GOOD; |
| 31649 | } |
| 31650 | |
| 31651 | /**** amalgamated original file "/src/server/ua_server_ns0_diagnostics.c" ****/ |
| 31652 | |
| 31653 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 31654 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 31655 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 31656 | * |
| 31657 | * Copyright 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 31658 | */ |
| 31659 | |
| 31660 | |
| 31661 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 31662 | |
| 31663 | static UA_Boolean |
| 31664 | equalBrowseName(UA_String *bn, char *n) { |
| 31665 | UA_String name = UA_STRING(chars: n); |
| 31666 | return UA_String_equal(p1: bn, p2: &name); |
| 31667 | } |
| 31668 | |
| 31669 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 31670 | |
| 31671 | /****************************/ |
| 31672 | /* Subscription Diagnostics */ |
| 31673 | /****************************/ |
| 31674 | |
| 31675 | static void |
| 31676 | fillSubscriptionDiagnostics(UA_Subscription *sub, |
| 31677 | UA_SubscriptionDiagnosticsDataType *diag) { |
| 31678 | UA_NodeId_copy(src: &sub->session->sessionId, dst: &diag->sessionId); /* ignore status */ |
| 31679 | diag->subscriptionId = sub->subscriptionId; |
| 31680 | diag->priority = sub->priority; |
| 31681 | diag->publishingInterval = sub->publishingInterval; |
| 31682 | diag->maxKeepAliveCount = sub->maxKeepAliveCount; |
| 31683 | diag->maxLifetimeCount = sub->lifeTimeCount; |
| 31684 | diag->maxNotificationsPerPublish = sub->notificationsPerPublish; |
| 31685 | diag->publishingEnabled = (sub->state > UA_SUBSCRIPTIONSTATE_ENABLED_NOPUBLISH); |
| 31686 | diag->modifyCount = sub->modifyCount; |
| 31687 | diag->enableCount = sub->enableCount; |
| 31688 | diag->disableCount = sub->disableCount; |
| 31689 | diag->republishRequestCount = sub->republishRequestCount; |
| 31690 | diag->republishMessageRequestCount = |
| 31691 | sub->republishRequestCount; /* Always equal to the previous republishRequestCount */ |
| 31692 | diag->republishMessageCount = sub->republishMessageCount; |
| 31693 | diag->transferRequestCount = sub->transferRequestCount; |
| 31694 | diag->transferredToAltClientCount = sub->transferredToAltClientCount; |
| 31695 | diag->transferredToSameClientCount = sub->transferredToSameClientCount; |
| 31696 | diag->publishRequestCount = sub->publishRequestCount; |
| 31697 | diag->dataChangeNotificationsCount = sub->dataChangeNotificationsCount; |
| 31698 | diag->eventNotificationsCount = sub->eventNotificationsCount; |
| 31699 | diag->notificationsCount = sub->notificationsCount; |
| 31700 | diag->latePublishRequestCount = sub->latePublishRequestCount; |
| 31701 | diag->currentKeepAliveCount = sub->currentKeepAliveCount; |
| 31702 | diag->currentLifetimeCount = sub->currentLifetimeCount; |
| 31703 | diag->unacknowledgedMessageCount = (UA_UInt32)sub->retransmissionQueueSize; |
| 31704 | diag->discardedMessageCount = sub->discardedMessageCount; |
| 31705 | diag->monitoredItemCount = sub->monitoredItemsSize; |
| 31706 | diag->monitoringQueueOverflowCount = sub->monitoringQueueOverflowCount; |
| 31707 | diag->nextSequenceNumber = sub->nextSequenceNumber; |
| 31708 | diag->eventQueueOverFlowCount = sub->eventQueueOverFlowCount; |
| 31709 | |
| 31710 | /* Count the disabled MonitoredItems */ |
| 31711 | UA_MonitoredItem *mon; |
| 31712 | LIST_FOREACH(mon, &sub->monitoredItems, listEntry) { |
| 31713 | if(mon->monitoringMode == UA_MONITORINGMODE_DISABLED) |
| 31714 | diag->disabledMonitoredItemCount++; |
| 31715 | } |
| 31716 | } |
| 31717 | |
| 31718 | /* The node context points to the subscription */ |
| 31719 | static UA_StatusCode |
| 31720 | readSubscriptionDiagnostics(UA_Server *server, |
| 31721 | const UA_NodeId *sessionId, void *sessionContext, |
| 31722 | const UA_NodeId *nodeId, void *nodeContext, |
| 31723 | UA_Boolean sourceTimestamp, |
| 31724 | const UA_NumericRange *range, UA_DataValue *value) { |
| 31725 | /* Check the Subscription pointer */ |
| 31726 | UA_Subscription *sub = (UA_Subscription*)nodeContext; |
| 31727 | if(!sub) |
| 31728 | return UA_STATUSCODE_BADINTERNALERROR; |
| 31729 | |
| 31730 | /* Read the BrowseName */ |
| 31731 | UA_QualifiedName bn; |
| 31732 | UA_StatusCode res = UA_Server_readBrowseName(server, nodeId: *nodeId, outBrowseName: &bn); |
| 31733 | if(res != UA_STATUSCODE_GOOD) |
| 31734 | return res; |
| 31735 | |
| 31736 | /* Set the value */ |
| 31737 | UA_SubscriptionDiagnosticsDataType sddt; |
| 31738 | UA_SubscriptionDiagnosticsDataType_init(p: &sddt); |
| 31739 | fillSubscriptionDiagnostics(sub, diag: &sddt); |
| 31740 | |
| 31741 | char memberName[128]; |
| 31742 | memcpy(dest: memberName, src: bn.name.data, n: bn.name.length); |
| 31743 | memberName[bn.name.length] = 0; |
| 31744 | |
| 31745 | size_t memberOffset; |
| 31746 | const UA_DataType *memberType; |
| 31747 | UA_Boolean isArray; |
| 31748 | UA_Boolean found = |
| 31749 | UA_DataType_getStructMember(type: &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE], |
| 31750 | memberName, outOffset: &memberOffset, outMemberType: &memberType, outIsArray: &isArray); |
| 31751 | if(!found) { |
| 31752 | /* Not the member, but the main subscription diagnostics variable... */ |
| 31753 | memberOffset = 0; |
| 31754 | memberType = &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]; |
| 31755 | } |
| 31756 | |
| 31757 | void *content = (void*)(((uintptr_t)&sddt) + memberOffset); |
| 31758 | res = UA_Variant_setScalarCopy(v: &value->value, p: content, type: memberType); |
| 31759 | if(UA_LIKELY(res == UA_STATUSCODE_GOOD)) |
| 31760 | value->hasValue = true; |
| 31761 | |
| 31762 | UA_SubscriptionDiagnosticsDataType_clear(p: &sddt); |
| 31763 | UA_QualifiedName_clear(p: &bn); |
| 31764 | return res; |
| 31765 | } |
| 31766 | |
| 31767 | /* Return all subscriptions in the server. */ |
| 31768 | UA_StatusCode |
| 31769 | readSubscriptionDiagnosticsArray(UA_Server *server, |
| 31770 | const UA_NodeId *sessionId, void *sessionContext, |
| 31771 | const UA_NodeId *nodeId, void *nodeContext, |
| 31772 | UA_Boolean sourceTimestamp, |
| 31773 | const UA_NumericRange *range, UA_DataValue *value) { |
| 31774 | lockServer(server); |
| 31775 | |
| 31776 | /* Get the current session */ |
| 31777 | size_t sdSize = 0; |
| 31778 | session_list_entry *sentry; |
| 31779 | LIST_FOREACH(sentry, &server->sessions, pointers) { |
| 31780 | sdSize += sentry->session.subscriptionsSize; |
| 31781 | } |
| 31782 | |
| 31783 | /* Allocate the output array */ |
| 31784 | UA_SubscriptionDiagnosticsDataType *sd = (UA_SubscriptionDiagnosticsDataType*) |
| 31785 | UA_Array_new(size: sdSize, type: &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]); |
| 31786 | if(!sd) { |
| 31787 | unlockServer(server); |
| 31788 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 31789 | } |
| 31790 | |
| 31791 | /* Collect the statistics */ |
| 31792 | size_t i = 0; |
| 31793 | UA_Subscription *sub; |
| 31794 | LIST_FOREACH(sentry, &server->sessions, pointers) { |
| 31795 | TAILQ_FOREACH(sub, &sentry->session.subscriptions, sessionListEntry) { |
| 31796 | fillSubscriptionDiagnostics(sub, diag: &sd[i]); |
| 31797 | i++; |
| 31798 | } |
| 31799 | } |
| 31800 | |
| 31801 | /* Set the output */ |
| 31802 | value->hasValue = true; |
| 31803 | UA_Variant_setArray(v: &value->value, array: sd, arraySize: sdSize, |
| 31804 | type: &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]); |
| 31805 | |
| 31806 | unlockServer(server); |
| 31807 | return UA_STATUSCODE_GOOD; |
| 31808 | } |
| 31809 | |
| 31810 | void |
| 31811 | createSubscriptionObject(UA_Server *server, UA_Session *session, |
| 31812 | UA_Subscription *sub) { |
| 31813 | UA_ExpandedNodeId *children = NULL; |
| 31814 | size_t childrenSize = 0; |
| 31815 | UA_ReferenceTypeSet refTypes; |
| 31816 | UA_NodeId hasComponent = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT); |
| 31817 | |
| 31818 | char subIdStr[32]; |
| 31819 | itoaUnsigned(value: sub->subscriptionId, buffer: subIdStr, base: 10); |
| 31820 | |
| 31821 | /* Find the NodeId of the SubscriptionDiagnosticsArray */ |
| 31822 | UA_BrowsePath bp; |
| 31823 | UA_BrowsePath_init(p: &bp); |
| 31824 | bp.startingNode = sub->session->sessionId; |
| 31825 | UA_RelativePathElement rpe[1]; |
| 31826 | memset(s: rpe, c: 0, n: sizeof(UA_RelativePathElement) * 1); |
| 31827 | rpe[0].targetName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "SubscriptionDiagnosticsArray"); |
| 31828 | bp.relativePath.elements = rpe; |
| 31829 | bp.relativePath.elementsSize = 1; |
| 31830 | UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp); |
| 31831 | if(bpr.targetsSize < 1) |
| 31832 | return; |
| 31833 | |
| 31834 | /* Create an object for the subscription. Instantiates all the mandatory |
| 31835 | * children. */ |
| 31836 | UA_VariableAttributes var_attr = UA_VariableAttributes_default; |
| 31837 | var_attr.displayName.text = UA_STRING(chars: subIdStr); |
| 31838 | var_attr.dataType = UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE].typeId; |
| 31839 | UA_NodeId refId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT); |
| 31840 | UA_QualifiedName browseName = UA_QUALIFIEDNAME(nsIndex: 0, chars: subIdStr); |
| 31841 | UA_NodeId typeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SUBSCRIPTIONDIAGNOSTICSTYPE); |
| 31842 | /* Assign a random free NodeId */ |
| 31843 | UA_StatusCode res = addNode(server, nodeClass: UA_NODECLASS_VARIABLE, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), |
| 31844 | parentNodeId: bpr.targets[0].targetId.nodeId, |
| 31845 | referenceTypeId: refId, browseName, typeDefinition: typeId, attr: &var_attr, |
| 31846 | attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], NULL, |
| 31847 | outNewNodeId: &sub->ns0Id); |
| 31848 | UA_CHECK_STATUS(res, goto cleanup); |
| 31849 | |
| 31850 | /* Add a second reference from the overall SubscriptionDiagnosticsArray variable */ |
| 31851 | const UA_NodeId subDiagArray = |
| 31852 | UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SUBSCRIPTIONDIAGNOSTICSARRAY); |
| 31853 | res = addRefWithSession(server, session, sourceId: &subDiagArray, referenceTypeId: &refId, targetId: &sub->ns0Id, true); |
| 31854 | if(res != UA_STATUSCODE_GOOD) |
| 31855 | goto cleanup; |
| 31856 | |
| 31857 | /* Get all children (including the variable itself) and set the contenxt + callback */ |
| 31858 | res = referenceTypeIndices(server, refType: &hasComponent, indices: &refTypes, false); |
| 31859 | if(UA_LIKELY(res == UA_STATUSCODE_GOOD)) { |
| 31860 | res = browseRecursive(server, startNodesSize: 1, startNodes: &sub->ns0Id, |
| 31861 | browseDirection: UA_BROWSEDIRECTION_FORWARD, refTypes: &refTypes, |
| 31862 | nodeClassMask: UA_NODECLASS_VARIABLE, true, resultsSize: &childrenSize, results: &children); |
| 31863 | } |
| 31864 | if(res != UA_STATUSCODE_GOOD) |
| 31865 | goto cleanup; |
| 31866 | |
| 31867 | /* Add the callback to all variables */ |
| 31868 | UA_DataSource subDiagSource = {readSubscriptionDiagnostics, NULL}; |
| 31869 | for(size_t i = 0; i < childrenSize; i++) { |
| 31870 | setVariableNode_dataSource(server, nodeId: children[i].nodeId, dataSource: subDiagSource); |
| 31871 | setNodeContext(server, nodeId: children[i].nodeId, nodeContext: sub); |
| 31872 | } |
| 31873 | |
| 31874 | UA_Array_delete(p: children, size: childrenSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 31875 | |
| 31876 | cleanup: |
| 31877 | UA_BrowsePathResult_clear(p: &bpr); |
| 31878 | if(res != UA_STATUSCODE_GOOD) { |
| 31879 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 31880 | "Creating the subscription diagnostics object failed " |
| 31881 | "with StatusCode %s", UA_StatusCode_name(res)); |
| 31882 | } |
| 31883 | } |
| 31884 | |
| 31885 | /***********************/ |
| 31886 | /* Session Diagnostics */ |
| 31887 | /***********************/ |
| 31888 | |
| 31889 | static UA_StatusCode |
| 31890 | setSessionSubscriptionDiagnostics(UA_Server *server, UA_Session *session, |
| 31891 | UA_DataValue *value) { |
| 31892 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 31893 | |
| 31894 | /* Get the current session */ |
| 31895 | size_t sdSize = session->subscriptionsSize; |
| 31896 | |
| 31897 | /* Allocate the output array */ |
| 31898 | UA_SubscriptionDiagnosticsDataType *sd = (UA_SubscriptionDiagnosticsDataType*) |
| 31899 | UA_Array_new(size: sdSize, type: &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]); |
| 31900 | if(!sd) |
| 31901 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 31902 | |
| 31903 | /* Collect the statistics */ |
| 31904 | size_t i = 0; |
| 31905 | UA_Subscription *sub; |
| 31906 | TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) { |
| 31907 | fillSubscriptionDiagnostics(sub, diag: &sd[i]); |
| 31908 | i++; |
| 31909 | } |
| 31910 | |
| 31911 | /* Set the output */ |
| 31912 | value->hasValue = true; |
| 31913 | UA_Variant_setArray(v: &value->value, array: sd, arraySize: sdSize, |
| 31914 | type: &UA_TYPES[UA_TYPES_SUBSCRIPTIONDIAGNOSTICSDATATYPE]); |
| 31915 | return UA_STATUSCODE_GOOD; |
| 31916 | } |
| 31917 | |
| 31918 | #endif /* UA_ENABLE_SUBSCRIPTIONS */ |
| 31919 | |
| 31920 | static void |
| 31921 | setSessionDiagnostics(UA_Session *session, UA_SessionDiagnosticsDataType *sd) { |
| 31922 | UA_SessionDiagnosticsDataType_copy(src: &session->diagnostics, dst: sd); |
| 31923 | UA_NodeId_copy(src: &session->sessionId, dst: &sd->sessionId); |
| 31924 | UA_String_copy(src: &session->sessionName, dst: &sd->sessionName); |
| 31925 | UA_ApplicationDescription_copy(src: &session->clientDescription, |
| 31926 | dst: &sd->clientDescription); |
| 31927 | sd->maxResponseMessageSize = session->maxResponseMessageSize; |
| 31928 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 31929 | sd->currentPublishRequestsInQueue = (UA_UInt32)session->responseQueueSize; |
| 31930 | #endif |
| 31931 | sd->actualSessionTimeout = session->timeout; |
| 31932 | |
| 31933 | /* Set LocaleIds */ |
| 31934 | UA_StatusCode res = |
| 31935 | UA_Array_copy(src: session->localeIds, size: session->localeIdsSize, |
| 31936 | dst: (void **)&sd->localeIds, type: &UA_TYPES[UA_TYPES_STRING]); |
| 31937 | if(UA_LIKELY(res == UA_STATUSCODE_GOOD)) |
| 31938 | sd->localeIdsSize = session->localeIdsSize; |
| 31939 | |
| 31940 | /* Set Subscription diagnostics */ |
| 31941 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 31942 | sd->currentSubscriptionsCount = (UA_UInt32)session->subscriptionsSize; |
| 31943 | |
| 31944 | UA_Subscription *sub; |
| 31945 | TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) { |
| 31946 | sd->currentMonitoredItemsCount += (UA_UInt32)sub->monitoredItemsSize; |
| 31947 | } |
| 31948 | #endif |
| 31949 | } |
| 31950 | |
| 31951 | UA_StatusCode |
| 31952 | readSessionDiagnosticsArray(UA_Server *server, |
| 31953 | const UA_NodeId *sessionId, void *sessionContext, |
| 31954 | const UA_NodeId *nodeId, void *nodeContext, |
| 31955 | UA_Boolean sourceTimestamp, |
| 31956 | const UA_NumericRange *range, UA_DataValue *value) { |
| 31957 | /* Allocate the output array */ |
| 31958 | UA_SessionDiagnosticsDataType *sd = (UA_SessionDiagnosticsDataType*) |
| 31959 | UA_Array_new(size: server->sessionCount, |
| 31960 | type: &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE]); |
| 31961 | if(!sd) |
| 31962 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 31963 | |
| 31964 | lockServer(server); |
| 31965 | |
| 31966 | /* Collect the statistics */ |
| 31967 | size_t i = 0; |
| 31968 | session_list_entry *session; |
| 31969 | LIST_FOREACH(session, &server->sessions, pointers) { |
| 31970 | setSessionDiagnostics(session: &session->session, sd: &sd[i]); |
| 31971 | i++; |
| 31972 | } |
| 31973 | |
| 31974 | /* Set the output */ |
| 31975 | value->hasValue = true; |
| 31976 | UA_Variant_setArray(v: &value->value, array: sd, arraySize: server->sessionCount, |
| 31977 | type: &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE]); |
| 31978 | |
| 31979 | unlockServer(server); |
| 31980 | return UA_STATUSCODE_GOOD; |
| 31981 | } |
| 31982 | |
| 31983 | static void |
| 31984 | setSessionSecurityDiagnostics(UA_Session *session, |
| 31985 | UA_SessionSecurityDiagnosticsDataType *sd) { |
| 31986 | UA_SessionSecurityDiagnosticsDataType_copy(src: &session->securityDiagnostics, dst: sd); |
| 31987 | UA_NodeId_copy(src: &session->sessionId, dst: &sd->sessionId); |
| 31988 | UA_String_copy(src: &session->clientUserIdOfSession, dst: &sd->clientUserIdOfSession); |
| 31989 | UA_SecureChannel *channel = session->header.channel; |
| 31990 | if(channel) { |
| 31991 | UA_ByteString_copy(src: &channel->remoteCertificate, dst: &sd->clientCertificate); |
| 31992 | UA_String_copy(src: &channel->securityPolicy->policyUri, dst: &sd->securityPolicyUri); |
| 31993 | sd->securityMode = channel->securityMode; |
| 31994 | sd->encoding = UA_STRING_ALLOC("UA Binary"); /* The only one atm */ |
| 31995 | sd->transportProtocol = UA_STRING_ALLOC("opc.tcp"); /* The only one atm */ |
| 31996 | } |
| 31997 | } |
| 31998 | |
| 31999 | static UA_StatusCode |
| 32000 | readSessionDiagnostics(UA_Server *server, |
| 32001 | const UA_NodeId *sessionId, void *sessionContext, |
| 32002 | const UA_NodeId *nodeId, void *nodeContext, |
| 32003 | UA_Boolean sourceTimestamp, |
| 32004 | const UA_NumericRange *range, UA_DataValue *value) { |
| 32005 | lockServer(server); |
| 32006 | |
| 32007 | /* Get the Session */ |
| 32008 | UA_Session *session = getSessionById(server, sessionId); |
| 32009 | if(!session) { |
| 32010 | unlockServer(server); |
| 32011 | return UA_STATUSCODE_BADINTERNALERROR; |
| 32012 | } |
| 32013 | |
| 32014 | /* Read the BrowseName */ |
| 32015 | UA_QualifiedName bn; |
| 32016 | UA_StatusCode res = readWithReadValue(server, nodeId, attributeId: UA_ATTRIBUTEID_BROWSENAME, v: &bn); |
| 32017 | if(res != UA_STATUSCODE_GOOD) { |
| 32018 | unlockServer(server); |
| 32019 | return res; |
| 32020 | } |
| 32021 | |
| 32022 | union { |
| 32023 | UA_SessionDiagnosticsDataType sddt; |
| 32024 | UA_SessionSecurityDiagnosticsDataType ssddt; |
| 32025 | } data; |
| 32026 | void *content; |
| 32027 | UA_Boolean isArray = false; |
| 32028 | const UA_DataType *type = NULL; |
| 32029 | UA_Boolean securityDiagnostics = false; |
| 32030 | |
| 32031 | char memberName[128]; |
| 32032 | size_t memberOffset; |
| 32033 | UA_Boolean found; |
| 32034 | |
| 32035 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 32036 | if(equalBrowseName(bn: &bn.name, n: "SubscriptionDiagnosticsArray")) { |
| 32037 | res = setSessionSubscriptionDiagnostics(server, session, value); |
| 32038 | goto cleanup; |
| 32039 | } |
| 32040 | #endif |
| 32041 | |
| 32042 | if(equalBrowseName(bn: &bn.name, n: "SessionDiagnostics")) { |
| 32043 | setSessionDiagnostics(session, sd: &data.sddt); |
| 32044 | content = &data.sddt; |
| 32045 | type = &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE]; |
| 32046 | } else if(equalBrowseName(bn: &bn.name, n: "SessionSecurityDiagnostics")) { |
| 32047 | setSessionSecurityDiagnostics(session, sd: &data.ssddt); |
| 32048 | securityDiagnostics = true; |
| 32049 | content = &data.ssddt; |
| 32050 | type = &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE]; |
| 32051 | } else { |
| 32052 | /* Try to find the member in SessionDiagnosticsDataType and |
| 32053 | * SessionSecurityDiagnosticsDataType */ |
| 32054 | memcpy(dest: memberName, src: bn.name.data, n: bn.name.length); |
| 32055 | memberName[bn.name.length] = 0; |
| 32056 | found = UA_DataType_getStructMember(type: &UA_TYPES[UA_TYPES_SESSIONDIAGNOSTICSDATATYPE], |
| 32057 | memberName, outOffset: &memberOffset, outMemberType: &type, outIsArray: &isArray); |
| 32058 | if(found) { |
| 32059 | setSessionDiagnostics(session, sd: &data.sddt); |
| 32060 | content = (void*)(((uintptr_t)&data.sddt) + memberOffset); |
| 32061 | } else { |
| 32062 | const UA_DataType *dt = &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE]; |
| 32063 | found = UA_DataType_getStructMember(type: dt, memberName, outOffset: &memberOffset, |
| 32064 | outMemberType: &type, outIsArray: &isArray); |
| 32065 | if(!found) { |
| 32066 | res = UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 32067 | goto cleanup; |
| 32068 | } |
| 32069 | setSessionSecurityDiagnostics(session, sd: &data.ssddt); |
| 32070 | securityDiagnostics = true; |
| 32071 | content = (void*)(((uintptr_t)&data.ssddt) + memberOffset); |
| 32072 | } |
| 32073 | } |
| 32074 | |
| 32075 | if(!isArray) { |
| 32076 | res = UA_Variant_setScalarCopy(v: &value->value, p: content, type); |
| 32077 | } else { |
| 32078 | size_t len = *(size_t*)content; |
| 32079 | content = *(void**)((uintptr_t)content + sizeof(size_t)); |
| 32080 | res = UA_Variant_setArrayCopy(v: &value->value, array: content, arraySize: len, type); |
| 32081 | } |
| 32082 | if(UA_LIKELY(res == UA_STATUSCODE_GOOD)) |
| 32083 | value->hasValue = true; |
| 32084 | |
| 32085 | if(securityDiagnostics) |
| 32086 | UA_SessionSecurityDiagnosticsDataType_clear(p: &data.ssddt); |
| 32087 | else |
| 32088 | UA_SessionDiagnosticsDataType_clear(p: &data.sddt); |
| 32089 | |
| 32090 | cleanup: |
| 32091 | UA_QualifiedName_clear(p: &bn); |
| 32092 | unlockServer(server); |
| 32093 | return res; |
| 32094 | } |
| 32095 | |
| 32096 | UA_StatusCode |
| 32097 | readSessionSecurityDiagnostics(UA_Server *server, |
| 32098 | const UA_NodeId *sessionId, void *sessionContext, |
| 32099 | const UA_NodeId *nodeId, void *nodeContext, |
| 32100 | UA_Boolean sourceTimestamp, |
| 32101 | const UA_NumericRange *range, UA_DataValue *value) { |
| 32102 | /* Allocate the output array */ |
| 32103 | UA_SessionSecurityDiagnosticsDataType *sd = (UA_SessionSecurityDiagnosticsDataType*) |
| 32104 | UA_Array_new(size: server->sessionCount, |
| 32105 | type: &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE]); |
| 32106 | if(!sd) |
| 32107 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 32108 | |
| 32109 | lockServer(server); |
| 32110 | |
| 32111 | /* Collect the statistics */ |
| 32112 | size_t i = 0; |
| 32113 | session_list_entry *session; |
| 32114 | LIST_FOREACH(session, &server->sessions, pointers) { |
| 32115 | setSessionSecurityDiagnostics(session: &session->session, sd: &sd[i]); |
| 32116 | i++; |
| 32117 | } |
| 32118 | |
| 32119 | /* Set the output */ |
| 32120 | value->hasValue = true; |
| 32121 | UA_Variant_setArray(v: &value->value, array: sd, arraySize: server->sessionCount, |
| 32122 | type: &UA_TYPES[UA_TYPES_SESSIONSECURITYDIAGNOSTICSDATATYPE]); |
| 32123 | |
| 32124 | unlockServer(server); |
| 32125 | return UA_STATUSCODE_GOOD; |
| 32126 | } |
| 32127 | |
| 32128 | void |
| 32129 | createSessionObject(UA_Server *server, UA_Session *session) { |
| 32130 | UA_ExpandedNodeId *children = NULL; |
| 32131 | size_t childrenSize = 0; |
| 32132 | UA_ReferenceTypeSet refTypes; |
| 32133 | UA_NodeId hasComponent = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT); |
| 32134 | |
| 32135 | /* Create an object for the session. Instantiates all the mandatory children. */ |
| 32136 | UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; |
| 32137 | object_attr.displayName.text = session->sessionName; |
| 32138 | UA_NodeId parentId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SESSIONSDIAGNOSTICSSUMMARY); |
| 32139 | UA_NodeId refId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT); |
| 32140 | UA_QualifiedName browseName = UA_QUALIFIEDNAME(nsIndex: 0, chars: ""); |
| 32141 | browseName.name = session->sessionName; /* shallow copy */ |
| 32142 | UA_NodeId typeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SESSIONDIAGNOSTICSOBJECTTYPE); |
| 32143 | UA_StatusCode res = addNode(server, nodeClass: UA_NODECLASS_OBJECT, requestedNewNodeId: session->sessionId, |
| 32144 | parentNodeId: parentId, referenceTypeId: refId, browseName, typeDefinition: typeId, attr: &object_attr, |
| 32145 | attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], NULL, NULL); |
| 32146 | if(res != UA_STATUSCODE_GOOD) |
| 32147 | goto cleanup; |
| 32148 | |
| 32149 | /* Recursively browse all children */ |
| 32150 | res = referenceTypeIndices(server, refType: &hasComponent, indices: &refTypes, false); |
| 32151 | if(res != UA_STATUSCODE_GOOD) |
| 32152 | goto cleanup; |
| 32153 | res = browseRecursive(server, startNodesSize: 1, startNodes: &session->sessionId, |
| 32154 | browseDirection: UA_BROWSEDIRECTION_FORWARD, refTypes: &refTypes, |
| 32155 | nodeClassMask: UA_NODECLASS_VARIABLE, false, resultsSize: &childrenSize, results: &children); |
| 32156 | if(res != UA_STATUSCODE_GOOD) |
| 32157 | goto cleanup; |
| 32158 | |
| 32159 | /* Add the callback to all variables */ |
| 32160 | UA_DataSource sessionDiagSource = {readSessionDiagnostics, NULL}; |
| 32161 | for(size_t i = 0; i < childrenSize; i++) { |
| 32162 | setVariableNode_dataSource(server, nodeId: children[i].nodeId, dataSource: sessionDiagSource); |
| 32163 | } |
| 32164 | |
| 32165 | cleanup: |
| 32166 | if(res != UA_STATUSCODE_GOOD) { |
| 32167 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 32168 | "Creating the session diagnostics object failed " |
| 32169 | "with StatusCode %s", UA_StatusCode_name(res)); |
| 32170 | } |
| 32171 | UA_Array_delete(p: children, size: childrenSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 32172 | } |
| 32173 | |
| 32174 | /***************************/ |
| 32175 | /* Server-Wide Diagnostics */ |
| 32176 | /***************************/ |
| 32177 | |
| 32178 | UA_StatusCode |
| 32179 | readDiagnostics(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 32180 | const UA_NodeId *nodeId, void *nodeContext, UA_Boolean sourceTimestamp, |
| 32181 | const UA_NumericRange *range, UA_DataValue *value) { |
| 32182 | if(range) { |
| 32183 | value->hasStatus = true; |
| 32184 | value->status = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 32185 | return UA_STATUSCODE_GOOD; |
| 32186 | } |
| 32187 | |
| 32188 | if(sourceTimestamp) { |
| 32189 | value->hasSourceTimestamp = true; |
| 32190 | value->sourceTimestamp = UA_DateTime_now(); |
| 32191 | } |
| 32192 | |
| 32193 | UA_assert(nodeId->identifierType == UA_NODEIDTYPE_NUMERIC); |
| 32194 | |
| 32195 | void *data = NULL; |
| 32196 | const UA_DataType *type = &UA_TYPES[UA_TYPES_UINT32]; /* Default */ |
| 32197 | |
| 32198 | lockServer(server); |
| 32199 | |
| 32200 | switch(nodeId->identifier.numeric) { |
| 32201 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY: |
| 32202 | server->serverDiagnosticsSummary.currentSessionCount = |
| 32203 | server->activeSessionCount; |
| 32204 | data = &server->serverDiagnosticsSummary; |
| 32205 | type = &UA_TYPES[UA_TYPES_SERVERDIAGNOSTICSSUMMARYDATATYPE]; |
| 32206 | break; |
| 32207 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SERVERVIEWCOUNT: |
| 32208 | data = &server->serverDiagnosticsSummary.serverViewCount; |
| 32209 | break; |
| 32210 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSESSIONCOUNT: |
| 32211 | data = &server->activeSessionCount; |
| 32212 | break; |
| 32213 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSESSIONCOUNT: |
| 32214 | data = &server->serverDiagnosticsSummary.cumulatedSessionCount; |
| 32215 | break; |
| 32216 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDSESSIONCOUNT: |
| 32217 | data = &server->serverDiagnosticsSummary.securityRejectedSessionCount; |
| 32218 | break; |
| 32219 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDSESSIONCOUNT: |
| 32220 | data = &server->serverDiagnosticsSummary.rejectedSessionCount; |
| 32221 | break; |
| 32222 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONTIMEOUTCOUNT: |
| 32223 | data = &server->serverDiagnosticsSummary.sessionTimeoutCount; |
| 32224 | break; |
| 32225 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SESSIONABORTCOUNT: |
| 32226 | data = &server->serverDiagnosticsSummary.sessionAbortCount; |
| 32227 | break; |
| 32228 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CURRENTSUBSCRIPTIONCOUNT: |
| 32229 | data = &server->serverDiagnosticsSummary.currentSubscriptionCount; |
| 32230 | break; |
| 32231 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_CUMULATEDSUBSCRIPTIONCOUNT: |
| 32232 | data = &server->serverDiagnosticsSummary.cumulatedSubscriptionCount; |
| 32233 | break; |
| 32234 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_PUBLISHINGINTERVALCOUNT: |
| 32235 | data = &server->serverDiagnosticsSummary.publishingIntervalCount; |
| 32236 | break; |
| 32237 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_SECURITYREJECTEDREQUESTSCOUNT: |
| 32238 | data = &server->serverDiagnosticsSummary.securityRejectedRequestsCount; |
| 32239 | break; |
| 32240 | case UA_NS0ID_SERVER_SERVERDIAGNOSTICS_SERVERDIAGNOSTICSSUMMARY_REJECTEDREQUESTSCOUNT: |
| 32241 | data = &server->serverDiagnosticsSummary.rejectedRequestsCount; |
| 32242 | break; |
| 32243 | default: |
| 32244 | unlockServer(server); |
| 32245 | return UA_STATUSCODE_BADINTERNALERROR; |
| 32246 | } |
| 32247 | |
| 32248 | UA_StatusCode res = UA_Variant_setScalarCopy(v: &value->value, p: data, type); |
| 32249 | if(res == UA_STATUSCODE_GOOD) |
| 32250 | value->hasValue = true; |
| 32251 | |
| 32252 | unlockServer(server); |
| 32253 | return res; |
| 32254 | } |
| 32255 | |
| 32256 | #endif /* UA_ENABLE_DIAGNOSTICS */ |
| 32257 | |
| 32258 | /**** amalgamated original file "/src/server/ua_server_config.c" ****/ |
| 32259 | |
| 32260 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 32261 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 32262 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 32263 | * |
| 32264 | * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 32265 | * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 32266 | */ |
| 32267 | |
| 32268 | |
| 32269 | |
| 32270 | void |
| 32271 | UA_ServerConfig_clean(UA_ServerConfig *config) { |
| 32272 | if(!config) |
| 32273 | return; |
| 32274 | |
| 32275 | /* Server Description */ |
| 32276 | UA_BuildInfo_clear(p: &config->buildInfo); |
| 32277 | UA_ApplicationDescription_clear(p: &config->applicationDescription); |
| 32278 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 32279 | UA_MdnsDiscoveryConfiguration_clear(&config->mdnsConfig); |
| 32280 | UA_String_clear(&config->mdnsInterfaceIP); |
| 32281 | # if !defined(UA_HAS_GETIFADDR) |
| 32282 | if (config->mdnsIpAddressListSize) { |
| 32283 | UA_free(config->mdnsIpAddressList); |
| 32284 | } |
| 32285 | # endif |
| 32286 | #endif |
| 32287 | |
| 32288 | /* Stop and delete the EventLoop */ |
| 32289 | UA_EventLoop *el = config->eventLoop; |
| 32290 | if(el && !config->externalEventLoop) { |
| 32291 | if(el->state != UA_EVENTLOOPSTATE_FRESH && |
| 32292 | el->state != UA_EVENTLOOPSTATE_STOPPED) { |
| 32293 | el->stop(el); |
| 32294 | while(el->state != UA_EVENTLOOPSTATE_STOPPED) { |
| 32295 | el->run(el, 100); |
| 32296 | } |
| 32297 | } |
| 32298 | el->free(el); |
| 32299 | config->eventLoop = NULL; |
| 32300 | } |
| 32301 | |
| 32302 | /* Networking */ |
| 32303 | UA_Array_delete(p: config->serverUrls, size: config->serverUrlsSize, |
| 32304 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 32305 | config->serverUrls = NULL; |
| 32306 | config->serverUrlsSize = 0; |
| 32307 | |
| 32308 | /* Security Policies */ |
| 32309 | for(size_t i = 0; i < config->securityPoliciesSize; ++i) { |
| 32310 | UA_SecurityPolicy *policy = &config->securityPolicies[i]; |
| 32311 | policy->clear(policy); |
| 32312 | } |
| 32313 | UA_free(ptr: config->securityPolicies); |
| 32314 | config->securityPolicies = NULL; |
| 32315 | config->securityPoliciesSize = 0; |
| 32316 | |
| 32317 | for(size_t i = 0; i < config->endpointsSize; ++i) |
| 32318 | UA_EndpointDescription_clear(p: &config->endpoints[i]); |
| 32319 | |
| 32320 | UA_free(ptr: config->endpoints); |
| 32321 | config->endpoints = NULL; |
| 32322 | config->endpointsSize = 0; |
| 32323 | |
| 32324 | /* Nodestore */ |
| 32325 | if(config->nodestore.context && config->nodestore.clear) { |
| 32326 | config->nodestore.clear(config->nodestore.context); |
| 32327 | config->nodestore.context = NULL; |
| 32328 | } |
| 32329 | |
| 32330 | /* Certificate Validation */ |
| 32331 | if(config->secureChannelPKI.clear) |
| 32332 | config->secureChannelPKI.clear(&config->secureChannelPKI); |
| 32333 | if(config->sessionPKI.clear) |
| 32334 | config->sessionPKI.clear(&config->sessionPKI); |
| 32335 | |
| 32336 | /* Access Control */ |
| 32337 | if(config->accessControl.clear) |
| 32338 | config->accessControl.clear(&config->accessControl); |
| 32339 | |
| 32340 | /* Historical data */ |
| 32341 | #ifdef UA_ENABLE_HISTORIZING |
| 32342 | if(config->historyDatabase.clear) |
| 32343 | config->historyDatabase.clear(&config->historyDatabase); |
| 32344 | #endif |
| 32345 | |
| 32346 | #ifdef UA_ENABLE_PUBSUB |
| 32347 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 32348 | if(config->pubSubConfig.securityPolicies != NULL) { |
| 32349 | for(size_t i = 0; i < config->pubSubConfig.securityPoliciesSize; i++) { |
| 32350 | config->pubSubConfig.securityPolicies[i].clear(&config->pubSubConfig.securityPolicies[i]); |
| 32351 | } |
| 32352 | UA_free(config->pubSubConfig.securityPolicies); |
| 32353 | config->pubSubConfig.securityPolicies = NULL; |
| 32354 | config->pubSubConfig.securityPoliciesSize = 0; |
| 32355 | } |
| 32356 | #endif |
| 32357 | #endif /* UA_ENABLE_PUBSUB */ |
| 32358 | |
| 32359 | /* Logger */ |
| 32360 | if(config->logging != NULL && config->logging->clear != NULL) |
| 32361 | config->logging->clear(config->logging); |
| 32362 | config->logging = NULL; |
| 32363 | |
| 32364 | /* Custom Data Types */ |
| 32365 | UA_cleanupDataTypeWithCustom(customTypes: config->customDataTypes); |
| 32366 | config->customDataTypes = NULL; |
| 32367 | } |
| 32368 | |
| 32369 | /**** amalgamated original file "/src/server/ua_server_binary.c" ****/ |
| 32370 | |
| 32371 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 32372 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 32373 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 32374 | * |
| 32375 | * Copyright 2014-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 32376 | * Copyright 2014-2016 (c) Sten Grüner |
| 32377 | * Copyright 2014-2015, 2017 (c) Florian Palm |
| 32378 | * Copyright 2015-2016 (c) Chris Iatrou |
| 32379 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 32380 | * Copyright 2016 (c) Joakim L. Gilje |
| 32381 | * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH |
| 32382 | * Copyright 2016 (c) TorbenD |
| 32383 | * Copyright 2017 (c) frax2222 |
| 32384 | * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB |
| 32385 | * Copyright 2019 (c) Kalycito Infotech Private Limited |
| 32386 | * Copyright 2023 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Phuong Nguyen) |
| 32387 | */ |
| 32388 | |
| 32389 | |
| 32390 | |
| 32391 | #define STARTCHANNELID 1 |
| 32392 | #define STARTTOKENID 1 |
| 32393 | |
| 32394 | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| 32395 | // store the authentication token and session ID so we can help fuzzing by setting |
| 32396 | // these values in the next request automatically |
| 32397 | UA_NodeId unsafe_fuzz_authenticationToken = {0, UA_NODEIDTYPE_NUMERIC, {0}}; |
| 32398 | #endif |
| 32399 | |
| 32400 | #ifdef UA_DEBUG_DUMP_PKGS_FILE |
| 32401 | void UA_debug_dumpCompleteChunk(UA_Server *const server, UA_Connection *const connection, |
| 32402 | UA_ByteString *messageBuffer); |
| 32403 | #endif |
| 32404 | |
| 32405 | /************************************/ |
| 32406 | /* Binary Protocol Server Component */ |
| 32407 | /************************************/ |
| 32408 | |
| 32409 | /* Maximum numbers of sockets to listen on */ |
| 32410 | #define UA_MAXSERVERCONNECTIONS 16 |
| 32411 | |
| 32412 | /* SecureChannel Linked List */ |
| 32413 | typedef struct channel_entry { |
| 32414 | UA_SecureChannel channel; |
| 32415 | TAILQ_ENTRY(channel_entry) pointers; |
| 32416 | } channel_entry; |
| 32417 | |
| 32418 | typedef struct { |
| 32419 | UA_ConnectionState state; |
| 32420 | uintptr_t connectionId; |
| 32421 | UA_ConnectionManager *connectionManager; |
| 32422 | } UA_ServerConnection; |
| 32423 | |
| 32424 | /* Reverse connect */ |
| 32425 | typedef struct reverse_connect_context { |
| 32426 | UA_String hostname; |
| 32427 | UA_UInt16 port; |
| 32428 | UA_UInt64 handle; |
| 32429 | |
| 32430 | UA_SecureChannelState state; |
| 32431 | UA_Server_ReverseConnectStateCallback stateCallback; |
| 32432 | void *callbackContext; |
| 32433 | |
| 32434 | /* If this is set to true, the reverse connection is removed/freed when the |
| 32435 | * connection closes. Otherwise we try to reconnect when the connection |
| 32436 | * closes. */ |
| 32437 | UA_Boolean destruction; |
| 32438 | |
| 32439 | UA_ServerConnection currentConnection; |
| 32440 | UA_SecureChannel *channel; |
| 32441 | LIST_ENTRY(reverse_connect_context) next; |
| 32442 | } reverse_connect_context; |
| 32443 | |
| 32444 | /* Binary Protocol Manager */ |
| 32445 | typedef struct { |
| 32446 | UA_ServerComponent sc; |
| 32447 | UA_Server *server; /* remember the pointer so we don't need an additional |
| 32448 | context pointer for connections */ |
| 32449 | const UA_Logger *logging; /* shortcut */ |
| 32450 | UA_UInt64 houseKeepingCallbackId; |
| 32451 | |
| 32452 | UA_ServerConnection serverConnections[UA_MAXSERVERCONNECTIONS]; |
| 32453 | size_t serverConnectionsSize; |
| 32454 | |
| 32455 | UA_ConnectionConfig tcpConnectionConfig; /* Extracted from the server config |
| 32456 | * parameters */ |
| 32457 | |
| 32458 | /* SecureChannels */ |
| 32459 | TAILQ_HEAD(, channel_entry) channels; |
| 32460 | UA_UInt32 lastChannelId; |
| 32461 | UA_UInt32 lastTokenId; |
| 32462 | |
| 32463 | /* Reverse Connections */ |
| 32464 | LIST_HEAD(, reverse_connect_context) reverseConnects; |
| 32465 | UA_UInt64 reverseConnectsCheckHandle; |
| 32466 | UA_UInt64 lastReverseConnectHandle; |
| 32467 | } UA_BinaryProtocolManager; |
| 32468 | |
| 32469 | void setReverseConnectState(UA_Server *server, reverse_connect_context *context, |
| 32470 | UA_SecureChannelState newState); |
| 32471 | UA_StatusCode attemptReverseConnect(UA_BinaryProtocolManager *bpm, |
| 32472 | reverse_connect_context *context); |
| 32473 | UA_StatusCode setReverseConnectRetryCallback(UA_BinaryProtocolManager *bpm, |
| 32474 | UA_Boolean enabled); |
| 32475 | |
| 32476 | /********************/ |
| 32477 | /* Helper Functions */ |
| 32478 | /********************/ |
| 32479 | |
| 32480 | UA_UInt32 |
| 32481 | generateSecureChannelTokenId(UA_Server *server) { |
| 32482 | UA_ServerComponent *sc = |
| 32483 | getServerComponentByName(server, name: UA_STRING(chars: "binary")); |
| 32484 | if(!sc) { |
| 32485 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 32486 | msg: "Cannot generate a SecureChannel Token Id. " |
| 32487 | "No BinaryProtocolManager configured."); |
| 32488 | return 0; |
| 32489 | } |
| 32490 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)sc; |
| 32491 | return bpm->lastTokenId++; |
| 32492 | } |
| 32493 | |
| 32494 | static void |
| 32495 | setBinaryProtocolManagerState(UA_Server *server, |
| 32496 | UA_BinaryProtocolManager *bpm, |
| 32497 | UA_LifecycleState state) { |
| 32498 | if(state == bpm->sc.state) |
| 32499 | return; |
| 32500 | bpm->sc.state = state; |
| 32501 | if(bpm->sc.notifyState) |
| 32502 | bpm->sc.notifyState(server, &bpm->sc, state); |
| 32503 | } |
| 32504 | |
| 32505 | static void |
| 32506 | deleteServerSecureChannel(UA_BinaryProtocolManager *bpm, |
| 32507 | UA_SecureChannel *channel) { |
| 32508 | UA_LOCK_ASSERT(&bpm->server->serviceMutex, 1); |
| 32509 | |
| 32510 | /* Detach the channel from the server list */ |
| 32511 | TAILQ_REMOVE(&bpm->channels, (channel_entry*)channel, pointers); |
| 32512 | |
| 32513 | /* Update the statistics */ |
| 32514 | UA_SecureChannelStatistics *scs = &bpm->server->secureChannelStatistics; |
| 32515 | scs->currentChannelCount--; |
| 32516 | switch(channel->shutdownReason) { |
| 32517 | case UA_SHUTDOWNREASON_CLOSE: |
| 32518 | UA_LOG_INFO_CHANNEL(bpm->logging, channel, "SecureChannel closed"); |
| 32519 | break; |
| 32520 | case UA_SHUTDOWNREASON_TIMEOUT: |
| 32521 | UA_LOG_INFO_CHANNEL(bpm->logging, channel, "SecureChannel closed due to timeout"); |
| 32522 | scs->channelTimeoutCount++; |
| 32523 | break; |
| 32524 | case UA_SHUTDOWNREASON_PURGE: |
| 32525 | UA_LOG_INFO_CHANNEL(bpm->logging, channel, "SecureChannel was purged"); |
| 32526 | scs->channelPurgeCount++; |
| 32527 | break; |
| 32528 | case UA_SHUTDOWNREASON_REJECT: |
| 32529 | case UA_SHUTDOWNREASON_SECURITYREJECT: |
| 32530 | UA_LOG_INFO_CHANNEL(bpm->logging, channel, "SecureChannel was rejected"); |
| 32531 | scs->rejectedChannelCount++; |
| 32532 | break; |
| 32533 | case UA_SHUTDOWNREASON_ABORT: |
| 32534 | UA_LOG_INFO_CHANNEL(bpm->logging, channel, "SecureChannel was aborted"); |
| 32535 | scs->channelAbortCount++; |
| 32536 | break; |
| 32537 | default: |
| 32538 | UA_assert(false); |
| 32539 | break; |
| 32540 | } |
| 32541 | |
| 32542 | /* Clean up the SecureChannel. This is the only place where |
| 32543 | * UA_SecureChannel_clear must be called within the server code-base. */ |
| 32544 | UA_SecureChannel_clear(channel); |
| 32545 | UA_free(ptr: channel); |
| 32546 | } |
| 32547 | |
| 32548 | UA_StatusCode |
| 32549 | sendServiceFault(UA_SecureChannel *channel, UA_UInt32 requestId, |
| 32550 | UA_UInt32 requestHandle, UA_StatusCode statusCode) { |
| 32551 | UA_ServiceFault response; |
| 32552 | UA_ServiceFault_init(p: &response); |
| 32553 | UA_ResponseHeader *responseHeader = &response.responseHeader; |
| 32554 | responseHeader->requestHandle = requestHandle; |
| 32555 | responseHeader->timestamp = UA_DateTime_now(); |
| 32556 | responseHeader->serviceResult = statusCode; |
| 32557 | |
| 32558 | UA_LOG_DEBUG(logger: channel->securityPolicy->logger, category: UA_LOGCATEGORY_SERVER, |
| 32559 | msg: "Sending response for RequestId %u with ServiceResult %s", |
| 32560 | (unsigned)requestId, UA_StatusCode_name(code: statusCode)); |
| 32561 | |
| 32562 | /* Send error message. Message type is MSG and not ERR, since we are on a |
| 32563 | * SecureChannel! */ |
| 32564 | return UA_SecureChannel_sendSymmetricMessage(channel, requestId, |
| 32565 | messageType: UA_MESSAGETYPE_MSG, payload: &response, |
| 32566 | payloadType: &UA_TYPES[UA_TYPES_SERVICEFAULT]); |
| 32567 | } |
| 32568 | |
| 32569 | /* This is not an ERR message, the connection is not closed afterwards */ |
| 32570 | static UA_StatusCode |
| 32571 | decodeHeaderSendServiceFault(UA_SecureChannel *channel, const UA_ByteString *msg, |
| 32572 | size_t offset, const UA_DataType *responseType, |
| 32573 | UA_UInt32 requestId, UA_StatusCode error) { |
| 32574 | UA_RequestHeader requestHeader; |
| 32575 | UA_StatusCode retval = |
| 32576 | UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &requestHeader, |
| 32577 | type: &UA_TYPES[UA_TYPES_REQUESTHEADER], NULL); |
| 32578 | if(retval != UA_STATUSCODE_GOOD) |
| 32579 | return retval; |
| 32580 | retval = sendServiceFault(channel, requestId, requestHandle: requestHeader.requestHandle, statusCode: error); |
| 32581 | UA_RequestHeader_clear(p: &requestHeader); |
| 32582 | return retval; |
| 32583 | } |
| 32584 | |
| 32585 | /* The counterOffset is the offset of the UA_ServiceCounterDataType for the |
| 32586 | * service in the UA_ SessionDiagnosticsDataType. */ |
| 32587 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 32588 | #define UA_SERVICECOUNTER_OFFSET(X) \ |
| 32589 | *counterOffset = offsetof(UA_SessionDiagnosticsDataType, X) |
| 32590 | #else |
| 32591 | #define UA_SERVICECOUNTER_OFFSET(X) |
| 32592 | #endif |
| 32593 | |
| 32594 | static void |
| 32595 | getServicePointers(UA_UInt32 requestTypeId, const UA_DataType **requestType, |
| 32596 | const UA_DataType **responseType, UA_Service *service, |
| 32597 | UA_Boolean *requiresSession, size_t *counterOffset) { |
| 32598 | switch(requestTypeId) { |
| 32599 | case UA_NS0ID_GETENDPOINTSREQUEST_ENCODING_DEFAULTBINARY: |
| 32600 | *service = (UA_Service)Service_GetEndpoints; |
| 32601 | *requestType = &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST]; |
| 32602 | *responseType = &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]; |
| 32603 | *requiresSession = false; |
| 32604 | break; |
| 32605 | case UA_NS0ID_FINDSERVERSREQUEST_ENCODING_DEFAULTBINARY: |
| 32606 | *service = (UA_Service)Service_FindServers; |
| 32607 | *requestType = &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST]; |
| 32608 | *responseType = &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]; |
| 32609 | *requiresSession = false; |
| 32610 | break; |
| 32611 | #ifdef UA_ENABLE_DISCOVERY |
| 32612 | # ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 32613 | case UA_NS0ID_FINDSERVERSONNETWORKREQUEST_ENCODING_DEFAULTBINARY: |
| 32614 | *service = (UA_Service)Service_FindServersOnNetwork; |
| 32615 | *requestType = &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST]; |
| 32616 | *responseType = &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE]; |
| 32617 | *requiresSession = false; |
| 32618 | break; |
| 32619 | # endif |
| 32620 | case UA_NS0ID_REGISTERSERVERREQUEST_ENCODING_DEFAULTBINARY: |
| 32621 | *service = (UA_Service)Service_RegisterServer; |
| 32622 | *requestType = &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST]; |
| 32623 | *responseType = &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]; |
| 32624 | *requiresSession = false; |
| 32625 | break; |
| 32626 | case UA_NS0ID_REGISTERSERVER2REQUEST_ENCODING_DEFAULTBINARY: |
| 32627 | *service = (UA_Service)Service_RegisterServer2; |
| 32628 | *requestType = &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST]; |
| 32629 | *responseType = &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]; |
| 32630 | *requiresSession = false; |
| 32631 | break; |
| 32632 | #endif |
| 32633 | case UA_NS0ID_CREATESESSIONREQUEST_ENCODING_DEFAULTBINARY: |
| 32634 | *service = (UA_Service)Service_CreateSession; |
| 32635 | *requestType = &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]; |
| 32636 | *responseType = &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE]; |
| 32637 | *requiresSession = false; |
| 32638 | break; |
| 32639 | case UA_NS0ID_ACTIVATESESSIONREQUEST_ENCODING_DEFAULTBINARY: |
| 32640 | *service = (UA_Service)Service_ActivateSession; |
| 32641 | *requestType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST]; |
| 32642 | *responseType = &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE]; |
| 32643 | break; |
| 32644 | case UA_NS0ID_CLOSESESSIONREQUEST_ENCODING_DEFAULTBINARY: |
| 32645 | *service = (UA_Service)Service_CloseSession; |
| 32646 | *requestType = &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]; |
| 32647 | *responseType = &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]; |
| 32648 | break; |
| 32649 | case UA_NS0ID_CANCELREQUEST_ENCODING_DEFAULTBINARY: |
| 32650 | *service = (UA_Service)Service_Cancel; |
| 32651 | *requestType = &UA_TYPES[UA_TYPES_CANCELREQUEST]; |
| 32652 | *responseType = &UA_TYPES[UA_TYPES_CANCELRESPONSE]; |
| 32653 | break; |
| 32654 | case UA_NS0ID_READREQUEST_ENCODING_DEFAULTBINARY: |
| 32655 | *service = (UA_Service)Service_Read; |
| 32656 | *requestType = &UA_TYPES[UA_TYPES_READREQUEST]; |
| 32657 | *responseType = &UA_TYPES[UA_TYPES_READRESPONSE]; |
| 32658 | UA_SERVICECOUNTER_OFFSET(readCount); |
| 32659 | break; |
| 32660 | case UA_NS0ID_WRITEREQUEST_ENCODING_DEFAULTBINARY: |
| 32661 | *service = (UA_Service)Service_Write; |
| 32662 | *requestType = &UA_TYPES[UA_TYPES_WRITEREQUEST]; |
| 32663 | *responseType = &UA_TYPES[UA_TYPES_WRITERESPONSE]; |
| 32664 | UA_SERVICECOUNTER_OFFSET(writeCount); |
| 32665 | break; |
| 32666 | case UA_NS0ID_BROWSEREQUEST_ENCODING_DEFAULTBINARY: |
| 32667 | *service = (UA_Service)Service_Browse; |
| 32668 | *requestType = &UA_TYPES[UA_TYPES_BROWSEREQUEST]; |
| 32669 | *responseType = &UA_TYPES[UA_TYPES_BROWSERESPONSE]; |
| 32670 | UA_SERVICECOUNTER_OFFSET(browseCount); |
| 32671 | break; |
| 32672 | case UA_NS0ID_BROWSENEXTREQUEST_ENCODING_DEFAULTBINARY: |
| 32673 | *service = (UA_Service)Service_BrowseNext; |
| 32674 | *requestType = &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST]; |
| 32675 | *responseType = &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE]; |
| 32676 | UA_SERVICECOUNTER_OFFSET(browseNextCount); |
| 32677 | break; |
| 32678 | case UA_NS0ID_REGISTERNODESREQUEST_ENCODING_DEFAULTBINARY: |
| 32679 | *service = (UA_Service)Service_RegisterNodes; |
| 32680 | *requestType = &UA_TYPES[UA_TYPES_REGISTERNODESREQUEST]; |
| 32681 | *responseType = &UA_TYPES[UA_TYPES_REGISTERNODESRESPONSE]; |
| 32682 | UA_SERVICECOUNTER_OFFSET(registerNodesCount); |
| 32683 | break; |
| 32684 | case UA_NS0ID_UNREGISTERNODESREQUEST_ENCODING_DEFAULTBINARY: |
| 32685 | *service = (UA_Service)Service_UnregisterNodes; |
| 32686 | *requestType = &UA_TYPES[UA_TYPES_UNREGISTERNODESREQUEST]; |
| 32687 | *responseType = &UA_TYPES[UA_TYPES_UNREGISTERNODESRESPONSE]; |
| 32688 | UA_SERVICECOUNTER_OFFSET(unregisterNodesCount); |
| 32689 | break; |
| 32690 | case UA_NS0ID_TRANSLATEBROWSEPATHSTONODEIDSREQUEST_ENCODING_DEFAULTBINARY: |
| 32691 | *service = (UA_Service)Service_TranslateBrowsePathsToNodeIds; |
| 32692 | *requestType = &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSREQUEST]; |
| 32693 | *responseType = &UA_TYPES[UA_TYPES_TRANSLATEBROWSEPATHSTONODEIDSRESPONSE]; |
| 32694 | UA_SERVICECOUNTER_OFFSET(translateBrowsePathsToNodeIdsCount); |
| 32695 | break; |
| 32696 | |
| 32697 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 32698 | case UA_NS0ID_CREATESUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY: |
| 32699 | *service = (UA_Service)Service_CreateSubscription; |
| 32700 | *requestType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST]; |
| 32701 | *responseType = &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]; |
| 32702 | UA_SERVICECOUNTER_OFFSET(createSubscriptionCount); |
| 32703 | break; |
| 32704 | case UA_NS0ID_PUBLISHREQUEST_ENCODING_DEFAULTBINARY: |
| 32705 | *requestType = &UA_TYPES[UA_TYPES_PUBLISHREQUEST]; |
| 32706 | *responseType = &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]; |
| 32707 | UA_SERVICECOUNTER_OFFSET(publishCount); |
| 32708 | break; |
| 32709 | case UA_NS0ID_REPUBLISHREQUEST_ENCODING_DEFAULTBINARY: |
| 32710 | *service = (UA_Service)Service_Republish; |
| 32711 | *requestType = &UA_TYPES[UA_TYPES_REPUBLISHREQUEST]; |
| 32712 | *responseType = &UA_TYPES[UA_TYPES_REPUBLISHRESPONSE]; |
| 32713 | UA_SERVICECOUNTER_OFFSET(republishCount); |
| 32714 | break; |
| 32715 | case UA_NS0ID_MODIFYSUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY: |
| 32716 | *service = (UA_Service)Service_ModifySubscription; |
| 32717 | *requestType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST]; |
| 32718 | *responseType = &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]; |
| 32719 | UA_SERVICECOUNTER_OFFSET(modifySubscriptionCount); |
| 32720 | break; |
| 32721 | case UA_NS0ID_SETPUBLISHINGMODEREQUEST_ENCODING_DEFAULTBINARY: |
| 32722 | *service = (UA_Service)Service_SetPublishingMode; |
| 32723 | *requestType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODEREQUEST]; |
| 32724 | *responseType = &UA_TYPES[UA_TYPES_SETPUBLISHINGMODERESPONSE]; |
| 32725 | UA_SERVICECOUNTER_OFFSET(setPublishingModeCount); |
| 32726 | break; |
| 32727 | case UA_NS0ID_DELETESUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY: |
| 32728 | *service = (UA_Service)Service_DeleteSubscriptions; |
| 32729 | *requestType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST]; |
| 32730 | *responseType = &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]; |
| 32731 | UA_SERVICECOUNTER_OFFSET(deleteSubscriptionsCount); |
| 32732 | break; |
| 32733 | case UA_NS0ID_TRANSFERSUBSCRIPTIONSREQUEST_ENCODING_DEFAULTBINARY: |
| 32734 | *service = (UA_Service)Service_TransferSubscriptions; |
| 32735 | *requestType = &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSREQUEST]; |
| 32736 | *responseType = &UA_TYPES[UA_TYPES_TRANSFERSUBSCRIPTIONSRESPONSE]; |
| 32737 | UA_SERVICECOUNTER_OFFSET(transferSubscriptionsCount); |
| 32738 | break; |
| 32739 | case UA_NS0ID_CREATEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY: |
| 32740 | *service = (UA_Service)Service_CreateMonitoredItems; |
| 32741 | *requestType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST]; |
| 32742 | *responseType = &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]; |
| 32743 | UA_SERVICECOUNTER_OFFSET(createMonitoredItemsCount); |
| 32744 | break; |
| 32745 | case UA_NS0ID_DELETEMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY: |
| 32746 | *service = (UA_Service)Service_DeleteMonitoredItems; |
| 32747 | *requestType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST]; |
| 32748 | *responseType = &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]; |
| 32749 | UA_SERVICECOUNTER_OFFSET(deleteMonitoredItemsCount); |
| 32750 | break; |
| 32751 | case UA_NS0ID_MODIFYMONITOREDITEMSREQUEST_ENCODING_DEFAULTBINARY: |
| 32752 | *service = (UA_Service)Service_ModifyMonitoredItems; |
| 32753 | *requestType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST]; |
| 32754 | *responseType = &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE]; |
| 32755 | UA_SERVICECOUNTER_OFFSET(modifyMonitoredItemsCount); |
| 32756 | break; |
| 32757 | case UA_NS0ID_SETMONITORINGMODEREQUEST_ENCODING_DEFAULTBINARY: |
| 32758 | *service = (UA_Service)Service_SetMonitoringMode; |
| 32759 | *requestType = &UA_TYPES[UA_TYPES_SETMONITORINGMODEREQUEST]; |
| 32760 | *responseType = &UA_TYPES[UA_TYPES_SETMONITORINGMODERESPONSE]; |
| 32761 | UA_SERVICECOUNTER_OFFSET(setMonitoringModeCount); |
| 32762 | break; |
| 32763 | case UA_NS0ID_SETTRIGGERINGREQUEST_ENCODING_DEFAULTBINARY: |
| 32764 | *service = (UA_Service)Service_SetTriggering; |
| 32765 | *requestType = &UA_TYPES[UA_TYPES_SETTRIGGERINGREQUEST]; |
| 32766 | *responseType = &UA_TYPES[UA_TYPES_SETTRIGGERINGRESPONSE]; |
| 32767 | UA_SERVICECOUNTER_OFFSET(setTriggeringCount); |
| 32768 | break; |
| 32769 | #endif |
| 32770 | #ifdef UA_ENABLE_HISTORIZING |
| 32771 | /* For History read */ |
| 32772 | case UA_NS0ID_HISTORYREADREQUEST_ENCODING_DEFAULTBINARY: |
| 32773 | *service = (UA_Service)Service_HistoryRead; |
| 32774 | *requestType = &UA_TYPES[UA_TYPES_HISTORYREADREQUEST]; |
| 32775 | *responseType = &UA_TYPES[UA_TYPES_HISTORYREADRESPONSE]; |
| 32776 | UA_SERVICECOUNTER_OFFSET(historyReadCount); |
| 32777 | break; |
| 32778 | /* For History update */ |
| 32779 | case UA_NS0ID_HISTORYUPDATEREQUEST_ENCODING_DEFAULTBINARY: |
| 32780 | *service = (UA_Service)Service_HistoryUpdate; |
| 32781 | *requestType = &UA_TYPES[UA_TYPES_HISTORYUPDATEREQUEST]; |
| 32782 | *responseType = &UA_TYPES[UA_TYPES_HISTORYUPDATERESPONSE]; |
| 32783 | UA_SERVICECOUNTER_OFFSET(historyUpdateCount); |
| 32784 | break; |
| 32785 | #endif |
| 32786 | |
| 32787 | #ifdef UA_ENABLE_METHODCALLS |
| 32788 | case UA_NS0ID_CALLREQUEST_ENCODING_DEFAULTBINARY: |
| 32789 | *service = (UA_Service)Service_Call; |
| 32790 | *requestType = &UA_TYPES[UA_TYPES_CALLREQUEST]; |
| 32791 | *responseType = &UA_TYPES[UA_TYPES_CALLRESPONSE]; |
| 32792 | UA_SERVICECOUNTER_OFFSET(callCount); |
| 32793 | break; |
| 32794 | #endif |
| 32795 | |
| 32796 | #ifdef UA_ENABLE_NODEMANAGEMENT |
| 32797 | case UA_NS0ID_ADDNODESREQUEST_ENCODING_DEFAULTBINARY: |
| 32798 | *service = (UA_Service)Service_AddNodes; |
| 32799 | *requestType = &UA_TYPES[UA_TYPES_ADDNODESREQUEST]; |
| 32800 | *responseType = &UA_TYPES[UA_TYPES_ADDNODESRESPONSE]; |
| 32801 | UA_SERVICECOUNTER_OFFSET(addNodesCount); |
| 32802 | break; |
| 32803 | case UA_NS0ID_ADDREFERENCESREQUEST_ENCODING_DEFAULTBINARY: |
| 32804 | *service = (UA_Service)Service_AddReferences; |
| 32805 | *requestType = &UA_TYPES[UA_TYPES_ADDREFERENCESREQUEST]; |
| 32806 | *responseType = &UA_TYPES[UA_TYPES_ADDREFERENCESRESPONSE]; |
| 32807 | UA_SERVICECOUNTER_OFFSET(addReferencesCount); |
| 32808 | break; |
| 32809 | case UA_NS0ID_DELETENODESREQUEST_ENCODING_DEFAULTBINARY: |
| 32810 | *service = (UA_Service)Service_DeleteNodes; |
| 32811 | *requestType = &UA_TYPES[UA_TYPES_DELETENODESREQUEST]; |
| 32812 | *responseType = &UA_TYPES[UA_TYPES_DELETENODESRESPONSE]; |
| 32813 | UA_SERVICECOUNTER_OFFSET(deleteNodesCount); |
| 32814 | break; |
| 32815 | case UA_NS0ID_DELETEREFERENCESREQUEST_ENCODING_DEFAULTBINARY: |
| 32816 | *service = (UA_Service)Service_DeleteReferences; |
| 32817 | *requestType = &UA_TYPES[UA_TYPES_DELETEREFERENCESREQUEST]; |
| 32818 | *responseType = &UA_TYPES[UA_TYPES_DELETEREFERENCESRESPONSE]; |
| 32819 | UA_SERVICECOUNTER_OFFSET(deleteReferencesCount); |
| 32820 | break; |
| 32821 | #endif |
| 32822 | |
| 32823 | default: |
| 32824 | break; |
| 32825 | } |
| 32826 | } |
| 32827 | |
| 32828 | /*************************/ |
| 32829 | /* Process Message Types */ |
| 32830 | /*************************/ |
| 32831 | |
| 32832 | /* HEL -> Open up the connection */ |
| 32833 | static UA_StatusCode |
| 32834 | processHEL(UA_Server *server, UA_SecureChannel *channel, const UA_ByteString *msg) { |
| 32835 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 32836 | |
| 32837 | UA_ConnectionManager *cm = channel->connectionManager; |
| 32838 | if(!cm || (channel->state != UA_SECURECHANNELSTATE_CONNECTED && |
| 32839 | channel->state != UA_SECURECHANNELSTATE_RHE_SENT)) |
| 32840 | return UA_STATUSCODE_BADINTERNALERROR; |
| 32841 | |
| 32842 | size_t offset = 0; /* Go to the beginning of the TcpHelloMessage */ |
| 32843 | UA_TcpHelloMessage helloMessage; |
| 32844 | UA_StatusCode retval = |
| 32845 | UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &helloMessage, |
| 32846 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE], NULL); |
| 32847 | if(retval != UA_STATUSCODE_GOOD) |
| 32848 | return retval; |
| 32849 | |
| 32850 | /* Currently not checked */ |
| 32851 | UA_String_copy(src: &helloMessage.endpointUrl, dst: &channel->endpointUrl); |
| 32852 | UA_String_clear(p: &helloMessage.endpointUrl); |
| 32853 | |
| 32854 | /* Parameterize the connection. The TcpHelloMessage casts to a |
| 32855 | * TcpAcknowledgeMessage. */ |
| 32856 | retval = UA_SecureChannel_processHELACK(channel, |
| 32857 | remoteConfig: (UA_TcpAcknowledgeMessage*)&helloMessage); |
| 32858 | if(retval != UA_STATUSCODE_GOOD) { |
| 32859 | UA_LOG_INFO_CHANNEL(server->config.logging, channel, |
| 32860 | "Error during the HEL/ACK handshake"); |
| 32861 | return retval; |
| 32862 | } |
| 32863 | |
| 32864 | /* Get the send buffer from the network layer */ |
| 32865 | UA_ByteString ack_msg; |
| 32866 | UA_ByteString_init(p: &ack_msg); |
| 32867 | retval = cm->allocNetworkBuffer(cm, channel->connectionId, |
| 32868 | &ack_msg, channel->config.sendBufferSize); |
| 32869 | if(retval != UA_STATUSCODE_GOOD) |
| 32870 | return retval; |
| 32871 | |
| 32872 | /* Build acknowledge response */ |
| 32873 | UA_TcpAcknowledgeMessage ackMessage; |
| 32874 | ackMessage.protocolVersion = 0; |
| 32875 | ackMessage.receiveBufferSize = channel->config.recvBufferSize; |
| 32876 | ackMessage.sendBufferSize = channel->config.sendBufferSize; |
| 32877 | ackMessage.maxMessageSize = channel->config.localMaxMessageSize; |
| 32878 | ackMessage.maxChunkCount = channel->config.localMaxChunkCount; |
| 32879 | |
| 32880 | UA_TcpMessageHeader ackHeader; |
| 32881 | ackHeader.messageTypeAndChunkType = UA_MESSAGETYPE_ACK + UA_CHUNKTYPE_FINAL; |
| 32882 | ackHeader.messageSize = 8 + 20; /* ackHeader + ackMessage */ |
| 32883 | |
| 32884 | /* Encode and send the response */ |
| 32885 | UA_Byte *bufPos = ack_msg.data; |
| 32886 | const UA_Byte *bufEnd = &ack_msg.data[ack_msg.length]; |
| 32887 | retval |= UA_encodeBinaryInternal(src: &ackHeader, |
| 32888 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], |
| 32889 | bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 32890 | retval |= UA_encodeBinaryInternal(src: &ackMessage, |
| 32891 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE], |
| 32892 | bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 32893 | if(retval != UA_STATUSCODE_GOOD) { |
| 32894 | cm->freeNetworkBuffer(cm, channel->connectionId, &ack_msg); |
| 32895 | return retval; |
| 32896 | } |
| 32897 | |
| 32898 | ack_msg.length = ackHeader.messageSize; |
| 32899 | retval = cm->sendWithConnection(cm, channel->connectionId, &UA_KEYVALUEMAP_NULL, &ack_msg); |
| 32900 | if(retval == UA_STATUSCODE_GOOD) |
| 32901 | channel->state = UA_SECURECHANNELSTATE_ACK_SENT; |
| 32902 | return retval; |
| 32903 | } |
| 32904 | |
| 32905 | /* OPN -> Open up/renew the securechannel */ |
| 32906 | static UA_StatusCode |
| 32907 | processOPN(UA_Server *server, UA_SecureChannel *channel, |
| 32908 | const UA_UInt32 requestId, const UA_ByteString *msg) { |
| 32909 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 32910 | |
| 32911 | if(channel->state != UA_SECURECHANNELSTATE_ACK_SENT && |
| 32912 | channel->state != UA_SECURECHANNELSTATE_OPEN) |
| 32913 | return UA_STATUSCODE_BADINTERNALERROR; |
| 32914 | /* Decode the request */ |
| 32915 | UA_NodeId requestType; |
| 32916 | UA_OpenSecureChannelRequest openSecureChannelRequest; |
| 32917 | size_t offset = 0; |
| 32918 | UA_StatusCode retval = UA_NodeId_decodeBinary(src: msg, offset: &offset, dst: &requestType); |
| 32919 | if(retval != UA_STATUSCODE_GOOD) { |
| 32920 | UA_NodeId_clear(p: &requestType); |
| 32921 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 32922 | "Could not decode the NodeId. " |
| 32923 | "Closing the SecureChannel."); |
| 32924 | UA_SecureChannel_shutdown(channel, shutdownReason: UA_SHUTDOWNREASON_REJECT); |
| 32925 | return retval; |
| 32926 | } |
| 32927 | retval = UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &openSecureChannelRequest, |
| 32928 | type: &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST], NULL); |
| 32929 | |
| 32930 | /* Error occurred */ |
| 32931 | const UA_NodeId *opnRequestId = |
| 32932 | &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST].binaryEncodingId; |
| 32933 | if(retval != UA_STATUSCODE_GOOD || !UA_NodeId_equal(p1: &requestType, p2: opnRequestId)) { |
| 32934 | UA_NodeId_clear(p: &requestType); |
| 32935 | UA_OpenSecureChannelRequest_clear(p: &openSecureChannelRequest); |
| 32936 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 32937 | "Could not decode the OPN message. " |
| 32938 | "Closing the SecureChannel."); |
| 32939 | UA_SecureChannel_shutdown(channel, shutdownReason: UA_SHUTDOWNREASON_REJECT); |
| 32940 | return retval; |
| 32941 | } |
| 32942 | UA_NodeId_clear(p: &requestType); |
| 32943 | |
| 32944 | /* Call the service */ |
| 32945 | UA_OpenSecureChannelResponse openScResponse; |
| 32946 | UA_OpenSecureChannelResponse_init(p: &openScResponse); |
| 32947 | Service_OpenSecureChannel(server, channel, request: &openSecureChannelRequest, response: &openScResponse); |
| 32948 | UA_OpenSecureChannelRequest_clear(p: &openSecureChannelRequest); |
| 32949 | if(openScResponse.responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 32950 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 32951 | "Could not open a SecureChannel. " |
| 32952 | "Closing the connection."); |
| 32953 | UA_SecureChannel_shutdown(channel, shutdownReason: UA_SHUTDOWNREASON_REJECT); |
| 32954 | return openScResponse.responseHeader.serviceResult; |
| 32955 | } |
| 32956 | |
| 32957 | /* Send the response */ |
| 32958 | retval = UA_SecureChannel_sendAsymmetricOPNMessage(channel, requestId, content: &openScResponse, |
| 32959 | contentType: &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE]); |
| 32960 | UA_OpenSecureChannelResponse_clear(p: &openScResponse); |
| 32961 | if(retval != UA_STATUSCODE_GOOD) { |
| 32962 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 32963 | "Could not send the OPN answer with error code %s", |
| 32964 | UA_StatusCode_name(retval)); |
| 32965 | UA_SecureChannel_shutdown(channel, shutdownReason: UA_SHUTDOWNREASON_REJECT); |
| 32966 | } |
| 32967 | |
| 32968 | return retval; |
| 32969 | } |
| 32970 | |
| 32971 | /* The responseHeader must have the requestHandle already set */ |
| 32972 | UA_StatusCode |
| 32973 | sendResponse(UA_Server *server, UA_Session *session, UA_SecureChannel *channel, |
| 32974 | UA_UInt32 requestId, UA_Response *response, const UA_DataType *responseType) { |
| 32975 | if(!channel) |
| 32976 | return UA_STATUSCODE_BADINTERNALERROR; |
| 32977 | |
| 32978 | /* If the overall service call failed, answer with a ServiceFault */ |
| 32979 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) |
| 32980 | return sendServiceFault(channel, requestId, requestHandle: response->responseHeader.requestHandle, |
| 32981 | statusCode: response->responseHeader.serviceResult); |
| 32982 | |
| 32983 | /* Prepare the ResponseHeader */ |
| 32984 | response->responseHeader.timestamp = UA_DateTime_now(); |
| 32985 | |
| 32986 | if(session) { |
| 32987 | #ifdef UA_ENABLE_TYPEDESCRIPTION |
| 32988 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 32989 | "Sending response for RequestId %u of type %s", |
| 32990 | (unsigned)requestId, responseType->typeName); |
| 32991 | #else |
| 32992 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 32993 | "Sending reponse for RequestId %u of type %"PRIu32, |
| 32994 | (unsigned)requestId, responseType->binaryEncodingId.identifier.numeric); |
| 32995 | #endif |
| 32996 | } else { |
| 32997 | #ifdef UA_ENABLE_TYPEDESCRIPTION |
| 32998 | UA_LOG_DEBUG_CHANNEL(server->config.logging, channel, |
| 32999 | "Sending response for RequestId %u of type %s", |
| 33000 | (unsigned)requestId, responseType->typeName); |
| 33001 | #else |
| 33002 | UA_LOG_DEBUG_CHANNEL(server->config.logging, channel, |
| 33003 | "Sending reponse for RequestId %u of type %"PRIu32, |
| 33004 | (unsigned)requestId, responseType->binaryEncodingId.identifier.numeric); |
| 33005 | #endif |
| 33006 | } |
| 33007 | |
| 33008 | /* Start the message context */ |
| 33009 | UA_MessageContext mc; |
| 33010 | UA_StatusCode retval = UA_MessageContext_begin(mc: &mc, channel, requestId, messageType: UA_MESSAGETYPE_MSG); |
| 33011 | if(retval != UA_STATUSCODE_GOOD) |
| 33012 | return retval; |
| 33013 | |
| 33014 | /* Assert's required for clang-analyzer */ |
| 33015 | UA_assert(mc.buf_pos == &mc.messageBuffer.data[UA_SECURECHANNEL_SYMMETRIC_HEADER_TOTALLENGTH]); |
| 33016 | UA_assert(mc.buf_end <= &mc.messageBuffer.data[mc.messageBuffer.length]); |
| 33017 | |
| 33018 | /* Encode the response type */ |
| 33019 | retval = UA_MessageContext_encode(mc: &mc, content: &responseType->binaryEncodingId, |
| 33020 | contentType: &UA_TYPES[UA_TYPES_NODEID]); |
| 33021 | if(retval != UA_STATUSCODE_GOOD) |
| 33022 | return retval; |
| 33023 | |
| 33024 | /* Encode the response */ |
| 33025 | retval = UA_MessageContext_encode(mc: &mc, content: response, contentType: responseType); |
| 33026 | if(retval != UA_STATUSCODE_GOOD) |
| 33027 | return retval; |
| 33028 | |
| 33029 | /* Finish / send out */ |
| 33030 | return UA_MessageContext_finish(mc: &mc); |
| 33031 | } |
| 33032 | |
| 33033 | /* A Session is "bound" to a SecureChannel if it was created by the |
| 33034 | * SecureChannel or if it was activated on it. A Session can only be bound to |
| 33035 | * one SecureChannel. A Session can only be closed from the SecureChannel to |
| 33036 | * which it is bound. |
| 33037 | * |
| 33038 | * Returns Good if the AuthenticationToken exists nowhere (for CTT). */ |
| 33039 | UA_StatusCode |
| 33040 | getBoundSession(UA_Server *server, const UA_SecureChannel *channel, |
| 33041 | const UA_NodeId *token, UA_Session **session) { |
| 33042 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 33043 | |
| 33044 | UA_DateTime now = UA_DateTime_nowMonotonic(); |
| 33045 | UA_SessionHeader *sh; |
| 33046 | SLIST_FOREACH(sh, &channel->sessions, next) { |
| 33047 | if(!UA_NodeId_equal(p1: token, p2: &sh->authenticationToken)) |
| 33048 | continue; |
| 33049 | UA_Session *current = (UA_Session*)sh; |
| 33050 | /* Has the session timed out? */ |
| 33051 | if(current->validTill < now) { |
| 33052 | server->serverDiagnosticsSummary.rejectedSessionCount++; |
| 33053 | return UA_STATUSCODE_BADSESSIONCLOSED; |
| 33054 | } |
| 33055 | *session = current; |
| 33056 | return UA_STATUSCODE_GOOD; |
| 33057 | } |
| 33058 | |
| 33059 | server->serverDiagnosticsSummary.rejectedSessionCount++; |
| 33060 | |
| 33061 | /* Session exists on another SecureChannel. The CTT expect this error. */ |
| 33062 | UA_Session *tmpSession = getSessionByToken(server, token); |
| 33063 | if(tmpSession) { |
| 33064 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 33065 | tmpSession->diagnostics.unauthorizedRequestCount++; |
| 33066 | #endif |
| 33067 | return UA_STATUSCODE_BADSECURECHANNELIDINVALID; |
| 33068 | } |
| 33069 | |
| 33070 | return UA_STATUSCODE_GOOD; |
| 33071 | } |
| 33072 | |
| 33073 | static const UA_String securityPolicyNone = |
| 33074 | UA_STRING_STATIC("http://opcfoundation.org/UA/SecurityPolicy#None"); |
| 33075 | |
| 33076 | /* Returns a status of the SecureChannel. The detailed service status (usually |
| 33077 | * part of the response) is set in the serviceResult argument. */ |
| 33078 | static UA_StatusCode |
| 33079 | processMSGDecoded(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 requestId, |
| 33080 | UA_Service service, const UA_Request *request, |
| 33081 | const UA_DataType *requestType, UA_Response *response, |
| 33082 | const UA_DataType *responseType, UA_Boolean sessionRequired, |
| 33083 | size_t counterOffset) { |
| 33084 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 33085 | |
| 33086 | UA_Session anonymousSession; |
| 33087 | UA_Session *session = NULL; |
| 33088 | UA_StatusCode channelRes = UA_STATUSCODE_GOOD; |
| 33089 | UA_ResponseHeader *rh = &response->responseHeader; |
| 33090 | |
| 33091 | /* If it is an unencrypted (#None) channel, only allow the discovery services */ |
| 33092 | if(server->config.securityPolicyNoneDiscoveryOnly && |
| 33093 | UA_String_equal(p1: &channel->securityPolicy->policyUri, p2: &securityPolicyNone ) && |
| 33094 | requestType != &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST] && |
| 33095 | requestType != &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST] |
| 33096 | #if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST) |
| 33097 | && requestType != &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST] |
| 33098 | #endif |
| 33099 | ) { |
| 33100 | rh->serviceResult = UA_STATUSCODE_BADSECURITYPOLICYREJECTED; |
| 33101 | goto send_response; |
| 33102 | } |
| 33103 | |
| 33104 | /* Session lifecycle services. */ |
| 33105 | if(requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST] || |
| 33106 | requestType == &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST] || |
| 33107 | requestType == &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]) { |
| 33108 | ((UA_ChannelService)service)(server, channel, request, response); |
| 33109 | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| 33110 | /* Store the authentication token so we can help fuzzing by setting |
| 33111 | * these values in the next request automatically */ |
| 33112 | if(requestType == &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST]) { |
| 33113 | UA_CreateSessionResponse *res = &response->createSessionResponse; |
| 33114 | UA_NodeId_copy(&res->authenticationToken, &unsafe_fuzz_authenticationToken); |
| 33115 | } |
| 33116 | #endif |
| 33117 | goto send_response; |
| 33118 | } |
| 33119 | |
| 33120 | /* Get the Session bound to the SecureChannel (not necessarily activated) */ |
| 33121 | if(!UA_NodeId_isNull(p: &request->requestHeader.authenticationToken)) { |
| 33122 | rh->serviceResult = getBoundSession(server, channel, |
| 33123 | token: &request->requestHeader.authenticationToken, |
| 33124 | session: &session); |
| 33125 | if(rh->serviceResult != UA_STATUSCODE_GOOD) |
| 33126 | goto send_response; |
| 33127 | } |
| 33128 | |
| 33129 | /* Set an anonymous, inactive session for services that need no session */ |
| 33130 | if(!session) { |
| 33131 | if(sessionRequired) { |
| 33132 | #ifdef UA_ENABLE_TYPEDESCRIPTION |
| 33133 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 33134 | "%s refused without a valid session", |
| 33135 | requestType->typeName); |
| 33136 | #else |
| 33137 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 33138 | "Service %"PRIu32 " refused without a valid session", |
| 33139 | requestType->binaryEncodingId.identifier.numeric); |
| 33140 | #endif |
| 33141 | rh->serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID; |
| 33142 | goto send_response; |
| 33143 | } |
| 33144 | |
| 33145 | UA_Session_init(session: &anonymousSession); |
| 33146 | anonymousSession.sessionId = UA_NODEID_GUID(nsIndex: 0, guid: UA_GUID_NULL); |
| 33147 | anonymousSession.header.channel = channel; |
| 33148 | session = &anonymousSession; |
| 33149 | } |
| 33150 | |
| 33151 | UA_assert(session != NULL); |
| 33152 | |
| 33153 | /* Trying to use a non-activated session? */ |
| 33154 | if(sessionRequired && !session->activated) { |
| 33155 | #ifdef UA_ENABLE_TYPEDESCRIPTION |
| 33156 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 33157 | "%s refused on a non-activated session", |
| 33158 | requestType->typeName); |
| 33159 | #else |
| 33160 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 33161 | "Service %"PRIu32 " refused on a non-activated session", |
| 33162 | requestType->binaryEncodingId.identifier.numeric); |
| 33163 | #endif |
| 33164 | if(session != &anonymousSession) { |
| 33165 | UA_Server_removeSessionByToken(server, token: &session->header.authenticationToken, |
| 33166 | shutdownReason: UA_SHUTDOWNREASON_ABORT); |
| 33167 | } |
| 33168 | rh->serviceResult = UA_STATUSCODE_BADSESSIONNOTACTIVATED; |
| 33169 | goto send_response; |
| 33170 | } |
| 33171 | |
| 33172 | /* Update the session lifetime */ |
| 33173 | UA_Session_updateLifetime(session); |
| 33174 | |
| 33175 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 33176 | /* The publish request is not answered immediately */ |
| 33177 | if(requestType == &UA_TYPES[UA_TYPES_PUBLISHREQUEST]) { |
| 33178 | rh->serviceResult = |
| 33179 | Service_Publish(server, session, request: &request->publishRequest, requestId); |
| 33180 | |
| 33181 | /* Don't send a response */ |
| 33182 | goto update_statistics; |
| 33183 | } |
| 33184 | #endif |
| 33185 | |
| 33186 | #if UA_MULTITHREADING >= 100 && defined(UA_ENABLE_METHODCALLS) |
| 33187 | /* The call request might not be answered immediately */ |
| 33188 | if(requestType == &UA_TYPES[UA_TYPES_CALLREQUEST]) { |
| 33189 | UA_Boolean finished = true; |
| 33190 | Service_CallAsync(server, session, requestId, &request->callRequest, |
| 33191 | &response->callResponse, &finished); |
| 33192 | |
| 33193 | /* Async method calls remain. Don't send a response now. In case we have |
| 33194 | * an async call, count as a "good" request for the diagnostics |
| 33195 | * statistic. */ |
| 33196 | if(UA_LIKELY(finished)) |
| 33197 | goto send_response; |
| 33198 | goto update_statistics; |
| 33199 | } |
| 33200 | #endif |
| 33201 | |
| 33202 | /* Execute the synchronous service call */ |
| 33203 | service(server, session, request, response); |
| 33204 | |
| 33205 | /* Upon success, send the response. Otherwise a ServiceFault. */ |
| 33206 | send_response: |
| 33207 | channelRes = sendResponse(server, session, channel, |
| 33208 | requestId, response, responseType); |
| 33209 | |
| 33210 | /* Update the diagnostics statistics */ |
| 33211 | update_statistics: |
| 33212 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 33213 | if(session && session != &server->adminSession) { |
| 33214 | session->diagnostics.totalRequestCount.totalCount++; |
| 33215 | if(rh->serviceResult != UA_STATUSCODE_GOOD) |
| 33216 | session->diagnostics.totalRequestCount.errorCount++; |
| 33217 | if(counterOffset != 0) { |
| 33218 | UA_ServiceCounterDataType *serviceCounter = (UA_ServiceCounterDataType*) |
| 33219 | (((uintptr_t)&session->diagnostics) + counterOffset); |
| 33220 | serviceCounter->totalCount++; |
| 33221 | if(rh->serviceResult != UA_STATUSCODE_GOOD) |
| 33222 | serviceCounter->errorCount++; |
| 33223 | } |
| 33224 | } |
| 33225 | #endif |
| 33226 | |
| 33227 | return channelRes; |
| 33228 | } |
| 33229 | |
| 33230 | static UA_StatusCode |
| 33231 | processMSG(UA_Server *server, UA_SecureChannel *channel, |
| 33232 | UA_UInt32 requestId, const UA_ByteString *msg) { |
| 33233 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 33234 | |
| 33235 | if(channel->state != UA_SECURECHANNELSTATE_OPEN) |
| 33236 | return UA_STATUSCODE_BADINTERNALERROR; |
| 33237 | /* Decode the nodeid */ |
| 33238 | size_t offset = 0; |
| 33239 | UA_NodeId requestTypeId; |
| 33240 | UA_StatusCode retval = UA_NodeId_decodeBinary(src: msg, offset: &offset, dst: &requestTypeId); |
| 33241 | if(retval != UA_STATUSCODE_GOOD) |
| 33242 | return retval; |
| 33243 | if(requestTypeId.namespaceIndex != 0 || |
| 33244 | requestTypeId.identifierType != UA_NODEIDTYPE_NUMERIC) |
| 33245 | UA_NodeId_clear(p: &requestTypeId); /* leads to badserviceunsupported */ |
| 33246 | |
| 33247 | size_t requestPos = offset; /* Store the offset (for sendServiceFault) */ |
| 33248 | |
| 33249 | /* Get the service pointers */ |
| 33250 | UA_Service service = NULL; |
| 33251 | UA_Boolean sessionRequired = true; |
| 33252 | const UA_DataType *requestType = NULL; |
| 33253 | const UA_DataType *responseType = NULL; |
| 33254 | size_t counterOffset = 0; |
| 33255 | getServicePointers(requestTypeId: requestTypeId.identifier.numeric, requestType: &requestType, |
| 33256 | responseType: &responseType, service: &service, requiresSession: &sessionRequired, counterOffset: &counterOffset); |
| 33257 | if(!requestType) { |
| 33258 | if(requestTypeId.identifier.numeric == |
| 33259 | UA_NS0ID_CREATESUBSCRIPTIONREQUEST_ENCODING_DEFAULTBINARY) { |
| 33260 | UA_LOG_INFO_CHANNEL(server->config.logging, channel, |
| 33261 | "Client requested a subscription, " |
| 33262 | "but those are not enabled in the build"); |
| 33263 | } else { |
| 33264 | UA_LOG_INFO_CHANNEL(server->config.logging, channel, |
| 33265 | "Unknown request with type identifier %"PRIi32, |
| 33266 | requestTypeId.identifier.numeric); |
| 33267 | } |
| 33268 | return decodeHeaderSendServiceFault(channel, msg, offset: requestPos, |
| 33269 | responseType: &UA_TYPES[UA_TYPES_SERVICEFAULT], |
| 33270 | requestId, UA_STATUSCODE_BADSERVICEUNSUPPORTED); |
| 33271 | } |
| 33272 | UA_assert(responseType); |
| 33273 | |
| 33274 | /* Decode the request */ |
| 33275 | UA_Request request; |
| 33276 | retval = UA_decodeBinaryInternal(src: msg, offset: &offset, dst: &request, |
| 33277 | type: requestType, customTypes: server->config.customDataTypes); |
| 33278 | if(retval != UA_STATUSCODE_GOOD) { |
| 33279 | UA_LOG_DEBUG_CHANNEL(server->config.logging, channel, |
| 33280 | "Could not decode the request with StatusCode %s", |
| 33281 | UA_StatusCode_name(retval)); |
| 33282 | return decodeHeaderSendServiceFault(channel, msg, offset: requestPos, |
| 33283 | responseType, requestId, error: retval); |
| 33284 | } |
| 33285 | |
| 33286 | /* Check timestamp in the request header */ |
| 33287 | UA_RequestHeader *requestHeader = &request.requestHeader; |
| 33288 | if(requestHeader->timestamp == 0 && |
| 33289 | server->config.verifyRequestTimestamp <= UA_RULEHANDLING_WARN) { |
| 33290 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 33291 | "The server sends no timestamp in the request header. " |
| 33292 | "See the 'verifyRequestTimestamp' setting."); |
| 33293 | if(server->config.verifyRequestTimestamp <= UA_RULEHANDLING_ABORT) { |
| 33294 | retval = sendServiceFault(channel, requestId, requestHandle: requestHeader->requestHandle, |
| 33295 | UA_STATUSCODE_BADINVALIDTIMESTAMP); |
| 33296 | UA_clear(p: &request, type: requestType); |
| 33297 | return retval; |
| 33298 | } |
| 33299 | } |
| 33300 | |
| 33301 | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
| 33302 | /* Set the authenticationToken from the create session request to help |
| 33303 | * fuzzing cover more lines */ |
| 33304 | if(!UA_NodeId_isNull(&unsafe_fuzz_authenticationToken) && |
| 33305 | !UA_NodeId_isNull(&requestHeader->authenticationToken)) { |
| 33306 | UA_NodeId_clear(&requestHeader->authenticationToken); |
| 33307 | UA_NodeId_copy(&unsafe_fuzz_authenticationToken, &requestHeader->authenticationToken); |
| 33308 | } |
| 33309 | #endif |
| 33310 | |
| 33311 | /* Prepare the respone and process the request */ |
| 33312 | UA_Response response; |
| 33313 | UA_init(p: &response, type: responseType); |
| 33314 | response.responseHeader.requestHandle = requestHeader->requestHandle; |
| 33315 | retval = processMSGDecoded(server, channel, requestId, service, request: &request, requestType, |
| 33316 | response: &response, responseType, sessionRequired, counterOffset); |
| 33317 | |
| 33318 | /* Clean up */ |
| 33319 | UA_clear(p: &request, type: requestType); |
| 33320 | UA_clear(p: &response, type: responseType); |
| 33321 | return retval; |
| 33322 | } |
| 33323 | |
| 33324 | /* Takes decoded messages starting at the nodeid of the content type. */ |
| 33325 | static UA_StatusCode |
| 33326 | processSecureChannelMessage(UA_Server *server, UA_SecureChannel *channel, |
| 33327 | UA_MessageType messagetype, UA_UInt32 requestId, |
| 33328 | UA_ByteString *message) { |
| 33329 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 33330 | |
| 33331 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 33332 | switch(messagetype) { |
| 33333 | case UA_MESSAGETYPE_HEL: |
| 33334 | UA_LOG_TRACE_CHANNEL(server->config.logging, channel, "Process a HEL message"); |
| 33335 | retval = processHEL(server, channel, msg: message); |
| 33336 | break; |
| 33337 | case UA_MESSAGETYPE_OPN: |
| 33338 | UA_LOG_TRACE_CHANNEL(server->config.logging, channel, "Process an OPN message"); |
| 33339 | retval = processOPN(server, channel, requestId, msg: message); |
| 33340 | break; |
| 33341 | case UA_MESSAGETYPE_MSG: |
| 33342 | UA_LOG_TRACE_CHANNEL(server->config.logging, channel, "Process a MSG"); |
| 33343 | retval = processMSG(server, channel, requestId, msg: message); |
| 33344 | break; |
| 33345 | case UA_MESSAGETYPE_CLO: |
| 33346 | UA_LOG_TRACE_CHANNEL(server->config.logging, channel, "Process a CLO"); |
| 33347 | Service_CloseSecureChannel(server, channel); /* Regular close */ |
| 33348 | break; |
| 33349 | default: |
| 33350 | UA_LOG_TRACE_CHANNEL(server->config.logging, channel, "Invalid message type"); |
| 33351 | retval = UA_STATUSCODE_BADTCPMESSAGETYPEINVALID; |
| 33352 | break; |
| 33353 | } |
| 33354 | if(retval != UA_STATUSCODE_GOOD) { |
| 33355 | if(!UA_SecureChannel_isConnected(channel)) { |
| 33356 | UA_LOG_INFO_CHANNEL(server->config.logging, channel, |
| 33357 | "Processing the message failed. Channel already closed " |
| 33358 | "with StatusCode %s. ", UA_StatusCode_name(retval)); |
| 33359 | return retval; |
| 33360 | } |
| 33361 | |
| 33362 | UA_LOG_INFO_CHANNEL(server->config.logging, channel, |
| 33363 | "Processing the message failed with StatusCode %s. " |
| 33364 | "Closing the channel.", UA_StatusCode_name(retval)); |
| 33365 | UA_TcpErrorMessage errMsg; |
| 33366 | UA_TcpErrorMessage_init(p: &errMsg); |
| 33367 | errMsg.error = retval; |
| 33368 | UA_SecureChannel_sendError(channel, error: &errMsg); |
| 33369 | UA_ShutdownReason reason; |
| 33370 | switch(retval) { |
| 33371 | case UA_STATUSCODE_BADSECURITYMODEREJECTED: |
| 33372 | case UA_STATUSCODE_BADSECURITYCHECKSFAILED: |
| 33373 | case UA_STATUSCODE_BADSECURECHANNELIDINVALID: |
| 33374 | case UA_STATUSCODE_BADSECURECHANNELTOKENUNKNOWN: |
| 33375 | case UA_STATUSCODE_BADSECURITYPOLICYREJECTED: |
| 33376 | case UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED: |
| 33377 | reason = UA_SHUTDOWNREASON_SECURITYREJECT; |
| 33378 | break; |
| 33379 | default: |
| 33380 | reason = UA_SHUTDOWNREASON_CLOSE; |
| 33381 | break; |
| 33382 | } |
| 33383 | UA_SecureChannel_shutdown(channel, shutdownReason: reason); |
| 33384 | } |
| 33385 | |
| 33386 | return retval; |
| 33387 | } |
| 33388 | |
| 33389 | /* remove the first channel that has no session attached */ |
| 33390 | static UA_Boolean |
| 33391 | purgeFirstChannelWithoutSession(UA_BinaryProtocolManager *bpm) { |
| 33392 | channel_entry *entry; |
| 33393 | TAILQ_FOREACH(entry, &bpm->channels, pointers) { |
| 33394 | if(SLIST_FIRST(&entry->channel.sessions)) |
| 33395 | continue; |
| 33396 | UA_LOG_INFO_CHANNEL(bpm->logging, &entry->channel, |
| 33397 | "Channel was purged since maxSecureChannels was " |
| 33398 | "reached and channel had no session attached"); |
| 33399 | UA_SecureChannel_shutdown(channel: &entry->channel, shutdownReason: UA_SHUTDOWNREASON_PURGE); |
| 33400 | return true; |
| 33401 | } |
| 33402 | return false; |
| 33403 | } |
| 33404 | |
| 33405 | static UA_StatusCode |
| 33406 | configServerSecureChannel(void *application, UA_SecureChannel *channel, |
| 33407 | const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) { |
| 33408 | if(channel->securityPolicy) |
| 33409 | return UA_STATUSCODE_GOOD; |
| 33410 | |
| 33411 | /* Iterate over available endpoints and choose the correct one */ |
| 33412 | UA_Server *server = (UA_Server *)application; |
| 33413 | UA_SecurityPolicy *securityPolicy = NULL; |
| 33414 | for(size_t i = 0; i < server->config.securityPoliciesSize; ++i) { |
| 33415 | UA_SecurityPolicy *policy = &server->config.securityPolicies[i]; |
| 33416 | if(!UA_ByteString_equal(p1: &asymHeader->securityPolicyUri, p2: &policy->policyUri)) |
| 33417 | continue; |
| 33418 | |
| 33419 | UA_StatusCode res = policy->asymmetricModule. |
| 33420 | compareCertificateThumbprint(policy, &asymHeader->receiverCertificateThumbprint); |
| 33421 | if(res != UA_STATUSCODE_GOOD) |
| 33422 | continue; |
| 33423 | |
| 33424 | /* We found the correct policy (except for security mode). The endpoint |
| 33425 | * needs to be selected by the client / server to match the security |
| 33426 | * mode in the endpoint for the session. */ |
| 33427 | securityPolicy = policy; |
| 33428 | break; |
| 33429 | } |
| 33430 | |
| 33431 | if(!securityPolicy) |
| 33432 | return UA_STATUSCODE_BADSECURITYPOLICYREJECTED; |
| 33433 | |
| 33434 | /* If the sender provides a chain of certificates then we shall extract the |
| 33435 | * ApplicationInstanceCertificate. and ignore the extra bytes. See also: OPC |
| 33436 | * UA Part 6, V1.04, 6.7.2.3 Security Header, Table 42 - Asymmetric |
| 33437 | * algorithm Security header */ |
| 33438 | UA_ByteString appInstCert = getLeafCertificate(chain: asymHeader->senderCertificate); |
| 33439 | |
| 33440 | /* Create the channel context and parse the sender (remote) certificate used |
| 33441 | * for the secureChannel. */ |
| 33442 | return UA_SecureChannel_setSecurityPolicy(channel, securityPolicy, remoteCertificate: &appInstCert); |
| 33443 | } |
| 33444 | |
| 33445 | static UA_StatusCode |
| 33446 | createServerSecureChannel(UA_BinaryProtocolManager *bpm, UA_ConnectionManager *cm, |
| 33447 | uintptr_t connectionId, UA_SecureChannel **outChannel) { |
| 33448 | UA_LOCK_ASSERT(&bpm->server->serviceMutex, 1); |
| 33449 | |
| 33450 | UA_Server *server = bpm->server; |
| 33451 | UA_ServerConfig *config = &server->config; |
| 33452 | |
| 33453 | /* Check if we have space for another SC, otherwise try to find an SC |
| 33454 | * without a session and purge it */ |
| 33455 | UA_SecureChannelStatistics *scs = &server->secureChannelStatistics; |
| 33456 | if(scs->currentChannelCount >= config->maxSecureChannels && |
| 33457 | !purgeFirstChannelWithoutSession(bpm)) |
| 33458 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 33459 | |
| 33460 | /* Allocate memory for the SecureChannel */ |
| 33461 | channel_entry *entry = (channel_entry *)UA_calloc(nmemb: 1, size: sizeof(channel_entry)); |
| 33462 | if(!entry) |
| 33463 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 33464 | |
| 33465 | /* Set up the initial connection config */ |
| 33466 | UA_ConnectionConfig connConfig; |
| 33467 | connConfig.protocolVersion = 0; |
| 33468 | connConfig.recvBufferSize = config->tcpBufSize; |
| 33469 | connConfig.sendBufferSize = config->tcpBufSize; |
| 33470 | connConfig.localMaxMessageSize = config->tcpMaxMsgSize; |
| 33471 | connConfig.remoteMaxMessageSize = config->tcpMaxMsgSize; |
| 33472 | connConfig.localMaxChunkCount = config->tcpMaxChunks; |
| 33473 | connConfig.remoteMaxChunkCount = config->tcpMaxChunks; |
| 33474 | |
| 33475 | if(connConfig.recvBufferSize == 0) |
| 33476 | connConfig.recvBufferSize = 1 << 16; /* 64kB */ |
| 33477 | if(connConfig.sendBufferSize == 0) |
| 33478 | connConfig.sendBufferSize = 1 << 16; /* 64kB */ |
| 33479 | |
| 33480 | /* Set up the new SecureChannel */ |
| 33481 | UA_SecureChannel_init(channel: &entry->channel); |
| 33482 | entry->channel.config = connConfig; |
| 33483 | entry->channel.certificateVerification = &config->secureChannelPKI; |
| 33484 | entry->channel.processOPNHeader = configServerSecureChannel; |
| 33485 | entry->channel.processOPNHeaderApplication = server; |
| 33486 | entry->channel.connectionManager = cm; |
| 33487 | entry->channel.connectionId = connectionId; |
| 33488 | |
| 33489 | /* Set the SecureChannel identifier already here. So we get the right |
| 33490 | * identifier for logging right away. The rest of the SecurityToken is set |
| 33491 | * in UA_SecureChannelManager_open. Set the ChannelId also in the |
| 33492 | * alternative security token, we don't touch this value during the token |
| 33493 | * rollover. */ |
| 33494 | entry->channel.securityToken.channelId = bpm->lastChannelId++; |
| 33495 | |
| 33496 | /* Set an initial timeout before the negotiation handshake. So the channel |
| 33497 | * is caught if the client is unresponsive. |
| 33498 | * |
| 33499 | * TODO: Make this a configuration option */ |
| 33500 | entry->channel.securityToken.createdAt = UA_DateTime_nowMonotonic(); |
| 33501 | entry->channel.securityToken.revisedLifetime = 10000; /* 10s should be enough */ |
| 33502 | |
| 33503 | /* Add to the server's list */ |
| 33504 | TAILQ_INSERT_TAIL(&bpm->channels, entry, pointers); |
| 33505 | |
| 33506 | /* Update the statistics */ |
| 33507 | server->secureChannelStatistics.currentChannelCount++; |
| 33508 | server->secureChannelStatistics.cumulatedChannelCount++; |
| 33509 | |
| 33510 | *outChannel = &entry->channel; |
| 33511 | return UA_STATUSCODE_GOOD; |
| 33512 | } |
| 33513 | |
| 33514 | static void |
| 33515 | addDiscoveryUrl(UA_Server *server, const UA_String hostname, UA_UInt16 port) { |
| 33516 | char urlstr[1024]; |
| 33517 | mp_snprintf(s: urlstr, count: 1024, format: "opc.tcp://%.*s:%d", |
| 33518 | (int)hostname.length, (char*)hostname.data, port); |
| 33519 | UA_String discoveryServerUrl = UA_STRING(chars: urlstr); |
| 33520 | |
| 33521 | /* Check if the ServerUrl is already present in the DiscoveryUrl array. |
| 33522 | * Add if not already there. */ |
| 33523 | for(size_t i = 0; i < server->config.applicationDescription.discoveryUrlsSize; i++) { |
| 33524 | if(UA_String_equal(p1: &discoveryServerUrl, |
| 33525 | p2: &server->config.applicationDescription.discoveryUrls[i])) |
| 33526 | return; |
| 33527 | } |
| 33528 | |
| 33529 | /* Add to the list of discovery url */ |
| 33530 | UA_StatusCode res = |
| 33531 | UA_Array_appendCopy(p: (void **)&server->config.applicationDescription.discoveryUrls, |
| 33532 | size: &server->config.applicationDescription.discoveryUrlsSize, |
| 33533 | newElem: &discoveryServerUrl, type: &UA_TYPES[UA_TYPES_STRING]); |
| 33534 | if(res == UA_STATUSCODE_GOOD) { |
| 33535 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 33536 | msg: "New DiscoveryUrl added: %.*s", (int)discoveryServerUrl.length, |
| 33537 | (char*)discoveryServerUrl.data); |
| 33538 | } else { |
| 33539 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 33540 | msg: "Could not register DiscoveryUrl -- out of memory"); |
| 33541 | } |
| 33542 | } |
| 33543 | |
| 33544 | /* Callback of a TCP socket (server socket or an active connection) */ |
| 33545 | static void |
| 33546 | serverNetworkCallbackLocked(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 33547 | void *application, void **connectionContext, |
| 33548 | UA_ConnectionState state, |
| 33549 | const UA_KeyValueMap *params, |
| 33550 | UA_ByteString msg) { |
| 33551 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)application; |
| 33552 | UA_LOCK_ASSERT(&bpm->server->serviceMutex, 1); |
| 33553 | |
| 33554 | /* A server socket that is not yet registered in the server. Register it and |
| 33555 | * set the connection context to the pointer in the |
| 33556 | * bpm->serverConnections list. New connections on that server socket |
| 33557 | * inherit the context (and on the first callback we set the context of |
| 33558 | * client-connections to a SecureChannel). */ |
| 33559 | if(*connectionContext == NULL) { |
| 33560 | /* The socket is closing without being previously registered -> ignore */ |
| 33561 | if(state == UA_CONNECTIONSTATE_CLOSED || |
| 33562 | state == UA_CONNECTIONSTATE_CLOSING) |
| 33563 | return; |
| 33564 | |
| 33565 | /* Cannot register */ |
| 33566 | if(bpm->serverConnectionsSize >= UA_MAXSERVERCONNECTIONS) { |
| 33567 | UA_LOG_WARNING(logger: bpm->logging, category: UA_LOGCATEGORY_SERVER, |
| 33568 | msg: "Cannot register server socket - too many already open"); |
| 33569 | cm->closeConnection(cm, connectionId); |
| 33570 | return; |
| 33571 | } |
| 33572 | |
| 33573 | /* Find and use a free connection slot */ |
| 33574 | bpm->serverConnectionsSize++; |
| 33575 | UA_ServerConnection *sc = bpm->serverConnections; |
| 33576 | while(sc->connectionId != 0) |
| 33577 | sc++; |
| 33578 | sc->state = state; |
| 33579 | sc->connectionId = connectionId; |
| 33580 | sc->connectionManager = cm; |
| 33581 | *connectionContext = (void*)sc; /* Set the context pointer in the connection */ |
| 33582 | |
| 33583 | /* Add to the DiscoveryUrls */ |
| 33584 | const UA_UInt16 *port = (const UA_UInt16*) |
| 33585 | UA_KeyValueMap_getScalar(map: params, key: UA_QUALIFIEDNAME(nsIndex: 0, chars: "listen-port"), |
| 33586 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 33587 | const UA_String *address = (const UA_String*) |
| 33588 | UA_KeyValueMap_getScalar(map: params, key: UA_QUALIFIEDNAME(nsIndex: 0, chars: "listen-address"), |
| 33589 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 33590 | if(port && address) |
| 33591 | addDiscoveryUrl(server: bpm->server, hostname: *address, port: *port); |
| 33592 | return; |
| 33593 | } |
| 33594 | |
| 33595 | UA_ServerConnection *sc = (UA_ServerConnection*)*connectionContext; |
| 33596 | UA_SecureChannel *channel = (UA_SecureChannel*)*connectionContext; |
| 33597 | UA_Boolean serverSocket = (sc >= bpm->serverConnections && |
| 33598 | sc < &bpm->serverConnections[UA_MAXSERVERCONNECTIONS]); |
| 33599 | |
| 33600 | /* The connection is closing. This is the last callback for it. */ |
| 33601 | if(state == UA_CONNECTIONSTATE_CLOSING) { |
| 33602 | if(serverSocket) { |
| 33603 | /* Server socket is closed */ |
| 33604 | sc->state = UA_CONNECTIONSTATE_CLOSED; |
| 33605 | sc->connectionId = 0; |
| 33606 | bpm->serverConnectionsSize--; |
| 33607 | } else { |
| 33608 | /* A connection attached to a SecureChannel is closing. This is the |
| 33609 | * only place where deleteSecureChannel must be used. */ |
| 33610 | deleteServerSecureChannel(bpm, channel); |
| 33611 | } |
| 33612 | |
| 33613 | /* Set BinaryProtocolManager to STOPPED if it is STOPPING and the last |
| 33614 | * socket just closed */ |
| 33615 | if(bpm->sc.state == UA_LIFECYCLESTATE_STOPPING && |
| 33616 | bpm->serverConnectionsSize == 0 && |
| 33617 | LIST_EMPTY(&bpm->reverseConnects) && |
| 33618 | TAILQ_EMPTY(&bpm->channels)) { |
| 33619 | setBinaryProtocolManagerState(server: bpm->server, bpm, |
| 33620 | state: UA_LIFECYCLESTATE_STOPPED); |
| 33621 | } |
| 33622 | return; |
| 33623 | } |
| 33624 | |
| 33625 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 33626 | if(serverSocket) { |
| 33627 | /* A new connection is opening. This is the only place where |
| 33628 | * createSecureChannel is used. */ |
| 33629 | retval = createServerSecureChannel(bpm, cm, connectionId, outChannel: &channel); |
| 33630 | if(retval != UA_STATUSCODE_GOOD) { |
| 33631 | UA_LOG_WARNING(logger: bpm->logging, category: UA_LOGCATEGORY_SERVER, |
| 33632 | msg: "TCP %lu\t| Could not accept the connection with status %s", |
| 33633 | (unsigned long)sc->connectionId, UA_StatusCode_name(code: retval)); |
| 33634 | *connectionContext = NULL; |
| 33635 | cm->closeConnection(cm, connectionId); |
| 33636 | return; |
| 33637 | } |
| 33638 | |
| 33639 | /* Set the new channel as the new context for the connection */ |
| 33640 | *connectionContext = (void*)channel; |
| 33641 | |
| 33642 | /* Set the channel state to CONNECTED until the HEL message is received */ |
| 33643 | channel->state = UA_SECURECHANNELSTATE_CONNECTED; |
| 33644 | |
| 33645 | UA_LOG_INFO_CHANNEL(bpm->logging, channel, "SecureChannel created"); |
| 33646 | } |
| 33647 | |
| 33648 | /* Received a message on a normal connection */ |
| 33649 | #ifdef UA_DEBUG_DUMP_PKGS |
| 33650 | UA_dump_hex_pkg(message->data, message->length); |
| 33651 | #endif |
| 33652 | #ifdef UA_DEBUG_DUMP_PKGS_FILE |
| 33653 | UA_debug_dumpCompleteChunk(server, channel->connection, message); |
| 33654 | #endif |
| 33655 | |
| 33656 | /* Process all complete messages */ |
| 33657 | retval = UA_SecureChannel_loadBuffer(channel, buffer: msg); |
| 33658 | while(UA_LIKELY(retval == UA_STATUSCODE_GOOD)) { |
| 33659 | UA_MessageType messageType; |
| 33660 | UA_UInt32 requestId = 0; |
| 33661 | UA_ByteString payload = UA_BYTESTRING_NULL; |
| 33662 | UA_Boolean copied = false; |
| 33663 | retval = UA_SecureChannel_getCompleteMessage(channel, messageType: &messageType, requestId: &requestId, |
| 33664 | payload: &payload, copied: &copied); |
| 33665 | if(retval != UA_STATUSCODE_GOOD || payload.length == 0) |
| 33666 | break; |
| 33667 | retval = processSecureChannelMessage(server: bpm->server, channel, |
| 33668 | messagetype: messageType, requestId, message: &payload); |
| 33669 | if(copied) |
| 33670 | UA_ByteString_clear(p: &payload); |
| 33671 | } |
| 33672 | retval |= UA_SecureChannel_persistBuffer(channel); |
| 33673 | |
| 33674 | if(retval != UA_STATUSCODE_GOOD) { |
| 33675 | UA_LOG_WARNING_CHANNEL(bpm->logging, channel, |
| 33676 | "Processing the message failed with error %s", |
| 33677 | UA_StatusCode_name(retval)); |
| 33678 | |
| 33679 | /* Send an ERR message and close the connection */ |
| 33680 | UA_TcpErrorMessage error; |
| 33681 | error.error = retval; |
| 33682 | error.reason = UA_STRING_NULL; |
| 33683 | UA_SecureChannel_sendError(channel, error: &error); |
| 33684 | UA_SecureChannel_shutdown(channel, shutdownReason: UA_SHUTDOWNREASON_ABORT); |
| 33685 | } |
| 33686 | } |
| 33687 | |
| 33688 | void |
| 33689 | serverNetworkCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 33690 | void *application, void **connectionContext, |
| 33691 | UA_ConnectionState state, |
| 33692 | const UA_KeyValueMap *params, |
| 33693 | UA_ByteString msg) { |
| 33694 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)application; |
| 33695 | lockServer(server: bpm->server); |
| 33696 | serverNetworkCallbackLocked(cm, connectionId, application, connectionContext, |
| 33697 | state, params, msg); |
| 33698 | unlockServer(server: bpm->server); |
| 33699 | } |
| 33700 | |
| 33701 | static UA_StatusCode |
| 33702 | createServerConnection(UA_BinaryProtocolManager *bpm, const UA_String *serverUrl) { |
| 33703 | UA_Server *server = bpm->server; |
| 33704 | UA_ServerConfig *config = &server->config; |
| 33705 | |
| 33706 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 33707 | |
| 33708 | /* Extract the protocol, hostname and port from the url */ |
| 33709 | UA_String hostname = UA_STRING_NULL; |
| 33710 | UA_String path = UA_STRING_NULL; |
| 33711 | UA_UInt16 port = 4840; /* default */ |
| 33712 | UA_StatusCode res = UA_parseEndpointUrl(endpointUrl: serverUrl, outHostname: &hostname, outPort: &port, outPath: &path); |
| 33713 | if(res != UA_STATUSCODE_GOOD) |
| 33714 | return res; |
| 33715 | |
| 33716 | UA_String tcpString = UA_STRING(chars: "tcp"); |
| 33717 | for(UA_EventSource *es = config->eventLoop->eventSources; |
| 33718 | es != NULL; es = es->next) { |
| 33719 | /* Is this a usable connection manager? */ |
| 33720 | if(es->eventSourceType != UA_EVENTSOURCETYPE_CONNECTIONMANAGER) |
| 33721 | continue; |
| 33722 | UA_ConnectionManager *cm = (UA_ConnectionManager*)es; |
| 33723 | if(!UA_String_equal(p1: &tcpString, p2: &cm->protocol)) |
| 33724 | continue; |
| 33725 | |
| 33726 | /* Set up the parameters */ |
| 33727 | UA_KeyValuePair params[4]; |
| 33728 | size_t paramsSize = 3; |
| 33729 | |
| 33730 | params[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "port"); |
| 33731 | UA_Variant_setScalar(v: ¶ms[0].value, p: &port, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 33732 | |
| 33733 | UA_Boolean listen = true; |
| 33734 | params[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "listen"); |
| 33735 | UA_Variant_setScalar(v: ¶ms[1].value, p: &listen, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 33736 | |
| 33737 | UA_Boolean reuseaddr = config->tcpReuseAddr; |
| 33738 | params[2].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "reuse"); |
| 33739 | UA_Variant_setScalar(v: ¶ms[2].value, p: &reuseaddr, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 33740 | |
| 33741 | /* The hostname is non-empty */ |
| 33742 | if(hostname.length > 0) { |
| 33743 | params[3].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "address"); |
| 33744 | UA_Variant_setArray(v: ¶ms[3].value, array: &hostname, arraySize: 1, type: &UA_TYPES[UA_TYPES_STRING]); |
| 33745 | paramsSize = 4; |
| 33746 | } |
| 33747 | |
| 33748 | UA_KeyValueMap paramsMap; |
| 33749 | paramsMap.map = params; |
| 33750 | paramsMap.mapSize = paramsSize; |
| 33751 | |
| 33752 | /* Open the server connection */ |
| 33753 | res = cm->openConnection(cm, ¶msMap, bpm, NULL, serverNetworkCallback); |
| 33754 | if(res == UA_STATUSCODE_GOOD) |
| 33755 | return res; |
| 33756 | } |
| 33757 | |
| 33758 | return UA_STATUSCODE_BADINTERNALERROR; |
| 33759 | } |
| 33760 | |
| 33761 | /* Remove timed out SecureChannels */ |
| 33762 | static void |
| 33763 | secureChannelHouseKeeping(UA_Server *server, void *context) { |
| 33764 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)context; |
| 33765 | lockServer(server); |
| 33766 | |
| 33767 | UA_DateTime nowMonotonic = UA_DateTime_nowMonotonic(); |
| 33768 | channel_entry *entry; |
| 33769 | TAILQ_FOREACH(entry, &bpm->channels, pointers) { |
| 33770 | /* Compute the timeout date of the SecurityToken */ |
| 33771 | UA_DateTime timeout = |
| 33772 | entry->channel.securityToken.createdAt + |
| 33773 | (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_DATETIME_MSEC); |
| 33774 | |
| 33775 | /* The token has timed out. Try to do the token revolving now instead of |
| 33776 | * shutting the channel down. |
| 33777 | * |
| 33778 | * Part 4, 5.5.2 says: Servers shall use the existing SecurityToken to |
| 33779 | * secure outgoing Messages until the SecurityToken expires or the |
| 33780 | * Server receives a Message secured with a new SecurityToken.*/ |
| 33781 | if(timeout < nowMonotonic && |
| 33782 | entry->channel.renewState == UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER) { |
| 33783 | /* Revolve the token manually. This is otherwise done in checkSymHeader. */ |
| 33784 | entry->channel.renewState = UA_SECURECHANNELRENEWSTATE_NORMAL; |
| 33785 | entry->channel.securityToken = entry->channel.altSecurityToken; |
| 33786 | UA_ChannelSecurityToken_init(p: &entry->channel.altSecurityToken); |
| 33787 | UA_SecureChannel_generateLocalKeys(channel: &entry->channel); |
| 33788 | generateRemoteKeys(channel: &entry->channel); |
| 33789 | |
| 33790 | /* Use the timeout of the new SecurityToken */ |
| 33791 | timeout = entry->channel.securityToken.createdAt + |
| 33792 | (UA_DateTime)(entry->channel.securityToken.revisedLifetime * UA_DATETIME_MSEC); |
| 33793 | } |
| 33794 | |
| 33795 | if(timeout < nowMonotonic) { |
| 33796 | UA_LOG_INFO_CHANNEL(bpm->logging, &entry->channel, |
| 33797 | "SecureChannel has timed out"); |
| 33798 | UA_SecureChannel_shutdown(channel: &entry->channel, shutdownReason: UA_SHUTDOWNREASON_TIMEOUT); |
| 33799 | } |
| 33800 | } |
| 33801 | unlockServer(server); |
| 33802 | } |
| 33803 | |
| 33804 | /**********************/ |
| 33805 | /* Reverse Connection */ |
| 33806 | /**********************/ |
| 33807 | |
| 33808 | #define UA_MINMESSAGESIZE 8192 |
| 33809 | |
| 33810 | static UA_StatusCode |
| 33811 | sendRHEMessage(UA_Server *server, uintptr_t connectionId, |
| 33812 | UA_ConnectionManager *cm) { |
| 33813 | UA_ServerConfig *config = UA_Server_getConfig(server); |
| 33814 | |
| 33815 | /* Get a buffer */ |
| 33816 | UA_ByteString message; |
| 33817 | UA_StatusCode retval = |
| 33818 | cm->allocNetworkBuffer(cm, connectionId, &message, UA_MINMESSAGESIZE); |
| 33819 | if(retval != UA_STATUSCODE_GOOD) |
| 33820 | return retval; |
| 33821 | |
| 33822 | /* Prepare the RHE message and encode at offset 8 */ |
| 33823 | UA_TcpReverseHelloMessage reverseHello; |
| 33824 | UA_TcpReverseHelloMessage_init(p: &reverseHello); |
| 33825 | reverseHello.serverUri = config->applicationDescription.applicationUri; |
| 33826 | if(config->applicationDescription.discoveryUrlsSize) |
| 33827 | reverseHello.endpointUrl = config->applicationDescription.discoveryUrls[0]; |
| 33828 | |
| 33829 | UA_Byte *bufPos = &message.data[8]; /* skip the header */ |
| 33830 | const UA_Byte *bufEnd = &message.data[message.length]; |
| 33831 | UA_StatusCode result = |
| 33832 | UA_encodeBinaryInternal(src: &reverseHello, |
| 33833 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPREVERSEHELLOMESSAGE], |
| 33834 | bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 33835 | |
| 33836 | if(result != UA_STATUSCODE_GOOD) { |
| 33837 | cm->freeNetworkBuffer(cm, connectionId, &message); |
| 33838 | return result; |
| 33839 | } |
| 33840 | |
| 33841 | /* Encode the message header at offset 0 */ |
| 33842 | UA_TcpMessageHeader messageHeader; |
| 33843 | messageHeader.messageTypeAndChunkType = UA_CHUNKTYPE_FINAL + UA_MESSAGETYPE_RHE; |
| 33844 | messageHeader.messageSize = (UA_UInt32) ((uintptr_t)bufPos - (uintptr_t)message.data); |
| 33845 | bufPos = message.data; |
| 33846 | retval = UA_encodeBinaryInternal(src: &messageHeader, |
| 33847 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], |
| 33848 | bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 33849 | if(retval != UA_STATUSCODE_GOOD) { |
| 33850 | cm->freeNetworkBuffer(cm, connectionId, &message); |
| 33851 | return retval; |
| 33852 | } |
| 33853 | |
| 33854 | /* Send the RHE message */ |
| 33855 | message.length = messageHeader.messageSize; |
| 33856 | return cm->sendWithConnection(cm, connectionId, NULL, &message); |
| 33857 | } |
| 33858 | |
| 33859 | static void |
| 33860 | retryReverseConnectCallback(UA_Server *server, void *context) { |
| 33861 | lockServer(server); |
| 33862 | |
| 33863 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)context; |
| 33864 | |
| 33865 | reverse_connect_context *rc = NULL; |
| 33866 | LIST_FOREACH(rc, &bpm->reverseConnects, next) { |
| 33867 | if(rc->currentConnection.connectionId) |
| 33868 | continue; |
| 33869 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 33870 | msg: "Attempt to reverse reconnect to %.*s:%d", |
| 33871 | (int)rc->hostname.length, rc->hostname.data, rc->port); |
| 33872 | attemptReverseConnect(bpm, context: rc); |
| 33873 | } |
| 33874 | |
| 33875 | unlockServer(server); |
| 33876 | } |
| 33877 | |
| 33878 | UA_StatusCode |
| 33879 | setReverseConnectRetryCallback(UA_BinaryProtocolManager *bpm, UA_Boolean enabled) { |
| 33880 | UA_Server *server = bpm->server; |
| 33881 | UA_ServerConfig *config = &server->config; |
| 33882 | |
| 33883 | if(enabled && !bpm->reverseConnectsCheckHandle) { |
| 33884 | UA_UInt32 reconnectInterval = config->reverseReconnectInterval ? |
| 33885 | config->reverseReconnectInterval : 15000; |
| 33886 | return addRepeatedCallback(server, callback: retryReverseConnectCallback, data: bpm, |
| 33887 | interval_ms: reconnectInterval, callbackId: &bpm->reverseConnectsCheckHandle); |
| 33888 | } else if(!enabled && bpm->reverseConnectsCheckHandle) { |
| 33889 | removeCallback(server, callbackId: bpm->reverseConnectsCheckHandle); |
| 33890 | bpm->reverseConnectsCheckHandle = 0; |
| 33891 | } |
| 33892 | return UA_STATUSCODE_GOOD; |
| 33893 | } |
| 33894 | |
| 33895 | void |
| 33896 | setReverseConnectState(UA_Server *server, reverse_connect_context *context, |
| 33897 | UA_SecureChannelState newState) { |
| 33898 | if(context->state == newState) |
| 33899 | return; |
| 33900 | |
| 33901 | context->state = newState; |
| 33902 | |
| 33903 | if(context->stateCallback) |
| 33904 | context->stateCallback(server, context->handle, context->state, |
| 33905 | context->callbackContext); |
| 33906 | } |
| 33907 | |
| 33908 | static void |
| 33909 | serverReverseConnectCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 33910 | void *application, void **connectionContext, |
| 33911 | UA_ConnectionState state, const UA_KeyValueMap *params, |
| 33912 | UA_ByteString msg); |
| 33913 | |
| 33914 | UA_StatusCode |
| 33915 | attemptReverseConnect(UA_BinaryProtocolManager *bpm, reverse_connect_context *context) { |
| 33916 | UA_Server *server = bpm->server; |
| 33917 | UA_ServerConfig *config = &server->config; |
| 33918 | UA_EventLoop *el = config->eventLoop; |
| 33919 | |
| 33920 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 33921 | |
| 33922 | /* Find a TCP ConnectionManager */ |
| 33923 | UA_String tcpString = UA_STRING_STATIC("tcp"); |
| 33924 | for(UA_EventSource *es = el->eventSources; es != NULL; es = es->next) { |
| 33925 | /* Is this a usable connection manager? */ |
| 33926 | if(es->eventSourceType != UA_EVENTSOURCETYPE_CONNECTIONMANAGER) |
| 33927 | continue; |
| 33928 | |
| 33929 | UA_ConnectionManager *cm = (UA_ConnectionManager*)es; |
| 33930 | if(!UA_String_equal(p1: &tcpString, p2: &cm->protocol)) |
| 33931 | continue; |
| 33932 | |
| 33933 | if(es->state != UA_EVENTSOURCESTATE_STARTED) |
| 33934 | continue; |
| 33935 | |
| 33936 | /* Set up the parameters */ |
| 33937 | UA_KeyValuePair params[2]; |
| 33938 | params[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "address"); |
| 33939 | UA_Variant_setScalar(v: ¶ms[0].value, p: &context->hostname, |
| 33940 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 33941 | params[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "port"); |
| 33942 | UA_Variant_setScalar(v: ¶ms[1].value, p: &context->port, |
| 33943 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 33944 | UA_KeyValueMap kvm = {2, params}; |
| 33945 | |
| 33946 | /* Open the connection */ |
| 33947 | UA_StatusCode res = cm->openConnection(cm, &kvm, bpm, context, |
| 33948 | serverReverseConnectCallback); |
| 33949 | if(res != UA_STATUSCODE_GOOD) { |
| 33950 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 33951 | msg: "Failed to create connection for reverse connect: %s\n", |
| 33952 | UA_StatusCode_name(code: res)); |
| 33953 | } |
| 33954 | return res; |
| 33955 | } |
| 33956 | |
| 33957 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 33958 | msg: "No ConnectionManager found for reverse connect"); |
| 33959 | return UA_STATUSCODE_BADINTERNALERROR; |
| 33960 | } |
| 33961 | |
| 33962 | UA_StatusCode |
| 33963 | UA_Server_addReverseConnect(UA_Server *server, UA_String url, |
| 33964 | UA_Server_ReverseConnectStateCallback stateCallback, |
| 33965 | void *callbackContext, UA_UInt64 *handle) { |
| 33966 | UA_ServerConfig *config = UA_Server_getConfig(server); |
| 33967 | UA_ServerComponent *sc = |
| 33968 | getServerComponentByName(server, name: UA_STRING(chars: "binary")); |
| 33969 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)sc; |
| 33970 | if(!bpm) { |
| 33971 | UA_LOG_ERROR(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 33972 | msg: "No BinaryProtocolManager configured"); |
| 33973 | return UA_STATUSCODE_BADINTERNALERROR; |
| 33974 | } |
| 33975 | |
| 33976 | /* Parse the reverse connect URL */ |
| 33977 | UA_String hostname = UA_STRING_NULL; |
| 33978 | UA_UInt16 port = 0; |
| 33979 | UA_StatusCode res = UA_parseEndpointUrl(endpointUrl: &url, outHostname: &hostname, outPort: &port, NULL); |
| 33980 | if(res != UA_STATUSCODE_GOOD) { |
| 33981 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 33982 | msg: "OPC UA URL is invalid: %.*s", |
| 33983 | (int)url.length, url.data); |
| 33984 | return res; |
| 33985 | } |
| 33986 | |
| 33987 | /* Set up the reverse connection */ |
| 33988 | reverse_connect_context *newContext = (reverse_connect_context *) |
| 33989 | UA_calloc(nmemb: 1, size: sizeof(reverse_connect_context)); |
| 33990 | if(!newContext) |
| 33991 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 33992 | |
| 33993 | UA_String_copy(src: &hostname, dst: &newContext->hostname); |
| 33994 | newContext->port = port; |
| 33995 | newContext->handle = ++bpm->lastReverseConnectHandle; |
| 33996 | newContext->stateCallback = stateCallback; |
| 33997 | newContext->callbackContext = callbackContext; |
| 33998 | |
| 33999 | lockServer(server); |
| 34000 | |
| 34001 | /* Register the retry callback */ |
| 34002 | setReverseConnectRetryCallback(bpm, true); |
| 34003 | |
| 34004 | /* Register the new reverse connection */ |
| 34005 | LIST_INSERT_HEAD(&bpm->reverseConnects, newContext, next); |
| 34006 | |
| 34007 | if(handle) |
| 34008 | *handle = newContext->handle; |
| 34009 | |
| 34010 | /* Attempt to connect right away */ |
| 34011 | res = attemptReverseConnect(bpm, context: newContext); |
| 34012 | |
| 34013 | unlockServer(server); |
| 34014 | return res; |
| 34015 | } |
| 34016 | |
| 34017 | UA_StatusCode |
| 34018 | UA_Server_removeReverseConnect(UA_Server *server, UA_UInt64 handle) { |
| 34019 | UA_StatusCode result = UA_STATUSCODE_BADNOTFOUND; |
| 34020 | |
| 34021 | lockServer(server); |
| 34022 | |
| 34023 | UA_ServerComponent *sc = |
| 34024 | getServerComponentByName(server, name: UA_STRING(chars: "binary")); |
| 34025 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)sc; |
| 34026 | if(!bpm) { |
| 34027 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 34028 | msg: "No BinaryProtocolManager configured"); |
| 34029 | unlockServer(server); |
| 34030 | return UA_STATUSCODE_BADINTERNALERROR; |
| 34031 | } |
| 34032 | |
| 34033 | reverse_connect_context *rev, *temp; |
| 34034 | LIST_FOREACH_SAFE(rev, &bpm->reverseConnects, next, temp) { |
| 34035 | if(rev->handle != handle) |
| 34036 | continue; |
| 34037 | |
| 34038 | LIST_REMOVE(rev, next); |
| 34039 | |
| 34040 | /* Connected -> disconnect, otherwise free immediately */ |
| 34041 | if(rev->currentConnection.connectionId) { |
| 34042 | UA_ConnectionManager *cm = rev->currentConnection.connectionManager; |
| 34043 | rev->destruction = true; |
| 34044 | cm->closeConnection(cm, rev->currentConnection.connectionId); |
| 34045 | } else { |
| 34046 | setReverseConnectState(server, context: rev, newState: UA_SECURECHANNELSTATE_CLOSED); |
| 34047 | UA_String_clear(p: &rev->hostname); |
| 34048 | UA_free(ptr: rev); |
| 34049 | } |
| 34050 | result = UA_STATUSCODE_GOOD; |
| 34051 | break; |
| 34052 | } |
| 34053 | |
| 34054 | if(LIST_EMPTY(&bpm->reverseConnects)) |
| 34055 | setReverseConnectRetryCallback(bpm, false); |
| 34056 | |
| 34057 | unlockServer(server); |
| 34058 | return result; |
| 34059 | } |
| 34060 | |
| 34061 | static void |
| 34062 | serverReverseConnectCallbackLocked(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 34063 | void *application, void **connectionContext, |
| 34064 | UA_ConnectionState state, const UA_KeyValueMap *params, |
| 34065 | UA_ByteString msg) { |
| 34066 | (void)params; |
| 34067 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)application; |
| 34068 | UA_LOCK_ASSERT(&bpm->server->serviceMutex, 1); |
| 34069 | |
| 34070 | UA_LOG_DEBUG(logger: bpm->logging, category: UA_LOGCATEGORY_SERVER, |
| 34071 | msg: "Activity for reverse connect %lu with state %d", |
| 34072 | (long unsigned)connectionId, state); |
| 34073 | |
| 34074 | reverse_connect_context *context = (reverse_connect_context *)*connectionContext; |
| 34075 | context->currentConnection.state = state; |
| 34076 | |
| 34077 | /* New connection */ |
| 34078 | if(context->currentConnection.connectionId == 0) { |
| 34079 | context->currentConnection.connectionId = connectionId; |
| 34080 | context->currentConnection.connectionManager = cm; |
| 34081 | setReverseConnectState(server: bpm->server, context, newState: UA_SECURECHANNELSTATE_CONNECTING); |
| 34082 | /* Fall through -- e.g. if state == ESTABLISHED already */ |
| 34083 | } |
| 34084 | |
| 34085 | /* The connection is closing. This is the last callback for it. */ |
| 34086 | if(state == UA_CONNECTIONSTATE_CLOSING) { |
| 34087 | if(context->channel) { |
| 34088 | deleteServerSecureChannel(bpm, channel: context->channel); |
| 34089 | context->channel = NULL; |
| 34090 | } |
| 34091 | |
| 34092 | /* Delete the ReverseConnect entry */ |
| 34093 | if(context->destruction) { |
| 34094 | setReverseConnectState(server: bpm->server, context, newState: UA_SECURECHANNELSTATE_CLOSED); |
| 34095 | LIST_REMOVE(context, next); |
| 34096 | UA_String_clear(p: &context->hostname); |
| 34097 | UA_free(ptr: context); |
| 34098 | |
| 34099 | /* Check if the Binary Protocol Manager is stopped */ |
| 34100 | if(bpm->sc.state == UA_LIFECYCLESTATE_STOPPING && |
| 34101 | bpm->serverConnectionsSize == 0 && |
| 34102 | LIST_EMPTY(&bpm->reverseConnects) && |
| 34103 | TAILQ_EMPTY(&bpm->channels)) { |
| 34104 | setBinaryProtocolManagerState(server: bpm->server, bpm, |
| 34105 | state: UA_LIFECYCLESTATE_STOPPED); |
| 34106 | } |
| 34107 | return; |
| 34108 | } |
| 34109 | |
| 34110 | /* Reset. Will be picked up in the regular retry callback. */ |
| 34111 | context->currentConnection.connectionId = 0; |
| 34112 | setReverseConnectState(server: bpm->server, context, newState: UA_SECURECHANNELSTATE_CONNECTING); |
| 34113 | return; |
| 34114 | } |
| 34115 | |
| 34116 | if(state != UA_CONNECTIONSTATE_ESTABLISHED) |
| 34117 | return; |
| 34118 | |
| 34119 | /* A new connection is opening. This is the only place where |
| 34120 | * createSecureChannel is used. */ |
| 34121 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 34122 | if(!context->channel) { |
| 34123 | retval = createServerSecureChannel(bpm, cm, connectionId, outChannel: &context->channel); |
| 34124 | if(retval != UA_STATUSCODE_GOOD) { |
| 34125 | UA_LOG_WARNING(logger: bpm->logging, category: UA_LOGCATEGORY_SERVER, |
| 34126 | msg: "TCP %lu\t| Could not accept the reverse " |
| 34127 | "connection with status %s", |
| 34128 | (unsigned long)context->currentConnection.connectionId, |
| 34129 | UA_StatusCode_name(code: retval)); |
| 34130 | cm->closeConnection(cm, connectionId); |
| 34131 | return; |
| 34132 | } |
| 34133 | |
| 34134 | /* Send the RHE message */ |
| 34135 | retval = sendRHEMessage(server: bpm->server, connectionId, cm); |
| 34136 | if(retval != UA_STATUSCODE_GOOD) { |
| 34137 | UA_LOG_WARNING(logger: bpm->logging, category: UA_LOGCATEGORY_SERVER, |
| 34138 | msg: "TCP %lu\t| Could not send the RHE message " |
| 34139 | "with status %s", |
| 34140 | (unsigned long)context->currentConnection.connectionId, |
| 34141 | UA_StatusCode_name(code: retval)); |
| 34142 | cm->closeConnection(cm, connectionId); |
| 34143 | return; |
| 34144 | } |
| 34145 | |
| 34146 | context->channel->state = UA_SECURECHANNELSTATE_RHE_SENT; |
| 34147 | setReverseConnectState(server: bpm->server, context, newState: UA_SECURECHANNELSTATE_RHE_SENT); |
| 34148 | return; |
| 34149 | } |
| 34150 | |
| 34151 | /* The connection is fully opened and we have a SecureChannel. |
| 34152 | * Process the received buffer */ |
| 34153 | retval = UA_SecureChannel_loadBuffer(channel: context->channel, buffer: msg); |
| 34154 | while(UA_LIKELY(retval == UA_STATUSCODE_GOOD)) { |
| 34155 | UA_MessageType messageType; |
| 34156 | UA_UInt32 requestId = 0; |
| 34157 | UA_ByteString payload = UA_BYTESTRING_NULL; |
| 34158 | UA_Boolean copied = false; |
| 34159 | retval = UA_SecureChannel_getCompleteMessage(channel: context->channel, messageType: &messageType, |
| 34160 | requestId: &requestId, payload: &payload, copied: &copied); |
| 34161 | if(retval != UA_STATUSCODE_GOOD || payload.length == 0) |
| 34162 | break; |
| 34163 | retval = processSecureChannelMessage(server: bpm->server, channel: context->channel, |
| 34164 | messagetype: messageType, requestId, message: &payload); |
| 34165 | if(copied) |
| 34166 | UA_ByteString_clear(p: &payload); |
| 34167 | } |
| 34168 | retval |= UA_SecureChannel_persistBuffer(channel: context->channel); |
| 34169 | |
| 34170 | if(retval != UA_STATUSCODE_GOOD) { |
| 34171 | UA_LOG_WARNING_CHANNEL(bpm->logging, context->channel, |
| 34172 | "Processing the message failed with error %s", |
| 34173 | UA_StatusCode_name(retval)); |
| 34174 | |
| 34175 | /* Processing the buffer failed within the SecureChannel. |
| 34176 | * Send an ERR message and close the connection. */ |
| 34177 | UA_TcpErrorMessage error; |
| 34178 | error.error = retval; |
| 34179 | error.reason = UA_STRING_NULL; |
| 34180 | UA_SecureChannel_sendError(channel: context->channel, error: &error); |
| 34181 | UA_SecureChannel_shutdown(channel: context->channel, shutdownReason: UA_SHUTDOWNREASON_ABORT); |
| 34182 | setReverseConnectState(server: bpm->server, context, newState: UA_SECURECHANNELSTATE_CLOSING); |
| 34183 | return; |
| 34184 | } |
| 34185 | |
| 34186 | /* Update the state with the current SecureChannel state */ |
| 34187 | setReverseConnectState(server: bpm->server, context, newState: context->channel->state); |
| 34188 | } |
| 34189 | |
| 34190 | void |
| 34191 | serverReverseConnectCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 34192 | void *application, void **connectionContext, |
| 34193 | UA_ConnectionState state, const UA_KeyValueMap *params, |
| 34194 | UA_ByteString msg) { |
| 34195 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)application; |
| 34196 | lockServer(server: bpm->server); |
| 34197 | serverReverseConnectCallbackLocked(cm, connectionId, application, connectionContext, |
| 34198 | state, params, msg); |
| 34199 | unlockServer(server: bpm->server); |
| 34200 | } |
| 34201 | |
| 34202 | /***************************/ |
| 34203 | /* Binary Protocol Manager */ |
| 34204 | /***************************/ |
| 34205 | |
| 34206 | static UA_StatusCode |
| 34207 | UA_BinaryProtocolManager_start(UA_Server *server, |
| 34208 | UA_ServerComponent *sc) { |
| 34209 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)sc; |
| 34210 | UA_ServerConfig *config = &server->config; |
| 34211 | |
| 34212 | UA_StatusCode retVal = |
| 34213 | addRepeatedCallback(server, callback: secureChannelHouseKeeping, |
| 34214 | data: bpm, interval_ms: 1000.0, callbackId: &bpm->houseKeepingCallbackId); |
| 34215 | if(retVal != UA_STATUSCODE_GOOD) |
| 34216 | return retVal; |
| 34217 | |
| 34218 | /* Open server sockets */ |
| 34219 | UA_Boolean haveServerSocket = false; |
| 34220 | if(config->serverUrlsSize == 0) { |
| 34221 | /* Empty hostname -> listen on all devices */ |
| 34222 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 34223 | msg: "No Server URL configured. Using \"opc.tcp://:4840\" " |
| 34224 | "to configure the listen socket."); |
| 34225 | UA_String defaultUrl = UA_STRING(chars: "opc.tcp://:4840"); |
| 34226 | retVal = createServerConnection(bpm, serverUrl: &defaultUrl); |
| 34227 | if(retVal == UA_STATUSCODE_GOOD) |
| 34228 | haveServerSocket = true; |
| 34229 | } else { |
| 34230 | for(size_t i = 0; i < config->serverUrlsSize; i++) { |
| 34231 | retVal = createServerConnection(bpm, serverUrl: &config->serverUrls[i]); |
| 34232 | if(retVal == UA_STATUSCODE_GOOD) |
| 34233 | haveServerSocket = true; |
| 34234 | } |
| 34235 | } |
| 34236 | |
| 34237 | if(!haveServerSocket) { |
| 34238 | UA_LOG_ERROR(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 34239 | msg: "The server has no server socket"); |
| 34240 | return UA_STATUSCODE_BADINTERNALERROR; |
| 34241 | } |
| 34242 | |
| 34243 | /* Update the application description to include the server urls for |
| 34244 | * discovery. Don't add the urls with an empty host (listening on all |
| 34245 | * interfaces) */ |
| 34246 | for(size_t i = 0; i < config->serverUrlsSize; i++) { |
| 34247 | UA_String hostname = UA_STRING_NULL; |
| 34248 | UA_String path = UA_STRING_NULL; |
| 34249 | UA_UInt16 port = 0; |
| 34250 | retVal = UA_parseEndpointUrl(endpointUrl: &config->serverUrls[i], |
| 34251 | outHostname: &hostname, outPort: &port, outPath: &path); |
| 34252 | if(retVal != UA_STATUSCODE_GOOD || hostname.length == 0) |
| 34253 | continue; |
| 34254 | |
| 34255 | /* Check if the ServerUrl is already present in the DiscoveryUrl array. |
| 34256 | * Add if not already there. */ |
| 34257 | size_t j = 0; |
| 34258 | for(; j < config->applicationDescription.discoveryUrlsSize; j++) { |
| 34259 | if(UA_String_equal(p1: &config->serverUrls[i], |
| 34260 | p2: &config->applicationDescription.discoveryUrls[j])) |
| 34261 | break; |
| 34262 | } |
| 34263 | if(j == config->applicationDescription.discoveryUrlsSize) { |
| 34264 | retVal = |
| 34265 | UA_Array_appendCopy(p: (void**)&config->applicationDescription.discoveryUrls, |
| 34266 | size: &config->applicationDescription.discoveryUrlsSize, |
| 34267 | newElem: &config->serverUrls[i], type: &UA_TYPES[UA_TYPES_STRING]); |
| 34268 | (void)retVal; |
| 34269 | } |
| 34270 | } |
| 34271 | |
| 34272 | /* Set the state to started */ |
| 34273 | setBinaryProtocolManagerState(server: bpm->server, bpm, |
| 34274 | state: UA_LIFECYCLESTATE_STARTED); |
| 34275 | |
| 34276 | return UA_STATUSCODE_GOOD; |
| 34277 | } |
| 34278 | |
| 34279 | static void |
| 34280 | UA_BinaryProtocolManager_stop(UA_Server *server, |
| 34281 | UA_ServerComponent *comp) { |
| 34282 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*)comp; |
| 34283 | |
| 34284 | /* Stop the Housekeeping Task */ |
| 34285 | removeCallback(server, callbackId: bpm->houseKeepingCallbackId); |
| 34286 | bpm->houseKeepingCallbackId = 0; |
| 34287 | |
| 34288 | /* Stop the regular retry callback */ |
| 34289 | setReverseConnectRetryCallback(bpm, false); |
| 34290 | |
| 34291 | /* Close or free all reverse connections */ |
| 34292 | reverse_connect_context *rev, *rev_tmp; |
| 34293 | LIST_FOREACH_SAFE(rev, &bpm->reverseConnects, next, rev_tmp) { |
| 34294 | if(rev->currentConnection.connectionId) { |
| 34295 | UA_ConnectionManager *cm = rev->currentConnection.connectionManager; |
| 34296 | rev->destruction = true; |
| 34297 | cm->closeConnection(cm, rev->currentConnection.connectionId); |
| 34298 | } else { |
| 34299 | LIST_REMOVE(rev, next); |
| 34300 | setReverseConnectState(server, context: rev, newState: UA_SECURECHANNELSTATE_CLOSED); |
| 34301 | UA_String_clear(p: &rev->hostname); |
| 34302 | UA_free(ptr: rev); |
| 34303 | } |
| 34304 | } |
| 34305 | |
| 34306 | /* Stop all SecureChannels */ |
| 34307 | channel_entry *entry; |
| 34308 | TAILQ_FOREACH(entry, &bpm->channels, pointers) { |
| 34309 | UA_SecureChannel_shutdown(channel: &entry->channel, shutdownReason: UA_SHUTDOWNREASON_CLOSE); |
| 34310 | } |
| 34311 | |
| 34312 | /* Stop all server sockets */ |
| 34313 | for(size_t i = 0; i < UA_MAXSERVERCONNECTIONS; i++) { |
| 34314 | UA_ServerConnection *sc = &bpm->serverConnections[i]; |
| 34315 | UA_ConnectionManager *cm = sc->connectionManager; |
| 34316 | if(sc->connectionId > 0) |
| 34317 | cm->closeConnection(cm, sc->connectionId); |
| 34318 | } |
| 34319 | |
| 34320 | /* If open sockets remain, set to STOPPING */ |
| 34321 | if(bpm->serverConnectionsSize == 0 && |
| 34322 | LIST_EMPTY(&bpm->reverseConnects) && |
| 34323 | TAILQ_EMPTY(&bpm->channels)) { |
| 34324 | setBinaryProtocolManagerState(server: bpm->server, bpm, |
| 34325 | state: UA_LIFECYCLESTATE_STOPPED); |
| 34326 | } else { |
| 34327 | setBinaryProtocolManagerState(server: bpm->server, bpm, |
| 34328 | state: UA_LIFECYCLESTATE_STOPPING); |
| 34329 | } |
| 34330 | } |
| 34331 | |
| 34332 | static UA_StatusCode |
| 34333 | UA_BinaryProtocolManager_free(UA_Server *server, |
| 34334 | UA_ServerComponent *sc) { |
| 34335 | if(sc->state != UA_LIFECYCLESTATE_STOPPED) |
| 34336 | return UA_STATUSCODE_BADINTERNALERROR; |
| 34337 | |
| 34338 | UA_free(ptr: sc); |
| 34339 | return UA_STATUSCODE_GOOD; |
| 34340 | } |
| 34341 | |
| 34342 | UA_ServerComponent * |
| 34343 | UA_BinaryProtocolManager_new(UA_Server *server) { |
| 34344 | UA_BinaryProtocolManager *bpm = (UA_BinaryProtocolManager*) |
| 34345 | UA_calloc(nmemb: 1, size: sizeof(UA_BinaryProtocolManager)); |
| 34346 | if(!bpm) |
| 34347 | return NULL; |
| 34348 | |
| 34349 | bpm->server = server; |
| 34350 | bpm->logging = server->config.logging; |
| 34351 | |
| 34352 | /* Initialize SecureChannel */ |
| 34353 | TAILQ_INIT(&bpm->channels); |
| 34354 | |
| 34355 | /* TODO: use an ID that is likely to be unique after a restart */ |
| 34356 | bpm->lastChannelId = STARTCHANNELID; |
| 34357 | bpm->lastTokenId = STARTTOKENID; |
| 34358 | |
| 34359 | bpm->sc.name = UA_STRING(chars: "binary"); |
| 34360 | bpm->sc.start = UA_BinaryProtocolManager_start; |
| 34361 | bpm->sc.stop = UA_BinaryProtocolManager_stop; |
| 34362 | bpm->sc.free = UA_BinaryProtocolManager_free; |
| 34363 | return &bpm->sc; |
| 34364 | } |
| 34365 | |
| 34366 | /**** amalgamated original file "/src/server/ua_server_utils.c" ****/ |
| 34367 | |
| 34368 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 34369 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 34370 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 34371 | * |
| 34372 | * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 34373 | * Copyright 2016 (c) Lorenz Haas |
| 34374 | * Copyright 2017 (c) frax2222 |
| 34375 | * Copyright 2017 (c) Florian Palm |
| 34376 | * Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH |
| 34377 | * Copyright 2017 (c) Julian Grothoff |
| 34378 | */ |
| 34379 | |
| 34380 | |
| 34381 | const UA_DataType * |
| 34382 | UA_Server_findDataType(UA_Server *server, const UA_NodeId *typeId) { |
| 34383 | return UA_findDataTypeWithCustom(typeId, customTypes: server->config.customDataTypes); |
| 34384 | } |
| 34385 | |
| 34386 | /********************************/ |
| 34387 | /* Information Model Operations */ |
| 34388 | /********************************/ |
| 34389 | |
| 34390 | static void * |
| 34391 | returnFirstType(void *context, UA_ReferenceTarget *t) { |
| 34392 | UA_Server *server = (UA_Server*)context; |
| 34393 | /* Don't release the node that is returned. |
| 34394 | * Continues to iterate if NULL is returned. */ |
| 34395 | return (void*)(uintptr_t)UA_NODESTORE_GETFROMREF(server, target: t->targetId); |
| 34396 | } |
| 34397 | |
| 34398 | const UA_Node * |
| 34399 | getNodeType(UA_Server *server, const UA_NodeHead *head) { |
| 34400 | /* The reference to the parent is different for variable and variabletype */ |
| 34401 | UA_Byte parentRefIndex; |
| 34402 | UA_Boolean inverse; |
| 34403 | switch(head->nodeClass) { |
| 34404 | case UA_NODECLASS_OBJECT: |
| 34405 | case UA_NODECLASS_VARIABLE: |
| 34406 | parentRefIndex = UA_REFERENCETYPEINDEX_HASTYPEDEFINITION; |
| 34407 | inverse = false; |
| 34408 | break; |
| 34409 | case UA_NODECLASS_OBJECTTYPE: |
| 34410 | case UA_NODECLASS_VARIABLETYPE: |
| 34411 | case UA_NODECLASS_REFERENCETYPE: |
| 34412 | case UA_NODECLASS_DATATYPE: |
| 34413 | parentRefIndex = UA_REFERENCETYPEINDEX_HASSUBTYPE; |
| 34414 | inverse = true; |
| 34415 | break; |
| 34416 | default: |
| 34417 | return NULL; |
| 34418 | } |
| 34419 | |
| 34420 | /* Return the first matching candidate */ |
| 34421 | for(size_t i = 0; i < head->referencesSize; ++i) { |
| 34422 | UA_NodeReferenceKind *rk = &head->references[i]; |
| 34423 | if(rk->isInverse != inverse) |
| 34424 | continue; |
| 34425 | if(rk->referenceTypeIndex != parentRefIndex) |
| 34426 | continue; |
| 34427 | const UA_Node *type = (const UA_Node*) |
| 34428 | UA_NodeReferenceKind_iterate(rk, callback: returnFirstType, context: server); |
| 34429 | if(type) |
| 34430 | return type; |
| 34431 | } |
| 34432 | |
| 34433 | return NULL; |
| 34434 | } |
| 34435 | |
| 34436 | UA_Boolean |
| 34437 | UA_Node_hasSubTypeOrInstances(const UA_NodeHead *head) { |
| 34438 | for(size_t i = 0; i < head->referencesSize; ++i) { |
| 34439 | if(head->references[i].isInverse == false && |
| 34440 | head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASSUBTYPE) |
| 34441 | return true; |
| 34442 | if(head->references[i].isInverse == true && |
| 34443 | head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASTYPEDEFINITION) |
| 34444 | return true; |
| 34445 | } |
| 34446 | return false; |
| 34447 | } |
| 34448 | |
| 34449 | UA_StatusCode |
| 34450 | getParentTypeAndInterfaceHierarchy(UA_Server *server, const UA_NodeId *typeNode, |
| 34451 | UA_NodeId **typeHierarchy, size_t *typeHierarchySize) { |
| 34452 | UA_ReferenceTypeSet reftypes_subtype = |
| 34453 | UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE); |
| 34454 | UA_ExpandedNodeId *subTypes = NULL; |
| 34455 | size_t subTypesSize = 0; |
| 34456 | UA_StatusCode retval = browseRecursive(server, startNodesSize: 1, startNodes: typeNode, |
| 34457 | browseDirection: UA_BROWSEDIRECTION_INVERSE, |
| 34458 | refTypes: &reftypes_subtype, nodeClassMask: UA_NODECLASS_UNSPECIFIED, |
| 34459 | false, resultsSize: &subTypesSize, results: &subTypes); |
| 34460 | if(retval != UA_STATUSCODE_GOOD) |
| 34461 | return retval; |
| 34462 | |
| 34463 | UA_assert(subTypesSize < 1000); |
| 34464 | |
| 34465 | UA_ReferenceTypeSet reftypes_interface = |
| 34466 | UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE); |
| 34467 | UA_ExpandedNodeId *interfaces = NULL; |
| 34468 | size_t interfacesSize = 0; |
| 34469 | retval = browseRecursive(server, startNodesSize: 1, startNodes: typeNode, browseDirection: UA_BROWSEDIRECTION_FORWARD, |
| 34470 | refTypes: &reftypes_interface, nodeClassMask: UA_NODECLASS_UNSPECIFIED, |
| 34471 | false, resultsSize: &interfacesSize, results: &interfaces); |
| 34472 | if(retval != UA_STATUSCODE_GOOD) { |
| 34473 | UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 34474 | return retval; |
| 34475 | } |
| 34476 | |
| 34477 | UA_assert(interfacesSize < 1000); |
| 34478 | |
| 34479 | UA_NodeId *hierarchy = (UA_NodeId*) |
| 34480 | UA_malloc(size: sizeof(UA_NodeId) * (1 + subTypesSize + interfacesSize)); |
| 34481 | if(!hierarchy) { |
| 34482 | UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34483 | UA_Array_delete(p: interfaces, size: interfacesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34484 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 34485 | } |
| 34486 | |
| 34487 | retval = UA_NodeId_copy(src: typeNode, dst: hierarchy); |
| 34488 | if(retval != UA_STATUSCODE_GOOD) { |
| 34489 | UA_free(ptr: hierarchy); |
| 34490 | UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34491 | UA_Array_delete(p: interfaces, size: interfacesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34492 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 34493 | } |
| 34494 | |
| 34495 | for(size_t i = 0; i < subTypesSize; i++) { |
| 34496 | hierarchy[i+1] = subTypes[i].nodeId; |
| 34497 | UA_NodeId_init(p: &subTypes[i].nodeId); |
| 34498 | } |
| 34499 | for(size_t i = 0; i < interfacesSize; i++) { |
| 34500 | hierarchy[i+1+subTypesSize] = interfaces[i].nodeId; |
| 34501 | UA_NodeId_init(p: &interfaces[i].nodeId); |
| 34502 | } |
| 34503 | |
| 34504 | *typeHierarchy = hierarchy; |
| 34505 | *typeHierarchySize = subTypesSize + interfacesSize + 1; |
| 34506 | |
| 34507 | UA_assert(*typeHierarchySize < 1000); |
| 34508 | |
| 34509 | UA_Array_delete(p: subTypes, size: subTypesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34510 | UA_Array_delete(p: interfaces, size: interfacesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34511 | return UA_STATUSCODE_GOOD; |
| 34512 | } |
| 34513 | |
| 34514 | UA_StatusCode |
| 34515 | getAllInterfaceChildNodeIds(UA_Server *server, const UA_NodeId *objectNode, |
| 34516 | const UA_NodeId *objectTypeNode, |
| 34517 | UA_NodeId **interfaceChildNodes, |
| 34518 | size_t *interfaceChildNodesSize) { |
| 34519 | if(interfaceChildNodesSize == NULL || interfaceChildNodes == NULL) |
| 34520 | return UA_STATUSCODE_BADINTERNALERROR; |
| 34521 | *interfaceChildNodesSize = 0; |
| 34522 | *interfaceChildNodes = NULL; |
| 34523 | |
| 34524 | UA_ExpandedNodeId *hasInterfaceCandidates = NULL; |
| 34525 | size_t hasInterfaceCandidatesSize = 0; |
| 34526 | UA_ReferenceTypeSet reftypes_subtype = |
| 34527 | UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE); |
| 34528 | |
| 34529 | UA_StatusCode retval = |
| 34530 | browseRecursive(server, startNodesSize: 1, startNodes: objectTypeNode, browseDirection: UA_BROWSEDIRECTION_INVERSE, |
| 34531 | refTypes: &reftypes_subtype, nodeClassMask: UA_NODECLASS_OBJECTTYPE, |
| 34532 | true, resultsSize: &hasInterfaceCandidatesSize, |
| 34533 | results: &hasInterfaceCandidates); |
| 34534 | |
| 34535 | if(retval != UA_STATUSCODE_GOOD) |
| 34536 | return retval; |
| 34537 | |
| 34538 | /* The interface could also have been added manually before calling UA_Server_addNode_finish |
| 34539 | * This can be handled by adding the object node as a start node for the HasInterface lookup */ |
| 34540 | UA_ExpandedNodeId *resizedHasInterfaceCandidates = (UA_ExpandedNodeId*) |
| 34541 | UA_realloc(ptr: hasInterfaceCandidates, |
| 34542 | size: (hasInterfaceCandidatesSize + 1) * sizeof(UA_ExpandedNodeId)); |
| 34543 | |
| 34544 | if(!resizedHasInterfaceCandidates) { |
| 34545 | if(hasInterfaceCandidates) |
| 34546 | UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize, |
| 34547 | type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34548 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 34549 | } |
| 34550 | |
| 34551 | hasInterfaceCandidates = resizedHasInterfaceCandidates; |
| 34552 | hasInterfaceCandidatesSize += 1; |
| 34553 | UA_ExpandedNodeId_init(p: &hasInterfaceCandidates[hasInterfaceCandidatesSize - 1]); |
| 34554 | |
| 34555 | UA_ExpandedNodeId_init(p: &hasInterfaceCandidates[hasInterfaceCandidatesSize - 1]); |
| 34556 | UA_NodeId_copy(src: objectNode, dst: &hasInterfaceCandidates[hasInterfaceCandidatesSize - 1].nodeId); |
| 34557 | |
| 34558 | size_t outputIndex = 0; |
| 34559 | |
| 34560 | for(size_t i = 0; i < hasInterfaceCandidatesSize; ++i) { |
| 34561 | UA_ReferenceTypeSet reftypes_interface = |
| 34562 | UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE); |
| 34563 | UA_ExpandedNodeId *interfaceChildren = NULL; |
| 34564 | size_t interfacesChildrenSize = 0; |
| 34565 | retval = browseRecursive(server, startNodesSize: 1, startNodes: &hasInterfaceCandidates[i].nodeId, |
| 34566 | browseDirection: UA_BROWSEDIRECTION_FORWARD, |
| 34567 | refTypes: &reftypes_interface, nodeClassMask: UA_NODECLASS_OBJECTTYPE, |
| 34568 | false, resultsSize: &interfacesChildrenSize, results: &interfaceChildren); |
| 34569 | if(retval != UA_STATUSCODE_GOOD) { |
| 34570 | UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize, |
| 34571 | type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34572 | if(*interfaceChildNodesSize) { |
| 34573 | UA_Array_delete(p: *interfaceChildNodes, size: *interfaceChildNodesSize, |
| 34574 | type: &UA_TYPES[UA_TYPES_NODEID]); |
| 34575 | *interfaceChildNodesSize = 0; |
| 34576 | } |
| 34577 | return retval; |
| 34578 | } |
| 34579 | |
| 34580 | UA_assert(interfacesChildrenSize < 1000); |
| 34581 | |
| 34582 | if(interfacesChildrenSize == 0) { |
| 34583 | continue; |
| 34584 | } |
| 34585 | |
| 34586 | if(!*interfaceChildNodes) { |
| 34587 | *interfaceChildNodes = (UA_NodeId*) |
| 34588 | UA_calloc(nmemb: interfacesChildrenSize, size: sizeof(UA_NodeId)); |
| 34589 | *interfaceChildNodesSize = interfacesChildrenSize; |
| 34590 | |
| 34591 | if(!*interfaceChildNodes) { |
| 34592 | UA_Array_delete(p: interfaceChildren, size: interfacesChildrenSize, |
| 34593 | type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34594 | UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize, |
| 34595 | type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34596 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 34597 | } |
| 34598 | } else { |
| 34599 | UA_NodeId *resizedInterfaceChildNodes = (UA_NodeId*) |
| 34600 | UA_realloc(ptr: *interfaceChildNodes, |
| 34601 | size: ((*interfaceChildNodesSize + interfacesChildrenSize) * sizeof(UA_NodeId))); |
| 34602 | |
| 34603 | if(!resizedInterfaceChildNodes) { |
| 34604 | UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize, |
| 34605 | type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34606 | UA_Array_delete(p: interfaceChildren, size: interfacesChildrenSize, |
| 34607 | type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34608 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 34609 | } |
| 34610 | |
| 34611 | const size_t oldSize = *interfaceChildNodesSize; |
| 34612 | *interfaceChildNodesSize += interfacesChildrenSize; |
| 34613 | *interfaceChildNodes = resizedInterfaceChildNodes; |
| 34614 | |
| 34615 | for(size_t j = oldSize; j < *interfaceChildNodesSize; ++j) |
| 34616 | UA_NodeId_init(p: &(*interfaceChildNodes)[j]); |
| 34617 | } |
| 34618 | |
| 34619 | for(size_t j = 0; j < interfacesChildrenSize; j++) { |
| 34620 | (*interfaceChildNodes)[outputIndex++] = interfaceChildren[j].nodeId; |
| 34621 | } |
| 34622 | |
| 34623 | UA_assert(*interfaceChildNodesSize < 1000); |
| 34624 | UA_Array_delete(p: interfaceChildren, size: interfacesChildrenSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34625 | } |
| 34626 | |
| 34627 | UA_Array_delete(p: hasInterfaceCandidates, size: hasInterfaceCandidatesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 34628 | |
| 34629 | return UA_STATUSCODE_GOOD; |
| 34630 | } |
| 34631 | |
| 34632 | /* For mulithreading: make a copy of the node, edit and replace. |
| 34633 | * For singlethreading: edit the original */ |
| 34634 | UA_StatusCode |
| 34635 | UA_Server_editNode(UA_Server *server, UA_Session *session, |
| 34636 | const UA_NodeId *nodeId, UA_EditNodeCallback callback, |
| 34637 | void *data) { |
| 34638 | #ifndef UA_ENABLE_IMMUTABLE_NODES |
| 34639 | /* Get the node and process it in-situ */ |
| 34640 | const UA_Node *node = UA_NODESTORE_GET(server, nodeId); |
| 34641 | if(!node) |
| 34642 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 34643 | UA_StatusCode retval = callback(server, session, (UA_Node*)(uintptr_t)node, data); |
| 34644 | UA_NODESTORE_RELEASE(server, node); |
| 34645 | return retval; |
| 34646 | #else |
| 34647 | UA_StatusCode retval; |
| 34648 | do { |
| 34649 | /* Get an editable copy of the node */ |
| 34650 | UA_Node *node; |
| 34651 | retval = UA_NODESTORE_GETCOPY(server, nodeId, &node); |
| 34652 | if(retval != UA_STATUSCODE_GOOD) |
| 34653 | return retval; |
| 34654 | |
| 34655 | /* Run the operation on the copy */ |
| 34656 | retval = callback(server, session, node, data); |
| 34657 | if(retval != UA_STATUSCODE_GOOD) { |
| 34658 | UA_NODESTORE_DELETE(server, node); |
| 34659 | return retval; |
| 34660 | } |
| 34661 | |
| 34662 | /* Replace the node */ |
| 34663 | retval = UA_NODESTORE_REPLACE(server, node); |
| 34664 | } while(retval != UA_STATUSCODE_GOOD); |
| 34665 | return retval; |
| 34666 | #endif |
| 34667 | } |
| 34668 | |
| 34669 | UA_StatusCode |
| 34670 | UA_Server_processServiceOperations(UA_Server *server, UA_Session *session, |
| 34671 | UA_ServiceOperation operationCallback, |
| 34672 | const void *context, const size_t *requestOperations, |
| 34673 | const UA_DataType *requestOperationsType, |
| 34674 | size_t *responseOperations, |
| 34675 | const UA_DataType *responseOperationsType) { |
| 34676 | size_t ops = *requestOperations; |
| 34677 | if(ops == 0) |
| 34678 | return UA_STATUSCODE_BADNOTHINGTODO; |
| 34679 | |
| 34680 | /* No padding after size_t */ |
| 34681 | void **respPos = (void**)((uintptr_t)responseOperations + sizeof(size_t)); |
| 34682 | *respPos = UA_Array_new(size: ops, type: responseOperationsType); |
| 34683 | if(!(*respPos)) |
| 34684 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 34685 | |
| 34686 | *responseOperations = ops; |
| 34687 | uintptr_t respOp = (uintptr_t)*respPos; |
| 34688 | /* No padding after size_t */ |
| 34689 | uintptr_t reqOp = *(uintptr_t*)((uintptr_t)requestOperations + sizeof(size_t)); |
| 34690 | for(size_t i = 0; i < ops; i++) { |
| 34691 | operationCallback(server, session, context, (void*)reqOp, (void*)respOp); |
| 34692 | reqOp += requestOperationsType->memSize; |
| 34693 | respOp += responseOperationsType->memSize; |
| 34694 | } |
| 34695 | return UA_STATUSCODE_GOOD; |
| 34696 | } |
| 34697 | |
| 34698 | /* A few global NodeId definitions */ |
| 34699 | const UA_NodeId subtypeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}}; |
| 34700 | const UA_NodeId hierarchicalReferences = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HIERARCHICALREFERENCES}}; |
| 34701 | |
| 34702 | /*********************************/ |
| 34703 | /* Default attribute definitions */ |
| 34704 | /*********************************/ |
| 34705 | |
| 34706 | const UA_ObjectAttributes UA_ObjectAttributes_default = { |
| 34707 | 0, /* specifiedAttributes */ |
| 34708 | {{0, NULL}, {0, NULL}}, /* displayName */ |
| 34709 | {{0, NULL}, {0, NULL}}, /* description */ |
| 34710 | 0, 0, /* writeMask (userWriteMask) */ |
| 34711 | 0 /* eventNotifier */ |
| 34712 | }; |
| 34713 | |
| 34714 | const UA_VariableAttributes UA_VariableAttributes_default = { |
| 34715 | 0, /* specifiedAttributes */ |
| 34716 | {{0, NULL}, {0, NULL}}, /* displayName */ |
| 34717 | {{0, NULL}, {0, NULL}}, /* description */ |
| 34718 | 0, 0, /* writeMask (userWriteMask) */ |
| 34719 | {NULL, UA_VARIANT_DATA, |
| 34720 | 0, NULL, 0, NULL}, /* value */ |
| 34721 | {0, UA_NODEIDTYPE_NUMERIC, |
| 34722 | {UA_NS0ID_BASEDATATYPE}}, /* dataType */ |
| 34723 | UA_VALUERANK_ANY, /* valueRank */ |
| 34724 | 0, NULL, /* arrayDimensions */ |
| 34725 | UA_ACCESSLEVELMASK_READ | /* accessLevel */ |
| 34726 | UA_ACCESSLEVELMASK_STATUSWRITE | |
| 34727 | UA_ACCESSLEVELMASK_TIMESTAMPWRITE, |
| 34728 | 0, /* userAccessLevel */ |
| 34729 | 0.0, /* minimumSamplingInterval */ |
| 34730 | false /* historizing */ |
| 34731 | }; |
| 34732 | |
| 34733 | const UA_MethodAttributes UA_MethodAttributes_default = { |
| 34734 | 0, /* specifiedAttributes */ |
| 34735 | {{0, NULL}, {0, NULL}}, /* displayName */ |
| 34736 | {{0, NULL}, {0, NULL}}, /* description */ |
| 34737 | 0, 0, /* writeMask (userWriteMask) */ |
| 34738 | true, true /* executable (userExecutable) */ |
| 34739 | }; |
| 34740 | |
| 34741 | const UA_ObjectTypeAttributes UA_ObjectTypeAttributes_default = { |
| 34742 | 0, /* specifiedAttributes */ |
| 34743 | {{0, NULL}, {0, NULL}}, /* displayName */ |
| 34744 | {{0, NULL}, {0, NULL}}, /* description */ |
| 34745 | 0, 0, /* writeMask (userWriteMask) */ |
| 34746 | false /* isAbstract */ |
| 34747 | }; |
| 34748 | |
| 34749 | const UA_VariableTypeAttributes UA_VariableTypeAttributes_default = { |
| 34750 | 0, /* specifiedAttributes */ |
| 34751 | {{0, NULL}, {0, NULL}}, /* displayName */ |
| 34752 | {{0, NULL}, {0, NULL}}, /* description */ |
| 34753 | 0, 0, /* writeMask (userWriteMask) */ |
| 34754 | {NULL, UA_VARIANT_DATA, |
| 34755 | 0, NULL, 0, NULL}, /* value */ |
| 34756 | {0, UA_NODEIDTYPE_NUMERIC, |
| 34757 | {UA_NS0ID_BASEDATATYPE}}, /* dataType */ |
| 34758 | UA_VALUERANK_ANY, /* valueRank */ |
| 34759 | 0, NULL, /* arrayDimensions */ |
| 34760 | false /* isAbstract */ |
| 34761 | }; |
| 34762 | |
| 34763 | const UA_ReferenceTypeAttributes UA_ReferenceTypeAttributes_default = { |
| 34764 | 0, /* specifiedAttributes */ |
| 34765 | {{0, NULL}, {0, NULL}}, /* displayName */ |
| 34766 | {{0, NULL}, {0, NULL}}, /* description */ |
| 34767 | 0, 0, /* writeMask (userWriteMask) */ |
| 34768 | false, /* isAbstract */ |
| 34769 | false, /* symmetric */ |
| 34770 | {{0, NULL}, {0, NULL}} /* inverseName */ |
| 34771 | }; |
| 34772 | |
| 34773 | const UA_DataTypeAttributes UA_DataTypeAttributes_default = { |
| 34774 | 0, /* specifiedAttributes */ |
| 34775 | {{0, NULL}, {0, NULL}}, /* displayName */ |
| 34776 | {{0, NULL}, {0, NULL}}, /* description */ |
| 34777 | 0, 0, /* writeMask (userWriteMask) */ |
| 34778 | false /* isAbstract */ |
| 34779 | }; |
| 34780 | |
| 34781 | const UA_ViewAttributes UA_ViewAttributes_default = { |
| 34782 | 0, /* specifiedAttributes */ |
| 34783 | {{0, NULL}, {0, NULL}}, /* displayName */ |
| 34784 | {{0, NULL}, {0, NULL}}, /* description */ |
| 34785 | 0, 0, /* writeMask (userWriteMask) */ |
| 34786 | false, /* containsNoLoops */ |
| 34787 | 0 /* eventNotifier */ |
| 34788 | }; |
| 34789 | |
| 34790 | |
| 34791 | /**** amalgamated original file "/src/server/ua_server_async.c" ****/ |
| 34792 | |
| 34793 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 34794 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 34795 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 34796 | * |
| 34797 | * Copyright 2019 (c) Fraunhofer IOSB (Author: Klaus Schick) |
| 34798 | * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 34799 | */ |
| 34800 | |
| 34801 | |
| 34802 | #if UA_MULTITHREADING >= 100 |
| 34803 | |
| 34804 | static void |
| 34805 | UA_AsyncOperation_delete(UA_AsyncOperation *ar) { |
| 34806 | UA_CallMethodRequest_clear(&ar->request); |
| 34807 | UA_CallMethodResult_clear(&ar->response); |
| 34808 | UA_free(ar); |
| 34809 | } |
| 34810 | |
| 34811 | static void |
| 34812 | UA_AsyncManager_sendAsyncResponse(UA_AsyncManager *am, UA_Server *server, |
| 34813 | UA_AsyncResponse *ar) { |
| 34814 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 34815 | UA_LOCK_ASSERT(&am->queueLock, 1); |
| 34816 | |
| 34817 | /* Get the session */ |
| 34818 | UA_Session* session = getSessionById(server, &ar->sessionId); |
| 34819 | if(!session) { |
| 34820 | UA_String sessionId = UA_STRING_NULL; |
| 34821 | UA_NodeId_print(&ar->sessionId, &sessionId); |
| 34822 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 34823 | "Async Service: Session %.*s no longer exists", |
| 34824 | (int)sessionId.length, sessionId.data); |
| 34825 | UA_String_clear(&sessionId); |
| 34826 | UA_AsyncManager_removeAsyncResponse(&server->asyncManager, ar); |
| 34827 | return; |
| 34828 | } |
| 34829 | |
| 34830 | /* Check the channel */ |
| 34831 | UA_SecureChannel *channel = session->header.channel; |
| 34832 | if(!channel) { |
| 34833 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 34834 | "Async Service Response cannot be sent. " |
| 34835 | "No SecureChannel for the session."); |
| 34836 | UA_AsyncManager_removeAsyncResponse(&server->asyncManager, ar); |
| 34837 | return; |
| 34838 | } |
| 34839 | |
| 34840 | /* Set the request handle */ |
| 34841 | UA_ResponseHeader *responseHeader = (UA_ResponseHeader*) |
| 34842 | &ar->response.callResponse.responseHeader; |
| 34843 | responseHeader->requestHandle = ar->requestHandle; |
| 34844 | |
| 34845 | /* Send the Response */ |
| 34846 | UA_StatusCode res = |
| 34847 | sendResponse(server, session, channel, ar->requestId, |
| 34848 | (UA_Response*)&ar->response, &UA_TYPES[UA_TYPES_CALLRESPONSE]); |
| 34849 | if(res != UA_STATUSCODE_GOOD) { |
| 34850 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 34851 | "Async Response for Req# %"PRIu32 " failed " |
| 34852 | "with StatusCode %s", ar->requestId, |
| 34853 | UA_StatusCode_name(res)); |
| 34854 | } |
| 34855 | UA_AsyncManager_removeAsyncResponse(&server->asyncManager, ar); |
| 34856 | } |
| 34857 | |
| 34858 | /* Integrate operation result in the AsyncResponse and send out the response if |
| 34859 | * it is ready. */ |
| 34860 | static UA_Boolean |
| 34861 | integrateOperationResult(UA_AsyncManager *am, UA_Server *server, |
| 34862 | UA_AsyncOperation *ao) { |
| 34863 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 34864 | UA_LOCK_ASSERT(&am->queueLock, 1); |
| 34865 | |
| 34866 | /* Grab the open request, so we can continue to construct the response */ |
| 34867 | UA_AsyncResponse *ar = ao->parent; |
| 34868 | |
| 34869 | /* Reduce the number of open results */ |
| 34870 | ar->opCountdown -= 1; |
| 34871 | |
| 34872 | UA_LOG_DEBUG(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 34873 | "Return result in the server thread with %"PRIu32 " remaining", |
| 34874 | ar->opCountdown); |
| 34875 | |
| 34876 | /* Move the UA_CallMethodResult to UA_CallResponse */ |
| 34877 | ar->response.callResponse.results[ao->index] = ao->response; |
| 34878 | UA_CallMethodResult_init(&ao->response); |
| 34879 | |
| 34880 | /* Done with all operations -> send the response */ |
| 34881 | UA_Boolean done = (ar->opCountdown == 0); |
| 34882 | if(done) |
| 34883 | UA_AsyncManager_sendAsyncResponse(am, server, ar); |
| 34884 | return done; |
| 34885 | } |
| 34886 | |
| 34887 | /* Process all operations in the result queue -> move content over to the |
| 34888 | * AsyncResponse. This is only done by the server thread. Returns the nmber of |
| 34889 | * completed async sesponses. */ |
| 34890 | static UA_UInt32 |
| 34891 | processAsyncResults(UA_Server *server) { |
| 34892 | UA_AsyncManager *am = &server->asyncManager; |
| 34893 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 34894 | |
| 34895 | UA_UInt32 count = 0; |
| 34896 | UA_AsyncOperation *ao; |
| 34897 | UA_LOCK(&am->queueLock); |
| 34898 | while((ao = TAILQ_FIRST(&am->resultQueue))) { |
| 34899 | TAILQ_REMOVE(&am->resultQueue, ao, pointers); |
| 34900 | if(integrateOperationResult(am, server, ao)) |
| 34901 | count++; |
| 34902 | UA_AsyncOperation_delete(ao); |
| 34903 | /* Pacify clang-analyzer */ |
| 34904 | UA_assert(TAILQ_FIRST(&am->resultQueue) != ao); |
| 34905 | am->opsCount--; |
| 34906 | } |
| 34907 | UA_UNLOCK(&am->queueLock); |
| 34908 | return count; |
| 34909 | } |
| 34910 | |
| 34911 | /* Check if any operations have timed out */ |
| 34912 | static void |
| 34913 | checkTimeouts(UA_Server *server, void *_) { |
| 34914 | /* Timeouts are not configured */ |
| 34915 | if(server->config.asyncOperationTimeout <= 0.0) |
| 34916 | return; |
| 34917 | |
| 34918 | UA_AsyncManager *am = &server->asyncManager; |
| 34919 | const UA_DateTime tNow = UA_DateTime_now(); |
| 34920 | |
| 34921 | UA_LOCK(&am->queueLock); |
| 34922 | |
| 34923 | /* Loop over the queue of dispatched ops */ |
| 34924 | UA_AsyncOperation *op = NULL, *op_tmp = NULL; |
| 34925 | TAILQ_FOREACH_SAFE(op, &am->dispatchedQueue, pointers, op_tmp) { |
| 34926 | /* The timeout has not passed. Also for all elements following in the queue. */ |
| 34927 | if(tNow <= op->parent->timeout) |
| 34928 | break; |
| 34929 | |
| 34930 | /* Mark as timed out and put it into the result queue */ |
| 34931 | op->response.statusCode = UA_STATUSCODE_BADTIMEOUT; |
| 34932 | TAILQ_REMOVE(&am->dispatchedQueue, op, pointers); |
| 34933 | TAILQ_INSERT_TAIL(&am->resultQueue, op, pointers); |
| 34934 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 34935 | "Operation was removed due to a timeout"); |
| 34936 | } |
| 34937 | |
| 34938 | /* Loop over the queue of new ops */ |
| 34939 | TAILQ_FOREACH_SAFE(op, &am->newQueue, pointers, op_tmp) { |
| 34940 | /* The timeout has not passed. Also for all elements following in the queue. */ |
| 34941 | if(tNow <= op->parent->timeout) |
| 34942 | break; |
| 34943 | |
| 34944 | /* Mark as timed out and put it into the result queue */ |
| 34945 | op->response.statusCode = UA_STATUSCODE_BADTIMEOUT; |
| 34946 | TAILQ_REMOVE(&am->newQueue, op, pointers); |
| 34947 | TAILQ_INSERT_TAIL(&am->resultQueue, op, pointers); |
| 34948 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 34949 | "Operation was removed due to a timeout"); |
| 34950 | } |
| 34951 | |
| 34952 | UA_UNLOCK(&am->queueLock); |
| 34953 | |
| 34954 | /* Integrate async results and send out complete responses */ |
| 34955 | lockServer(server); |
| 34956 | processAsyncResults(server); |
| 34957 | unlockServer(server); |
| 34958 | } |
| 34959 | |
| 34960 | void |
| 34961 | UA_AsyncManager_init(UA_AsyncManager *am, UA_Server *server) { |
| 34962 | memset(am, 0, sizeof(UA_AsyncManager)); |
| 34963 | TAILQ_INIT(&am->asyncResponses); |
| 34964 | TAILQ_INIT(&am->newQueue); |
| 34965 | TAILQ_INIT(&am->dispatchedQueue); |
| 34966 | TAILQ_INIT(&am->resultQueue); |
| 34967 | UA_LOCK_INIT(&am->queueLock); |
| 34968 | |
| 34969 | /* Add a regular callback for cleanup and sending finished responses at a |
| 34970 | * 1s interval. */ |
| 34971 | addRepeatedCallback(server, (UA_ServerCallback)checkTimeouts, |
| 34972 | NULL, 1000.0, &am->checkTimeoutCallbackId); |
| 34973 | } |
| 34974 | |
| 34975 | void |
| 34976 | UA_AsyncManager_clear(UA_AsyncManager *am, UA_Server *server) { |
| 34977 | removeCallback(server, am->checkTimeoutCallbackId); |
| 34978 | |
| 34979 | UA_AsyncOperation *ar, *ar_tmp; |
| 34980 | |
| 34981 | /* Clean up queues */ |
| 34982 | UA_LOCK(&am->queueLock); |
| 34983 | TAILQ_FOREACH_SAFE(ar, &am->newQueue, pointers, ar_tmp) { |
| 34984 | TAILQ_REMOVE(&am->newQueue, ar, pointers); |
| 34985 | UA_AsyncOperation_delete(ar); |
| 34986 | } |
| 34987 | TAILQ_FOREACH_SAFE(ar, &am->dispatchedQueue, pointers, ar_tmp) { |
| 34988 | TAILQ_REMOVE(&am->dispatchedQueue, ar, pointers); |
| 34989 | UA_AsyncOperation_delete(ar); |
| 34990 | } |
| 34991 | TAILQ_FOREACH_SAFE(ar, &am->resultQueue, pointers, ar_tmp) { |
| 34992 | TAILQ_REMOVE(&am->resultQueue, ar, pointers); |
| 34993 | UA_AsyncOperation_delete(ar); |
| 34994 | } |
| 34995 | UA_UNLOCK(&am->queueLock); |
| 34996 | |
| 34997 | /* Remove responses */ |
| 34998 | UA_AsyncResponse *current, *temp; |
| 34999 | TAILQ_FOREACH_SAFE(current, &am->asyncResponses, pointers, temp) { |
| 35000 | UA_AsyncManager_removeAsyncResponse(am, current); |
| 35001 | } |
| 35002 | |
| 35003 | /* Delete all locks */ |
| 35004 | UA_LOCK_DESTROY(&am->queueLock); |
| 35005 | } |
| 35006 | |
| 35007 | UA_StatusCode |
| 35008 | UA_AsyncManager_createAsyncResponse(UA_AsyncManager *am, UA_Server *server, |
| 35009 | const UA_NodeId *sessionId, |
| 35010 | const UA_UInt32 requestId, const UA_UInt32 requestHandle, |
| 35011 | const UA_AsyncOperationType operationType, |
| 35012 | UA_AsyncResponse **outAr) { |
| 35013 | UA_AsyncResponse *newentry = (UA_AsyncResponse*)UA_calloc(1, sizeof(UA_AsyncResponse)); |
| 35014 | if(!newentry) |
| 35015 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 35016 | |
| 35017 | UA_StatusCode res = UA_NodeId_copy(sessionId, &newentry->sessionId); |
| 35018 | if(res != UA_STATUSCODE_GOOD) { |
| 35019 | UA_free(newentry); |
| 35020 | return res; |
| 35021 | } |
| 35022 | |
| 35023 | am->asyncResponsesCount += 1; |
| 35024 | newentry->requestId = requestId; |
| 35025 | newentry->requestHandle = requestHandle; |
| 35026 | newentry->timeout = UA_DateTime_now(); |
| 35027 | if(server->config.asyncOperationTimeout > 0.0) |
| 35028 | newentry->timeout += (UA_DateTime) |
| 35029 | (server->config.asyncOperationTimeout * (UA_DateTime)UA_DATETIME_MSEC); |
| 35030 | TAILQ_INSERT_TAIL(&am->asyncResponses, newentry, pointers); |
| 35031 | |
| 35032 | *outAr = newentry; |
| 35033 | return UA_STATUSCODE_GOOD; |
| 35034 | } |
| 35035 | |
| 35036 | /* Remove entry and free all allocated data */ |
| 35037 | void |
| 35038 | UA_AsyncManager_removeAsyncResponse(UA_AsyncManager *am, UA_AsyncResponse *ar) { |
| 35039 | TAILQ_REMOVE(&am->asyncResponses, ar, pointers); |
| 35040 | am->asyncResponsesCount -= 1; |
| 35041 | UA_CallResponse_clear(&ar->response.callResponse); |
| 35042 | UA_NodeId_clear(&ar->sessionId); |
| 35043 | UA_free(ar); |
| 35044 | } |
| 35045 | |
| 35046 | /* Enqueue next MethodRequest */ |
| 35047 | UA_StatusCode |
| 35048 | UA_AsyncManager_createAsyncOp(UA_AsyncManager *am, UA_Server *server, |
| 35049 | UA_AsyncResponse *ar, size_t opIndex, |
| 35050 | const UA_CallMethodRequest *opRequest) { |
| 35051 | if(server->config.maxAsyncOperationQueueSize != 0 && |
| 35052 | am->opsCount >= server->config.maxAsyncOperationQueueSize) { |
| 35053 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 35054 | "UA_Server_SetNextAsyncMethod: Queue exceeds limit (%d).", |
| 35055 | (int unsigned)server->config.maxAsyncOperationQueueSize); |
| 35056 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 35057 | } |
| 35058 | |
| 35059 | UA_AsyncOperation *ao = (UA_AsyncOperation*)UA_calloc(1, sizeof(UA_AsyncOperation)); |
| 35060 | if(!ao) { |
| 35061 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 35062 | "UA_Server_SetNextAsyncMethod: Mem alloc failed."); |
| 35063 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 35064 | } |
| 35065 | |
| 35066 | UA_StatusCode result = UA_CallMethodRequest_copy(opRequest, &ao->request); |
| 35067 | if(result != UA_STATUSCODE_GOOD) { |
| 35068 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 35069 | "UA_Server_SetAsyncMethodResult: UA_CallMethodRequest_copy failed."); |
| 35070 | UA_free(ao); |
| 35071 | return result; |
| 35072 | } |
| 35073 | |
| 35074 | UA_CallMethodResult_init(&ao->response); |
| 35075 | ao->index = opIndex; |
| 35076 | ao->parent = ar; |
| 35077 | |
| 35078 | UA_LOCK(&am->queueLock); |
| 35079 | TAILQ_INSERT_TAIL(&am->newQueue, ao, pointers); |
| 35080 | am->opsCount++; |
| 35081 | ar->opCountdown++; |
| 35082 | UA_UNLOCK(&am->queueLock); |
| 35083 | |
| 35084 | if(server->config.asyncOperationNotifyCallback) |
| 35085 | server->config.asyncOperationNotifyCallback(server); |
| 35086 | |
| 35087 | return UA_STATUSCODE_GOOD; |
| 35088 | } |
| 35089 | |
| 35090 | /* Get and remove next Method Call Request */ |
| 35091 | UA_Boolean |
| 35092 | UA_Server_getAsyncOperationNonBlocking(UA_Server *server, UA_AsyncOperationType *type, |
| 35093 | const UA_AsyncOperationRequest **request, |
| 35094 | void **context, UA_DateTime *timeout) { |
| 35095 | UA_AsyncManager *am = &server->asyncManager; |
| 35096 | |
| 35097 | UA_Boolean bRV = false; |
| 35098 | *type = UA_ASYNCOPERATIONTYPE_INVALID; |
| 35099 | UA_LOCK(&am->queueLock); |
| 35100 | UA_AsyncOperation *ao = TAILQ_FIRST(&am->newQueue); |
| 35101 | if(ao) { |
| 35102 | TAILQ_REMOVE(&am->newQueue, ao, pointers); |
| 35103 | TAILQ_INSERT_TAIL(&am->dispatchedQueue, ao, pointers); |
| 35104 | *type = UA_ASYNCOPERATIONTYPE_CALL; |
| 35105 | *request = (UA_AsyncOperationRequest*)&ao->request; |
| 35106 | *context = (void*)ao; |
| 35107 | if(timeout) |
| 35108 | *timeout = ao->parent->timeout; |
| 35109 | bRV = true; |
| 35110 | } |
| 35111 | UA_UNLOCK(&am->queueLock); |
| 35112 | |
| 35113 | return bRV; |
| 35114 | } |
| 35115 | |
| 35116 | /* Worker submits Method Call Response */ |
| 35117 | void |
| 35118 | UA_Server_setAsyncOperationResult(UA_Server *server, |
| 35119 | const UA_AsyncOperationResponse *response, |
| 35120 | void *context) { |
| 35121 | UA_AsyncManager *am = &server->asyncManager; |
| 35122 | |
| 35123 | UA_AsyncOperation *ao = (UA_AsyncOperation*)context; |
| 35124 | if(!ao) { |
| 35125 | /* Something went wrong. Not a good AsyncOp. */ |
| 35126 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 35127 | "UA_Server_SetAsyncMethodResult: Invalid context"); |
| 35128 | return; |
| 35129 | } |
| 35130 | |
| 35131 | UA_LOCK(&am->queueLock); |
| 35132 | |
| 35133 | /* See if the operation is still in the dispatched queue. Otherwise it has |
| 35134 | * been removed due to a timeout. |
| 35135 | * |
| 35136 | * TODO: Add a tree-structure for the dispatch queue. The linear lookup does |
| 35137 | * not scale. */ |
| 35138 | UA_Boolean found = false; |
| 35139 | UA_AsyncOperation *op = NULL; |
| 35140 | TAILQ_FOREACH(op, &am->dispatchedQueue, pointers) { |
| 35141 | if(op == ao) { |
| 35142 | found = true; |
| 35143 | break; |
| 35144 | } |
| 35145 | } |
| 35146 | |
| 35147 | if(!found) { |
| 35148 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 35149 | "UA_Server_SetAsyncMethodResult: The operation has timed out"); |
| 35150 | UA_UNLOCK(&am->queueLock); |
| 35151 | return; |
| 35152 | } |
| 35153 | |
| 35154 | /* Copy the result into the internal AsyncOperation */ |
| 35155 | UA_StatusCode result = |
| 35156 | UA_CallMethodResult_copy(&response->callMethodResult, &ao->response); |
| 35157 | if(result != UA_STATUSCODE_GOOD) { |
| 35158 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 35159 | "UA_Server_SetAsyncMethodResult: UA_CallMethodResult_copy failed."); |
| 35160 | ao->response.statusCode = UA_STATUSCODE_BADOUTOFMEMORY; |
| 35161 | } |
| 35162 | |
| 35163 | /* Move to the result queue */ |
| 35164 | TAILQ_REMOVE(&am->dispatchedQueue, ao, pointers); |
| 35165 | TAILQ_INSERT_TAIL(&am->resultQueue, ao, pointers); |
| 35166 | |
| 35167 | UA_UNLOCK(&am->queueLock); |
| 35168 | |
| 35169 | UA_LOG_DEBUG(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 35170 | "Set the result from the worker thread"); |
| 35171 | } |
| 35172 | |
| 35173 | /******************/ |
| 35174 | /* Server Methods */ |
| 35175 | /******************/ |
| 35176 | |
| 35177 | static UA_StatusCode |
| 35178 | setMethodNodeAsync(UA_Server *server, UA_Session *session, |
| 35179 | UA_Node *node, UA_Boolean *isAsync) { |
| 35180 | if(node->head.nodeClass != UA_NODECLASS_METHOD) |
| 35181 | return UA_STATUSCODE_BADNODECLASSINVALID; |
| 35182 | node->methodNode.async = *isAsync; |
| 35183 | return UA_STATUSCODE_GOOD; |
| 35184 | } |
| 35185 | |
| 35186 | UA_StatusCode |
| 35187 | UA_Server_setMethodNodeAsync(UA_Server *server, const UA_NodeId id, |
| 35188 | UA_Boolean isAsync) { |
| 35189 | lockServer(server); |
| 35190 | UA_StatusCode res = |
| 35191 | UA_Server_editNode(server, &server->adminSession, &id, |
| 35192 | (UA_EditNodeCallback)setMethodNodeAsync, &isAsync); |
| 35193 | unlockServer(server); |
| 35194 | return res; |
| 35195 | } |
| 35196 | |
| 35197 | UA_StatusCode |
| 35198 | UA_Server_processServiceOperationsAsync(UA_Server *server, UA_Session *session, |
| 35199 | UA_UInt32 requestId, UA_UInt32 requestHandle, |
| 35200 | UA_AsyncServiceOperation operationCallback, |
| 35201 | const size_t *requestOperations, |
| 35202 | const UA_DataType *requestOperationsType, |
| 35203 | size_t *responseOperations, |
| 35204 | const UA_DataType *responseOperationsType, |
| 35205 | UA_AsyncResponse **ar) { |
| 35206 | size_t ops = *requestOperations; |
| 35207 | if(ops == 0) |
| 35208 | return UA_STATUSCODE_BADNOTHINGTODO; |
| 35209 | |
| 35210 | /* Allocate the response array. No padding after size_t */ |
| 35211 | void **respPos = (void**)((uintptr_t)responseOperations + sizeof(size_t)); |
| 35212 | *respPos = UA_Array_new(ops, responseOperationsType); |
| 35213 | if(!*respPos) |
| 35214 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 35215 | *responseOperations = ops; |
| 35216 | |
| 35217 | /* Finish / dispatch the operations. This may allocate a new AsyncResponse internally */ |
| 35218 | uintptr_t respOp = (uintptr_t)*respPos; |
| 35219 | uintptr_t reqOp = *(uintptr_t*)((uintptr_t)requestOperations + sizeof(size_t)); |
| 35220 | for(size_t i = 0; i < ops; i++) { |
| 35221 | operationCallback(server, session, requestId, requestHandle, |
| 35222 | i, (void*)reqOp, (void*)respOp, ar); |
| 35223 | reqOp += requestOperationsType->memSize; |
| 35224 | respOp += responseOperationsType->memSize; |
| 35225 | } |
| 35226 | |
| 35227 | return UA_STATUSCODE_GOOD; |
| 35228 | } |
| 35229 | |
| 35230 | UA_UInt32 |
| 35231 | UA_AsyncManager_cancel(UA_Server *server, UA_Session *session, UA_UInt32 requestHandle) { |
| 35232 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 35233 | UA_AsyncManager *am = &server->asyncManager; |
| 35234 | |
| 35235 | UA_LOCK(&am->queueLock); |
| 35236 | |
| 35237 | /* Loop over the queue of dispatched ops */ |
| 35238 | UA_AsyncOperation *op = NULL, *op_tmp = NULL; |
| 35239 | TAILQ_FOREACH_SAFE(op, &am->dispatchedQueue, pointers, op_tmp) { |
| 35240 | if(op->parent->requestHandle != requestHandle || |
| 35241 | !UA_NodeId_equal(&session->sessionId, &op->parent->sessionId)) |
| 35242 | continue; |
| 35243 | |
| 35244 | /* Set status and put it into the result queue */ |
| 35245 | op->response.statusCode = UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT; |
| 35246 | TAILQ_REMOVE(&am->dispatchedQueue, op, pointers); |
| 35247 | TAILQ_INSERT_TAIL(&am->resultQueue, op, pointers); |
| 35248 | |
| 35249 | /* Also set the status of the overall response */ |
| 35250 | op->parent->response.callResponse.responseHeader. |
| 35251 | serviceResult = UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT; |
| 35252 | } |
| 35253 | |
| 35254 | /* Idem for waiting ops */ |
| 35255 | TAILQ_FOREACH_SAFE(op, &am->newQueue, pointers, op_tmp) { |
| 35256 | if(op->parent->requestHandle != requestHandle || |
| 35257 | !UA_NodeId_equal(&session->sessionId, &op->parent->sessionId)) |
| 35258 | continue; |
| 35259 | |
| 35260 | /* Mark as timed out and put it into the result queue */ |
| 35261 | op->response.statusCode = UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT; |
| 35262 | TAILQ_REMOVE(&am->newQueue, op, pointers); |
| 35263 | TAILQ_INSERT_TAIL(&am->resultQueue, op, pointers); |
| 35264 | |
| 35265 | op->parent->response.callResponse.responseHeader. |
| 35266 | serviceResult = UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT; |
| 35267 | } |
| 35268 | |
| 35269 | UA_UNLOCK(&am->queueLock); |
| 35270 | |
| 35271 | /* Process messages that have all ops completed */ |
| 35272 | return processAsyncResults(server); |
| 35273 | } |
| 35274 | |
| 35275 | #endif |
| 35276 | |
| 35277 | /**** amalgamated original file "/src/server/ua_services_view.c" ****/ |
| 35278 | |
| 35279 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 35280 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 35281 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 35282 | * |
| 35283 | * Copyright 2014-2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 35284 | * Copyright 2014-2017 (c) Florian Palm |
| 35285 | * Copyright 2015-2016 (c) Sten Grüner |
| 35286 | * Copyright 2015 (c) LEvertz |
| 35287 | * Copyright 2015 (c) Chris Iatrou |
| 35288 | * Copyright 2015 (c) Ecosmos |
| 35289 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 35290 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 35291 | * Copyright 2016 (c) Lorenz Haas |
| 35292 | * Copyright 2017 (c) pschoppe |
| 35293 | * Copyright 2017 (c) Julian Grothoff |
| 35294 | * Copyright 2017 (c) Henrik Norrman |
| 35295 | */ |
| 35296 | |
| 35297 | |
| 35298 | #define UA_MAX_TREE_RECURSE 50 /* How deep up/down the tree do we recurse at most? */ |
| 35299 | |
| 35300 | static UA_UInt32 |
| 35301 | resultMask2AttributesMask(UA_UInt32 resultMask) { |
| 35302 | UA_UInt32 result = 0; |
| 35303 | if(resultMask & UA_BROWSERESULTMASK_NODECLASS) |
| 35304 | result |= UA_NODEATTRIBUTESMASK_NODECLASS; |
| 35305 | if(resultMask & UA_BROWSERESULTMASK_BROWSENAME) |
| 35306 | result |= UA_NODEATTRIBUTESMASK_BROWSENAME; |
| 35307 | if(resultMask & UA_BROWSERESULTMASK_DISPLAYNAME) |
| 35308 | result |= UA_NODEATTRIBUTESMASK_DISPLAYNAME; |
| 35309 | return result; |
| 35310 | } |
| 35311 | |
| 35312 | UA_StatusCode |
| 35313 | referenceTypeIndices(UA_Server *server, const UA_NodeId *refType, |
| 35314 | UA_ReferenceTypeSet *indices, UA_Boolean includeSubtypes) { |
| 35315 | if(UA_NodeId_isNull(p: refType)) { |
| 35316 | *indices = UA_REFERENCETYPESET_ALL; |
| 35317 | return UA_STATUSCODE_GOOD; |
| 35318 | } |
| 35319 | |
| 35320 | UA_ReferenceTypeSet_init(set: indices); |
| 35321 | |
| 35322 | /* Get the node with only the NodeClass attribute. If it is a |
| 35323 | * ReferenceTypeNode, then the indices are always included, as this is an |
| 35324 | * open62541 specific field (not selectable via the attribute id). */ |
| 35325 | const UA_Node *refNode = |
| 35326 | UA_NODESTORE_GET_SELECTIVE(server, refType, |
| 35327 | UA_NODEATTRIBUTESMASK_NODECLASS, |
| 35328 | UA_REFERENCETYPESET_NONE, |
| 35329 | UA_BROWSEDIRECTION_INVALID); |
| 35330 | |
| 35331 | if(!refNode) |
| 35332 | return UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 35333 | |
| 35334 | if(refNode->head.nodeClass != UA_NODECLASS_REFERENCETYPE) { |
| 35335 | UA_NODESTORE_RELEASE(server, refNode); |
| 35336 | return UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 35337 | } |
| 35338 | |
| 35339 | if(!includeSubtypes) |
| 35340 | *indices = UA_REFTYPESET(index: refNode->referenceTypeNode.referenceTypeIndex); |
| 35341 | else |
| 35342 | *indices = refNode->referenceTypeNode.subTypes; |
| 35343 | |
| 35344 | UA_NODESTORE_RELEASE(server, refNode); |
| 35345 | return UA_STATUSCODE_GOOD; |
| 35346 | } |
| 35347 | |
| 35348 | static UA_Boolean |
| 35349 | matchClassMask(const UA_Node *node, UA_UInt32 nodeClassMask) { |
| 35350 | if(nodeClassMask != UA_NODECLASS_UNSPECIFIED && |
| 35351 | (node->head.nodeClass & nodeClassMask) == 0) |
| 35352 | return false; |
| 35353 | return true; |
| 35354 | } |
| 35355 | |
| 35356 | /****************/ |
| 35357 | /* IsNodeInTree */ |
| 35358 | /****************/ |
| 35359 | |
| 35360 | /* Internal method to check if a node is already upwards from a leaf node */ |
| 35361 | |
| 35362 | static enum ZIP_CMP |
| 35363 | cmpRefTarget(const void *a, const void *b) { |
| 35364 | const UA_ReferenceTarget *aa = (const UA_ReferenceTarget*)a; |
| 35365 | const UA_ReferenceTarget *bb = (const UA_ReferenceTarget*)b; |
| 35366 | return (enum ZIP_CMP)UA_NodePointer_order(p1: aa->targetId, p2: bb->targetId); |
| 35367 | } |
| 35368 | |
| 35369 | typedef ZIP_HEAD(UA_ParentRefsTree, UA_ReferenceTargetTreeElem) UA_ParentRefsTree; |
| 35370 | ZIP_FUNCTIONS(UA_ParentRefsTree, UA_ReferenceTargetTreeElem, idTreeEntry, |
| 35371 | UA_NodePointer, target, cmpRefTarget) |
| 35372 | |
| 35373 | struct IsNodeInTreeContext { |
| 35374 | UA_Server *server; |
| 35375 | UA_NodePointer nodeToFind; |
| 35376 | UA_ParentRefsTree parents; |
| 35377 | UA_ReferenceTypeSet relevantRefs; |
| 35378 | UA_UInt16 depth; |
| 35379 | }; |
| 35380 | |
| 35381 | static void * |
| 35382 | isNodeInTreeIterateCallback(void *context, UA_ReferenceTarget *t) { |
| 35383 | struct IsNodeInTreeContext *tc = |
| 35384 | (struct IsNodeInTreeContext*)context; |
| 35385 | |
| 35386 | /* Don't follow remote targets */ |
| 35387 | if(!UA_NodePointer_isLocal(np: t->targetId)) |
| 35388 | return NULL; |
| 35389 | |
| 35390 | /* Found the node? -> return non-NULL */ |
| 35391 | if(UA_NodePointer_equal(p1: tc->nodeToFind, p2: t->targetId)) |
| 35392 | return (void*)0x01; |
| 35393 | |
| 35394 | /* Prevent endless loop */ |
| 35395 | if(ZIP_FIND(UA_ParentRefsTree, &tc->parents, &t->targetId)) |
| 35396 | return NULL; |
| 35397 | |
| 35398 | /* Prevent pathological recursion depth */ |
| 35399 | if(tc->depth >= UA_MAX_TREE_RECURSE) |
| 35400 | return NULL; |
| 35401 | |
| 35402 | /* Get the node without attributes (if the NodeStore supports it) and only |
| 35403 | * the relevant references in inverse direction */ |
| 35404 | const UA_Node *node = |
| 35405 | UA_NODESTORE_GETFROMREF_SELECTIVE(tc->server, t->targetId, |
| 35406 | UA_NODEATTRIBUTESMASK_NONE, |
| 35407 | tc->relevantRefs, |
| 35408 | UA_BROWSEDIRECTION_INVERSE); |
| 35409 | if(!node) |
| 35410 | return NULL; |
| 35411 | |
| 35412 | /* Add current NodeId to parents tree */ |
| 35413 | UA_ReferenceTargetTreeElem stackElem; |
| 35414 | stackElem.target = *t; |
| 35415 | ZIP_INSERT(UA_ParentRefsTree, &tc->parents, &stackElem); |
| 35416 | |
| 35417 | /* Recurse into appropriate references starting from this tree */ |
| 35418 | tc->depth++; |
| 35419 | void *res = NULL; |
| 35420 | for(size_t i = 0; i < node->head.referencesSize && !res; i++) { |
| 35421 | UA_NodeReferenceKind *rk = &node->head.references[i]; |
| 35422 | /* Search upwards in the tree */ |
| 35423 | if(!rk->isInverse) |
| 35424 | continue; |
| 35425 | |
| 35426 | /* Consider only the indicated reference types */ |
| 35427 | if(!UA_ReferenceTypeSet_contains(set: &tc->relevantRefs, index: rk->referenceTypeIndex)) |
| 35428 | continue; |
| 35429 | |
| 35430 | res = UA_NodeReferenceKind_iterate(rk, callback: isNodeInTreeIterateCallback, context: tc); |
| 35431 | } |
| 35432 | tc->depth--; |
| 35433 | |
| 35434 | /* Clean up */ |
| 35435 | UA_NODESTORE_RELEASE(tc->server, node); |
| 35436 | ZIP_REMOVE(UA_ParentRefsTree, &tc->parents, &stackElem); |
| 35437 | return res; |
| 35438 | } |
| 35439 | |
| 35440 | UA_Boolean |
| 35441 | isNodeInTree(UA_Server *server, const UA_NodeId *leafNode, |
| 35442 | const UA_NodeId *nodeToFind, |
| 35443 | const UA_ReferenceTypeSet *relevantRefs) { |
| 35444 | struct IsNodeInTreeContext ctx; |
| 35445 | memset(s: &ctx, c: 0, n: sizeof(struct IsNodeInTreeContext)); |
| 35446 | ctx.server = server; |
| 35447 | ctx.nodeToFind = UA_NodePointer_fromNodeId(id: nodeToFind); |
| 35448 | ctx.relevantRefs = *relevantRefs; |
| 35449 | UA_ReferenceTarget tmpTarget; |
| 35450 | memset(s: &tmpTarget, c: 0, n: sizeof(UA_ReferenceTarget)); |
| 35451 | tmpTarget.targetId = UA_NodePointer_fromNodeId(id: leafNode); |
| 35452 | return (isNodeInTreeIterateCallback(context: &ctx, t: &tmpTarget) != NULL); |
| 35453 | } |
| 35454 | |
| 35455 | UA_Boolean |
| 35456 | isNodeInTree_singleRef(UA_Server *server, const UA_NodeId *leafNode, |
| 35457 | const UA_NodeId *nodeToFind, const UA_Byte relevantRefTypeIndex) { |
| 35458 | UA_ReferenceTypeSet reftypes = UA_REFTYPESET(index: relevantRefTypeIndex); |
| 35459 | return isNodeInTree(server, leafNode, nodeToFind, relevantRefs: &reftypes); |
| 35460 | } |
| 35461 | |
| 35462 | static enum ZIP_CMP |
| 35463 | cmpTarget(const void *a, const void *b) { |
| 35464 | const RefEntry *aa = (const RefEntry*)a; |
| 35465 | const RefEntry *bb = (const RefEntry*)b; |
| 35466 | if(aa->targetHash < bb->targetHash) |
| 35467 | return ZIP_CMP_LESS; |
| 35468 | if(aa->targetHash > bb->targetHash) |
| 35469 | return ZIP_CMP_MORE; |
| 35470 | return (enum ZIP_CMP)UA_ExpandedNodeId_order(n1: aa->target, n2: bb->target); |
| 35471 | } |
| 35472 | |
| 35473 | ZIP_FUNCTIONS(RefHead, RefEntry, zipfields, RefEntry, zipfields, cmpTarget) |
| 35474 | |
| 35475 | UA_StatusCode |
| 35476 | RefTree_init(RefTree *rt) { |
| 35477 | rt->size = 0; |
| 35478 | rt->capacity = 0; |
| 35479 | ZIP_INIT(&rt->head); |
| 35480 | size_t space = (sizeof(UA_ExpandedNodeId) + sizeof(RefEntry)) * UA_REFTREE_INITIAL_SIZE; |
| 35481 | rt->targets = (UA_ExpandedNodeId*)UA_malloc(size: space); |
| 35482 | if(!rt->targets) |
| 35483 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 35484 | rt->capacity = UA_REFTREE_INITIAL_SIZE; |
| 35485 | return UA_STATUSCODE_GOOD; |
| 35486 | } |
| 35487 | |
| 35488 | void |
| 35489 | RefTree_clear(RefTree *rt) { |
| 35490 | for(size_t i = 0; i < rt->size; i++) |
| 35491 | UA_ExpandedNodeId_clear(p: &rt->targets[i]); |
| 35492 | if(rt->targets) |
| 35493 | UA_free(ptr: rt->targets); |
| 35494 | } |
| 35495 | |
| 35496 | /* Double the capacity of the reftree */ |
| 35497 | static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT |
| 35498 | RefTree_double(RefTree *rt) { |
| 35499 | size_t capacity = rt->capacity * 2; |
| 35500 | UA_assert(capacity > 0); |
| 35501 | size_t space = (sizeof(UA_ExpandedNodeId) + sizeof(RefEntry)) * capacity; |
| 35502 | UA_ExpandedNodeId *newTargets = (UA_ExpandedNodeId*)UA_realloc(ptr: rt->targets, size: space); |
| 35503 | if(!newTargets) |
| 35504 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 35505 | |
| 35506 | /* Move the entries to the new location */ |
| 35507 | RefEntry *reArray = (RefEntry*) |
| 35508 | ((uintptr_t)newTargets + (capacity * sizeof(UA_ExpandedNodeId))); |
| 35509 | RefEntry *oldReArray = (RefEntry*) |
| 35510 | ((uintptr_t)newTargets + (rt->capacity * sizeof(UA_ExpandedNodeId))); |
| 35511 | memmove(dest: reArray, src: oldReArray, n: rt->size * sizeof(RefEntry)); |
| 35512 | |
| 35513 | /* Reinsert all entries into the tree. The new pointer location has changed |
| 35514 | * their ziptree rank. */ |
| 35515 | rt->head.root = NULL; |
| 35516 | for(size_t i = 0; i < rt->size; i++) { |
| 35517 | reArray[i].target = &newTargets[i]; |
| 35518 | ZIP_INSERT(RefHead, &rt->head, &reArray[i]); |
| 35519 | } |
| 35520 | |
| 35521 | rt->capacity = capacity; |
| 35522 | rt->targets = newTargets; |
| 35523 | return UA_STATUSCODE_GOOD; |
| 35524 | } |
| 35525 | |
| 35526 | static UA_StatusCode |
| 35527 | RefTree_add(RefTree *rt, UA_NodePointer target, UA_Boolean *duplicate) { |
| 35528 | UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(np: target); |
| 35529 | |
| 35530 | /* Is the target already in the tree? */ |
| 35531 | RefEntry dummy; |
| 35532 | memset(s: &dummy, c: 0, n: sizeof(RefEntry)); |
| 35533 | dummy.target = &en; |
| 35534 | dummy.targetHash = UA_ExpandedNodeId_hash(n: &en); |
| 35535 | if(ZIP_FIND(RefHead, &rt->head, &dummy)) { |
| 35536 | if(duplicate) |
| 35537 | *duplicate = true; |
| 35538 | return UA_STATUSCODE_GOOD; |
| 35539 | } |
| 35540 | |
| 35541 | UA_StatusCode s = UA_STATUSCODE_GOOD; |
| 35542 | if(rt->capacity <= rt->size) { |
| 35543 | s = RefTree_double(rt); |
| 35544 | if(s != UA_STATUSCODE_GOOD) |
| 35545 | return s; |
| 35546 | } |
| 35547 | s = UA_ExpandedNodeId_copy(src: &en, dst: &rt->targets[rt->size]); |
| 35548 | if(s != UA_STATUSCODE_GOOD) |
| 35549 | return s; |
| 35550 | RefEntry *re = (RefEntry*)((uintptr_t)rt->targets + |
| 35551 | (sizeof(UA_ExpandedNodeId) * rt->capacity) + |
| 35552 | (sizeof(RefEntry) * rt->size)); |
| 35553 | re->target = &rt->targets[rt->size]; |
| 35554 | re->targetHash = dummy.targetHash; |
| 35555 | ZIP_INSERT(RefHead, &rt->head, re); |
| 35556 | rt->size++; |
| 35557 | return UA_STATUSCODE_GOOD; |
| 35558 | } |
| 35559 | |
| 35560 | UA_StatusCode |
| 35561 | RefTree_addNodeId(RefTree *rt, const UA_NodeId *target, |
| 35562 | UA_Boolean *duplicate) { |
| 35563 | return RefTree_add(rt, target: UA_NodePointer_fromNodeId(id: target), duplicate); |
| 35564 | } |
| 35565 | |
| 35566 | UA_Boolean |
| 35567 | RefTree_contains(RefTree *rt, const UA_ExpandedNodeId *target) { |
| 35568 | RefEntry dummy; |
| 35569 | dummy.target = target; |
| 35570 | dummy.targetHash = UA_ExpandedNodeId_hash(n: target); |
| 35571 | return !!ZIP_FIND(RefHead, &rt->head, &dummy); |
| 35572 | } |
| 35573 | |
| 35574 | UA_Boolean |
| 35575 | RefTree_containsNodeId(RefTree *rt, const UA_NodeId *target) { |
| 35576 | UA_ExpandedNodeId en; |
| 35577 | en.nodeId = *target; |
| 35578 | en.namespaceUri = UA_STRING_NULL; |
| 35579 | en.serverIndex = 0; |
| 35580 | return RefTree_contains(rt, target: &en); |
| 35581 | } |
| 35582 | |
| 35583 | /********************/ |
| 35584 | /* Browse Recursive */ |
| 35585 | /********************/ |
| 35586 | |
| 35587 | struct BrowseRecursiveContext { |
| 35588 | UA_Server *server; |
| 35589 | RefTree *rt; |
| 35590 | UA_UInt16 depth; |
| 35591 | UA_BrowseDirection browseDirection; |
| 35592 | UA_ReferenceTypeSet refTypes; |
| 35593 | UA_UInt32 nodeClassMask; |
| 35594 | UA_StatusCode status; |
| 35595 | UA_Boolean includeStartNodes; |
| 35596 | }; |
| 35597 | |
| 35598 | static void * |
| 35599 | browseRecursiveCallback(void *context, UA_ReferenceTarget *t) { |
| 35600 | struct BrowseRecursiveContext *brc = |
| 35601 | (struct BrowseRecursiveContext*)context; |
| 35602 | |
| 35603 | /* Have we reached the max recursion depth? */ |
| 35604 | if(brc->depth >= UA_MAX_TREE_RECURSE) |
| 35605 | return NULL; |
| 35606 | |
| 35607 | /* Is this a non-local reference? If yes include it in the returned set. */ |
| 35608 | if(!UA_NodePointer_isLocal(np: t->targetId)) { |
| 35609 | brc->status = RefTree_add(rt: brc->rt, target: t->targetId, NULL); |
| 35610 | return (brc->status == UA_STATUSCODE_GOOD) ? NULL : (void*)0x01; |
| 35611 | } |
| 35612 | |
| 35613 | /* We only look at the NodeClass attribute and a subset of the references. |
| 35614 | * Get a node with only these elements if the NodeStore supports that. */ |
| 35615 | const UA_Node *node = |
| 35616 | UA_NODESTORE_GETFROMREF_SELECTIVE(brc->server, t->targetId, |
| 35617 | UA_NODEATTRIBUTESMASK_NODECLASS, |
| 35618 | brc->refTypes, brc->browseDirection); |
| 35619 | if(!node) |
| 35620 | return NULL; |
| 35621 | |
| 35622 | /* Add the current node if we don't want to skip it as a start node and it |
| 35623 | * matches the nodeClassMask filter Recurse into the children in any |
| 35624 | * case. */ |
| 35625 | const UA_NodeHead *head = &node->head; |
| 35626 | if((brc->includeStartNodes || brc->depth > 0) && |
| 35627 | matchClassMask(node, nodeClassMask: brc->nodeClassMask)) { |
| 35628 | UA_Boolean duplicate = false; |
| 35629 | brc->status = RefTree_addNodeId(rt: brc->rt, target: &head->nodeId, duplicate: &duplicate); |
| 35630 | if(duplicate || brc->status != UA_STATUSCODE_GOOD) |
| 35631 | goto cleanup; |
| 35632 | } |
| 35633 | |
| 35634 | /* Recurse */ |
| 35635 | brc->depth++; |
| 35636 | void *res = NULL; |
| 35637 | for(size_t i = 0; i < head->referencesSize && !res; i++) { |
| 35638 | UA_NodeReferenceKind *rk = &head->references[i]; |
| 35639 | |
| 35640 | /* Reference in the right direction? */ |
| 35641 | if(rk->isInverse && brc->browseDirection == UA_BROWSEDIRECTION_FORWARD) |
| 35642 | continue; |
| 35643 | if(!rk->isInverse && brc->browseDirection == UA_BROWSEDIRECTION_INVERSE) |
| 35644 | continue; |
| 35645 | |
| 35646 | /* Is the reference part of the hierarchy of references we look for? */ |
| 35647 | if(!UA_ReferenceTypeSet_contains(set: &brc->refTypes, index: rk->referenceTypeIndex)) |
| 35648 | continue; |
| 35649 | |
| 35650 | res = UA_NodeReferenceKind_iterate(rk, callback: browseRecursiveCallback, context: brc); |
| 35651 | } |
| 35652 | brc->depth--; |
| 35653 | |
| 35654 | cleanup: |
| 35655 | UA_NODESTORE_RELEASE(brc->server, node); |
| 35656 | return (brc->status == UA_STATUSCODE_GOOD) ? NULL : (void*)0x01; |
| 35657 | } |
| 35658 | |
| 35659 | UA_StatusCode |
| 35660 | browseRecursive(UA_Server *server, size_t startNodesSize, const UA_NodeId *startNodes, |
| 35661 | UA_BrowseDirection browseDirection, const UA_ReferenceTypeSet *refTypes, |
| 35662 | UA_UInt32 nodeClassMask, UA_Boolean includeStartNodes, |
| 35663 | size_t *resultsSize, UA_ExpandedNodeId **results) { |
| 35664 | RefTree rt; |
| 35665 | UA_StatusCode retval = RefTree_init(rt: &rt); |
| 35666 | if(retval != UA_STATUSCODE_GOOD) |
| 35667 | return retval; |
| 35668 | |
| 35669 | struct BrowseRecursiveContext brc; |
| 35670 | brc.server = server; |
| 35671 | brc.rt = &rt; |
| 35672 | brc.depth = 0; |
| 35673 | brc.refTypes = *refTypes; |
| 35674 | brc.nodeClassMask = nodeClassMask; |
| 35675 | brc.status = UA_STATUSCODE_GOOD; |
| 35676 | brc.includeStartNodes = includeStartNodes; |
| 35677 | |
| 35678 | for(size_t i = 0; i < startNodesSize && brc.status == UA_STATUSCODE_GOOD; i++) { |
| 35679 | UA_ReferenceTarget target; |
| 35680 | target.targetId = UA_NodePointer_fromNodeId(id: &startNodes[i]); |
| 35681 | |
| 35682 | /* Call the inner recursive browse separately for the search direction. |
| 35683 | * Otherwise we might take one step up and another step down in the |
| 35684 | * search tree. */ |
| 35685 | if(browseDirection == UA_BROWSEDIRECTION_FORWARD || |
| 35686 | browseDirection == UA_BROWSEDIRECTION_BOTH) { |
| 35687 | brc.browseDirection = UA_BROWSEDIRECTION_FORWARD; |
| 35688 | browseRecursiveCallback(context: &brc, t: &target); |
| 35689 | } |
| 35690 | |
| 35691 | if(browseDirection == UA_BROWSEDIRECTION_INVERSE || |
| 35692 | browseDirection == UA_BROWSEDIRECTION_BOTH) { |
| 35693 | brc.browseDirection = UA_BROWSEDIRECTION_INVERSE; |
| 35694 | browseRecursiveCallback(context: &brc, t: &target); |
| 35695 | } |
| 35696 | } |
| 35697 | |
| 35698 | if(rt.size > 0 && brc.status == UA_STATUSCODE_GOOD) { |
| 35699 | *results = rt.targets; |
| 35700 | *resultsSize = rt.size; |
| 35701 | } else { |
| 35702 | RefTree_clear(rt: &rt); |
| 35703 | } |
| 35704 | return brc.status; |
| 35705 | } |
| 35706 | |
| 35707 | UA_StatusCode |
| 35708 | UA_Server_browseRecursive(UA_Server *server, const UA_BrowseDescription *bd, |
| 35709 | size_t *resultsSize, UA_ExpandedNodeId **results) { |
| 35710 | lockServer(server); |
| 35711 | |
| 35712 | /* Set the list of relevant reference types */ |
| 35713 | UA_ReferenceTypeSet refTypes; |
| 35714 | UA_StatusCode retval = referenceTypeIndices(server, refType: &bd->referenceTypeId, |
| 35715 | indices: &refTypes, includeSubtypes: bd->includeSubtypes); |
| 35716 | if(retval != UA_STATUSCODE_GOOD) { |
| 35717 | unlockServer(server); |
| 35718 | return retval; |
| 35719 | } |
| 35720 | |
| 35721 | /* Browse */ |
| 35722 | retval = browseRecursive(server, startNodesSize: 1, startNodes: &bd->nodeId, browseDirection: bd->browseDirection, |
| 35723 | refTypes: &refTypes, nodeClassMask: bd->nodeClassMask, false, resultsSize, results); |
| 35724 | |
| 35725 | unlockServer(server); |
| 35726 | return retval; |
| 35727 | } |
| 35728 | |
| 35729 | /**********/ |
| 35730 | /* Browse */ |
| 35731 | /**********/ |
| 35732 | |
| 35733 | typedef struct { |
| 35734 | size_t size; |
| 35735 | size_t capacity; |
| 35736 | UA_ReferenceDescription *descr; |
| 35737 | } RefResult; |
| 35738 | |
| 35739 | static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT |
| 35740 | RefResult_init(RefResult *rr) { |
| 35741 | memset(s: rr, c: 0, n: sizeof(RefResult)); |
| 35742 | rr->descr = (UA_ReferenceDescription*) |
| 35743 | UA_Array_new(UA_REFTREE_INITIAL_SIZE, type: &UA_TYPES[UA_TYPES_REFERENCEDESCRIPTION]); |
| 35744 | if(!rr->descr) |
| 35745 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 35746 | rr->capacity = UA_REFTREE_INITIAL_SIZE; |
| 35747 | rr->size = 0; |
| 35748 | return UA_STATUSCODE_GOOD; |
| 35749 | } |
| 35750 | |
| 35751 | static UA_StatusCode UA_FUNC_ATTR_WARN_UNUSED_RESULT |
| 35752 | RefResult_double(RefResult *rr) { |
| 35753 | size_t newSize = rr->capacity * 2; |
| 35754 | UA_ReferenceDescription *rd = (UA_ReferenceDescription*) |
| 35755 | UA_realloc(ptr: rr->descr, size: newSize * sizeof(UA_ReferenceDescription)); |
| 35756 | if(!rd) |
| 35757 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 35758 | memset(s: &rd[rr->size], c: 0, n: sizeof(UA_ReferenceDescription) * (newSize - rr->size)); |
| 35759 | rr->descr = rd; |
| 35760 | rr->capacity = newSize; |
| 35761 | return UA_STATUSCODE_GOOD; |
| 35762 | } |
| 35763 | |
| 35764 | static void |
| 35765 | RefResult_clear(RefResult *rr) { |
| 35766 | UA_assert(rr->descr != NULL); |
| 35767 | for(size_t i = 0; i < rr->size; i++) |
| 35768 | UA_ReferenceDescription_clear(p: &rr->descr[i]); |
| 35769 | UA_free(ptr: rr->descr); |
| 35770 | } |
| 35771 | |
| 35772 | struct ContinuationPoint { |
| 35773 | ContinuationPoint *next; |
| 35774 | UA_ByteString identifier; |
| 35775 | |
| 35776 | /* Parameters of the Browse Request */ |
| 35777 | UA_BrowseDescription browseDescription; |
| 35778 | UA_UInt32 maxReferences; |
| 35779 | UA_ReferenceTypeSet relevantReferences; |
| 35780 | |
| 35781 | /* The last reference target that was transmitted to the client. The results |
| 35782 | * list may be incomplete if the last target is removed or references added |
| 35783 | * between the calls to Browse/BrowseNext. */ |
| 35784 | UA_NodePointer lastTarget; |
| 35785 | UA_Byte lastRefKindIndex; |
| 35786 | UA_Boolean lastRefInverse; |
| 35787 | }; |
| 35788 | |
| 35789 | ContinuationPoint * |
| 35790 | ContinuationPoint_clear(ContinuationPoint *cp) { |
| 35791 | UA_ByteString_clear(p: &cp->identifier); |
| 35792 | UA_BrowseDescription_clear(p: &cp->browseDescription); |
| 35793 | UA_NodePointer_clear(np: &cp->lastTarget); |
| 35794 | return cp->next; |
| 35795 | } |
| 35796 | |
| 35797 | struct BrowseContext { |
| 35798 | /* Context */ |
| 35799 | ContinuationPoint *cp; |
| 35800 | UA_Server *server; |
| 35801 | UA_Session *session; |
| 35802 | UA_NodeReferenceKind *rk; |
| 35803 | UA_ReferenceTypeSet resultRefs; /* With additional references for type |
| 35804 | * lookups */ |
| 35805 | UA_Boolean activeCP; /* true during "forwarding" to the position of the last |
| 35806 | * reference target */ |
| 35807 | |
| 35808 | /* Results */ |
| 35809 | RefResult rr; |
| 35810 | UA_StatusCode status; |
| 35811 | UA_Boolean done; |
| 35812 | }; |
| 35813 | |
| 35814 | /* Target node on top of the stack */ |
| 35815 | static UA_StatusCode |
| 35816 | addReferenceDescription(struct BrowseContext *bc, UA_NodePointer nodeP, |
| 35817 | const UA_Node *curr) { |
| 35818 | UA_assert(curr); |
| 35819 | UA_BrowseDescription *bd = &bc->cp->browseDescription; |
| 35820 | |
| 35821 | /* Ensure capacity is left */ |
| 35822 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 35823 | if(bc->rr.size >= bc->rr.capacity) { |
| 35824 | res = RefResult_double(rr: &bc->rr); |
| 35825 | if(res != UA_STATUSCODE_GOOD) |
| 35826 | return res; |
| 35827 | } |
| 35828 | |
| 35829 | UA_ReferenceDescription *descr = &bc->rr.descr[bc->rr.size]; |
| 35830 | |
| 35831 | /* Fields without access to the actual node */ |
| 35832 | UA_ExpandedNodeId en = UA_NodePointer_toExpandedNodeId(np: nodeP); |
| 35833 | res = UA_ExpandedNodeId_copy(src: &en, dst: &descr->nodeId); |
| 35834 | if(bd->resultMask & UA_BROWSERESULTMASK_REFERENCETYPEID) { |
| 35835 | const UA_NodeId *refTypeId = |
| 35836 | UA_NODESTORE_GETREFERENCETYPEID(bc->server, bc->rk->referenceTypeIndex); |
| 35837 | res |= UA_NodeId_copy(src: refTypeId, dst: &descr->referenceTypeId); |
| 35838 | } |
| 35839 | if(bd->resultMask & UA_BROWSERESULTMASK_ISFORWARD) |
| 35840 | descr->isForward = !bc->rk->isInverse; |
| 35841 | |
| 35842 | /* Create fields that require access to the actual node */ |
| 35843 | if(bd->resultMask & UA_BROWSERESULTMASK_NODECLASS) |
| 35844 | descr->nodeClass = curr->head.nodeClass; |
| 35845 | |
| 35846 | if(bd->resultMask & UA_BROWSERESULTMASK_BROWSENAME) |
| 35847 | res |= UA_QualifiedName_copy(src: &curr->head.browseName, |
| 35848 | dst: &descr->browseName); |
| 35849 | |
| 35850 | if(bd->resultMask & UA_BROWSERESULTMASK_DISPLAYNAME) { |
| 35851 | UA_LocalizedText displayname = |
| 35852 | UA_Session_getNodeDisplayName(session: bc->session, head: &curr->head); |
| 35853 | res |= UA_LocalizedText_copy(src: &displayname, dst: &descr->displayName); |
| 35854 | } |
| 35855 | |
| 35856 | if(bd->resultMask & UA_BROWSERESULTMASK_TYPEDEFINITION) { |
| 35857 | if(curr->head.nodeClass == UA_NODECLASS_OBJECT || |
| 35858 | curr->head.nodeClass == UA_NODECLASS_VARIABLE) { |
| 35859 | const UA_Node *type = getNodeType(server: bc->server, head: &curr->head); |
| 35860 | if(type) { |
| 35861 | res |= UA_NodeId_copy(src: &type->head.nodeId, |
| 35862 | dst: &descr->typeDefinition.nodeId); |
| 35863 | UA_NODESTORE_RELEASE(bc->server, type); |
| 35864 | } |
| 35865 | } |
| 35866 | } |
| 35867 | |
| 35868 | /* Clean up and return */ |
| 35869 | if(res != UA_STATUSCODE_GOOD) { |
| 35870 | UA_ReferenceDescription_clear(p: descr); |
| 35871 | return res; |
| 35872 | } |
| 35873 | bc->rr.size++; |
| 35874 | return UA_STATUSCODE_GOOD; |
| 35875 | } |
| 35876 | |
| 35877 | static void * |
| 35878 | browseReferencTargetCallback(void *context, UA_ReferenceTarget *t) { |
| 35879 | struct BrowseContext *bc = (struct BrowseContext*)context; |
| 35880 | const UA_BrowseDescription *bd = &bc->cp->browseDescription; |
| 35881 | ContinuationPoint *cp = bc->cp; |
| 35882 | |
| 35883 | /* Remote references are ignored */ |
| 35884 | if(!UA_NodePointer_isLocal(np: t->targetId)) |
| 35885 | return NULL; |
| 35886 | |
| 35887 | /* Get the node. Include only the ReferenceTypes we are interested in, |
| 35888 | * including those for figuring out the TypeDefinition (if that was |
| 35889 | * requested). */ |
| 35890 | const UA_Node *target = |
| 35891 | UA_NODESTORE_GETFROMREF_SELECTIVE(bc->server, t->targetId, |
| 35892 | resultMask2AttributesMask(bd->resultMask), |
| 35893 | bc->resultRefs, bd->browseDirection); |
| 35894 | if(!target) |
| 35895 | return NULL; |
| 35896 | |
| 35897 | /* The node class has to match */ |
| 35898 | if(!matchClassMask(node: target, nodeClassMask: bd->nodeClassMask)) { |
| 35899 | UA_NODESTORE_RELEASE(bc->server, target); |
| 35900 | return NULL; |
| 35901 | } |
| 35902 | |
| 35903 | /* Reached maxrefs. Return the "abort" signal. */ |
| 35904 | if(bc->rr.size >= cp->maxReferences) { |
| 35905 | UA_NODESTORE_RELEASE(bc->server, target); |
| 35906 | return (void*)0x01; |
| 35907 | } |
| 35908 | |
| 35909 | /* Create the reference description */ |
| 35910 | bc->status = addReferenceDescription(bc, nodeP: t->targetId, curr: target); |
| 35911 | |
| 35912 | /* Release the node */ |
| 35913 | UA_NODESTORE_RELEASE(bc->server, target); |
| 35914 | |
| 35915 | /* Store as last target. The itarget-id is a shallow copy for now. */ |
| 35916 | cp->lastTarget = t->targetId; |
| 35917 | cp->lastRefKindIndex = bc->rk->referenceTypeIndex; |
| 35918 | cp->lastRefInverse = bc->rk->isInverse; |
| 35919 | |
| 35920 | /* Abort if the status is not good. Also doesn't make a deep-copy of |
| 35921 | * cp->lastTarget after returning from here. */ |
| 35922 | if(bc->status != UA_STATUSCODE_GOOD) { |
| 35923 | UA_NodePointer_init(np: &cp->lastTarget); |
| 35924 | return (void*)0x01; |
| 35925 | } |
| 35926 | return NULL; |
| 35927 | } |
| 35928 | |
| 35929 | /* Returns whether the node / continuationpoint is done */ |
| 35930 | static void |
| 35931 | browseWithNode(struct BrowseContext *bc, const UA_NodeHead *head ) { |
| 35932 | ContinuationPoint *cp = bc->cp; |
| 35933 | const UA_BrowseDescription *bd = &cp->browseDescription; |
| 35934 | |
| 35935 | /* Loop over the ReferenceKinds */ |
| 35936 | for(size_t i = 0; i < head->referencesSize && bc->status == UA_STATUSCODE_GOOD; ++i) { |
| 35937 | UA_NodeReferenceKind *rk = &head->references[i]; |
| 35938 | |
| 35939 | /* If the continuation point was previously used, skip forward to the |
| 35940 | * last ReferenceType that was transmitted */ |
| 35941 | if(bc->activeCP && rk->referenceTypeIndex != cp->lastRefKindIndex) |
| 35942 | continue; |
| 35943 | if(bc->activeCP && rk->isInverse != cp->lastRefInverse) |
| 35944 | continue; |
| 35945 | |
| 35946 | /* Reference in the right direction? */ |
| 35947 | if(rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_FORWARD) |
| 35948 | continue; |
| 35949 | if(!rk->isInverse && bd->browseDirection == UA_BROWSEDIRECTION_INVERSE) |
| 35950 | continue; |
| 35951 | |
| 35952 | /* Is the reference part of the hierarchy of references we look for? */ |
| 35953 | if(!UA_ReferenceTypeSet_contains(set: &cp->relevantReferences, index: rk->referenceTypeIndex)) |
| 35954 | continue; |
| 35955 | |
| 35956 | /* We have a matching ReferenceKind */ |
| 35957 | |
| 35958 | /* Skip ahead to the target where the last continuation point stopped. |
| 35959 | * This temporarily modifies rk. */ |
| 35960 | UA_ReferenceIdTree left = {NULL}, right = {NULL}; |
| 35961 | size_t nextTargetIndex = 0; |
| 35962 | if(bc->activeCP) { |
| 35963 | if(rk->hasRefTree) { |
| 35964 | /* Unzip the tree until the continuation point. All NodeIds |
| 35965 | * larger than the last target are guaranteed to sit on the |
| 35966 | * right-hand side. */ |
| 35967 | UA_ExpandedNodeId lastEn = |
| 35968 | UA_NodePointer_toExpandedNodeId(np: cp->lastTarget); |
| 35969 | UA_ReferenceTargetTreeElem key; |
| 35970 | key.target.targetId = cp->lastTarget; |
| 35971 | key.targetIdHash = UA_ExpandedNodeId_hash(n: &lastEn); |
| 35972 | ZIP_UNZIP(UA_ReferenceIdTree, |
| 35973 | (UA_ReferenceIdTree*)&rk->targets.tree.idRoot, |
| 35974 | &key, &left, &right); |
| 35975 | rk->targets.tree.idRoot = right.root; |
| 35976 | } else { |
| 35977 | /* Iterate over the array to find the match */ |
| 35978 | for(; nextTargetIndex < rk->targetsSize; nextTargetIndex++) { |
| 35979 | UA_ReferenceTarget *t = &rk->targets.array[nextTargetIndex]; |
| 35980 | if(UA_NodePointer_equal(p1: cp->lastTarget, p2: t->targetId)) |
| 35981 | break; |
| 35982 | } |
| 35983 | if(nextTargetIndex == rk->targetsSize) { |
| 35984 | /* Not found - assume that this reference kind is done */ |
| 35985 | bc->activeCP = false; |
| 35986 | continue; |
| 35987 | } |
| 35988 | nextTargetIndex++; /* From the last index to the next index */ |
| 35989 | rk->targets.array = &rk->targets.array[nextTargetIndex]; |
| 35990 | rk->targetsSize -= nextTargetIndex; |
| 35991 | } |
| 35992 | |
| 35993 | /* Clear cp->lastTarget before it gets overwritten in the following |
| 35994 | * browse steps. */ |
| 35995 | UA_NodePointer_clear(np: &cp->lastTarget); |
| 35996 | } |
| 35997 | |
| 35998 | /* Iterate over all reference targets */ |
| 35999 | bc->rk = rk; |
| 36000 | void *res = UA_NodeReferenceKind_iterate(rk, callback: browseReferencTargetCallback, context: bc); |
| 36001 | |
| 36002 | /* Undo the "skipping ahead" for the continuation point */ |
| 36003 | if(bc->activeCP) { |
| 36004 | if(rk->hasRefTree) { |
| 36005 | rk->targets.tree.idRoot = |
| 36006 | ZIP_ZIP(UA_ReferenceIdTree, left.root, right.root); |
| 36007 | } else { |
| 36008 | /* rk->targets.array = rk->targets.array[-nextTargetIndex]; */ |
| 36009 | rk->targets.array = rk->targets.array - nextTargetIndex; |
| 36010 | rk->targetsSize += nextTargetIndex; |
| 36011 | UA_assert(rk->targetsSize > 0); |
| 36012 | } |
| 36013 | bc->activeCP = false; |
| 36014 | } |
| 36015 | |
| 36016 | /* The iteration was aborted */ |
| 36017 | if(res != NULL) { |
| 36018 | /* Aborted with status code good -> the maximum number of browse |
| 36019 | * results was reached. Make a deep copy of the last target for the |
| 36020 | * continuation point. */ |
| 36021 | if(bc->status == UA_STATUSCODE_GOOD) |
| 36022 | bc->status = UA_NodePointer_copy(in: cp->lastTarget, out: &cp->lastTarget); |
| 36023 | return; |
| 36024 | } |
| 36025 | } |
| 36026 | |
| 36027 | /* Reset last-target to prevent clearing it up */ |
| 36028 | UA_NodePointer_init(np: &cp->lastTarget); |
| 36029 | |
| 36030 | /* Browsing the node is done */ |
| 36031 | bc->done = true; |
| 36032 | } |
| 36033 | |
| 36034 | /* Results for a single browsedescription. This is the inner loop for both |
| 36035 | * Browse and BrowseNext. The ContinuationPoint contains all the data used. |
| 36036 | * Including the BrowseDescription. Returns whether there are remaining |
| 36037 | * references. */ |
| 36038 | static void |
| 36039 | browse(struct BrowseContext *bc) { |
| 36040 | /* Is the browsedirection valid? */ |
| 36041 | struct ContinuationPoint *cp = bc->cp; |
| 36042 | const UA_BrowseDescription *descr = &cp->browseDescription; |
| 36043 | if(descr->browseDirection != UA_BROWSEDIRECTION_BOTH && |
| 36044 | descr->browseDirection != UA_BROWSEDIRECTION_FORWARD && |
| 36045 | descr->browseDirection != UA_BROWSEDIRECTION_INVERSE) { |
| 36046 | bc->status = UA_STATUSCODE_BADBROWSEDIRECTIONINVALID; |
| 36047 | return; |
| 36048 | } |
| 36049 | |
| 36050 | /* Get node with only the selected references and attributes */ |
| 36051 | const UA_Node *node = |
| 36052 | UA_NODESTORE_GET_SELECTIVE(bc->server, &descr->nodeId, |
| 36053 | resultMask2AttributesMask(descr->resultMask), |
| 36054 | bc->resultRefs, descr->browseDirection); |
| 36055 | if(!node) { |
| 36056 | bc->status = UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 36057 | return; |
| 36058 | } |
| 36059 | |
| 36060 | /* Check AccessControl rights */ |
| 36061 | if(bc->session != &bc->server->adminSession) { |
| 36062 | UA_LOCK_ASSERT(&bc->server->serviceMutex, 1); |
| 36063 | if(!bc->server->config.accessControl. |
| 36064 | allowBrowseNode(bc->server, &bc->server->config.accessControl, |
| 36065 | &bc->session->sessionId, bc->session->sessionHandle, |
| 36066 | &descr->nodeId, node->head.context)) { |
| 36067 | UA_NODESTORE_RELEASE(bc->server, node); |
| 36068 | bc->status = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 36069 | return; |
| 36070 | } |
| 36071 | } |
| 36072 | |
| 36073 | /* Browse the node */ |
| 36074 | browseWithNode(bc, head: &node->head); |
| 36075 | UA_NODESTORE_RELEASE(bc->server, node); |
| 36076 | |
| 36077 | /* Is the reference type valid? This is very infrequent. So we only test |
| 36078 | * this if browsing came up empty. If the node has references of that type, |
| 36079 | * we know the reftype to be good. */ |
| 36080 | if(bc->rr.size == 0 && !UA_NodeId_isNull(p: &descr->referenceTypeId)) { |
| 36081 | const UA_Node *reftype = |
| 36082 | UA_NODESTORE_GET_SELECTIVE(bc->server, &descr->referenceTypeId, |
| 36083 | UA_NODEATTRIBUTESMASK_NODECLASS, |
| 36084 | UA_REFERENCETYPESET_NONE, |
| 36085 | UA_BROWSEDIRECTION_INVALID); |
| 36086 | if(!reftype) { |
| 36087 | bc->status = UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 36088 | return; |
| 36089 | } |
| 36090 | |
| 36091 | UA_Boolean isRef = (reftype->head.nodeClass == UA_NODECLASS_REFERENCETYPE); |
| 36092 | UA_NODESTORE_RELEASE(bc->server, reftype); |
| 36093 | |
| 36094 | if(!isRef) { |
| 36095 | bc->status = UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 36096 | return; |
| 36097 | } |
| 36098 | } |
| 36099 | } |
| 36100 | |
| 36101 | /* Start to browse with no previous cp */ |
| 36102 | void |
| 36103 | Operation_Browse(UA_Server *server, UA_Session *session, const UA_UInt32 *maxrefs, |
| 36104 | const UA_BrowseDescription *descr, UA_BrowseResult *result) { |
| 36105 | /* Stack-allocate a temporary cp */ |
| 36106 | ContinuationPoint cp; |
| 36107 | memset(s: &cp, c: 0, n: sizeof(ContinuationPoint)); |
| 36108 | cp.maxReferences = *maxrefs; |
| 36109 | cp.browseDescription = *descr; /* Shallow copy. Deep-copy later if we persist the cp. */ |
| 36110 | |
| 36111 | /* How many references can we return at most? */ |
| 36112 | if(cp.maxReferences == 0) { |
| 36113 | if(server->config.maxReferencesPerNode != 0) { |
| 36114 | cp.maxReferences = server->config.maxReferencesPerNode; |
| 36115 | } else { |
| 36116 | cp.maxReferences = UA_INT32_MAX; |
| 36117 | } |
| 36118 | } else { |
| 36119 | if(server->config.maxReferencesPerNode != 0 && |
| 36120 | cp.maxReferences > server->config.maxReferencesPerNode) { |
| 36121 | cp.maxReferences= server->config.maxReferencesPerNode; |
| 36122 | } |
| 36123 | } |
| 36124 | |
| 36125 | /* Get the list of relevant reference types */ |
| 36126 | result->statusCode = |
| 36127 | referenceTypeIndices(server, refType: &descr->referenceTypeId, |
| 36128 | indices: &cp.relevantReferences, includeSubtypes: descr->includeSubtypes); |
| 36129 | if(result->statusCode != UA_STATUSCODE_GOOD) |
| 36130 | return; |
| 36131 | |
| 36132 | /* Prepare the context */ |
| 36133 | struct BrowseContext bc; |
| 36134 | bc.cp = &cp; |
| 36135 | bc.server = server; |
| 36136 | bc.session = session; |
| 36137 | bc.status = UA_STATUSCODE_GOOD; |
| 36138 | bc.done = false; |
| 36139 | bc.activeCP = false; |
| 36140 | bc.resultRefs = cp.relevantReferences; |
| 36141 | if(cp.browseDescription.resultMask & UA_BROWSERESULTMASK_TYPEDEFINITION) { |
| 36142 | /* Get the node with additional reference types if we need to lookup the |
| 36143 | * TypeDefinition */ |
| 36144 | bc.resultRefs = UA_ReferenceTypeSet_union(setA: bc.resultRefs, |
| 36145 | setB: UA_ReferenceTypeSet_union(setA: UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASTYPEDEFINITION), |
| 36146 | setB: UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE))); |
| 36147 | } |
| 36148 | result->statusCode = RefResult_init(rr: &bc.rr); |
| 36149 | if(result->statusCode != UA_STATUSCODE_GOOD) |
| 36150 | return; |
| 36151 | |
| 36152 | /* Perform the browse */ |
| 36153 | browse(bc: &bc); |
| 36154 | |
| 36155 | if(bc.status != UA_STATUSCODE_GOOD || bc.rr.size == 0) { |
| 36156 | /* No relevant references, return array of length zero */ |
| 36157 | RefResult_clear(rr: &bc.rr); |
| 36158 | result->references = (UA_ReferenceDescription*)UA_EMPTY_ARRAY_SENTINEL; |
| 36159 | result->statusCode = bc.status; |
| 36160 | return; |
| 36161 | } |
| 36162 | |
| 36163 | /* Move results */ |
| 36164 | result->references = bc.rr.descr; |
| 36165 | result->referencesSize = bc.rr.size; |
| 36166 | |
| 36167 | /* Exit early if done */ |
| 36168 | if(bc.done) |
| 36169 | return; |
| 36170 | |
| 36171 | /* Persist the continuation point */ |
| 36172 | |
| 36173 | ContinuationPoint *cp2 = NULL; |
| 36174 | UA_Guid *ident = NULL; |
| 36175 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 36176 | |
| 36177 | /* Enough space for the continuation point? */ |
| 36178 | if(session->availableContinuationPoints == 0) { |
| 36179 | retval = UA_STATUSCODE_BADNOCONTINUATIONPOINTS; |
| 36180 | goto cleanup; |
| 36181 | } |
| 36182 | |
| 36183 | /* Allocate and fill the data structure */ |
| 36184 | cp2 = (ContinuationPoint*)UA_calloc(nmemb: 1, size: sizeof(ContinuationPoint)); |
| 36185 | if(!cp2) { |
| 36186 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 36187 | goto cleanup; |
| 36188 | } |
| 36189 | |
| 36190 | /* The BrowseDescription is only a shallow copy so far */ |
| 36191 | retval = UA_BrowseDescription_copy(src: descr, dst: &cp2->browseDescription); |
| 36192 | if(retval != UA_STATUSCODE_GOOD) |
| 36193 | goto cleanup; |
| 36194 | cp2->maxReferences = cp.maxReferences; |
| 36195 | cp2->relevantReferences = cp.relevantReferences; |
| 36196 | cp2->lastTarget = cp.lastTarget; /* Move the (deep) copy */ |
| 36197 | UA_NodePointer_init(np: &cp.lastTarget); /* No longer clear below (cleanup) */ |
| 36198 | cp2->lastRefKindIndex = cp.lastRefKindIndex; |
| 36199 | cp2->lastRefInverse = cp.lastRefInverse; |
| 36200 | |
| 36201 | /* Create a random bytestring via a Guid */ |
| 36202 | ident = UA_Guid_new(); |
| 36203 | if(!ident) { |
| 36204 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 36205 | goto cleanup; |
| 36206 | } |
| 36207 | *ident = UA_Guid_random(); |
| 36208 | cp2->identifier.data = (UA_Byte*)ident; |
| 36209 | cp2->identifier.length = sizeof(UA_Guid); |
| 36210 | |
| 36211 | /* Return the cp identifier */ |
| 36212 | retval = UA_ByteString_copy(src: &cp2->identifier, dst: &result->continuationPoint); |
| 36213 | if(retval != UA_STATUSCODE_GOOD) |
| 36214 | goto cleanup; |
| 36215 | |
| 36216 | /* Attach the cp to the session */ |
| 36217 | cp2->next = session->continuationPoints; |
| 36218 | session->continuationPoints = cp2; |
| 36219 | --session->availableContinuationPoints; |
| 36220 | return; |
| 36221 | |
| 36222 | cleanup: |
| 36223 | if(cp2) { |
| 36224 | ContinuationPoint_clear(cp: cp2); |
| 36225 | UA_free(ptr: cp2); |
| 36226 | } |
| 36227 | UA_NodePointer_clear(np: &cp.lastTarget); |
| 36228 | UA_BrowseResult_clear(p: result); |
| 36229 | result->statusCode = retval; |
| 36230 | } |
| 36231 | |
| 36232 | void Service_Browse(UA_Server *server, UA_Session *session, |
| 36233 | const UA_BrowseRequest *request, UA_BrowseResponse *response) { |
| 36234 | UA_LOG_DEBUG_SESSION(server->config.logging, session, "Processing BrowseRequest"); |
| 36235 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 36236 | |
| 36237 | /* Test the number of operations in the request */ |
| 36238 | if(server->config.maxNodesPerBrowse != 0 && |
| 36239 | request->nodesToBrowseSize > server->config.maxNodesPerBrowse) { |
| 36240 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 36241 | return; |
| 36242 | } |
| 36243 | |
| 36244 | /* No views supported at the moment */ |
| 36245 | if(!UA_NodeId_isNull(p: &request->view.viewId)) { |
| 36246 | response->responseHeader.serviceResult = UA_STATUSCODE_BADVIEWIDUNKNOWN; |
| 36247 | return; |
| 36248 | } |
| 36249 | |
| 36250 | response->responseHeader.serviceResult = |
| 36251 | UA_Server_processServiceOperations(server, session, |
| 36252 | operationCallback: (UA_ServiceOperation)Operation_Browse, |
| 36253 | context: &request->requestedMaxReferencesPerNode, |
| 36254 | requestOperations: &request->nodesToBrowseSize, |
| 36255 | requestOperationsType: &UA_TYPES[UA_TYPES_BROWSEDESCRIPTION], |
| 36256 | responseOperations: &response->resultsSize, |
| 36257 | responseOperationsType: &UA_TYPES[UA_TYPES_BROWSERESULT]); |
| 36258 | } |
| 36259 | |
| 36260 | UA_BrowseResult |
| 36261 | UA_Server_browse(UA_Server *server, UA_UInt32 maxReferences, |
| 36262 | const UA_BrowseDescription *bd) { |
| 36263 | UA_BrowseResult result; |
| 36264 | UA_BrowseResult_init(p: &result); |
| 36265 | lockServer(server); |
| 36266 | Operation_Browse(server, session: &server->adminSession, maxrefs: &maxReferences, descr: bd, result: &result); |
| 36267 | unlockServer(server); |
| 36268 | return result; |
| 36269 | } |
| 36270 | |
| 36271 | static void |
| 36272 | Operation_BrowseNext(UA_Server *server, UA_Session *session, |
| 36273 | const UA_Boolean *releaseContinuationPoints, |
| 36274 | const UA_ByteString *continuationPoint, UA_BrowseResult *result) { |
| 36275 | /* Find the continuation point */ |
| 36276 | ContinuationPoint **prev = &session->continuationPoints; |
| 36277 | ContinuationPoint *cp; |
| 36278 | while((cp = *prev)) { |
| 36279 | if(UA_ByteString_equal(p1: &cp->identifier, p2: continuationPoint)) |
| 36280 | break; |
| 36281 | prev = &cp->next; |
| 36282 | } |
| 36283 | if(!cp) { |
| 36284 | result->statusCode = UA_STATUSCODE_BADCONTINUATIONPOINTINVALID; |
| 36285 | return; |
| 36286 | } |
| 36287 | |
| 36288 | /* Remove the cp */ |
| 36289 | if(*releaseContinuationPoints) { |
| 36290 | *prev = ContinuationPoint_clear(cp); |
| 36291 | UA_free(ptr: cp); |
| 36292 | ++session->availableContinuationPoints; |
| 36293 | return; |
| 36294 | } |
| 36295 | |
| 36296 | /* Prepare the context */ |
| 36297 | struct BrowseContext bc; |
| 36298 | bc.cp = cp; |
| 36299 | bc.server = server; |
| 36300 | bc.session = session; |
| 36301 | bc.status = UA_STATUSCODE_GOOD; |
| 36302 | bc.done = false; |
| 36303 | bc.activeCP = true; |
| 36304 | bc.resultRefs = cp->relevantReferences; |
| 36305 | if(cp->browseDescription.resultMask & UA_BROWSERESULTMASK_TYPEDEFINITION) { |
| 36306 | /* Get the node with additional reference types if we need to lookup the |
| 36307 | * TypeDefinition */ |
| 36308 | bc.resultRefs = UA_ReferenceTypeSet_union(setA: bc.resultRefs, |
| 36309 | setB: UA_ReferenceTypeSet_union(setA: UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASTYPEDEFINITION), |
| 36310 | setB: UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE))); |
| 36311 | } |
| 36312 | result->statusCode = RefResult_init(rr: &bc.rr); |
| 36313 | if(result->statusCode != UA_STATUSCODE_GOOD) |
| 36314 | return; |
| 36315 | |
| 36316 | /* Continue browsing */ |
| 36317 | browse(bc: &bc); |
| 36318 | |
| 36319 | if(bc.status != UA_STATUSCODE_GOOD || bc.rr.size == 0) { |
| 36320 | /* No relevant references, return array of length zero */ |
| 36321 | RefResult_clear(rr: &bc.rr); |
| 36322 | result->references = (UA_ReferenceDescription*)UA_EMPTY_ARRAY_SENTINEL; |
| 36323 | result->statusCode = bc.status; |
| 36324 | goto remove_cp; |
| 36325 | } |
| 36326 | |
| 36327 | /* Move results */ |
| 36328 | result->references = bc.rr.descr; |
| 36329 | result->referencesSize = bc.rr.size; |
| 36330 | |
| 36331 | if(bc.done) |
| 36332 | goto remove_cp; |
| 36333 | |
| 36334 | /* Return the cp identifier to signal that there are references left */ |
| 36335 | bc.status = UA_ByteString_copy(src: &cp->identifier, dst: &result->continuationPoint); |
| 36336 | if(bc.status != UA_STATUSCODE_GOOD) { |
| 36337 | UA_BrowseResult_clear(p: result); |
| 36338 | result->statusCode = bc.status; |
| 36339 | } |
| 36340 | return; |
| 36341 | |
| 36342 | remove_cp: |
| 36343 | /* Remove the cp */ |
| 36344 | *prev = ContinuationPoint_clear(cp); |
| 36345 | UA_free(ptr: cp); |
| 36346 | ++session->availableContinuationPoints; |
| 36347 | } |
| 36348 | |
| 36349 | void |
| 36350 | Service_BrowseNext(UA_Server *server, UA_Session *session, |
| 36351 | const UA_BrowseNextRequest *request, |
| 36352 | UA_BrowseNextResponse *response) { |
| 36353 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 36354 | "Processing BrowseNextRequest"); |
| 36355 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 36356 | |
| 36357 | UA_Boolean releaseContinuationPoints = |
| 36358 | request->releaseContinuationPoints; /* request is const */ |
| 36359 | response->responseHeader.serviceResult = |
| 36360 | UA_Server_processServiceOperations(server, session, |
| 36361 | operationCallback: (UA_ServiceOperation)Operation_BrowseNext, |
| 36362 | context: &releaseContinuationPoints, |
| 36363 | requestOperations: &request->continuationPointsSize, |
| 36364 | requestOperationsType: &UA_TYPES[UA_TYPES_BYTESTRING], |
| 36365 | responseOperations: &response->resultsSize, |
| 36366 | responseOperationsType: &UA_TYPES[UA_TYPES_BROWSERESULT]); |
| 36367 | } |
| 36368 | |
| 36369 | UA_BrowseResult |
| 36370 | UA_Server_browseNext(UA_Server *server, UA_Boolean releaseContinuationPoint, |
| 36371 | const UA_ByteString *continuationPoint) { |
| 36372 | UA_BrowseResult result; |
| 36373 | UA_BrowseResult_init(p: &result); |
| 36374 | lockServer(server); |
| 36375 | Operation_BrowseNext(server, session: &server->adminSession, releaseContinuationPoints: &releaseContinuationPoint, |
| 36376 | continuationPoint, result: &result); |
| 36377 | unlockServer(server); |
| 36378 | return result; |
| 36379 | } |
| 36380 | |
| 36381 | /***********************/ |
| 36382 | /* TranslateBrowsePath */ |
| 36383 | /***********************/ |
| 36384 | |
| 36385 | /* Add all entries for the hash. There are possible duplicates due to hash |
| 36386 | * collisions. The full browsename is checked afterwards. */ |
| 36387 | static void * |
| 36388 | addBrowseHashTarget(void *context, UA_ReferenceTargetTreeElem *elem) { |
| 36389 | RefTree *next = (RefTree*)context; |
| 36390 | return (void*)(uintptr_t)RefTree_add(rt: next, target: elem->target.targetId, NULL); |
| 36391 | } |
| 36392 | |
| 36393 | static UA_StatusCode |
| 36394 | walkBrowsePathElement(UA_Server *server, UA_Session *session, |
| 36395 | const UA_RelativePath *path, const size_t pathIndex, |
| 36396 | UA_UInt32 nodeClassMask, const UA_QualifiedName *lastBrowseName, |
| 36397 | UA_BrowsePathResult *result, RefTree *current, RefTree *next) { |
| 36398 | /* For the next level. Note the difference from lastBrowseName */ |
| 36399 | const UA_RelativePathElement *elem = &path->elements[pathIndex]; |
| 36400 | UA_UInt32 browseNameHash = UA_QualifiedName_hash(q: &elem->targetName); |
| 36401 | |
| 36402 | /* Get the relevant ReferenceTypes */ |
| 36403 | UA_ReferenceTypeSet refTypes; |
| 36404 | UA_StatusCode res = |
| 36405 | referenceTypeIndices(server, refType: &elem->referenceTypeId, |
| 36406 | indices: &refTypes, includeSubtypes: elem->includeSubtypes); |
| 36407 | if(res != UA_STATUSCODE_GOOD) |
| 36408 | return UA_STATUSCODE_BADNOMATCH; |
| 36409 | |
| 36410 | /* Loop over all Nodes in the current depth level */ |
| 36411 | for(size_t i = 0; i < current->size; i++) { |
| 36412 | /* Remote Node. Immediately add to the results with the |
| 36413 | * RemainingPathIndex set. */ |
| 36414 | if(!UA_ExpandedNodeId_isLocal(n: ¤t->targets[i])) { |
| 36415 | /* Increase the size of the results array */ |
| 36416 | UA_BrowsePathTarget *tmpResults = (UA_BrowsePathTarget*) |
| 36417 | UA_realloc(ptr: result->targets, size: sizeof(UA_BrowsePathTarget) * |
| 36418 | (result->targetsSize + 1)); |
| 36419 | if(!tmpResults) |
| 36420 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 36421 | result->targets = tmpResults; |
| 36422 | |
| 36423 | /* Copy over the result */ |
| 36424 | res = UA_ExpandedNodeId_copy(src: ¤t->targets[i], |
| 36425 | dst: &result->targets[result->targetsSize].targetId); |
| 36426 | result->targets[result->targetsSize].remainingPathIndex = (UA_UInt32)pathIndex; |
| 36427 | result->targetsSize++; |
| 36428 | if(res != UA_STATUSCODE_GOOD) |
| 36429 | break; |
| 36430 | continue; |
| 36431 | } |
| 36432 | |
| 36433 | /* Local Node. Add to the tree of results at the next depth. Get only |
| 36434 | * the NodeClass + BrowseName attribute and the selected ReferenceTypes |
| 36435 | * if the nodestore supports that. */ |
| 36436 | const UA_Node *node = |
| 36437 | UA_NODESTORE_GET_SELECTIVE(server, ¤t->targets[i].nodeId, |
| 36438 | UA_NODEATTRIBUTESMASK_NODECLASS | |
| 36439 | UA_NODEATTRIBUTESMASK_BROWSENAME, |
| 36440 | refTypes, |
| 36441 | elem->isInverse ? UA_BROWSEDIRECTION_INVERSE : |
| 36442 | UA_BROWSEDIRECTION_FORWARD); |
| 36443 | if(!node) |
| 36444 | continue; |
| 36445 | |
| 36446 | /* Test whether the node fits the class mask */ |
| 36447 | UA_Boolean skip = !matchClassMask(node, nodeClassMask); |
| 36448 | |
| 36449 | /* Does the BrowseName match for the current node (not the references |
| 36450 | * going out here) */ |
| 36451 | skip |= (lastBrowseName && |
| 36452 | !UA_QualifiedName_equal(p1: lastBrowseName, p2: &node->head.browseName)); |
| 36453 | |
| 36454 | if(skip) { |
| 36455 | UA_NODESTORE_RELEASE(server, node); |
| 36456 | continue; |
| 36457 | } |
| 36458 | |
| 36459 | /* Loop over the ReferenceKinds */ |
| 36460 | UA_ReferenceTarget targetHashKey; |
| 36461 | targetHashKey.targetNameHash = browseNameHash; |
| 36462 | for(size_t j = 0; j < node->head.referencesSize; j++) { |
| 36463 | UA_NodeReferenceKind *rk = &node->head.references[j]; |
| 36464 | |
| 36465 | /* Does the direction of the reference match? */ |
| 36466 | if(rk->isInverse != elem->isInverse) |
| 36467 | continue; |
| 36468 | |
| 36469 | /* Does the reference type match? */ |
| 36470 | if(!UA_ReferenceTypeSet_contains(set: &refTypes, index: rk->referenceTypeIndex)) |
| 36471 | continue; |
| 36472 | |
| 36473 | /* Retrieve by BrowseName hash. We might have several nodes where |
| 36474 | * the hash matches. The exact BrowseName will be verified in the |
| 36475 | * next iteration of the outer loop. So we only have to retrieve |
| 36476 | * every node just once. */ |
| 36477 | |
| 36478 | if(rk->hasRefTree) { |
| 36479 | res = (UA_StatusCode)(uintptr_t) |
| 36480 | ZIP_ITER_KEY(UA_ReferenceNameTree, |
| 36481 | (UA_ReferenceNameTree*)&rk->targets.tree.nameRoot, |
| 36482 | &targetHashKey, addBrowseHashTarget, next); |
| 36483 | if(res != UA_STATUSCODE_GOOD) |
| 36484 | break; |
| 36485 | } else { |
| 36486 | /* The array entries don't have a BrowseName hash. Add all of |
| 36487 | * them at this level to be checked with a full string |
| 36488 | * comparison. */ |
| 36489 | for(size_t k = 0; k < rk->targetsSize; k++) { |
| 36490 | if(rk->targets.array[k].targetNameHash != browseNameHash) |
| 36491 | continue; |
| 36492 | res = RefTree_add(rt: next, target: rk->targets.array[k].targetId, NULL); |
| 36493 | if(res != UA_STATUSCODE_GOOD) |
| 36494 | break; |
| 36495 | } |
| 36496 | if(res != UA_STATUSCODE_GOOD) |
| 36497 | break; |
| 36498 | } |
| 36499 | } |
| 36500 | |
| 36501 | UA_NODESTORE_RELEASE(server, node); |
| 36502 | } |
| 36503 | return res; |
| 36504 | } |
| 36505 | |
| 36506 | static void |
| 36507 | Operation_TranslateBrowsePathToNodeIds(UA_Server *server, UA_Session *session, |
| 36508 | const UA_UInt32 *nodeClassMask, |
| 36509 | const UA_BrowsePath *path, |
| 36510 | UA_BrowsePathResult *result) { |
| 36511 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 36512 | |
| 36513 | if(path->relativePath.elementsSize == 0) { |
| 36514 | result->statusCode = UA_STATUSCODE_BADNOTHINGTODO; |
| 36515 | return; |
| 36516 | } |
| 36517 | |
| 36518 | /* RelativePath elements must not have an empty targetName */ |
| 36519 | for(size_t i = 0; i < path->relativePath.elementsSize; ++i) { |
| 36520 | if(UA_QualifiedName_isNull(q: &path->relativePath.elements[i].targetName)) { |
| 36521 | result->statusCode = UA_STATUSCODE_BADBROWSENAMEINVALID; |
| 36522 | return; |
| 36523 | } |
| 36524 | } |
| 36525 | |
| 36526 | /* Check if the starting node exists */ |
| 36527 | const UA_Node *startingNode = |
| 36528 | UA_NODESTORE_GET_SELECTIVE(server, &path->startingNode, |
| 36529 | UA_NODEATTRIBUTESMASK_NONE, |
| 36530 | UA_REFERENCETYPESET_NONE, |
| 36531 | UA_BROWSEDIRECTION_INVALID); |
| 36532 | if(!startingNode) { |
| 36533 | result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 36534 | return; |
| 36535 | } |
| 36536 | UA_NODESTORE_RELEASE(server, startingNode); |
| 36537 | |
| 36538 | /* Create two RefTrees that are alternated between path elements */ |
| 36539 | RefTree rt1; |
| 36540 | RefTree rt2; |
| 36541 | RefTree *current = &rt1; |
| 36542 | RefTree *next = &rt2; |
| 36543 | RefTree *tmp; |
| 36544 | result->statusCode |= RefTree_init(rt: &rt1); |
| 36545 | result->statusCode |= RefTree_init(rt: &rt2); |
| 36546 | UA_BrowsePathTarget *tmpResults = NULL; |
| 36547 | UA_QualifiedName *browseNameFilter = NULL; |
| 36548 | if(result->statusCode != UA_STATUSCODE_GOOD) |
| 36549 | goto cleanup; |
| 36550 | |
| 36551 | /* Copy the starting node into next */ |
| 36552 | result->statusCode = RefTree_addNodeId(rt: next, target: &path->startingNode, NULL); |
| 36553 | if(result->statusCode != UA_STATUSCODE_GOOD) |
| 36554 | goto cleanup; |
| 36555 | |
| 36556 | /* Walk the path elements. Retrieve the nodes only once from the NodeStore. |
| 36557 | * Hence the BrowseName is checked with one element "delay". */ |
| 36558 | for(size_t i = 0; i < path->relativePath.elementsSize; i++) { |
| 36559 | /* Switch the trees */ |
| 36560 | tmp = current; |
| 36561 | current = next; |
| 36562 | next = tmp; |
| 36563 | |
| 36564 | /* Clear up current, keep the capacity */ |
| 36565 | for(size_t j = 0; j < next->size; j++) |
| 36566 | UA_ExpandedNodeId_clear(p: &next->targets[j]); |
| 36567 | next->size = 0; |
| 36568 | ZIP_INIT(&next->head); |
| 36569 | |
| 36570 | /* Do this check after next->size has been set to zero */ |
| 36571 | if(current->size == 0) |
| 36572 | break; |
| 36573 | |
| 36574 | /* Walk element for all NodeIds in the "current" tree. |
| 36575 | * Puts new results in the "next" tree. */ |
| 36576 | result->statusCode = |
| 36577 | walkBrowsePathElement(server, session, path: &path->relativePath, pathIndex: i, |
| 36578 | nodeClassMask: *nodeClassMask, lastBrowseName: browseNameFilter, result, current, next); |
| 36579 | if(result->statusCode != UA_STATUSCODE_GOOD) |
| 36580 | goto cleanup; |
| 36581 | |
| 36582 | browseNameFilter = &path->relativePath.elements[i].targetName; |
| 36583 | } |
| 36584 | |
| 36585 | /* Allocate space for the results array */ |
| 36586 | tmpResults = (UA_BrowsePathTarget*) |
| 36587 | UA_realloc(ptr: result->targets, size: sizeof(UA_BrowsePathTarget) * |
| 36588 | (result->targetsSize + next->size)); |
| 36589 | if(!tmpResults && next->size > 0) { |
| 36590 | result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY; |
| 36591 | goto cleanup; |
| 36592 | } |
| 36593 | result->targets = tmpResults; |
| 36594 | |
| 36595 | for(size_t k = 0; k < next->size; k++) { |
| 36596 | /* Check the BrowseName. It has been filtered only via its hash so far. |
| 36597 | * Get only the BrowseName attribute if the nodestore supports that. */ |
| 36598 | const UA_Node *node = |
| 36599 | UA_NODESTORE_GET_SELECTIVE(server, &next->targets[k].nodeId, |
| 36600 | UA_NODEATTRIBUTESMASK_BROWSENAME, |
| 36601 | UA_REFERENCETYPESET_NONE, |
| 36602 | UA_BROWSEDIRECTION_INVALID); |
| 36603 | if(!node) |
| 36604 | continue; |
| 36605 | UA_Boolean match = UA_QualifiedName_equal(p1: browseNameFilter, p2: &node->head.browseName); |
| 36606 | UA_NODESTORE_RELEASE(server, node); |
| 36607 | if(!match) |
| 36608 | continue; |
| 36609 | |
| 36610 | /* Move to the target to the results array */ |
| 36611 | result->targets[result->targetsSize].targetId = next->targets[k]; |
| 36612 | result->targets[result->targetsSize].remainingPathIndex = UA_UINT32_MAX; |
| 36613 | UA_ExpandedNodeId_init(p: &next->targets[k]); |
| 36614 | result->targetsSize++; |
| 36615 | } |
| 36616 | |
| 36617 | /* No results => BadNoMatch status code */ |
| 36618 | if(result->targetsSize == 0 && result->statusCode == UA_STATUSCODE_GOOD) |
| 36619 | result->statusCode = UA_STATUSCODE_BADNOMATCH; |
| 36620 | |
| 36621 | /* Clean up the temporary arrays and the targets */ |
| 36622 | cleanup: |
| 36623 | RefTree_clear(rt: &rt1); |
| 36624 | RefTree_clear(rt: &rt2); |
| 36625 | if(result->statusCode != UA_STATUSCODE_GOOD) { |
| 36626 | for(size_t i = 0; i < result->targetsSize; ++i) |
| 36627 | UA_BrowsePathTarget_clear(p: &result->targets[i]); |
| 36628 | if(result->targets) |
| 36629 | UA_free(ptr: result->targets); |
| 36630 | result->targets = NULL; |
| 36631 | result->targetsSize = 0; |
| 36632 | } |
| 36633 | } |
| 36634 | |
| 36635 | UA_BrowsePathResult |
| 36636 | translateBrowsePathToNodeIds(UA_Server *server, |
| 36637 | const UA_BrowsePath *browsePath) { |
| 36638 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 36639 | UA_BrowsePathResult result; |
| 36640 | UA_BrowsePathResult_init(p: &result); |
| 36641 | UA_UInt32 nodeClassMask = 0; /* All node classes */ |
| 36642 | Operation_TranslateBrowsePathToNodeIds(server, session: &server->adminSession, nodeClassMask: &nodeClassMask, |
| 36643 | path: browsePath, result: &result); |
| 36644 | return result; |
| 36645 | } |
| 36646 | |
| 36647 | UA_BrowsePathResult |
| 36648 | UA_Server_translateBrowsePathToNodeIds(UA_Server *server, |
| 36649 | const UA_BrowsePath *browsePath) { |
| 36650 | lockServer(server); |
| 36651 | UA_BrowsePathResult result = translateBrowsePathToNodeIds(server, browsePath); |
| 36652 | unlockServer(server); |
| 36653 | return result; |
| 36654 | } |
| 36655 | |
| 36656 | void |
| 36657 | Service_TranslateBrowsePathsToNodeIds(UA_Server *server, UA_Session *session, |
| 36658 | const UA_TranslateBrowsePathsToNodeIdsRequest *request, |
| 36659 | UA_TranslateBrowsePathsToNodeIdsResponse *response) { |
| 36660 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 36661 | "Processing TranslateBrowsePathsToNodeIdsRequest"); |
| 36662 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 36663 | |
| 36664 | /* Test the number of operations in the request */ |
| 36665 | if(server->config.maxNodesPerTranslateBrowsePathsToNodeIds != 0 && |
| 36666 | request->browsePathsSize > server->config.maxNodesPerTranslateBrowsePathsToNodeIds) { |
| 36667 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 36668 | return; |
| 36669 | } |
| 36670 | |
| 36671 | UA_UInt32 nodeClassMask = 0; /* All node classes */ |
| 36672 | response->responseHeader.serviceResult = |
| 36673 | UA_Server_processServiceOperations(server, session, |
| 36674 | operationCallback: (UA_ServiceOperation)Operation_TranslateBrowsePathToNodeIds, |
| 36675 | context: &nodeClassMask, |
| 36676 | requestOperations: &request->browsePathsSize, requestOperationsType: &UA_TYPES[UA_TYPES_BROWSEPATH], |
| 36677 | responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_BROWSEPATHRESULT]); |
| 36678 | } |
| 36679 | |
| 36680 | UA_BrowsePathResult |
| 36681 | browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin, |
| 36682 | size_t browsePathSize, const UA_QualifiedName *browsePath) { |
| 36683 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 36684 | |
| 36685 | UA_BrowsePathResult bpr; |
| 36686 | UA_BrowsePathResult_init(p: &bpr); |
| 36687 | if(browsePathSize > UA_MAX_TREE_RECURSE) { |
| 36688 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 36689 | msg: "Simplified Browse Path too long"); |
| 36690 | bpr.statusCode = UA_STATUSCODE_BADINTERNALERROR; |
| 36691 | return bpr; |
| 36692 | } |
| 36693 | |
| 36694 | /* Construct the BrowsePath */ |
| 36695 | UA_BrowsePath bp; |
| 36696 | UA_BrowsePath_init(p: &bp); |
| 36697 | bp.startingNode = origin; |
| 36698 | |
| 36699 | UA_RelativePathElement rpe[UA_MAX_TREE_RECURSE]; |
| 36700 | memset(s: rpe, c: 0, n: sizeof(UA_RelativePathElement) * browsePathSize); |
| 36701 | for(size_t j = 0; j < browsePathSize; j++) { |
| 36702 | rpe[j].referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES); |
| 36703 | rpe[j].includeSubtypes = true; |
| 36704 | rpe[j].targetName = browsePath[j]; |
| 36705 | } |
| 36706 | bp.relativePath.elements = rpe; |
| 36707 | bp.relativePath.elementsSize = browsePathSize; |
| 36708 | |
| 36709 | /* Browse */ |
| 36710 | UA_UInt32 nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_OBJECTTYPE; |
| 36711 | |
| 36712 | Operation_TranslateBrowsePathToNodeIds(server, session: &server->adminSession, nodeClassMask: &nodeClassMask, path: &bp, result: &bpr); |
| 36713 | return bpr; |
| 36714 | } |
| 36715 | |
| 36716 | UA_BrowsePathResult |
| 36717 | UA_Server_browseSimplifiedBrowsePath(UA_Server *server, const UA_NodeId origin, |
| 36718 | size_t browsePathSize, const UA_QualifiedName *browsePath) { |
| 36719 | lockServer(server); |
| 36720 | UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin, browsePathSize, browsePath); |
| 36721 | unlockServer(server); |
| 36722 | return bpr; |
| 36723 | } |
| 36724 | |
| 36725 | /************/ |
| 36726 | /* Register */ |
| 36727 | /************/ |
| 36728 | |
| 36729 | void Service_RegisterNodes(UA_Server *server, UA_Session *session, |
| 36730 | const UA_RegisterNodesRequest *request, |
| 36731 | UA_RegisterNodesResponse *response) { |
| 36732 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 36733 | "Processing RegisterNodesRequest"); |
| 36734 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 36735 | |
| 36736 | //TODO: hang the nodeids to the session if really needed |
| 36737 | if(request->nodesToRegisterSize == 0) { |
| 36738 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO; |
| 36739 | return; |
| 36740 | } |
| 36741 | |
| 36742 | /* Test the number of operations in the request */ |
| 36743 | if(server->config.maxNodesPerRegisterNodes != 0 && |
| 36744 | request->nodesToRegisterSize > server->config.maxNodesPerRegisterNodes) { |
| 36745 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 36746 | return; |
| 36747 | } |
| 36748 | |
| 36749 | response->responseHeader.serviceResult = |
| 36750 | UA_Array_copy(src: request->nodesToRegister, size: request->nodesToRegisterSize, |
| 36751 | dst: (void**)&response->registeredNodeIds, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 36752 | if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) |
| 36753 | response->registeredNodeIdsSize = request->nodesToRegisterSize; |
| 36754 | } |
| 36755 | |
| 36756 | void Service_UnregisterNodes(UA_Server *server, UA_Session *session, |
| 36757 | const UA_UnregisterNodesRequest *request, |
| 36758 | UA_UnregisterNodesResponse *response) { |
| 36759 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 36760 | "Processing UnRegisterNodesRequest"); |
| 36761 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 36762 | |
| 36763 | //TODO: remove the nodeids from the session if really needed |
| 36764 | if(request->nodesToUnregisterSize == 0) |
| 36765 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO; |
| 36766 | |
| 36767 | /* Test the number of operations in the request */ |
| 36768 | if(server->config.maxNodesPerRegisterNodes != 0 && |
| 36769 | request->nodesToUnregisterSize > server->config.maxNodesPerRegisterNodes) { |
| 36770 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 36771 | return; |
| 36772 | } |
| 36773 | } |
| 36774 | |
| 36775 | /**** amalgamated original file "/src/server/ua_services_method.c" ****/ |
| 36776 | |
| 36777 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 36778 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 36779 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 36780 | * |
| 36781 | * Copyright 2015 (c) Chris Iatrou |
| 36782 | * Copyright 2015-2017 (c) Florian Palm |
| 36783 | * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 36784 | * Copyright 2015-2016 (c) Sten Grüner |
| 36785 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 36786 | * Copyright 2016 (c) LEvertz |
| 36787 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 36788 | * Copyright 2017 (c) Julian Grothoff |
| 36789 | * Copyright 2020 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang) |
| 36790 | */ |
| 36791 | |
| 36792 | |
| 36793 | #ifdef UA_ENABLE_METHODCALLS /* conditional compilation */ |
| 36794 | |
| 36795 | #define UA_MAX_METHOD_ARGUMENTS 64 |
| 36796 | |
| 36797 | struct GetArgumentsNodeContext { |
| 36798 | UA_Server *server; |
| 36799 | UA_String withBrowseName; |
| 36800 | }; |
| 36801 | |
| 36802 | static void * |
| 36803 | getArgumentsNodeCallback(void *context, UA_ReferenceTarget *t) { |
| 36804 | struct GetArgumentsNodeContext *ctx = (struct GetArgumentsNodeContext*)context; |
| 36805 | const UA_Node *refTarget = |
| 36806 | UA_NODESTORE_GETFROMREF_SELECTIVE(ctx->server, t->targetId, |
| 36807 | UA_NODEATTRIBUTESMASK_NODECLASS | |
| 36808 | UA_NODEATTRIBUTESMASK_VALUE, |
| 36809 | UA_REFERENCETYPESET_NONE, |
| 36810 | UA_BROWSEDIRECTION_INVALID); |
| 36811 | if(!refTarget) |
| 36812 | return NULL; |
| 36813 | if(refTarget->head.nodeClass == UA_NODECLASS_VARIABLE && |
| 36814 | refTarget->head.browseName.namespaceIndex == 0 && |
| 36815 | UA_String_equal(p1: &ctx->withBrowseName, p2: &refTarget->head.browseName.name)) { |
| 36816 | return (void*)(uintptr_t)&refTarget->variableNode; |
| 36817 | } |
| 36818 | UA_NODESTORE_RELEASE(ctx->server, refTarget); |
| 36819 | return NULL; |
| 36820 | } |
| 36821 | |
| 36822 | static const UA_VariableNode * |
| 36823 | getArgumentsVariableNode(UA_Server *server, const UA_NodeHead *head, |
| 36824 | UA_String withBrowseName) { |
| 36825 | for(size_t i = 0; i < head->referencesSize; ++i) { |
| 36826 | UA_NodeReferenceKind *rk = &head->references[i]; |
| 36827 | if(rk->isInverse) |
| 36828 | continue; |
| 36829 | if(rk->referenceTypeIndex != UA_REFERENCETYPEINDEX_HASPROPERTY) |
| 36830 | continue; |
| 36831 | struct GetArgumentsNodeContext ctx; |
| 36832 | ctx.server = server; |
| 36833 | ctx.withBrowseName = withBrowseName; |
| 36834 | return (const UA_VariableNode*) |
| 36835 | UA_NodeReferenceKind_iterate(rk, callback: getArgumentsNodeCallback, context: &ctx); |
| 36836 | } |
| 36837 | return NULL; |
| 36838 | } |
| 36839 | |
| 36840 | /* inputArgumentResults has the length request->inputArgumentsSize */ |
| 36841 | static UA_StatusCode |
| 36842 | checkAdjustArguments(UA_Server *server, UA_Session *session, |
| 36843 | const UA_VariableNode *argRequirements, size_t argsSize, |
| 36844 | UA_Variant *args, UA_StatusCode *inputArgumentResults) { |
| 36845 | /* Verify that we have a Variant containing UA_Argument (scalar or array) in |
| 36846 | * the "InputArguments" node */ |
| 36847 | if(argRequirements->valueSource != UA_VALUESOURCE_DATA) |
| 36848 | return UA_STATUSCODE_BADINTERNALERROR; |
| 36849 | if(!argRequirements->value.data.value.hasValue) |
| 36850 | return UA_STATUSCODE_BADINTERNALERROR; |
| 36851 | if(argRequirements->value.data.value.value.type != &UA_TYPES[UA_TYPES_ARGUMENT]) |
| 36852 | return UA_STATUSCODE_BADINTERNALERROR; |
| 36853 | |
| 36854 | /* Verify the number of arguments. A scalar argument value is interpreted as |
| 36855 | * an array of length 1. */ |
| 36856 | size_t argReqsSize = argRequirements->value.data.value.value.arrayLength; |
| 36857 | if(UA_Variant_isScalar(v: &argRequirements->value.data.value.value)) |
| 36858 | argReqsSize = 1; |
| 36859 | if(argReqsSize > argsSize) |
| 36860 | return UA_STATUSCODE_BADARGUMENTSMISSING; |
| 36861 | if(argReqsSize < argsSize) |
| 36862 | return UA_STATUSCODE_BADTOOMANYARGUMENTS; |
| 36863 | |
| 36864 | /* Type-check every argument against the definition */ |
| 36865 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 36866 | UA_Argument *argReqs = (UA_Argument*)argRequirements->value.data.value.value.data; |
| 36867 | const char *reason; |
| 36868 | for(size_t i = 0; i < argReqsSize; ++i) { |
| 36869 | /* Incompatible value. Try to correct the type if possible. */ |
| 36870 | adjustValueType(server, value: &args[i], targetDataTypeId: &argReqs[i].dataType); |
| 36871 | |
| 36872 | /* Check */ |
| 36873 | if(!compatibleValue(server, session, targetDataTypeId: &argReqs[i].dataType, targetValueRank: argReqs[i].valueRank, |
| 36874 | targetArrayDimensionsSize: argReqs[i].arrayDimensionsSize, targetArrayDimensions: argReqs[i].arrayDimensions, |
| 36875 | value: &args[i], NULL, reason: &reason)) { |
| 36876 | inputArgumentResults[i] = UA_STATUSCODE_BADTYPEMISMATCH; |
| 36877 | retval = UA_STATUSCODE_BADINVALIDARGUMENT; |
| 36878 | } |
| 36879 | } |
| 36880 | return retval; |
| 36881 | } |
| 36882 | |
| 36883 | static const UA_NodeId hasComponentNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}}; |
| 36884 | static const UA_NodeId organizedByNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}}; |
| 36885 | static const UA_String namespaceDiModel = UA_STRING_STATIC("http://opcfoundation.org/UA/DI/"); |
| 36886 | static const UA_NodeId hasTypeDefinitionNodeId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASTYPEDEFINITION}}; |
| 36887 | // ns=0 will be replace dynamically. DI-Spec. 1.01: <UAObjectType NodeId="ns=1;i=1005" BrowseName="1:FunctionalGroupType"> |
| 36888 | static UA_NodeId functionGroupNodeId = {0, UA_NODEIDTYPE_NUMERIC, {1005}}; |
| 36889 | |
| 36890 | static UA_Boolean |
| 36891 | checkMethodReference(const UA_NodeHead *h, UA_ReferenceTypeSet refs, |
| 36892 | const UA_ExpandedNodeId *methodId) { |
| 36893 | for(size_t i = 0; i < h->referencesSize; i++) { |
| 36894 | const UA_NodeReferenceKind *rk = &h->references[i]; |
| 36895 | if(rk->isInverse) |
| 36896 | continue; |
| 36897 | if(!UA_ReferenceTypeSet_contains(set: &refs, index: rk->referenceTypeIndex)) |
| 36898 | continue; |
| 36899 | if(UA_NodeReferenceKind_findTarget(rk, targetId: methodId)) |
| 36900 | return true; |
| 36901 | } |
| 36902 | return false; |
| 36903 | } |
| 36904 | |
| 36905 | static void * |
| 36906 | iterateFunctionGroupSearch(void *context, UA_ReferenceTarget *t) { |
| 36907 | UA_Server *server = (UA_Server*)context; |
| 36908 | if(!UA_NodePointer_isLocal(np: t->targetId)) |
| 36909 | return NULL; |
| 36910 | |
| 36911 | UA_NodeId tmpId = UA_NodePointer_toNodeId(np: t->targetId); |
| 36912 | if(isNodeInTree_singleRef(server, leafNode: &tmpId, nodeToFind: &functionGroupNodeId, |
| 36913 | UA_REFERENCETYPEINDEX_HASSUBTYPE)) |
| 36914 | return (void*)0x01; |
| 36915 | return NULL; |
| 36916 | } |
| 36917 | |
| 36918 | static UA_StatusCode |
| 36919 | checkFunctionalGroupMethodReference(UA_Server *server, const UA_NodeHead *h, |
| 36920 | const UA_ExpandedNodeId *methodId, |
| 36921 | UA_Boolean *found) { |
| 36922 | /* Check whether the DI namespace is available */ |
| 36923 | size_t foundNamespace = 0; |
| 36924 | UA_StatusCode res = getNamespaceByName(server, namespaceUri: namespaceDiModel, foundIndex: &foundNamespace); |
| 36925 | UA_CHECK_STATUS(res, return UA_STATUSCODE_BADMETHODINVALID); |
| 36926 | functionGroupNodeId.namespaceIndex = (UA_UInt16)foundNamespace; |
| 36927 | |
| 36928 | UA_ReferenceTypeSet hasTypeDefinitionRefs; |
| 36929 | res = referenceTypeIndices(server, refType: &hasTypeDefinitionNodeId, |
| 36930 | indices: &hasTypeDefinitionRefs, true); |
| 36931 | UA_CHECK_STATUS(res, return res); |
| 36932 | |
| 36933 | /* Search for a HasTypeDefinition (or sub-) reference to the FunctionGroupType */ |
| 36934 | UA_Boolean isFunctionGroup = false; |
| 36935 | for(size_t i = 0; i < h->referencesSize && !isFunctionGroup; ++i) { |
| 36936 | UA_NodeReferenceKind *rk = &h->references[i]; |
| 36937 | if(rk->isInverse) |
| 36938 | continue; |
| 36939 | |
| 36940 | /* Are these HasTypeDefinition references */ |
| 36941 | if(!UA_ReferenceTypeSet_contains(set: &hasTypeDefinitionRefs, index: rk->referenceTypeIndex)) |
| 36942 | continue; |
| 36943 | |
| 36944 | /* Reference points to FunctionGroupType (or sub-type) from the DI |
| 36945 | * model? */ |
| 36946 | isFunctionGroup = |
| 36947 | (UA_NodeReferenceKind_iterate(rk, callback: iterateFunctionGroupSearch, |
| 36948 | context: server) != NULL); |
| 36949 | if(isFunctionGroup) |
| 36950 | break; |
| 36951 | } |
| 36952 | if(!isFunctionGroup) |
| 36953 | return UA_STATUSCODE_GOOD; |
| 36954 | |
| 36955 | /* Search for the called method with reference Organize (or sub-type) from |
| 36956 | * the parent object */ |
| 36957 | UA_ReferenceTypeSet organizesRefs; |
| 36958 | res = referenceTypeIndices(server, refType: &organizedByNodeId, indices: &organizesRefs, true); |
| 36959 | UA_CHECK_STATUS(res, return res); |
| 36960 | for(size_t k = 0; k < h->referencesSize; ++k) { |
| 36961 | const UA_NodeReferenceKind *rk = &h->references[k]; |
| 36962 | if(rk->isInverse) |
| 36963 | continue; |
| 36964 | if(!UA_ReferenceTypeSet_contains(set: &organizesRefs, index: rk->referenceTypeIndex)) |
| 36965 | continue; |
| 36966 | if(UA_NodeReferenceKind_findTarget(rk, targetId: methodId)) { |
| 36967 | *found = true; |
| 36968 | break; |
| 36969 | } |
| 36970 | } |
| 36971 | return UA_STATUSCODE_GOOD; |
| 36972 | } |
| 36973 | |
| 36974 | static void |
| 36975 | callWithMethodAndObject(UA_Server *server, UA_Session *session, |
| 36976 | const UA_CallMethodRequest *request, UA_CallMethodResult *result, |
| 36977 | const UA_MethodNode *method, const UA_ObjectNode *object) { |
| 36978 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 36979 | |
| 36980 | /* Verify the object's NodeClass */ |
| 36981 | if(object->head.nodeClass != UA_NODECLASS_OBJECT && |
| 36982 | object->head.nodeClass != UA_NODECLASS_OBJECTTYPE) { |
| 36983 | result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID; |
| 36984 | return; |
| 36985 | } |
| 36986 | |
| 36987 | /* Verify the method's NodeClass */ |
| 36988 | if(method->head.nodeClass != UA_NODECLASS_METHOD) { |
| 36989 | result->statusCode = UA_STATUSCODE_BADNODECLASSINVALID; |
| 36990 | return; |
| 36991 | } |
| 36992 | |
| 36993 | /* Is there a method to execute? */ |
| 36994 | if(!method->method) { |
| 36995 | result->statusCode = UA_STATUSCODE_BADINTERNALERROR; |
| 36996 | return; |
| 36997 | } |
| 36998 | |
| 36999 | /* Verify method/object relations. Object must have a hasComponent or a |
| 37000 | * subtype of hasComponent reference to the method node. Therefore, check |
| 37001 | * every reference between the parent object and the method node if there is |
| 37002 | * a hasComponent (or subtype) reference */ |
| 37003 | UA_ExpandedNodeId methodId = UA_EXPANDEDNODEID_NODEID(nodeId: request->methodId); |
| 37004 | UA_ReferenceTypeSet hasComponentRefs; |
| 37005 | result->statusCode = referenceTypeIndices(server, refType: &hasComponentNodeId, |
| 37006 | indices: &hasComponentRefs, true); |
| 37007 | UA_CHECK_STATUS(result->statusCode, return); |
| 37008 | UA_Boolean found = checkMethodReference(h: &object->head, refs: hasComponentRefs, methodId: &methodId); |
| 37009 | |
| 37010 | if(!found) { |
| 37011 | /* If the object doesn't have a hasComponent reference to the method node, |
| 37012 | * check its objectType (and its supertypes). Invoked method can be a component |
| 37013 | * of objectType and be invoked on this objectType's instance (or on a instance |
| 37014 | * of one of its subtypes). */ |
| 37015 | const UA_Node *objectType = getNodeType(server, head: &object->head); |
| 37016 | if(objectType) { |
| 37017 | found = checkMethodReference(h: &objectType->head, refs: hasComponentRefs, methodId: &methodId); |
| 37018 | UA_NODESTORE_RELEASE(server, objectType); |
| 37019 | } |
| 37020 | } |
| 37021 | |
| 37022 | if(!found) { |
| 37023 | /* The following ParentObject evaluation is a workaround only to fulfill |
| 37024 | * the OPC UA Spec. Part 100 - Devices requirements regarding functional |
| 37025 | * groups. Compare OPC UA Spec. Part 100 - Devices, Release 1.02 |
| 37026 | * - 5.4 FunctionalGroupType |
| 37027 | * - B.1 Functional Group Usages |
| 37028 | * A functional group is a sub-type of the FolderType and is used to |
| 37029 | * organize the Parameters and Methods from the complete set (named |
| 37030 | * ParameterSet and MethodSet) in (Functional) groups for instance |
| 37031 | * Configuration or Identification. The same Property, Parameter or |
| 37032 | * Method can be referenced from more than one FunctionalGroup. */ |
| 37033 | result->statusCode = |
| 37034 | checkFunctionalGroupMethodReference(server, h: &object->head, methodId: &methodId, found: &found); |
| 37035 | if(!found && result->statusCode == UA_STATUSCODE_GOOD) |
| 37036 | result->statusCode = UA_STATUSCODE_BADMETHODINVALID; |
| 37037 | UA_CHECK_STATUS(result->statusCode, return); |
| 37038 | } |
| 37039 | |
| 37040 | /* Verify access rights */ |
| 37041 | UA_Boolean executable = method->executable; |
| 37042 | if(session != &server->adminSession) { |
| 37043 | executable = executable && server->config.accessControl. |
| 37044 | getUserExecutableOnObject(server, &server->config.accessControl, |
| 37045 | &session->sessionId, session->sessionHandle, |
| 37046 | &request->methodId, method->head.context, |
| 37047 | &request->objectId, object->head.context); |
| 37048 | } |
| 37049 | |
| 37050 | if(!executable) { |
| 37051 | result->statusCode = UA_STATUSCODE_BADNOTEXECUTABLE; |
| 37052 | return; |
| 37053 | } |
| 37054 | |
| 37055 | /* The input arguments are const and not changed. We move the input |
| 37056 | * arguments to a secondary array that is mutable. This is used for small |
| 37057 | * adjustments on the type level during the type checking. But it has to be |
| 37058 | * ensured that the original array can still by _clear'ed after the methods |
| 37059 | * call. */ |
| 37060 | if(request->inputArgumentsSize > UA_MAX_METHOD_ARGUMENTS) { |
| 37061 | result->statusCode = UA_STATUSCODE_BADTOOMANYARGUMENTS; |
| 37062 | return; |
| 37063 | } |
| 37064 | UA_Variant mutableInputArgs[UA_MAX_METHOD_ARGUMENTS]; |
| 37065 | memcpy(dest: mutableInputArgs, src: request->inputArguments, |
| 37066 | n: sizeof(UA_Variant) * request->inputArgumentsSize); |
| 37067 | |
| 37068 | /* Allocate the inputArgumentResults array */ |
| 37069 | result->inputArgumentResults = (UA_StatusCode*) |
| 37070 | UA_Array_new(size: request->inputArgumentsSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 37071 | if(!result->inputArgumentResults) { |
| 37072 | result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY; |
| 37073 | return; |
| 37074 | } |
| 37075 | result->inputArgumentResultsSize = request->inputArgumentsSize; |
| 37076 | |
| 37077 | /* Type-check the input arguments */ |
| 37078 | const UA_VariableNode *inputArguments = |
| 37079 | getArgumentsVariableNode(server, head: &method->head, withBrowseName: UA_STRING(chars: "InputArguments")); |
| 37080 | if(inputArguments) { |
| 37081 | result->statusCode = |
| 37082 | checkAdjustArguments(server, session, argRequirements: inputArguments, argsSize: request->inputArgumentsSize, |
| 37083 | args: mutableInputArgs, inputArgumentResults: result->inputArgumentResults); |
| 37084 | UA_NODESTORE_RELEASE(server, (const UA_Node*)inputArguments); |
| 37085 | } else { |
| 37086 | if(request->inputArgumentsSize > 0) { |
| 37087 | result->statusCode = UA_STATUSCODE_BADTOOMANYARGUMENTS; |
| 37088 | return; |
| 37089 | } |
| 37090 | } |
| 37091 | |
| 37092 | /* Return inputArgumentResults only for BADINVALIDARGUMENT */ |
| 37093 | if(result->statusCode != UA_STATUSCODE_BADINVALIDARGUMENT) { |
| 37094 | UA_Array_delete(p: result->inputArgumentResults, size: result->inputArgumentResultsSize, |
| 37095 | type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 37096 | result->inputArgumentResults = NULL; |
| 37097 | result->inputArgumentResultsSize = 0; |
| 37098 | } |
| 37099 | |
| 37100 | /* Error during type-checking? */ |
| 37101 | if(result->statusCode != UA_STATUSCODE_GOOD) |
| 37102 | return; |
| 37103 | |
| 37104 | /* Get the output arguments node */ |
| 37105 | const UA_VariableNode *outputArguments = |
| 37106 | getArgumentsVariableNode(server, head: &method->head, withBrowseName: UA_STRING(chars: "OutputArguments")); |
| 37107 | |
| 37108 | /* Allocate the output arguments array */ |
| 37109 | size_t outputArgsSize = 0; |
| 37110 | if(outputArguments) |
| 37111 | outputArgsSize = outputArguments->value.data.value.value.arrayLength; |
| 37112 | result->outputArguments = (UA_Variant*) |
| 37113 | UA_Array_new(size: outputArgsSize, type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 37114 | if(!result->outputArguments) { |
| 37115 | result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY; |
| 37116 | return; |
| 37117 | } |
| 37118 | result->outputArgumentsSize = outputArgsSize; |
| 37119 | |
| 37120 | /* Release the output arguments node */ |
| 37121 | UA_NODESTORE_RELEASE(server, (const UA_Node*)outputArguments); |
| 37122 | |
| 37123 | /* Call the method. If this is an async method, unlock the server lock for |
| 37124 | * the duration of the (long-running) call. */ |
| 37125 | #if UA_MULTITHREADING >= 100 |
| 37126 | if(method->async) |
| 37127 | unlockServer(server); |
| 37128 | #endif |
| 37129 | result->statusCode = method->method(server, &session->sessionId, session->sessionHandle, |
| 37130 | &method->head.nodeId, method->head.context, |
| 37131 | &object->head.nodeId, object->head.context, |
| 37132 | request->inputArgumentsSize, mutableInputArgs, |
| 37133 | result->outputArgumentsSize, result->outputArguments); |
| 37134 | #if UA_MULTITHREADING >= 100 |
| 37135 | if(method->async) |
| 37136 | lockServer(server); |
| 37137 | #endif |
| 37138 | |
| 37139 | /* TODO: Verify Output matches the argument definition */ |
| 37140 | } |
| 37141 | |
| 37142 | #if UA_MULTITHREADING >= 100 |
| 37143 | |
| 37144 | static void |
| 37145 | Operation_CallMethodAsync(UA_Server *server, UA_Session *session, UA_UInt32 requestId, |
| 37146 | UA_UInt32 requestHandle, size_t opIndex, |
| 37147 | UA_CallMethodRequest *opRequest, UA_CallMethodResult *opResult, |
| 37148 | UA_AsyncResponse **ar) { |
| 37149 | /* Get the method node. We only need the nodeClass and executable attribute. |
| 37150 | * Take all forward hasProperty references to get the input/output argument |
| 37151 | * definition variables. */ |
| 37152 | const UA_Node *method = |
| 37153 | UA_NODESTORE_GET_SELECTIVE(server, &opRequest->methodId, |
| 37154 | UA_NODEATTRIBUTESMASK_NODECLASS | |
| 37155 | UA_NODEATTRIBUTESMASK_EXECUTABLE, |
| 37156 | UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASPROPERTY), |
| 37157 | UA_BROWSEDIRECTION_FORWARD); |
| 37158 | if(!method) { |
| 37159 | opResult->statusCode = UA_STATUSCODE_BADMETHODINVALID; |
| 37160 | return; |
| 37161 | } |
| 37162 | |
| 37163 | /* Get the object node. We only need the NodeClass attribute. But take all |
| 37164 | * references for now. |
| 37165 | * |
| 37166 | * TODO: Which references do we need actually? */ |
| 37167 | const UA_Node *object = |
| 37168 | UA_NODESTORE_GET_SELECTIVE(server, &opRequest->objectId, |
| 37169 | UA_NODEATTRIBUTESMASK_NODECLASS, |
| 37170 | UA_REFERENCETYPESET_ALL, |
| 37171 | UA_BROWSEDIRECTION_BOTH); |
| 37172 | if(!object) { |
| 37173 | opResult->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 37174 | UA_NODESTORE_RELEASE(server, method); |
| 37175 | return; |
| 37176 | } |
| 37177 | |
| 37178 | /* Synchronous execution */ |
| 37179 | if(!method->methodNode.async) { |
| 37180 | callWithMethodAndObject(server, session, opRequest, opResult, |
| 37181 | &method->methodNode, &object->objectNode); |
| 37182 | goto cleanup; |
| 37183 | } |
| 37184 | |
| 37185 | /* <-- Async method call --> */ |
| 37186 | |
| 37187 | /* No AsyncResponse allocated so far */ |
| 37188 | if(!*ar) { |
| 37189 | opResult->statusCode = |
| 37190 | UA_AsyncManager_createAsyncResponse(&server->asyncManager, server, |
| 37191 | &session->sessionId, requestId, requestHandle, |
| 37192 | UA_ASYNCOPERATIONTYPE_CALL, ar); |
| 37193 | if(opResult->statusCode != UA_STATUSCODE_GOOD) |
| 37194 | goto cleanup; |
| 37195 | } |
| 37196 | |
| 37197 | /* Create the Async Request to be taken by workers */ |
| 37198 | opResult->statusCode = |
| 37199 | UA_AsyncManager_createAsyncOp(&server->asyncManager, |
| 37200 | server, *ar, opIndex, opRequest); |
| 37201 | |
| 37202 | cleanup: |
| 37203 | /* Release the method and object node */ |
| 37204 | UA_NODESTORE_RELEASE(server, method); |
| 37205 | UA_NODESTORE_RELEASE(server, object); |
| 37206 | } |
| 37207 | |
| 37208 | void |
| 37209 | Service_CallAsync(UA_Server *server, UA_Session *session, UA_UInt32 requestId, |
| 37210 | const UA_CallRequest *request, UA_CallResponse *response, |
| 37211 | UA_Boolean *finished) { |
| 37212 | UA_LOG_DEBUG_SESSION(server->config.logging, session, "Processing CallRequestAsync"); |
| 37213 | if(server->config.maxNodesPerMethodCall != 0 && |
| 37214 | request->methodsToCallSize > server->config.maxNodesPerMethodCall) { |
| 37215 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 37216 | return; |
| 37217 | } |
| 37218 | |
| 37219 | UA_AsyncResponse *ar = NULL; |
| 37220 | response->responseHeader.serviceResult = |
| 37221 | UA_Server_processServiceOperationsAsync(server, session, requestId, |
| 37222 | request->requestHeader.requestHandle, |
| 37223 | (UA_AsyncServiceOperation)Operation_CallMethodAsync, |
| 37224 | &request->methodsToCallSize, &UA_TYPES[UA_TYPES_CALLMETHODREQUEST], |
| 37225 | &response->resultsSize, &UA_TYPES[UA_TYPES_CALLMETHODRESULT], &ar); |
| 37226 | |
| 37227 | if(ar) { |
| 37228 | if(ar->opCountdown > 0) { |
| 37229 | /* Move all results to the AsyncResponse. The async operation |
| 37230 | * results will be overwritten when the workers return results. */ |
| 37231 | ar->response.callResponse = *response; |
| 37232 | UA_CallResponse_init(response); |
| 37233 | *finished = false; |
| 37234 | } else { |
| 37235 | /* If there is a new AsyncResponse, ensure it has at least one |
| 37236 | * pending operation */ |
| 37237 | UA_AsyncManager_removeAsyncResponse(&server->asyncManager, ar); |
| 37238 | } |
| 37239 | } |
| 37240 | } |
| 37241 | #endif |
| 37242 | |
| 37243 | static void |
| 37244 | Operation_CallMethod(UA_Server *server, UA_Session *session, void *context, |
| 37245 | const UA_CallMethodRequest *request, UA_CallMethodResult *result) { |
| 37246 | /* Get the method node. We only need the nodeClass and executable attribute. |
| 37247 | * Take all forward hasProperty references to get the input/output argument |
| 37248 | * definition variables. */ |
| 37249 | const UA_Node *method = |
| 37250 | UA_NODESTORE_GET_SELECTIVE(server, &request->methodId, |
| 37251 | UA_NODEATTRIBUTESMASK_NODECLASS | |
| 37252 | UA_NODEATTRIBUTESMASK_EXECUTABLE, |
| 37253 | UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASPROPERTY), |
| 37254 | UA_BROWSEDIRECTION_FORWARD); |
| 37255 | if(!method) { |
| 37256 | result->statusCode = UA_STATUSCODE_BADMETHODINVALID; |
| 37257 | return; |
| 37258 | } |
| 37259 | |
| 37260 | /* Get the object node. We only need the NodeClass attribute. But take all |
| 37261 | * references for now. |
| 37262 | * |
| 37263 | * TODO: Which references do we need actually? */ |
| 37264 | const UA_Node *object = |
| 37265 | UA_NODESTORE_GET_SELECTIVE(server, &request->objectId, |
| 37266 | UA_NODEATTRIBUTESMASK_NODECLASS, |
| 37267 | UA_REFERENCETYPESET_ALL, |
| 37268 | UA_BROWSEDIRECTION_BOTH); |
| 37269 | if(!object) { |
| 37270 | result->statusCode = UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 37271 | UA_NODESTORE_RELEASE(server, method); |
| 37272 | return; |
| 37273 | } |
| 37274 | |
| 37275 | /* Continue with method and object as context */ |
| 37276 | callWithMethodAndObject(server, session, request, result, |
| 37277 | method: &method->methodNode, object: &object->objectNode); |
| 37278 | |
| 37279 | /* Release the method and object node */ |
| 37280 | UA_NODESTORE_RELEASE(server, method); |
| 37281 | UA_NODESTORE_RELEASE(server, object); |
| 37282 | } |
| 37283 | |
| 37284 | void Service_Call(UA_Server *server, UA_Session *session, |
| 37285 | const UA_CallRequest *request, UA_CallResponse *response) { |
| 37286 | UA_LOG_DEBUG_SESSION(server->config.logging, session, "Processing CallRequest"); |
| 37287 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 37288 | |
| 37289 | if(server->config.maxNodesPerMethodCall != 0 && |
| 37290 | request->methodsToCallSize > server->config.maxNodesPerMethodCall) { |
| 37291 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 37292 | return; |
| 37293 | } |
| 37294 | |
| 37295 | response->responseHeader.serviceResult = |
| 37296 | UA_Server_processServiceOperations(server, session, |
| 37297 | operationCallback: (UA_ServiceOperation)Operation_CallMethod, NULL, |
| 37298 | requestOperations: &request->methodsToCallSize, requestOperationsType: &UA_TYPES[UA_TYPES_CALLMETHODREQUEST], |
| 37299 | responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_CALLMETHODRESULT]); |
| 37300 | } |
| 37301 | |
| 37302 | UA_CallMethodResult |
| 37303 | UA_Server_call(UA_Server *server, const UA_CallMethodRequest *request) { |
| 37304 | UA_CallMethodResult result; |
| 37305 | UA_CallMethodResult_init(p: &result); |
| 37306 | lockServer(server); |
| 37307 | Operation_CallMethod(server, session: &server->adminSession, NULL, request, result: &result); |
| 37308 | unlockServer(server); |
| 37309 | return result; |
| 37310 | } |
| 37311 | |
| 37312 | #endif /* UA_ENABLE_METHODCALLS */ |
| 37313 | |
| 37314 | /**** amalgamated original file "/src/server/ua_services_session.c" ****/ |
| 37315 | |
| 37316 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 37317 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 37318 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 37319 | * |
| 37320 | * Copyright 2014-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 37321 | * Copyright 2014-2017 (c) Florian Palm |
| 37322 | * Copyright 2014-2016 (c) Sten Grüner |
| 37323 | * Copyright 2015 (c) Chris Iatrou |
| 37324 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 37325 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 37326 | * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB |
| 37327 | * Copyright 2019 (c) Kalycito Infotech Private Limited |
| 37328 | * Copyright 2018-2020 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 37329 | */ |
| 37330 | |
| 37331 | |
| 37332 | /* Delayed callback to free the session memory */ |
| 37333 | static void |
| 37334 | removeSessionCallback(UA_Server *server, session_list_entry *entry) { |
| 37335 | lockServer(server); |
| 37336 | UA_Session_clear(session: &entry->session, server); |
| 37337 | unlockServer(server); |
| 37338 | UA_free(ptr: entry); |
| 37339 | } |
| 37340 | |
| 37341 | void |
| 37342 | UA_Server_removeSession(UA_Server *server, session_list_entry *sentry, |
| 37343 | UA_ShutdownReason shutdownReason) { |
| 37344 | UA_Session *session = &sentry->session; |
| 37345 | |
| 37346 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 37347 | |
| 37348 | /* Remove the Subscriptions */ |
| 37349 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 37350 | UA_Subscription *sub, *tempsub; |
| 37351 | TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, tempsub) { |
| 37352 | UA_Subscription_delete(server, sub); |
| 37353 | } |
| 37354 | |
| 37355 | UA_PublishResponseEntry *entry; |
| 37356 | while((entry = UA_Session_dequeuePublishReq(session))) { |
| 37357 | UA_PublishResponse_clear(p: &entry->response); |
| 37358 | UA_free(ptr: entry); |
| 37359 | } |
| 37360 | #endif |
| 37361 | |
| 37362 | /* Callback into userland access control */ |
| 37363 | if(server->config.accessControl.closeSession) { |
| 37364 | server->config.accessControl. |
| 37365 | closeSession(server, &server->config.accessControl, |
| 37366 | &session->sessionId, session->sessionHandle); |
| 37367 | } |
| 37368 | |
| 37369 | /* Detach the Session from the SecureChannel */ |
| 37370 | UA_Session_detachFromSecureChannel(session); |
| 37371 | |
| 37372 | /* Deactivate the session */ |
| 37373 | if(sentry->session.activated) { |
| 37374 | sentry->session.activated = false; |
| 37375 | server->activeSessionCount--; |
| 37376 | } |
| 37377 | |
| 37378 | /* Detach the session from the session manager and make the capacity |
| 37379 | * available */ |
| 37380 | LIST_REMOVE(sentry, pointers); |
| 37381 | server->sessionCount--; |
| 37382 | |
| 37383 | switch(shutdownReason) { |
| 37384 | case UA_SHUTDOWNREASON_CLOSE: |
| 37385 | case UA_SHUTDOWNREASON_PURGE: |
| 37386 | break; |
| 37387 | case UA_SHUTDOWNREASON_TIMEOUT: |
| 37388 | server->serverDiagnosticsSummary.sessionTimeoutCount++; |
| 37389 | break; |
| 37390 | case UA_SHUTDOWNREASON_REJECT: |
| 37391 | server->serverDiagnosticsSummary.rejectedSessionCount++; |
| 37392 | break; |
| 37393 | case UA_SHUTDOWNREASON_SECURITYREJECT: |
| 37394 | server->serverDiagnosticsSummary.securityRejectedSessionCount++; |
| 37395 | break; |
| 37396 | case UA_SHUTDOWNREASON_ABORT: |
| 37397 | server->serverDiagnosticsSummary.sessionAbortCount++; |
| 37398 | break; |
| 37399 | default: |
| 37400 | UA_assert(false); |
| 37401 | break; |
| 37402 | } |
| 37403 | |
| 37404 | /* Add a delayed callback to remove the session when the currently |
| 37405 | * scheduled jobs have completed */ |
| 37406 | sentry->cleanupCallback.callback = (UA_Callback)removeSessionCallback; |
| 37407 | sentry->cleanupCallback.application = server; |
| 37408 | sentry->cleanupCallback.context = sentry; |
| 37409 | UA_EventLoop *el = server->config.eventLoop; |
| 37410 | el->addDelayedCallback(el, &sentry->cleanupCallback); |
| 37411 | } |
| 37412 | |
| 37413 | UA_StatusCode |
| 37414 | UA_Server_removeSessionByToken(UA_Server *server, const UA_NodeId *token, |
| 37415 | UA_ShutdownReason shutdownReason) { |
| 37416 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 37417 | session_list_entry *entry; |
| 37418 | LIST_FOREACH(entry, &server->sessions, pointers) { |
| 37419 | if(UA_NodeId_equal(p1: &entry->session.header.authenticationToken, p2: token)) { |
| 37420 | UA_Server_removeSession(server, sentry: entry, shutdownReason); |
| 37421 | return UA_STATUSCODE_GOOD; |
| 37422 | } |
| 37423 | } |
| 37424 | return UA_STATUSCODE_BADSESSIONIDINVALID; |
| 37425 | } |
| 37426 | |
| 37427 | void |
| 37428 | UA_Server_cleanupSessions(UA_Server *server, UA_DateTime nowMonotonic) { |
| 37429 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 37430 | session_list_entry *sentry, *temp; |
| 37431 | LIST_FOREACH_SAFE(sentry, &server->sessions, pointers, temp) { |
| 37432 | /* Session has timed out? */ |
| 37433 | if(sentry->session.validTill >= nowMonotonic) |
| 37434 | continue; |
| 37435 | UA_LOG_INFO_SESSION(server->config.logging, &sentry->session, |
| 37436 | "Session has timed out"); |
| 37437 | UA_Server_removeSession(server, sentry, shutdownReason: UA_SHUTDOWNREASON_TIMEOUT); |
| 37438 | } |
| 37439 | } |
| 37440 | |
| 37441 | /************/ |
| 37442 | /* Services */ |
| 37443 | /************/ |
| 37444 | |
| 37445 | UA_Session * |
| 37446 | getSessionByToken(UA_Server *server, const UA_NodeId *token) { |
| 37447 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 37448 | |
| 37449 | session_list_entry *current = NULL; |
| 37450 | LIST_FOREACH(current, &server->sessions, pointers) { |
| 37451 | /* Token does not match */ |
| 37452 | if(!UA_NodeId_equal(p1: ¤t->session.header.authenticationToken, p2: token)) |
| 37453 | continue; |
| 37454 | |
| 37455 | /* Session has timed out */ |
| 37456 | if(UA_DateTime_nowMonotonic() > current->session.validTill) { |
| 37457 | UA_LOG_INFO_SESSION(server->config.logging, ¤t->session, |
| 37458 | "Client tries to use a session that has timed out"); |
| 37459 | return NULL; |
| 37460 | } |
| 37461 | |
| 37462 | return ¤t->session; |
| 37463 | } |
| 37464 | |
| 37465 | return NULL; |
| 37466 | } |
| 37467 | |
| 37468 | UA_Session * |
| 37469 | getSessionById(UA_Server *server, const UA_NodeId *sessionId) { |
| 37470 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 37471 | |
| 37472 | session_list_entry *current = NULL; |
| 37473 | LIST_FOREACH(current, &server->sessions, pointers) { |
| 37474 | /* Token does not match */ |
| 37475 | if(!UA_NodeId_equal(p1: ¤t->session.sessionId, p2: sessionId)) |
| 37476 | continue; |
| 37477 | |
| 37478 | /* Session has timed out */ |
| 37479 | if(UA_DateTime_nowMonotonic() > current->session.validTill) { |
| 37480 | UA_LOG_INFO_SESSION(server->config.logging, ¤t->session, |
| 37481 | "Client tries to use a session that has timed out"); |
| 37482 | return NULL; |
| 37483 | } |
| 37484 | |
| 37485 | return ¤t->session; |
| 37486 | } |
| 37487 | |
| 37488 | if(UA_NodeId_equal(p1: sessionId, p2: &server->adminSession.sessionId)) |
| 37489 | return &server->adminSession; |
| 37490 | |
| 37491 | return NULL; |
| 37492 | } |
| 37493 | |
| 37494 | static UA_StatusCode |
| 37495 | signCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel, |
| 37496 | const UA_CreateSessionRequest *request, |
| 37497 | UA_CreateSessionResponse *response) { |
| 37498 | if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN && |
| 37499 | channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 37500 | return UA_STATUSCODE_GOOD; |
| 37501 | |
| 37502 | const UA_SecurityPolicy *securityPolicy = channel->securityPolicy; |
| 37503 | UA_SignatureData *signatureData = &response->serverSignature; |
| 37504 | |
| 37505 | /* Prepare the signature */ |
| 37506 | const UA_SecurityPolicySignatureAlgorithm *signAlg = |
| 37507 | &securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 37508 | size_t signatureSize = signAlg->getLocalSignatureSize(channel->channelContext); |
| 37509 | UA_StatusCode retval = UA_String_copy(src: &signAlg->uri, dst: &signatureData->algorithm); |
| 37510 | retval |= UA_ByteString_allocBuffer(bs: &signatureData->signature, length: signatureSize); |
| 37511 | if(retval != UA_STATUSCODE_GOOD) |
| 37512 | return retval; |
| 37513 | |
| 37514 | /* Allocate a temp buffer */ |
| 37515 | size_t dataToSignSize = |
| 37516 | request->clientCertificate.length + request->clientNonce.length; |
| 37517 | UA_ByteString dataToSign; |
| 37518 | retval = UA_ByteString_allocBuffer(bs: &dataToSign, length: dataToSignSize); |
| 37519 | if(retval != UA_STATUSCODE_GOOD) |
| 37520 | return retval; /* signatureData->signature is cleaned up with the response */ |
| 37521 | |
| 37522 | /* Sign the signature */ |
| 37523 | memcpy(dest: dataToSign.data, src: request->clientCertificate.data, |
| 37524 | n: request->clientCertificate.length); |
| 37525 | memcpy(dest: dataToSign.data + request->clientCertificate.length, |
| 37526 | src: request->clientNonce.data, n: request->clientNonce.length); |
| 37527 | retval = securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm. |
| 37528 | sign(channel->channelContext, &dataToSign, &signatureData->signature); |
| 37529 | |
| 37530 | /* Clean up */ |
| 37531 | UA_ByteString_clear(p: &dataToSign); |
| 37532 | return retval; |
| 37533 | } |
| 37534 | |
| 37535 | /* Creates and adds a session. But it is not yet attached to a secure channel. */ |
| 37536 | UA_StatusCode |
| 37537 | UA_Server_createSession(UA_Server *server, UA_SecureChannel *channel, |
| 37538 | const UA_CreateSessionRequest *request, UA_Session **session) { |
| 37539 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 37540 | |
| 37541 | if(server->sessionCount >= server->config.maxSessions) { |
| 37542 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 37543 | "Could not create a Session - Server limits reached"); |
| 37544 | return UA_STATUSCODE_BADTOOMANYSESSIONS; |
| 37545 | } |
| 37546 | |
| 37547 | session_list_entry *newentry = (session_list_entry*) |
| 37548 | UA_malloc(size: sizeof(session_list_entry)); |
| 37549 | if(!newentry) |
| 37550 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 37551 | |
| 37552 | /* Initialize the Session */ |
| 37553 | UA_Session_init(session: &newentry->session); |
| 37554 | newentry->session.sessionId = UA_NODEID_GUID(nsIndex: 1, guid: UA_Guid_random()); |
| 37555 | newentry->session.header.authenticationToken = UA_NODEID_GUID(nsIndex: 1, guid: UA_Guid_random()); |
| 37556 | |
| 37557 | newentry->session.timeout = server->config.maxSessionTimeout; |
| 37558 | if(request->requestedSessionTimeout <= server->config.maxSessionTimeout && |
| 37559 | request->requestedSessionTimeout > 0) |
| 37560 | newentry->session.timeout = request->requestedSessionTimeout; |
| 37561 | |
| 37562 | /* Attach the session to the channel. But don't activate for now. */ |
| 37563 | if(channel) |
| 37564 | UA_Session_attachToSecureChannel(session: &newentry->session, channel); |
| 37565 | UA_Session_updateLifetime(session: &newentry->session); |
| 37566 | |
| 37567 | /* Add to the server */ |
| 37568 | LIST_INSERT_HEAD(&server->sessions, newentry, pointers); |
| 37569 | server->sessionCount++; |
| 37570 | |
| 37571 | *session = &newentry->session; |
| 37572 | return UA_STATUSCODE_GOOD; |
| 37573 | } |
| 37574 | |
| 37575 | void |
| 37576 | Service_CreateSession(UA_Server *server, UA_SecureChannel *channel, |
| 37577 | const UA_CreateSessionRequest *request, |
| 37578 | UA_CreateSessionResponse *response) { |
| 37579 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 37580 | UA_LOG_DEBUG_CHANNEL(server->config.logging, channel, "Trying to create session"); |
| 37581 | |
| 37582 | if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 37583 | channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 37584 | /* Compare the clientCertificate with the remoteCertificate of the channel. |
| 37585 | * Both the clientCertificate of this request and the remoteCertificate |
| 37586 | * of the channel may contain a partial or a complete certificate chain. |
| 37587 | * The compareCertificate function of the channelModule will compare the |
| 37588 | * first certificate of each chain. The end certificate shall be located |
| 37589 | * first in the chain according to the OPC UA specification Part 6 (1.04), |
| 37590 | * chapter 6.2.3.*/ |
| 37591 | UA_StatusCode retval = channel->securityPolicy->channelModule. |
| 37592 | compareCertificate(channel->channelContext, &request->clientCertificate); |
| 37593 | if(retval != UA_STATUSCODE_GOOD) { |
| 37594 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 37595 | "The client certificate did not validate"); |
| 37596 | response->responseHeader.serviceResult = UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 37597 | return; |
| 37598 | } |
| 37599 | } |
| 37600 | |
| 37601 | UA_assert(channel->securityToken.channelId != 0); |
| 37602 | |
| 37603 | if(!UA_ByteString_equal(p1: &channel->securityPolicy->policyUri, |
| 37604 | p2: &UA_SECURITY_POLICY_NONE_URI) && |
| 37605 | request->clientNonce.length < 32) { |
| 37606 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNONCEINVALID; |
| 37607 | return; |
| 37608 | } |
| 37609 | |
| 37610 | if(request->clientCertificate.length > 0) { |
| 37611 | UA_CertificateVerification *cv = &server->config.sessionPKI; |
| 37612 | response->responseHeader.serviceResult = |
| 37613 | cv->verifyApplicationURI(cv, &request->clientCertificate, |
| 37614 | &request->clientDescription.applicationUri); |
| 37615 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 37616 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 37617 | "The client's ApplicationURI did not match the certificate"); |
| 37618 | server->serverDiagnosticsSummary.securityRejectedSessionCount++; |
| 37619 | server->serverDiagnosticsSummary.rejectedSessionCount++; |
| 37620 | return; |
| 37621 | } |
| 37622 | } |
| 37623 | |
| 37624 | /* Create the Session */ |
| 37625 | UA_Session *newSession = NULL; |
| 37626 | response->responseHeader.serviceResult = |
| 37627 | UA_Server_createSession(server, channel, request, session: &newSession); |
| 37628 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 37629 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 37630 | "Processing CreateSessionRequest failed"); |
| 37631 | server->serverDiagnosticsSummary.rejectedSessionCount++; |
| 37632 | return; |
| 37633 | } |
| 37634 | |
| 37635 | /* If the session name is empty, use the generated SessionId */ |
| 37636 | response->responseHeader.serviceResult |= |
| 37637 | UA_String_copy(src: &request->sessionName, dst: &newSession->sessionName); |
| 37638 | if(newSession->sessionName.length == 0) |
| 37639 | response->responseHeader.serviceResult |= |
| 37640 | UA_NodeId_print(id: &newSession->sessionId, output: &newSession->sessionName); |
| 37641 | |
| 37642 | response->responseHeader.serviceResult |= UA_Session_generateNonce(session: newSession); |
| 37643 | newSession->maxResponseMessageSize = request->maxResponseMessageSize; |
| 37644 | newSession->maxRequestMessageSize = channel->config.localMaxMessageSize; |
| 37645 | response->responseHeader.serviceResult |= |
| 37646 | UA_ApplicationDescription_copy(src: &request->clientDescription, |
| 37647 | dst: &newSession->clientDescription); |
| 37648 | |
| 37649 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 37650 | response->responseHeader.serviceResult |= |
| 37651 | UA_String_copy(src: &request->serverUri, dst: &newSession->diagnostics.serverUri); |
| 37652 | response->responseHeader.serviceResult |= |
| 37653 | UA_String_copy(src: &request->endpointUrl, dst: &newSession->diagnostics.endpointUrl); |
| 37654 | #endif |
| 37655 | |
| 37656 | /* Prepare the response */ |
| 37657 | response->sessionId = newSession->sessionId; |
| 37658 | response->revisedSessionTimeout = (UA_Double)newSession->timeout; |
| 37659 | response->authenticationToken = newSession->header.authenticationToken; |
| 37660 | response->responseHeader.serviceResult |= |
| 37661 | UA_ByteString_copy(src: &newSession->serverNonce, dst: &response->serverNonce); |
| 37662 | |
| 37663 | /* Copy the server's endpointdescriptions into the response */ |
| 37664 | response->responseHeader.serviceResult = |
| 37665 | setCurrentEndPointsArray(server, endpointURL: request->endpointUrl, NULL, profileUrisSize: 0, |
| 37666 | arr: &response->serverEndpoints, |
| 37667 | arrSize: &response->serverEndpointsSize); |
| 37668 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 37669 | UA_Server_removeSessionByToken(server, token: &newSession->header.authenticationToken, |
| 37670 | shutdownReason: UA_SHUTDOWNREASON_REJECT); |
| 37671 | return; |
| 37672 | } |
| 37673 | |
| 37674 | /* Return the server certificate from the SecurityPolicy of the current |
| 37675 | * channel. Or, if the channel is unencrypted, return the standard policy |
| 37676 | * used for usertoken encryption. */ |
| 37677 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 37678 | if(UA_String_equal(p1: &UA_SECURITY_POLICY_NONE_URI, p2: &sp->policyUri) || |
| 37679 | sp->localCertificate.length == 0) |
| 37680 | sp = getDefaultEncryptedSecurityPolicy(server); |
| 37681 | if(sp) |
| 37682 | response->responseHeader.serviceResult |= |
| 37683 | UA_ByteString_copy(src: &sp->localCertificate, dst: &response->serverCertificate); |
| 37684 | |
| 37685 | /* Sign the signature */ |
| 37686 | response->responseHeader.serviceResult |= |
| 37687 | signCreateSessionResponse(server, channel, request, response); |
| 37688 | |
| 37689 | /* Failure -> remove the session */ |
| 37690 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 37691 | UA_Server_removeSessionByToken(server, token: &newSession->header.authenticationToken, |
| 37692 | shutdownReason: UA_SHUTDOWNREASON_REJECT); |
| 37693 | return; |
| 37694 | } |
| 37695 | |
| 37696 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 37697 | newSession->diagnostics.clientConnectionTime = UA_DateTime_now(); |
| 37698 | newSession->diagnostics.clientLastContactTime = |
| 37699 | newSession->diagnostics.clientConnectionTime; |
| 37700 | |
| 37701 | /* Create the object in the information model */ |
| 37702 | createSessionObject(server, session: newSession); |
| 37703 | #endif |
| 37704 | |
| 37705 | UA_LOG_INFO_SESSION(server->config.logging, newSession, "Session created"); |
| 37706 | } |
| 37707 | |
| 37708 | static UA_StatusCode |
| 37709 | checkCertificateSignature(const UA_Server *server, const UA_SecurityPolicy *securityPolicy, |
| 37710 | void *channelContext, const UA_ByteString *serverNonce, |
| 37711 | const UA_SignatureData *signature, |
| 37712 | const bool isUserTokenSignature) { |
| 37713 | /* Check for zero signature length */ |
| 37714 | if(signature->signature.length == 0) { |
| 37715 | if(isUserTokenSignature) |
| 37716 | return UA_STATUSCODE_BADUSERSIGNATUREINVALID; |
| 37717 | return UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID; |
| 37718 | } |
| 37719 | |
| 37720 | if(!securityPolicy) |
| 37721 | return UA_STATUSCODE_BADINTERNALERROR; |
| 37722 | |
| 37723 | /* Server certificate */ |
| 37724 | const UA_ByteString *localCertificate = &securityPolicy->localCertificate; |
| 37725 | /* Data to verify is calculated by appending the serverNonce to the local certificate */ |
| 37726 | UA_ByteString dataToVerify; |
| 37727 | size_t dataToVerifySize = localCertificate->length + serverNonce->length; |
| 37728 | UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &dataToVerify, length: dataToVerifySize); |
| 37729 | if(retval != UA_STATUSCODE_GOOD) |
| 37730 | return retval; |
| 37731 | |
| 37732 | memcpy(dest: dataToVerify.data, src: localCertificate->data, n: localCertificate->length); |
| 37733 | memcpy(dest: dataToVerify.data + localCertificate->length, |
| 37734 | src: serverNonce->data, n: serverNonce->length); |
| 37735 | retval = securityPolicy->asymmetricModule.cryptoModule.signatureAlgorithm. |
| 37736 | verify(channelContext, &dataToVerify, &signature->signature); |
| 37737 | UA_ByteString_clear(p: &dataToVerify); |
| 37738 | if(retval != UA_STATUSCODE_GOOD) { |
| 37739 | if(isUserTokenSignature) |
| 37740 | retval = UA_STATUSCODE_BADUSERSIGNATUREINVALID; |
| 37741 | else |
| 37742 | retval = UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID; |
| 37743 | } |
| 37744 | return retval; |
| 37745 | } |
| 37746 | |
| 37747 | static void |
| 37748 | selectEndpointAndTokenPolicy(UA_Server *server, UA_SecureChannel *channel, |
| 37749 | const UA_ExtensionObject *identityToken, |
| 37750 | const UA_EndpointDescription **ed, |
| 37751 | const UA_UserTokenPolicy **utp, |
| 37752 | const UA_SecurityPolicy **tokenSp) { |
| 37753 | UA_ServerConfig *sc = &server->config; |
| 37754 | for(size_t i = 0; i < sc->endpointsSize; ++i) { |
| 37755 | const UA_EndpointDescription *desc = &sc->endpoints[i]; |
| 37756 | |
| 37757 | /* Match the Security Mode */ |
| 37758 | if(desc->securityMode != channel->securityMode) |
| 37759 | continue; |
| 37760 | |
| 37761 | /* Match the SecurityPolicy of the endpoint with the current channel */ |
| 37762 | if(!UA_String_equal(p1: &desc->securityPolicyUri, p2: &channel->securityPolicy->policyUri)) |
| 37763 | continue; |
| 37764 | |
| 37765 | /* If no UserTokenPolicies are configured in the endpoint, then use |
| 37766 | * those of the AccessControl plugin. */ |
| 37767 | size_t identPoliciesSize = desc->userIdentityTokensSize; |
| 37768 | const UA_UserTokenPolicy *identPolicies = desc->userIdentityTokens; |
| 37769 | if(identPoliciesSize == 0) { |
| 37770 | identPoliciesSize = sc->accessControl.userTokenPoliciesSize; |
| 37771 | identPolicies = sc->accessControl.userTokenPolicies; |
| 37772 | } |
| 37773 | |
| 37774 | /* Match the UserTokenType */ |
| 37775 | const UA_DataType *tokenDataType = identityToken->content.decoded.type; |
| 37776 | for(size_t j = 0; j < identPoliciesSize ; j++) { |
| 37777 | const UA_UserTokenPolicy *pol = &identPolicies[j]; |
| 37778 | |
| 37779 | /* Part 4, Section 5.6.3.2, Table 17: A NULL or empty |
| 37780 | * UserIdentityToken should be treated as Anonymous */ |
| 37781 | if(identityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY && |
| 37782 | pol->tokenType == UA_USERTOKENTYPE_ANONYMOUS) { |
| 37783 | *ed = desc; |
| 37784 | *utp = pol; |
| 37785 | return; |
| 37786 | } |
| 37787 | |
| 37788 | /* Expect decoded content if not anonymous */ |
| 37789 | if(!tokenDataType) |
| 37790 | continue; |
| 37791 | |
| 37792 | if(pol->tokenType == UA_USERTOKENTYPE_ANONYMOUS) { |
| 37793 | if(tokenDataType != &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) |
| 37794 | continue; |
| 37795 | } else if(pol->tokenType == UA_USERTOKENTYPE_USERNAME) { |
| 37796 | if(tokenDataType != &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) |
| 37797 | continue; |
| 37798 | } else if(pol->tokenType == UA_USERTOKENTYPE_CERTIFICATE) { |
| 37799 | if(tokenDataType != &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) |
| 37800 | continue; |
| 37801 | } else if(pol->tokenType == UA_USERTOKENTYPE_ISSUEDTOKEN) { |
| 37802 | if(tokenDataType != &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN]) |
| 37803 | continue; |
| 37804 | } else { |
| 37805 | continue; |
| 37806 | } |
| 37807 | |
| 37808 | /* All valid token data types start with a string policyId */ |
| 37809 | UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*) |
| 37810 | identityToken->content.decoded.data; |
| 37811 | |
| 37812 | /* Select the SecurityPolicy used to encrypt the token. |
| 37813 | * The default is to use the SecurityPolicy of the SecureChannel. */ |
| 37814 | *tokenSp = channel->securityPolicy; |
| 37815 | #ifdef UA_ENABLE_ENCRYPTION |
| 37816 | if(identPolicies == sc->accessControl.userTokenPolicies) { |
| 37817 | /* If the standard UserTokenPolicies from the AccessControl |
| 37818 | * plugin are used, use the same logic as in |
| 37819 | * updateEndpointUserIdentityToken (ua_services_discovery.c). */ |
| 37820 | if(pol->tokenType != UA_USERTOKENTYPE_ANONYMOUS && |
| 37821 | !(sc->allowNonePolicyPassword && pol->tokenType == UA_USERTOKENTYPE_USERNAME) && |
| 37822 | UA_String_equal(p1: &channel->securityPolicy->policyUri, p2: &UA_SECURITY_POLICY_NONE_URI)) |
| 37823 | *tokenSp = getDefaultEncryptedSecurityPolicy(server); |
| 37824 | } else if(pol->securityPolicyUri.length > 0) { |
| 37825 | /* Manually defined UserTokenPolicy. Lookup by URI */ |
| 37826 | *tokenSp = getSecurityPolicyByUri(server, securityPolicyUri: &pol->securityPolicyUri); |
| 37827 | } |
| 37828 | if(!*tokenSp) |
| 37829 | continue; |
| 37830 | |
| 37831 | /* Anonymous tokens don't need encryption. All other tokens require |
| 37832 | * encryption with the exception of Username/Password if also the |
| 37833 | * allowNonePolicyPassword option has been set. */ |
| 37834 | if(pol->tokenType != UA_USERTOKENTYPE_ANONYMOUS && |
| 37835 | !(sc->allowNonePolicyPassword && pol->tokenType == UA_USERTOKENTYPE_USERNAME) && |
| 37836 | UA_String_equal(p1: &UA_SECURITY_POLICY_NONE_URI, p2: &(*tokenSp)->policyUri)) |
| 37837 | continue; |
| 37838 | #endif |
| 37839 | |
| 37840 | /* In setCurrentEndPointsArray we prepend the PolicyId with the |
| 37841 | * SecurityMode of the endpoint and the postfix of the |
| 37842 | * SecurityPolicyUri to make it unique. Check the SecurityPolicyUri |
| 37843 | * postfix. */ |
| 37844 | if(pol->policyId.length > token->policyId.length) |
| 37845 | continue; |
| 37846 | UA_String policyPrefix = token->policyId; |
| 37847 | policyPrefix.length = pol->policyId.length; |
| 37848 | if(!UA_String_equal(p1: &policyPrefix, p2: &pol->policyId)) |
| 37849 | continue; |
| 37850 | |
| 37851 | UA_String secPolPostfix = securityPolicyUriPostfix(uri: (*tokenSp)->policyUri); |
| 37852 | UA_String utPolPostfix = securityPolicyUriPostfix(uri: token->policyId); |
| 37853 | if(!UA_String_equal(p1: &secPolPostfix, p2: &utPolPostfix)) |
| 37854 | continue; |
| 37855 | |
| 37856 | /* Match found */ |
| 37857 | *ed = desc; |
| 37858 | *utp = pol; |
| 37859 | return; |
| 37860 | } |
| 37861 | } |
| 37862 | } |
| 37863 | |
| 37864 | #ifdef UA_ENABLE_ENCRYPTION |
| 37865 | static UA_StatusCode |
| 37866 | decryptUserToken(UA_Server *server, UA_Session *session, |
| 37867 | UA_SecureChannel *channel, const UA_SecurityPolicy *sp, |
| 37868 | const UA_String encryptionAlgorithm, UA_String *encrypted) { |
| 37869 | /* If SecurityPolicy is None there shall be no EncryptionAlgorithm */ |
| 37870 | if(UA_String_equal(p1: &sp->policyUri, p2: &UA_SECURITY_POLICY_NONE_URI)) { |
| 37871 | if(encryptionAlgorithm.length > 0) |
| 37872 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 37873 | if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE) { |
| 37874 | UA_LOG_WARNING_SESSION(server->config.logging, session, "ActivateSession: " |
| 37875 | "Received an unencrypted UserToken. " |
| 37876 | "Is the server misconfigured to allow that?"); |
| 37877 | } |
| 37878 | return UA_STATUSCODE_GOOD; |
| 37879 | } |
| 37880 | |
| 37881 | /* Test if the correct encryption algorithm is used */ |
| 37882 | if(!UA_String_equal(p1: &encryptionAlgorithm, |
| 37883 | p2: &sp->asymmetricModule.cryptoModule.encryptionAlgorithm.uri)) |
| 37884 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 37885 | |
| 37886 | /* Encrypted password -- Create a temporary channel context. |
| 37887 | * TODO: We should not need a ChannelContext at all for asymmetric |
| 37888 | * decryption where the remote certificate is not used. */ |
| 37889 | void *tempChannelContext = NULL; |
| 37890 | UA_StatusCode res = sp->channelModule.newContext(sp, &sp->localCertificate, &tempChannelContext); |
| 37891 | if(res != UA_STATUSCODE_GOOD) { |
| 37892 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 37893 | "ActivateSession: Failed to create a " |
| 37894 | "context for the SecurityPolicy %.*s", |
| 37895 | (int)sp->policyUri.length, |
| 37896 | sp->policyUri.data); |
| 37897 | return res; |
| 37898 | } |
| 37899 | |
| 37900 | UA_UInt32 secretLen = 0; |
| 37901 | UA_ByteString secret, tokenNonce; |
| 37902 | size_t tokenpos = 0; |
| 37903 | size_t offset = 0; |
| 37904 | UA_ByteString *sn = &session->serverNonce; |
| 37905 | const UA_SecurityPolicyEncryptionAlgorithm *asymEnc = |
| 37906 | &sp->asymmetricModule.cryptoModule.encryptionAlgorithm; |
| 37907 | |
| 37908 | res = UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 37909 | |
| 37910 | /* Decrypt the secret */ |
| 37911 | if(UA_ByteString_copy(src: encrypted, dst: &secret) != UA_STATUSCODE_GOOD || |
| 37912 | asymEnc->decrypt(tempChannelContext, &secret) != UA_STATUSCODE_GOOD) |
| 37913 | goto cleanup; |
| 37914 | |
| 37915 | /* The secret starts with a UInt32 length for the content */ |
| 37916 | if(UA_UInt32_decodeBinary(src: &secret, offset: &offset, dst: &secretLen) != UA_STATUSCODE_GOOD) |
| 37917 | goto cleanup; |
| 37918 | |
| 37919 | /* The decrypted data must be large enough to include the Encrypted Token |
| 37920 | * Secret Format and the length field must indicate enough data to include |
| 37921 | * the server nonce. */ |
| 37922 | if(secret.length < sizeof(UA_UInt32) + sn->length || |
| 37923 | secret.length < sizeof(UA_UInt32) + secretLen || |
| 37924 | secretLen < sn->length) |
| 37925 | goto cleanup; |
| 37926 | |
| 37927 | /* If the Encrypted Token Secret contains padding, the padding must be |
| 37928 | * zeroes according to the 1.04.1 specification errata, chapter 3. */ |
| 37929 | for(size_t i = sizeof(UA_UInt32) + secretLen; i < secret.length; i++) { |
| 37930 | if(secret.data[i] != 0) |
| 37931 | goto cleanup; |
| 37932 | } |
| 37933 | |
| 37934 | /* The server nonce must match according to the 1.04.1 specification errata, |
| 37935 | * chapter 3. */ |
| 37936 | tokenpos = sizeof(UA_UInt32) + secretLen - sn->length; |
| 37937 | tokenNonce.length = sn->length; |
| 37938 | tokenNonce.data = &secret.data[tokenpos]; |
| 37939 | if(!UA_ByteString_equal(p1: sn, p2: &tokenNonce)) |
| 37940 | goto cleanup; |
| 37941 | |
| 37942 | /* The password was decrypted successfully. Replace usertoken with the |
| 37943 | * decrypted password. The encryptionAlgorithm and policyId fields are left |
| 37944 | * in the UserToken as an indication for the AccessControl plugin that |
| 37945 | * evaluates the decrypted content. */ |
| 37946 | memcpy(dest: encrypted->data, |
| 37947 | src: &secret.data[sizeof(UA_UInt32)], n: secretLen - sn->length); |
| 37948 | encrypted->length = secretLen - sn->length; |
| 37949 | res = UA_STATUSCODE_GOOD; |
| 37950 | |
| 37951 | cleanup: |
| 37952 | UA_ByteString_clear(p: &secret); |
| 37953 | |
| 37954 | /* Remove the temporary channel context */ |
| 37955 | sp->channelModule.deleteContext(tempChannelContext); |
| 37956 | |
| 37957 | if(res != UA_STATUSCODE_GOOD) { |
| 37958 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 37959 | "ActivateSession: Failed to decrypt the " |
| 37960 | "password with the StatusCode %s", |
| 37961 | UA_StatusCode_name(res)); |
| 37962 | } |
| 37963 | return res; |
| 37964 | } |
| 37965 | |
| 37966 | static UA_StatusCode |
| 37967 | checkActivateSessionX509(UA_Server *server, UA_Session *session, |
| 37968 | const UA_SecurityPolicy *sp, UA_X509IdentityToken* token, |
| 37969 | const UA_SignatureData *tokenSignature) { |
| 37970 | /* The SecurityPolicy must not be None for the signature */ |
| 37971 | if(UA_String_equal(p1: &sp->policyUri, p2: &UA_SECURITY_POLICY_NONE_URI)) |
| 37972 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 37973 | |
| 37974 | /* We need a channel context with the user certificate in order to reuse |
| 37975 | * the signature checking code. */ |
| 37976 | void *tempChannelContext; |
| 37977 | UA_StatusCode res = sp->channelModule. newContext(sp, &token->certificateData, &tempChannelContext); |
| 37978 | if(res != UA_STATUSCODE_GOOD) { |
| 37979 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 37980 | "ActivateSession: Failed to create a context " |
| 37981 | "for the SecurityPolicy %.*s", |
| 37982 | (int)sp->policyUri.length, |
| 37983 | sp->policyUri.data); |
| 37984 | return res; |
| 37985 | } |
| 37986 | |
| 37987 | /* Check the user token signature */ |
| 37988 | res = checkCertificateSignature(server, securityPolicy: sp, channelContext: tempChannelContext, |
| 37989 | serverNonce: &session->serverNonce, signature: tokenSignature, true); |
| 37990 | if(res != UA_STATUSCODE_GOOD) { |
| 37991 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 37992 | "ActivateSession: User token signature check " |
| 37993 | "failed with StatusCode %s", UA_StatusCode_name(res)); |
| 37994 | } |
| 37995 | |
| 37996 | /* Delete the temporary channel context */ |
| 37997 | sp->channelModule.deleteContext(tempChannelContext); |
| 37998 | return res; |
| 37999 | } |
| 38000 | #endif |
| 38001 | |
| 38002 | /* TODO: Check all of the following: The Server shall verify that the |
| 38003 | * Certificate the Client used to create the new SecureChannel is the same as |
| 38004 | * the Certificate used to create the original SecureChannel. In addition, the |
| 38005 | * Server shall verify that the Client supplied a UserIdentityToken that is |
| 38006 | * identical to the token currently associated with the Session. Once the Server |
| 38007 | * accepts the new SecureChannel it shall reject requests sent via the old |
| 38008 | * SecureChannel. */ |
| 38009 | |
| 38010 | void |
| 38011 | Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel, |
| 38012 | const UA_ActivateSessionRequest *req, |
| 38013 | UA_ActivateSessionResponse *resp) { |
| 38014 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38015 | const UA_EndpointDescription *ed = NULL; |
| 38016 | const UA_UserTokenPolicy *utp = NULL; |
| 38017 | const UA_SecurityPolicy *tokenSp = NULL; |
| 38018 | UA_String *tmpLocaleIds; |
| 38019 | |
| 38020 | /* Get the session */ |
| 38021 | UA_Session *session = getSessionByToken(server, token: &req->requestHeader.authenticationToken); |
| 38022 | if(!session) { |
| 38023 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 38024 | "ActivateSession: Session not found"); |
| 38025 | resp->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID; |
| 38026 | goto rejected; |
| 38027 | } |
| 38028 | |
| 38029 | /* Part 4, §5.6.3: When the ActivateSession Service is called for the |
| 38030 | * first time then the Server shall reject the request if the |
| 38031 | * SecureChannel is not same as the one associated with the |
| 38032 | * CreateSession request. Subsequent calls to ActivateSession may be |
| 38033 | * associated with different SecureChannels. */ |
| 38034 | if(!session->activated && session->header.channel != channel) { |
| 38035 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 38036 | "ActivateSession: The Session has to be initially activated " |
| 38037 | "on the SecureChannel that created it"); |
| 38038 | resp->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID; |
| 38039 | goto rejected; |
| 38040 | } |
| 38041 | |
| 38042 | /* Has the session timed out? */ |
| 38043 | if(session->validTill < UA_DateTime_nowMonotonic()) { |
| 38044 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 38045 | "ActivateSession: The Session has timed out"); |
| 38046 | resp->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID; |
| 38047 | goto rejected; |
| 38048 | } |
| 38049 | |
| 38050 | /* Check the client signature */ |
| 38051 | if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 38052 | channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 38053 | resp->responseHeader.serviceResult = |
| 38054 | checkCertificateSignature(server, securityPolicy: channel->securityPolicy, |
| 38055 | channelContext: channel->channelContext, |
| 38056 | serverNonce: &session->serverNonce, |
| 38057 | signature: &req->clientSignature, false); |
| 38058 | if(resp->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 38059 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 38060 | "ActivateSession: Client signature check failed " |
| 38061 | "with StatusCode %s", |
| 38062 | UA_StatusCode_name(resp->responseHeader.serviceResult)); |
| 38063 | goto securityRejected; |
| 38064 | } |
| 38065 | } |
| 38066 | |
| 38067 | /* Find the matching Endpoint with UserTokenPolicy. |
| 38068 | * Also sets the SecurityPolicy used to encrypt the token. */ |
| 38069 | selectEndpointAndTokenPolicy(server, channel, identityToken: &req->userIdentityToken, |
| 38070 | ed: &ed, utp: &utp, tokenSp: &tokenSp); |
| 38071 | if(!ed || !tokenSp) { |
| 38072 | resp->responseHeader.serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 38073 | goto rejected; |
| 38074 | } |
| 38075 | |
| 38076 | /* Decrypt (or validate the signature) of the UserToken. The DataType of the |
| 38077 | * UserToken was already checked in selectEndpointAndTokenPolicy */ |
| 38078 | #ifdef UA_ENABLE_ENCRYPTION |
| 38079 | if(utp->tokenType == UA_USERTOKENTYPE_USERNAME) { |
| 38080 | /* If it is a UserNameIdentityToken, the password may be encrypted */ |
| 38081 | UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken *) |
| 38082 | req->userIdentityToken.content.decoded.data; |
| 38083 | resp->responseHeader.serviceResult = |
| 38084 | decryptUserToken(server, session, channel, sp: tokenSp, |
| 38085 | encryptionAlgorithm: userToken->encryptionAlgorithm, encrypted: &userToken->password); |
| 38086 | } else if(utp->tokenType == UA_USERTOKENTYPE_CERTIFICATE) { |
| 38087 | /* If it is a X509IdentityToken, check the userTokenSignature. Note this |
| 38088 | * only validates that the user has the corresponding private key for |
| 38089 | * the given user certificate. Checking whether the user certificate is |
| 38090 | * trusted has to be implemented in the access control plugin. The |
| 38091 | * entire token is forwarded in the call to ActivateSession. */ |
| 38092 | UA_X509IdentityToken* x509token = (UA_X509IdentityToken*) |
| 38093 | req->userIdentityToken.content.decoded.data; |
| 38094 | resp->responseHeader.serviceResult = |
| 38095 | checkActivateSessionX509(server, session, sp: tokenSp, |
| 38096 | token: x509token, tokenSignature: &req->userTokenSignature); |
| 38097 | } else if(utp->tokenType == UA_USERTOKENTYPE_ISSUEDTOKEN) { |
| 38098 | /* IssuedTokens are encrypted */ |
| 38099 | UA_IssuedIdentityToken *issuedToken = (UA_IssuedIdentityToken*) |
| 38100 | req->userIdentityToken.content.decoded.data; |
| 38101 | resp->responseHeader.serviceResult = decryptUserToken( |
| 38102 | server, session, channel, sp: tokenSp, encryptionAlgorithm: issuedToken->encryptionAlgorithm, |
| 38103 | encrypted: &issuedToken->tokenData); |
| 38104 | } /* else Anonymous */ |
| 38105 | if(resp->responseHeader.serviceResult != UA_STATUSCODE_GOOD) |
| 38106 | goto securityRejected; |
| 38107 | #endif |
| 38108 | |
| 38109 | /* Callback into userland access control */ |
| 38110 | resp->responseHeader.serviceResult = server->config.accessControl. |
| 38111 | activateSession(server, &server->config.accessControl, ed, |
| 38112 | &channel->remoteCertificate, &session->sessionId, |
| 38113 | &req->userIdentityToken, &session->sessionHandle); |
| 38114 | if(resp->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 38115 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 38116 | "ActivateSession: The AccessControl " |
| 38117 | "plugin denied the activation with the StatusCode %s", |
| 38118 | UA_StatusCode_name(resp->responseHeader.serviceResult)); |
| 38119 | goto securityRejected; |
| 38120 | } |
| 38121 | |
| 38122 | /* Attach the session to the currently used channel if the session isn't |
| 38123 | * attached to a channel or if the session is activated on a different |
| 38124 | * channel than it is attached to. */ |
| 38125 | if(!session->header.channel || session->header.channel != channel) { |
| 38126 | /* Attach the new SecureChannel, the old channel will be detached if present */ |
| 38127 | UA_Session_attachToSecureChannel(session, channel); |
| 38128 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 38129 | "ActivateSession: Session attached to new channel"); |
| 38130 | } |
| 38131 | |
| 38132 | /* Generate a new session nonce for the next time ActivateSession is called */ |
| 38133 | resp->responseHeader.serviceResult = UA_Session_generateNonce(session); |
| 38134 | resp->responseHeader.serviceResult |= |
| 38135 | UA_ByteString_copy(src: &session->serverNonce, dst: &resp->serverNonce); |
| 38136 | if(resp->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 38137 | UA_Session_detachFromSecureChannel(session); |
| 38138 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 38139 | "ActivateSession: Could not generate the server nonce"); |
| 38140 | goto rejected; |
| 38141 | } |
| 38142 | |
| 38143 | /* Set the Locale */ |
| 38144 | if(req->localeIdsSize > 0) { |
| 38145 | /* Part 4, §5.6.3.2: This parameter only needs to be specified during |
| 38146 | * the first call to ActivateSession during a single application |
| 38147 | * Session. If it is not specified the Server shall keep using the |
| 38148 | * current localeIds for the Session. */ |
| 38149 | resp->responseHeader.serviceResult |= |
| 38150 | UA_Array_copy(src: req->localeIds, size: req->localeIdsSize, |
| 38151 | dst: (void**)&tmpLocaleIds, type: &UA_TYPES[UA_TYPES_STRING]); |
| 38152 | if(resp->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 38153 | UA_Session_detachFromSecureChannel(session); |
| 38154 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 38155 | "ActivateSession: Could not store the Session LocaleIds"); |
| 38156 | goto rejected; |
| 38157 | } |
| 38158 | UA_Array_delete(p: session->localeIds, size: session->localeIdsSize, |
| 38159 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 38160 | session->localeIds = tmpLocaleIds; |
| 38161 | session->localeIdsSize = req->localeIdsSize; |
| 38162 | } |
| 38163 | |
| 38164 | /* Update the Session lifetime */ |
| 38165 | UA_Session_updateLifetime(session); |
| 38166 | |
| 38167 | /* Activate the session */ |
| 38168 | if(!session->activated) { |
| 38169 | session->activated = true; |
| 38170 | server->activeSessionCount++; |
| 38171 | server->serverDiagnosticsSummary.cumulatedSessionCount++; |
| 38172 | } |
| 38173 | |
| 38174 | /* Store the ClientUserId. tokenType can be NULL for the anonymous user. */ |
| 38175 | UA_String_clear(p: &session->clientUserIdOfSession); |
| 38176 | const UA_DataType *tokenType = req->userIdentityToken.content.decoded.type; |
| 38177 | if(tokenType == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) { |
| 38178 | const UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken*) |
| 38179 | req->userIdentityToken.content.decoded.data; |
| 38180 | UA_String_copy(src: &userToken->userName, dst: &session->clientUserIdOfSession); |
| 38181 | } else if(tokenType == &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) { |
| 38182 | UA_X509IdentityToken* userCertToken = (UA_X509IdentityToken*) |
| 38183 | req->userIdentityToken.content.decoded.data; |
| 38184 | if(server->config.sessionPKI.getSubjectName) |
| 38185 | server->config.sessionPKI. |
| 38186 | getSubjectName(&session->clientUserIdOfSession, |
| 38187 | &userCertToken->certificateData); |
| 38188 | } else { |
| 38189 | /* TODO: Handle issued token */ |
| 38190 | } |
| 38191 | |
| 38192 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 38193 | /* Add the ClientUserId to the diagnostics history */ |
| 38194 | UA_SessionSecurityDiagnosticsDataType *ssd = &session->securityDiagnostics; |
| 38195 | UA_StatusCode res = |
| 38196 | UA_Array_appendCopy(p: (void**)&ssd->clientUserIdHistory, |
| 38197 | size: &ssd->clientUserIdHistorySize, |
| 38198 | newElem: &ssd->clientUserIdOfSession, |
| 38199 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 38200 | (void)res; |
| 38201 | |
| 38202 | /* Store the auth mechanism */ |
| 38203 | UA_String_clear(p: &ssd->authenticationMechanism); |
| 38204 | switch(utp->tokenType) { |
| 38205 | case UA_USERTOKENTYPE_ANONYMOUS: |
| 38206 | ssd->authenticationMechanism = UA_STRING_ALLOC("Anonymous"); break; |
| 38207 | case UA_USERTOKENTYPE_USERNAME: |
| 38208 | ssd->authenticationMechanism = UA_STRING_ALLOC("UserName"); break; |
| 38209 | case UA_USERTOKENTYPE_CERTIFICATE: |
| 38210 | ssd->authenticationMechanism = UA_STRING_ALLOC("Certificate"); break; |
| 38211 | case UA_USERTOKENTYPE_ISSUEDTOKEN: |
| 38212 | ssd->authenticationMechanism = UA_STRING_ALLOC("IssuedToken"); break; |
| 38213 | default: break; |
| 38214 | } |
| 38215 | #endif |
| 38216 | |
| 38217 | /* Log the user for which the Session was activated */ |
| 38218 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 38219 | "ActivateSession: Session activated with ClientUserId \"%.*s\"", |
| 38220 | (int)session->clientUserIdOfSession.length, |
| 38221 | session->clientUserIdOfSession.data); |
| 38222 | return; |
| 38223 | |
| 38224 | securityRejected: |
| 38225 | server->serverDiagnosticsSummary.securityRejectedSessionCount++; |
| 38226 | rejected: |
| 38227 | server->serverDiagnosticsSummary.rejectedSessionCount++; |
| 38228 | } |
| 38229 | |
| 38230 | void |
| 38231 | Service_CloseSession(UA_Server *server, UA_SecureChannel *channel, |
| 38232 | const UA_CloseSessionRequest *request, |
| 38233 | UA_CloseSessionResponse *response) { |
| 38234 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38235 | |
| 38236 | /* Part 4, 5.6.4: When the CloseSession Service is called before the Session |
| 38237 | * is successfully activated, the Server shall reject the request if the |
| 38238 | * SecureChannel is not the same as the one associated with the |
| 38239 | * CreateSession request. |
| 38240 | * |
| 38241 | * A non-activated Session is already bound to the SecureChannel that |
| 38242 | * created the Session. */ |
| 38243 | UA_Session *session = NULL; |
| 38244 | response->responseHeader.serviceResult = |
| 38245 | getBoundSession(server, channel, token: &request->requestHeader.authenticationToken, session: &session); |
| 38246 | if(!session && response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) |
| 38247 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID; |
| 38248 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 38249 | UA_LOG_WARNING_CHANNEL(server->config.logging, channel, |
| 38250 | "CloseSession: No Session activated to the SecureChannel"); |
| 38251 | return; |
| 38252 | } |
| 38253 | |
| 38254 | UA_assert(session); /* Assured by the previous section */ |
| 38255 | UA_LOG_INFO_SESSION(server->config.logging, session, "Closing the Session"); |
| 38256 | |
| 38257 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 38258 | /* If Subscriptions are not deleted, detach them from the Session */ |
| 38259 | if(!request->deleteSubscriptions) { |
| 38260 | UA_Subscription *sub, *sub_tmp; |
| 38261 | TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, sub_tmp) { |
| 38262 | UA_LOG_INFO_SUBSCRIPTION(server->config.logging, sub, |
| 38263 | "Detaching the Subscription from the Session"); |
| 38264 | UA_Session_detachSubscription(server, session, sub, true); |
| 38265 | } |
| 38266 | } |
| 38267 | #endif |
| 38268 | |
| 38269 | /* Remove the sesison */ |
| 38270 | response->responseHeader.serviceResult = |
| 38271 | UA_Server_removeSessionByToken(server, token: &session->header.authenticationToken, |
| 38272 | shutdownReason: UA_SHUTDOWNREASON_CLOSE); |
| 38273 | } |
| 38274 | |
| 38275 | void Service_Cancel(UA_Server *server, UA_Session *session, |
| 38276 | const UA_CancelRequest *request, |
| 38277 | UA_CancelResponse *response) { |
| 38278 | /* If multithreading is disabled, then there are no async services. If all |
| 38279 | * services are answered "right away", then there are no services that can |
| 38280 | * be cancelled. */ |
| 38281 | #if UA_MULTITHREADING >= 100 |
| 38282 | response->cancelCount = UA_AsyncManager_cancel(server, session, request->requestHandle); |
| 38283 | #endif |
| 38284 | |
| 38285 | /* Publish requests for Subscriptions are stored separately */ |
| 38286 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 38287 | UA_PublishResponseEntry *pre, *pre_tmp; |
| 38288 | UA_PublishResponseEntry *prev = NULL; |
| 38289 | SIMPLEQ_FOREACH_SAFE(pre, &session->responseQueue, listEntry, pre_tmp) { |
| 38290 | /* Skip entry and set as the previous entry that is kept in the list */ |
| 38291 | if(pre->response.responseHeader.requestHandle != request->requestHandle) { |
| 38292 | prev = pre; |
| 38293 | continue; |
| 38294 | } |
| 38295 | |
| 38296 | /* Dequeue */ |
| 38297 | if(prev) |
| 38298 | SIMPLEQ_REMOVE_AFTER(&session->responseQueue, prev, listEntry); |
| 38299 | else |
| 38300 | SIMPLEQ_REMOVE_HEAD(&session->responseQueue, listEntry); |
| 38301 | session->responseQueueSize--; |
| 38302 | |
| 38303 | /* Send response and clean up */ |
| 38304 | response->responseHeader.serviceResult = UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT; |
| 38305 | sendResponse(server, session, channel: session->header.channel, requestId: pre->requestId, |
| 38306 | response: (UA_Response *)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]); |
| 38307 | UA_PublishResponse_clear(p: &pre->response); |
| 38308 | UA_free(ptr: pre); |
| 38309 | |
| 38310 | /* Increase the CancelCount */ |
| 38311 | response->cancelCount++; |
| 38312 | } |
| 38313 | #endif |
| 38314 | } |
| 38315 | |
| 38316 | /**** amalgamated original file "/src/server/ua_services_attribute.c" ****/ |
| 38317 | |
| 38318 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 38319 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 38320 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 38321 | * |
| 38322 | * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 38323 | * Copyright 2015-2016 (c) Sten Grüner |
| 38324 | * Copyright 2014-2017 (c) Florian Palm |
| 38325 | * Copyright 2015 (c) Christian Fimmers |
| 38326 | * Copyright 2015-2016 (c) Chris Iatrou |
| 38327 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 38328 | * Copyright 2015 (c) wuyangtang |
| 38329 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 38330 | * Copyright 2016 (c) Lorenz Haas |
| 38331 | * Copyright 2017 (c) frax2222 |
| 38332 | * Copyright 2017 (c) Thomas Bender |
| 38333 | * Copyright 2017 (c) Julian Grothoff |
| 38334 | * Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 38335 | * Copyright 2017 (c) Henrik Norrman |
| 38336 | * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 38337 | */ |
| 38338 | |
| 38339 | |
| 38340 | #ifdef UA_ENABLE_HISTORIZING |
| 38341 | #endif |
| 38342 | |
| 38343 | static const UA_NodeAttributesMask attr2mask[28] = { |
| 38344 | UA_NODEATTRIBUTESMASK_NODEID, |
| 38345 | UA_NODEATTRIBUTESMASK_NODECLASS, |
| 38346 | UA_NODEATTRIBUTESMASK_BROWSENAME, |
| 38347 | UA_NODEATTRIBUTESMASK_DISPLAYNAME, |
| 38348 | UA_NODEATTRIBUTESMASK_DESCRIPTION, |
| 38349 | UA_NODEATTRIBUTESMASK_WRITEMASK, |
| 38350 | UA_NODEATTRIBUTESMASK_USERWRITEMASK, |
| 38351 | UA_NODEATTRIBUTESMASK_ISABSTRACT, |
| 38352 | UA_NODEATTRIBUTESMASK_SYMMETRIC, |
| 38353 | UA_NODEATTRIBUTESMASK_INVERSENAME, |
| 38354 | UA_NODEATTRIBUTESMASK_CONTAINSNOLOOPS, |
| 38355 | UA_NODEATTRIBUTESMASK_EVENTNOTIFIER, |
| 38356 | UA_NODEATTRIBUTESMASK_VALUE, |
| 38357 | UA_NODEATTRIBUTESMASK_DATATYPE, |
| 38358 | UA_NODEATTRIBUTESMASK_VALUERANK, |
| 38359 | UA_NODEATTRIBUTESMASK_ARRAYDIMENSIONS, |
| 38360 | UA_NODEATTRIBUTESMASK_ACCESSLEVEL, |
| 38361 | UA_NODEATTRIBUTESMASK_USERACCESSLEVEL, |
| 38362 | UA_NODEATTRIBUTESMASK_MINIMUMSAMPLINGINTERVAL, |
| 38363 | UA_NODEATTRIBUTESMASK_HISTORIZING, |
| 38364 | UA_NODEATTRIBUTESMASK_EXECUTABLE, |
| 38365 | UA_NODEATTRIBUTESMASK_USEREXECUTABLE, |
| 38366 | UA_NODEATTRIBUTESMASK_DATATYPEDEFINITION, |
| 38367 | UA_NODEATTRIBUTESMASK_ROLEPERMISSIONS, |
| 38368 | UA_NODEATTRIBUTESMASK_ROLEPERMISSIONS, |
| 38369 | UA_NODEATTRIBUTESMASK_ACCESSRESTRICTIONS, |
| 38370 | UA_NODEATTRIBUTESMASK_ACCESSLEVEL |
| 38371 | }; |
| 38372 | |
| 38373 | static UA_UInt32 |
| 38374 | attributeId2AttributeMask(UA_AttributeId id) { |
| 38375 | if(UA_UNLIKELY(id > UA_ATTRIBUTEID_ACCESSLEVELEX)) |
| 38376 | return UA_NODEATTRIBUTESMASK_NONE; |
| 38377 | return attr2mask[id]; |
| 38378 | } |
| 38379 | |
| 38380 | /******************/ |
| 38381 | /* Access Control */ |
| 38382 | /******************/ |
| 38383 | |
| 38384 | /* Session for read operations can be NULL. For example for a MonitoredItem |
| 38385 | * where the underlying Subscription was detached during CloseSession. */ |
| 38386 | |
| 38387 | static UA_UInt32 |
| 38388 | getUserWriteMask(UA_Server *server, const UA_Session *session, |
| 38389 | const UA_NodeHead *head) { |
| 38390 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38391 | if(session == &server->adminSession) |
| 38392 | return 0xFFFFFFFF; /* the local admin user has all rights */ |
| 38393 | return head->writeMask & server->config.accessControl. |
| 38394 | getUserRightsMask(server, &server->config.accessControl, |
| 38395 | session ? &session->sessionId : NULL, |
| 38396 | session ? session->sessionHandle : NULL, |
| 38397 | &head->nodeId, head->context); |
| 38398 | } |
| 38399 | |
| 38400 | static UA_Byte |
| 38401 | getAccessLevel(UA_Server *server, const UA_Session *session, |
| 38402 | const UA_VariableNode *node) { |
| 38403 | if(session == &server->adminSession) |
| 38404 | return 0xFF; /* the local admin user has all rights */ |
| 38405 | return node->accessLevel; |
| 38406 | } |
| 38407 | |
| 38408 | static UA_Byte |
| 38409 | getUserAccessLevel(UA_Server *server, const UA_Session *session, |
| 38410 | const UA_VariableNode *node) { |
| 38411 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38412 | if(session == &server->adminSession) |
| 38413 | return 0xFF; /* the local admin user has all rights */ |
| 38414 | return node->accessLevel & server->config.accessControl. |
| 38415 | getUserAccessLevel(server, &server->config.accessControl, |
| 38416 | session ? &session->sessionId : NULL, |
| 38417 | session ? session->sessionHandle : NULL, |
| 38418 | &node->head.nodeId, node->head.context); |
| 38419 | } |
| 38420 | |
| 38421 | static UA_Boolean |
| 38422 | getUserExecutable(UA_Server *server, const UA_Session *session, |
| 38423 | const UA_MethodNode *node) { |
| 38424 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38425 | if(session == &server->adminSession) |
| 38426 | return true; /* the local admin user has all rights */ |
| 38427 | return node->executable & server->config.accessControl. |
| 38428 | getUserExecutable(server, &server->config.accessControl, |
| 38429 | session ? &session->sessionId : NULL, |
| 38430 | session ? session->sessionHandle : NULL, |
| 38431 | &node->head.nodeId, node->head.context); |
| 38432 | } |
| 38433 | |
| 38434 | /****************/ |
| 38435 | /* Read Service */ |
| 38436 | /****************/ |
| 38437 | |
| 38438 | static UA_StatusCode |
| 38439 | readIsAbstractAttribute(const UA_Node *node, UA_Variant *v) { |
| 38440 | const UA_Boolean *isAbstract; |
| 38441 | switch(node->head.nodeClass) { |
| 38442 | case UA_NODECLASS_REFERENCETYPE: |
| 38443 | isAbstract = &node->referenceTypeNode.isAbstract; |
| 38444 | break; |
| 38445 | case UA_NODECLASS_OBJECTTYPE: |
| 38446 | isAbstract = &node->objectTypeNode.isAbstract; |
| 38447 | break; |
| 38448 | case UA_NODECLASS_VARIABLETYPE: |
| 38449 | isAbstract = &node->variableTypeNode.isAbstract; |
| 38450 | break; |
| 38451 | case UA_NODECLASS_DATATYPE: |
| 38452 | isAbstract = &node->dataTypeNode.isAbstract; |
| 38453 | break; |
| 38454 | default: |
| 38455 | return UA_STATUSCODE_BADATTRIBUTEIDINVALID; |
| 38456 | } |
| 38457 | |
| 38458 | return UA_Variant_setScalarCopy(v, p: isAbstract, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 38459 | } |
| 38460 | |
| 38461 | static UA_StatusCode |
| 38462 | readValueAttributeFromNode(UA_Server *server, UA_Session *session, |
| 38463 | const UA_VariableNode *vn, UA_DataValue *v, |
| 38464 | UA_NumericRange *rangeptr) { |
| 38465 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38466 | /* Update the value by the user callback */ |
| 38467 | if(vn->value.data.callback.onRead) { |
| 38468 | vn->value.data.callback.onRead(server, |
| 38469 | session ? &session->sessionId : NULL, |
| 38470 | session ? session->sessionHandle : NULL, |
| 38471 | &vn->head.nodeId, vn->head.context, rangeptr, |
| 38472 | &vn->value.data.value); |
| 38473 | vn = (const UA_VariableNode*) |
| 38474 | UA_NODESTORE_GET_SELECTIVE(server, &vn->head.nodeId, |
| 38475 | UA_NODEATTRIBUTESMASK_VALUE, |
| 38476 | UA_REFERENCETYPESET_NONE, |
| 38477 | UA_BROWSEDIRECTION_INVALID); |
| 38478 | if(!vn) |
| 38479 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 38480 | } |
| 38481 | |
| 38482 | /* Set the result */ |
| 38483 | UA_StatusCode retval; |
| 38484 | if(!rangeptr) { |
| 38485 | retval = UA_DataValue_copy(src: &vn->value.data.value, dst: v); |
| 38486 | } else { |
| 38487 | *v = vn->value.data.value; /* Copy timestamps */ |
| 38488 | UA_Variant_init(p: &v->value); |
| 38489 | retval = UA_Variant_copyRange(src: &vn->value.data.value.value, dst: &v->value, range: *rangeptr); |
| 38490 | } |
| 38491 | |
| 38492 | /* Clean up */ |
| 38493 | if(vn->value.data.callback.onRead) |
| 38494 | UA_NODESTORE_RELEASE(server, (const UA_Node *)vn); |
| 38495 | return retval; |
| 38496 | } |
| 38497 | |
| 38498 | static UA_StatusCode |
| 38499 | readValueAttributeFromDataSource(UA_Server *server, UA_Session *session, |
| 38500 | const UA_VariableNode *vn, UA_DataValue *v, |
| 38501 | UA_TimestampsToReturn timestamps, |
| 38502 | UA_NumericRange *rangeptr) { |
| 38503 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38504 | if(!vn->value.dataSource.read) |
| 38505 | return UA_STATUSCODE_BADINTERNALERROR; |
| 38506 | UA_Boolean sourceTimeStamp = (timestamps == UA_TIMESTAMPSTORETURN_SOURCE || |
| 38507 | timestamps == UA_TIMESTAMPSTORETURN_BOTH); |
| 38508 | UA_DataValue v2; |
| 38509 | UA_DataValue_init(p: &v2); |
| 38510 | UA_StatusCode retval = vn->value.dataSource. |
| 38511 | read(server, |
| 38512 | session ? &session->sessionId : NULL, |
| 38513 | session ? session->sessionHandle : NULL, |
| 38514 | &vn->head.nodeId, vn->head.context, |
| 38515 | sourceTimeStamp, rangeptr, &v2); |
| 38516 | if(v2.hasValue && v2.value.storageType == UA_VARIANT_DATA_NODELETE) { |
| 38517 | retval = UA_DataValue_copy(src: &v2, dst: v); |
| 38518 | UA_DataValue_clear(p: &v2); |
| 38519 | } else { |
| 38520 | *v = v2; |
| 38521 | } |
| 38522 | return retval; |
| 38523 | } |
| 38524 | |
| 38525 | static UA_StatusCode |
| 38526 | readValueAttributeComplete(UA_Server *server, UA_Session *session, |
| 38527 | const UA_VariableNode *vn, UA_TimestampsToReturn timestamps, |
| 38528 | const UA_String *indexRange, UA_DataValue *v) { |
| 38529 | /* Compute the index range */ |
| 38530 | UA_NumericRange range; |
| 38531 | UA_NumericRange *rangeptr = NULL; |
| 38532 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 38533 | if(indexRange && indexRange->length > 0) { |
| 38534 | retval = UA_NumericRange_parse(range: &range, str: *indexRange); |
| 38535 | if(retval != UA_STATUSCODE_GOOD) |
| 38536 | return retval; |
| 38537 | rangeptr = ⦥ |
| 38538 | } |
| 38539 | |
| 38540 | switch(vn->valueBackend.backendType) { |
| 38541 | case UA_VALUEBACKENDTYPE_INTERNAL: |
| 38542 | retval = readValueAttributeFromNode(server, session, vn, v, rangeptr); |
| 38543 | //TODO change old structure to value backend |
| 38544 | break; |
| 38545 | case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK: |
| 38546 | retval = readValueAttributeFromDataSource(server, session, vn, v, |
| 38547 | timestamps, rangeptr); |
| 38548 | //TODO change old structure to value backend |
| 38549 | break; |
| 38550 | case UA_VALUEBACKENDTYPE_EXTERNAL: |
| 38551 | if(!vn->valueBackend.backend.external.callback.notificationRead) { |
| 38552 | retval = UA_STATUSCODE_BADNOTREADABLE; |
| 38553 | break; |
| 38554 | } |
| 38555 | retval = vn->valueBackend.backend.external.callback. |
| 38556 | notificationRead(server, |
| 38557 | session ? &session->sessionId : NULL, |
| 38558 | session ? session->sessionHandle : NULL, |
| 38559 | &vn->head.nodeId, vn->head.context, rangeptr); |
| 38560 | if(retval != UA_STATUSCODE_GOOD) |
| 38561 | break; |
| 38562 | |
| 38563 | /* Set the result */ |
| 38564 | if(rangeptr) |
| 38565 | retval = UA_DataValue_copyVariantRange( |
| 38566 | src: *vn->valueBackend.backend.external.value, dst: v, range: *rangeptr); |
| 38567 | else |
| 38568 | retval = UA_DataValue_copy(src: *vn->valueBackend.backend.external.value, dst: v); |
| 38569 | break; |
| 38570 | case UA_VALUEBACKENDTYPE_NONE: |
| 38571 | /* Read the value */ |
| 38572 | if(vn->valueSource == UA_VALUESOURCE_DATA) |
| 38573 | retval = readValueAttributeFromNode(server, session, vn, v, rangeptr); |
| 38574 | else |
| 38575 | retval = readValueAttributeFromDataSource(server, session, vn, v, |
| 38576 | timestamps, rangeptr); |
| 38577 | /* end lagacy */ |
| 38578 | break; |
| 38579 | } |
| 38580 | |
| 38581 | /* If not defined return a source timestamp of "now". |
| 38582 | * Static nodes always have the current time as source-time. */ |
| 38583 | if(!v->hasSourceTimestamp) { |
| 38584 | v->sourceTimestamp = UA_DateTime_now(); |
| 38585 | v->hasSourceTimestamp = true; |
| 38586 | } |
| 38587 | |
| 38588 | /* Clean up */ |
| 38589 | if(rangeptr) |
| 38590 | UA_free(ptr: range.dimensions); |
| 38591 | return retval; |
| 38592 | } |
| 38593 | |
| 38594 | UA_StatusCode |
| 38595 | readValueAttribute(UA_Server *server, UA_Session *session, |
| 38596 | const UA_VariableNode *vn, UA_DataValue *v) { |
| 38597 | return readValueAttributeComplete(server, session, vn, |
| 38598 | timestamps: UA_TIMESTAMPSTORETURN_NEITHER, NULL, v); |
| 38599 | } |
| 38600 | |
| 38601 | static const UA_String binEncoding = {sizeof("Default Binary")-1, (UA_Byte*) "Default Binary"}; |
| 38602 | static const UA_String xmlEncoding = {sizeof("Default XML")-1, (UA_Byte*) "Default XML"}; |
| 38603 | static const UA_String jsonEncoding = {sizeof("Default JSON")-1, (UA_Byte*) "Default JSON"}; |
| 38604 | |
| 38605 | #define CHECK_NODECLASS(CLASS) \ |
| 38606 | if(!(node->head.nodeClass & (CLASS))) { \ |
| 38607 | retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; \ |
| 38608 | break; \ |
| 38609 | } |
| 38610 | |
| 38611 | #ifdef UA_ENABLE_TYPEDESCRIPTION |
| 38612 | static const UA_DataType * |
| 38613 | findDataType(const UA_Node *node, const UA_DataTypeArray *customTypes) { |
| 38614 | for(size_t i = 0; i < UA_TYPES_COUNT; ++i) { |
| 38615 | if(UA_NodeId_equal(p1: &UA_TYPES[i].typeId, p2: &node->head.nodeId)) { |
| 38616 | return &UA_TYPES[i]; |
| 38617 | } |
| 38618 | } |
| 38619 | |
| 38620 | // lookup custom type |
| 38621 | while(customTypes) { |
| 38622 | for(size_t i = 0; i < customTypes->typesSize; ++i) { |
| 38623 | if(UA_NodeId_equal(p1: &customTypes->types[i].typeId, p2: &node->head.nodeId)) |
| 38624 | return &customTypes->types[i]; |
| 38625 | } |
| 38626 | customTypes = customTypes->next; |
| 38627 | } |
| 38628 | return NULL; |
| 38629 | } |
| 38630 | |
| 38631 | static UA_StatusCode |
| 38632 | getStructureDefinition(const UA_DataType *type, UA_StructureDefinition *def) { |
| 38633 | UA_StatusCode retval = |
| 38634 | UA_NodeId_copy(src: &type->binaryEncodingId, dst: &def->defaultEncodingId); |
| 38635 | if(retval != UA_STATUSCODE_GOOD) |
| 38636 | return retval; |
| 38637 | switch(type->typeKind) { |
| 38638 | case UA_DATATYPEKIND_STRUCTURE: |
| 38639 | def->structureType = UA_STRUCTURETYPE_STRUCTURE; |
| 38640 | def->baseDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_STRUCTURE); |
| 38641 | break; |
| 38642 | case UA_DATATYPEKIND_OPTSTRUCT: |
| 38643 | def->structureType = UA_STRUCTURETYPE_STRUCTUREWITHOPTIONALFIELDS; |
| 38644 | def->baseDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_STRUCTURE); |
| 38645 | break; |
| 38646 | case UA_DATATYPEKIND_UNION: |
| 38647 | def->structureType = UA_STRUCTURETYPE_UNION; |
| 38648 | def->baseDataType = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_UNION); |
| 38649 | break; |
| 38650 | default: |
| 38651 | return UA_STATUSCODE_BADENCODINGERROR; |
| 38652 | } |
| 38653 | def->fieldsSize = type->membersSize; |
| 38654 | def->fields = (UA_StructureField *) |
| 38655 | UA_calloc(nmemb: def->fieldsSize, size: sizeof(UA_StructureField)); |
| 38656 | if(!def->fields) { |
| 38657 | UA_NodeId_clear(p: &def->defaultEncodingId); |
| 38658 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 38659 | } |
| 38660 | |
| 38661 | for(size_t cnt = 0; cnt < def->fieldsSize; cnt++) { |
| 38662 | const UA_DataTypeMember *m = &type->members[cnt]; |
| 38663 | def->fields[cnt].valueRank = (m->isArray) ? UA_VALUERANK_ONE_DIMENSION : UA_VALUERANK_SCALAR; |
| 38664 | def->fields[cnt].arrayDimensions = NULL; |
| 38665 | def->fields[cnt].arrayDimensionsSize = 0; |
| 38666 | def->fields[cnt].name = UA_STRING(chars: (char *)(uintptr_t)m->memberName); |
| 38667 | def->fields[cnt].description.locale = UA_STRING_NULL; |
| 38668 | def->fields[cnt].description.text = UA_STRING_NULL; |
| 38669 | def->fields[cnt].dataType = m->memberType->typeId; |
| 38670 | def->fields[cnt].maxStringLength = 0; |
| 38671 | def->fields[cnt].isOptional = m->isOptional; |
| 38672 | } |
| 38673 | return UA_STATUSCODE_GOOD; |
| 38674 | } |
| 38675 | #endif |
| 38676 | |
| 38677 | /* Returns a datavalue that may point into the node via the |
| 38678 | * UA_VARIANT_DATA_NODELETE tag. Don't access the returned DataValue once the |
| 38679 | * node has been released! */ |
| 38680 | void |
| 38681 | ReadWithNode(const UA_Node *node, UA_Server *server, UA_Session *session, |
| 38682 | UA_TimestampsToReturn timestampsToReturn, |
| 38683 | const UA_ReadValueId *id, UA_DataValue *v) { |
| 38684 | UA_LOG_NODEID_TRACE(&node->head.nodeId, |
| 38685 | UA_LOG_TRACE_SESSION(server->config.logging, session, |
| 38686 | "Read attribute %"PRIi32 " of Node %.*s", |
| 38687 | id->attributeId, (int)nodeIdStr.length, |
| 38688 | nodeIdStr.data)); |
| 38689 | |
| 38690 | /* Only Binary Encoding is supported */ |
| 38691 | if(id->dataEncoding.name.length > 0 && |
| 38692 | !UA_String_equal(p1: &binEncoding, p2: &id->dataEncoding.name)) { |
| 38693 | if(UA_String_equal(p1: &xmlEncoding, p2: &id->dataEncoding.name) || |
| 38694 | UA_String_equal(p1: &jsonEncoding, p2: &id->dataEncoding.name)) |
| 38695 | v->status = UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED; |
| 38696 | else |
| 38697 | v->status = UA_STATUSCODE_BADDATAENCODINGINVALID; |
| 38698 | v->hasStatus = true; |
| 38699 | return; |
| 38700 | } |
| 38701 | |
| 38702 | /* Index range for an attribute other than value */ |
| 38703 | if(id->indexRange.length > 0 && id->attributeId != UA_ATTRIBUTEID_VALUE) { |
| 38704 | v->hasStatus = true; |
| 38705 | v->status = UA_STATUSCODE_BADINDEXRANGENODATA; |
| 38706 | return; |
| 38707 | } |
| 38708 | |
| 38709 | /* Read the attribute */ |
| 38710 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 38711 | switch(id->attributeId) { |
| 38712 | case UA_ATTRIBUTEID_NODEID: |
| 38713 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.nodeId, |
| 38714 | type: &UA_TYPES[UA_TYPES_NODEID]); |
| 38715 | break; |
| 38716 | case UA_ATTRIBUTEID_NODECLASS: |
| 38717 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.nodeClass, |
| 38718 | type: &UA_TYPES[UA_TYPES_NODECLASS]); |
| 38719 | break; |
| 38720 | case UA_ATTRIBUTEID_BROWSENAME: |
| 38721 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.browseName, |
| 38722 | type: &UA_TYPES[UA_TYPES_QUALIFIEDNAME]); |
| 38723 | break; |
| 38724 | case UA_ATTRIBUTEID_DISPLAYNAME: { |
| 38725 | UA_LocalizedText lt = UA_Session_getNodeDisplayName(session, head: &node->head); |
| 38726 | retval = UA_Variant_setScalarCopy(v: &v->value, p: <, |
| 38727 | type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 38728 | break; |
| 38729 | } |
| 38730 | case UA_ATTRIBUTEID_DESCRIPTION: { |
| 38731 | UA_LocalizedText lt = UA_Session_getNodeDescription(session, head: &node->head); |
| 38732 | retval = UA_Variant_setScalarCopy(v: &v->value, p: <, |
| 38733 | type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 38734 | break; |
| 38735 | } |
| 38736 | case UA_ATTRIBUTEID_WRITEMASK: |
| 38737 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->head.writeMask, |
| 38738 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 38739 | break; |
| 38740 | case UA_ATTRIBUTEID_USERWRITEMASK: { |
| 38741 | UA_UInt32 userWriteMask = getUserWriteMask(server, session, head: &node->head); |
| 38742 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &userWriteMask, |
| 38743 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 38744 | break; } |
| 38745 | case UA_ATTRIBUTEID_ISABSTRACT: |
| 38746 | retval = readIsAbstractAttribute(node, v: &v->value); |
| 38747 | break; |
| 38748 | case UA_ATTRIBUTEID_SYMMETRIC: |
| 38749 | CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE); |
| 38750 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->referenceTypeNode.symmetric, |
| 38751 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 38752 | break; |
| 38753 | case UA_ATTRIBUTEID_INVERSENAME: |
| 38754 | CHECK_NODECLASS(UA_NODECLASS_REFERENCETYPE); |
| 38755 | if(node->referenceTypeNode.symmetric) { |
| 38756 | /* Symmetric reference types don't have an inverse name */ |
| 38757 | retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; |
| 38758 | break; |
| 38759 | } |
| 38760 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->referenceTypeNode.inverseName, |
| 38761 | type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 38762 | break; |
| 38763 | case UA_ATTRIBUTEID_CONTAINSNOLOOPS: |
| 38764 | CHECK_NODECLASS(UA_NODECLASS_VIEW); |
| 38765 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->viewNode.containsNoLoops, |
| 38766 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 38767 | break; |
| 38768 | case UA_ATTRIBUTEID_EVENTNOTIFIER: |
| 38769 | CHECK_NODECLASS(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT); |
| 38770 | if(node->head.nodeClass == UA_NODECLASS_VIEW) { |
| 38771 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->viewNode.eventNotifier, |
| 38772 | type: &UA_TYPES[UA_TYPES_BYTE]); |
| 38773 | } else { |
| 38774 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->objectNode.eventNotifier, |
| 38775 | type: &UA_TYPES[UA_TYPES_BYTE]); |
| 38776 | } |
| 38777 | break; |
| 38778 | case UA_ATTRIBUTEID_VALUE: { |
| 38779 | CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE); |
| 38780 | /* VariableTypes don't have the AccessLevel concept. Always allow |
| 38781 | * reading the value. */ |
| 38782 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE) { |
| 38783 | /* The access to a value variable is granted via the AccessLevel |
| 38784 | * and UserAccessLevel attributes */ |
| 38785 | UA_Byte accessLevel = getAccessLevel(server, session, node: &node->variableNode); |
| 38786 | if(!(accessLevel & (UA_ACCESSLEVELMASK_READ))) { |
| 38787 | retval = UA_STATUSCODE_BADNOTREADABLE; |
| 38788 | break; |
| 38789 | } |
| 38790 | accessLevel = getUserAccessLevel(server, session, node: &node->variableNode); |
| 38791 | if(!(accessLevel & (UA_ACCESSLEVELMASK_READ))) { |
| 38792 | retval = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 38793 | break; |
| 38794 | } |
| 38795 | } |
| 38796 | retval = readValueAttributeComplete(server, session, vn: &node->variableNode, |
| 38797 | timestamps: timestampsToReturn, indexRange: &id->indexRange, v); |
| 38798 | break; |
| 38799 | } |
| 38800 | case UA_ATTRIBUTEID_DATATYPE: |
| 38801 | CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE); |
| 38802 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableTypeNode.dataType, |
| 38803 | type: &UA_TYPES[UA_TYPES_NODEID]); |
| 38804 | break; |
| 38805 | case UA_ATTRIBUTEID_VALUERANK: |
| 38806 | CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE); |
| 38807 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableTypeNode.valueRank, |
| 38808 | type: &UA_TYPES[UA_TYPES_INT32]); |
| 38809 | break; |
| 38810 | case UA_ATTRIBUTEID_ARRAYDIMENSIONS: |
| 38811 | CHECK_NODECLASS(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE); |
| 38812 | retval = UA_Variant_setArrayCopy(v: &v->value, array: node->variableTypeNode.arrayDimensions, |
| 38813 | arraySize: node->variableTypeNode.arrayDimensionsSize, |
| 38814 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 38815 | break; |
| 38816 | case UA_ATTRIBUTEID_ACCESSLEVEL: |
| 38817 | CHECK_NODECLASS(UA_NODECLASS_VARIABLE); |
| 38818 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableNode.accessLevel, |
| 38819 | type: &UA_TYPES[UA_TYPES_BYTE]); |
| 38820 | break; |
| 38821 | case UA_ATTRIBUTEID_ACCESSLEVELEX: |
| 38822 | CHECK_NODECLASS(UA_NODECLASS_VARIABLE); |
| 38823 | /* The normal AccessLevelEx contains the lowest 8 bits from the normal AccessLevel. |
| 38824 | * In our case, all other bits are zero. */ |
| 38825 | const UA_Byte accessLevel = *((const UA_Byte*)(&node->variableNode.accessLevel)); |
| 38826 | UA_UInt32 accessLevelEx = accessLevel & 0xFF; |
| 38827 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &accessLevelEx, |
| 38828 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 38829 | |
| 38830 | break; |
| 38831 | case UA_ATTRIBUTEID_USERACCESSLEVEL: { |
| 38832 | CHECK_NODECLASS(UA_NODECLASS_VARIABLE); |
| 38833 | UA_Byte userAccessLevel = getUserAccessLevel(server, session, node: &node->variableNode); |
| 38834 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &userAccessLevel, |
| 38835 | type: &UA_TYPES[UA_TYPES_BYTE]); |
| 38836 | break; } |
| 38837 | case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL: |
| 38838 | CHECK_NODECLASS(UA_NODECLASS_VARIABLE); |
| 38839 | retval = UA_Variant_setScalarCopy(v: &v->value, |
| 38840 | p: &node->variableNode.minimumSamplingInterval, |
| 38841 | type: &UA_TYPES[UA_TYPES_DOUBLE]); |
| 38842 | break; |
| 38843 | case UA_ATTRIBUTEID_HISTORIZING: |
| 38844 | CHECK_NODECLASS(UA_NODECLASS_VARIABLE); |
| 38845 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->variableNode.historizing, |
| 38846 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 38847 | break; |
| 38848 | case UA_ATTRIBUTEID_EXECUTABLE: |
| 38849 | CHECK_NODECLASS(UA_NODECLASS_METHOD); |
| 38850 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &node->methodNode.executable, |
| 38851 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 38852 | break; |
| 38853 | case UA_ATTRIBUTEID_USEREXECUTABLE: { |
| 38854 | CHECK_NODECLASS(UA_NODECLASS_METHOD); |
| 38855 | UA_Boolean userExecutable = |
| 38856 | getUserExecutable(server, session, node: &node->methodNode); |
| 38857 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &userExecutable, |
| 38858 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 38859 | break; } |
| 38860 | case UA_ATTRIBUTEID_DATATYPEDEFINITION: { |
| 38861 | CHECK_NODECLASS(UA_NODECLASS_DATATYPE); |
| 38862 | |
| 38863 | #ifdef UA_ENABLE_TYPEDESCRIPTION |
| 38864 | const UA_DataType *type = |
| 38865 | findDataType(node, customTypes: server->config.customDataTypes); |
| 38866 | if(!type) { |
| 38867 | retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; |
| 38868 | break; |
| 38869 | } |
| 38870 | |
| 38871 | if(UA_DATATYPEKIND_STRUCTURE == type->typeKind || |
| 38872 | UA_DATATYPEKIND_OPTSTRUCT == type->typeKind || |
| 38873 | UA_DATATYPEKIND_UNION == type->typeKind) { |
| 38874 | UA_StructureDefinition def; |
| 38875 | retval = getStructureDefinition(type, def: &def); |
| 38876 | if(UA_STATUSCODE_GOOD!=retval) |
| 38877 | break; |
| 38878 | retval = UA_Variant_setScalarCopy(v: &v->value, p: &def, |
| 38879 | type: &UA_TYPES[UA_TYPES_STRUCTUREDEFINITION]); |
| 38880 | UA_free(ptr: def.fields); |
| 38881 | break; |
| 38882 | } |
| 38883 | #endif |
| 38884 | retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; |
| 38885 | break; } |
| 38886 | |
| 38887 | case UA_ATTRIBUTEID_ROLEPERMISSIONS: |
| 38888 | case UA_ATTRIBUTEID_USERROLEPERMISSIONS: |
| 38889 | case UA_ATTRIBUTEID_ACCESSRESTRICTIONS: |
| 38890 | /* TODO: Add support for the attributes from the 1.04 spec */ |
| 38891 | retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; |
| 38892 | break; |
| 38893 | |
| 38894 | default: |
| 38895 | retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; |
| 38896 | } |
| 38897 | |
| 38898 | /* Reading has failed? */ |
| 38899 | if(retval == UA_STATUSCODE_GOOD) { |
| 38900 | v->hasValue = true; |
| 38901 | } else { |
| 38902 | v->hasStatus = true; |
| 38903 | v->status = retval; |
| 38904 | } |
| 38905 | |
| 38906 | /* Always use the current time as the server-timestamp */ |
| 38907 | if(timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER || |
| 38908 | timestampsToReturn == UA_TIMESTAMPSTORETURN_BOTH) { |
| 38909 | v->serverTimestamp = UA_DateTime_now(); |
| 38910 | v->hasServerTimestamp = true; |
| 38911 | v->hasServerPicoseconds = false; |
| 38912 | } else { |
| 38913 | v->hasServerTimestamp = false; |
| 38914 | v->hasServerPicoseconds = false; |
| 38915 | } |
| 38916 | |
| 38917 | /* Don't "invent" source timestamps. But remove them when not required. */ |
| 38918 | if(timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER || |
| 38919 | timestampsToReturn == UA_TIMESTAMPSTORETURN_NEITHER) { |
| 38920 | v->hasSourceTimestamp = false; |
| 38921 | v->hasSourcePicoseconds = false; |
| 38922 | } |
| 38923 | } |
| 38924 | |
| 38925 | void |
| 38926 | Operation_Read(UA_Server *server, UA_Session *session, UA_TimestampsToReturn *ttr, |
| 38927 | const UA_ReadValueId *rvi, UA_DataValue *dv) { |
| 38928 | /* Get the node (with only the selected attribute if the NodeStore supports that) */ |
| 38929 | const UA_Node *node = |
| 38930 | UA_NODESTORE_GET_SELECTIVE(server, &rvi->nodeId, |
| 38931 | attributeId2AttributeMask((UA_AttributeId)rvi->attributeId), |
| 38932 | UA_REFERENCETYPESET_NONE, |
| 38933 | UA_BROWSEDIRECTION_INVALID); |
| 38934 | if(!node) { |
| 38935 | dv->hasStatus = true; |
| 38936 | dv->status = UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 38937 | return; |
| 38938 | } |
| 38939 | |
| 38940 | /* Perform the read operation */ |
| 38941 | ReadWithNode(node, server, session, timestampsToReturn: *ttr, id: rvi, v: dv); |
| 38942 | UA_NODESTORE_RELEASE(server, node); |
| 38943 | } |
| 38944 | |
| 38945 | void |
| 38946 | Service_Read(UA_Server *server, UA_Session *session, |
| 38947 | const UA_ReadRequest *request, UA_ReadResponse *response) { |
| 38948 | UA_LOG_DEBUG_SESSION(server->config.logging, session, "Processing ReadRequest"); |
| 38949 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38950 | |
| 38951 | /* Check if the timestampstoreturn is valid */ |
| 38952 | if(request->timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) { |
| 38953 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID; |
| 38954 | return; |
| 38955 | } |
| 38956 | |
| 38957 | /* Check if maxAge is valid */ |
| 38958 | if(request->maxAge < 0) { |
| 38959 | response->responseHeader.serviceResult = UA_STATUSCODE_BADMAXAGEINVALID; |
| 38960 | return; |
| 38961 | } |
| 38962 | |
| 38963 | /* Check if there are too many operations */ |
| 38964 | if(server->config.maxNodesPerRead != 0 && |
| 38965 | request->nodesToReadSize > server->config.maxNodesPerRead) { |
| 38966 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 38967 | return; |
| 38968 | } |
| 38969 | |
| 38970 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38971 | |
| 38972 | response->responseHeader.serviceResult = |
| 38973 | UA_Server_processServiceOperations(server, session, |
| 38974 | operationCallback: (UA_ServiceOperation)Operation_Read, |
| 38975 | context: &request->timestampsToReturn, |
| 38976 | requestOperations: &request->nodesToReadSize, |
| 38977 | requestOperationsType: &UA_TYPES[UA_TYPES_READVALUEID], |
| 38978 | responseOperations: &response->resultsSize, |
| 38979 | responseOperationsType: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 38980 | } |
| 38981 | |
| 38982 | UA_DataValue |
| 38983 | readWithSession(UA_Server *server, UA_Session *session, |
| 38984 | const UA_ReadValueId *item, |
| 38985 | UA_TimestampsToReturn timestampsToReturn) { |
| 38986 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38987 | |
| 38988 | UA_DataValue dv; |
| 38989 | UA_DataValue_init(p: &dv); |
| 38990 | Operation_Read(server, session, ttr: ×tampsToReturn, rvi: item, dv: &dv); |
| 38991 | return dv; |
| 38992 | } |
| 38993 | |
| 38994 | UA_StatusCode |
| 38995 | readWithReadValue(UA_Server *server, const UA_NodeId *nodeId, |
| 38996 | const UA_AttributeId attributeId, void *v) { |
| 38997 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 38998 | |
| 38999 | /* Call the read service */ |
| 39000 | UA_ReadValueId item; |
| 39001 | UA_ReadValueId_init(p: &item); |
| 39002 | item.nodeId = *nodeId; |
| 39003 | item.attributeId = attributeId; |
| 39004 | UA_DataValue dv = readWithSession(server, session: &server->adminSession, |
| 39005 | item: &item, timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER); |
| 39006 | |
| 39007 | /* Check the return value */ |
| 39008 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 39009 | if(dv.hasStatus) |
| 39010 | retval = dv.status; |
| 39011 | else if(!dv.hasValue) |
| 39012 | retval = UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 39013 | if(retval != UA_STATUSCODE_GOOD) { |
| 39014 | UA_DataValue_clear(p: &dv); |
| 39015 | return retval; |
| 39016 | } |
| 39017 | |
| 39018 | if(attributeId == UA_ATTRIBUTEID_VALUE || |
| 39019 | attributeId == UA_ATTRIBUTEID_ARRAYDIMENSIONS) { |
| 39020 | /* Return the entire variant */ |
| 39021 | memcpy(dest: v, src: &dv.value, n: sizeof(UA_Variant)); |
| 39022 | } else { |
| 39023 | /* Return the variant content only */ |
| 39024 | memcpy(dest: v, src: dv.value.data, n: dv.value.type->memSize); |
| 39025 | UA_free(ptr: dv.value.data); |
| 39026 | } |
| 39027 | return retval; |
| 39028 | } |
| 39029 | |
| 39030 | /* Exposes the Read service to local users */ |
| 39031 | UA_DataValue |
| 39032 | UA_Server_read(UA_Server *server, const UA_ReadValueId *item, |
| 39033 | UA_TimestampsToReturn timestamps) { |
| 39034 | lockServer(server); |
| 39035 | UA_DataValue dv = readWithSession(server, session: &server->adminSession, item, timestampsToReturn: timestamps); |
| 39036 | unlockServer(server); |
| 39037 | return dv; |
| 39038 | } |
| 39039 | |
| 39040 | /* Used in inline functions exposing the Read service with more syntactic sugar |
| 39041 | * for individual attributes */ |
| 39042 | UA_StatusCode |
| 39043 | __UA_Server_read(UA_Server *server, const UA_NodeId *nodeId, |
| 39044 | const UA_AttributeId attributeId, void *v) { |
| 39045 | lockServer(server); |
| 39046 | UA_StatusCode retval = readWithReadValue(server, nodeId, attributeId, v); |
| 39047 | unlockServer(server); |
| 39048 | return retval; |
| 39049 | } |
| 39050 | |
| 39051 | UA_StatusCode |
| 39052 | readObjectProperty(UA_Server *server, const UA_NodeId objectId, |
| 39053 | const UA_QualifiedName propertyName, |
| 39054 | UA_Variant *value) { |
| 39055 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 39056 | |
| 39057 | /* Create a BrowsePath to get the target NodeId */ |
| 39058 | UA_RelativePathElement rpe; |
| 39059 | UA_RelativePathElement_init(p: &rpe); |
| 39060 | rpe.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY); |
| 39061 | rpe.isInverse = false; |
| 39062 | rpe.includeSubtypes = false; |
| 39063 | rpe.targetName = propertyName; |
| 39064 | |
| 39065 | UA_BrowsePath bp; |
| 39066 | UA_BrowsePath_init(p: &bp); |
| 39067 | bp.startingNode = objectId; |
| 39068 | bp.relativePath.elementsSize = 1; |
| 39069 | bp.relativePath.elements = &rpe; |
| 39070 | |
| 39071 | UA_StatusCode retval; |
| 39072 | UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp); |
| 39073 | if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { |
| 39074 | retval = bpr.statusCode; |
| 39075 | UA_BrowsePathResult_clear(p: &bpr); |
| 39076 | return retval; |
| 39077 | } |
| 39078 | |
| 39079 | /* Use the first result from the BrowsePath */ |
| 39080 | retval = readWithReadValue(server, nodeId: &bpr.targets[0].targetId.nodeId, |
| 39081 | attributeId: UA_ATTRIBUTEID_VALUE, v: value); |
| 39082 | |
| 39083 | UA_BrowsePathResult_clear(p: &bpr); |
| 39084 | return retval; |
| 39085 | } |
| 39086 | |
| 39087 | |
| 39088 | UA_StatusCode |
| 39089 | UA_Server_readObjectProperty(UA_Server *server, const UA_NodeId objectId, |
| 39090 | const UA_QualifiedName propertyName, |
| 39091 | UA_Variant *value) { |
| 39092 | lockServer(server); |
| 39093 | UA_StatusCode retval = readObjectProperty(server, objectId, propertyName, value); |
| 39094 | unlockServer(server); |
| 39095 | return retval; |
| 39096 | } |
| 39097 | |
| 39098 | /*****************/ |
| 39099 | /* Type Checking */ |
| 39100 | /*****************/ |
| 39101 | |
| 39102 | UA_Boolean |
| 39103 | compatibleValueDataType(UA_Server *server, const UA_DataType *dataType, |
| 39104 | const UA_NodeId *constraintDataType) { |
| 39105 | if(compatibleDataTypes(server, dataType: &dataType->typeId, constraintDataType)) |
| 39106 | return true; |
| 39107 | |
| 39108 | /* For actual values, the constraint DataType may be a subtype of the |
| 39109 | * DataType of the value -- subtyping in the wrong direction. E.g. UtcTime |
| 39110 | * is a subtype of DateTime. But we allow it to be encoded as a DateTime |
| 39111 | * value when transferred over the wire. |
| 39112 | * |
| 39113 | * We do not allow "subtyping in the "wrong direction" if the received type |
| 39114 | * is abstract. For example, ExtensionObjects (== "Structure" in the type |
| 39115 | * hierarchy) is an abstract type. But ExtensionObject could still be |
| 39116 | * transported over the network. */ |
| 39117 | UA_Boolean abstract = false; |
| 39118 | UA_StatusCode res = readWithReadValue(server, nodeId: &dataType->typeId, |
| 39119 | attributeId: UA_ATTRIBUTEID_ISABSTRACT, v: &abstract); |
| 39120 | if(res != UA_STATUSCODE_GOOD || abstract) |
| 39121 | return false; |
| 39122 | |
| 39123 | if(isNodeInTree_singleRef(server, leafNode: constraintDataType, nodeToFind: &dataType->typeId, |
| 39124 | UA_REFERENCETYPEINDEX_HASSUBTYPE)) |
| 39125 | return true; |
| 39126 | |
| 39127 | return false; |
| 39128 | } |
| 39129 | |
| 39130 | UA_Boolean |
| 39131 | compatibleDataTypes(UA_Server *server, const UA_NodeId *dataType, |
| 39132 | const UA_NodeId *constraintDataType) { |
| 39133 | /* Do not allow empty datatypes */ |
| 39134 | if(UA_NodeId_isNull(p: dataType)) |
| 39135 | return false; |
| 39136 | |
| 39137 | /* No constraint or Variant / BaseDataType which allows any content */ |
| 39138 | if(UA_NodeId_isNull(p: constraintDataType) || |
| 39139 | UA_NodeId_equal(p1: constraintDataType, p2: &UA_TYPES[UA_TYPES_VARIANT].typeId)) |
| 39140 | return true; |
| 39141 | |
| 39142 | /* Same datatypes */ |
| 39143 | if(UA_NodeId_equal(p1: dataType, p2: constraintDataType)) |
| 39144 | return true; |
| 39145 | |
| 39146 | /* Is the DataType a subtype of the constraint type? */ |
| 39147 | if(isNodeInTree_singleRef(server, leafNode: dataType, nodeToFind: constraintDataType, |
| 39148 | UA_REFERENCETYPEINDEX_HASSUBTYPE)) |
| 39149 | return true; |
| 39150 | |
| 39151 | return false; |
| 39152 | } |
| 39153 | |
| 39154 | /* Test whether a ValueRank and the given arraydimensions are compatible. |
| 39155 | * |
| 39156 | * 5.6.2 Variable NodeClass: If the maximum is unknown the value shall be 0. The |
| 39157 | * number of elements shall be equal to the value of the ValueRank Attribute. |
| 39158 | * This Attribute shall be null if ValueRank <= 0. */ |
| 39159 | UA_Boolean |
| 39160 | compatibleValueRankArrayDimensions(UA_Server *server, UA_Session *session, |
| 39161 | UA_Int32 valueRank, size_t arrayDimensionsSize) { |
| 39162 | /* ValueRank invalid */ |
| 39163 | if(valueRank < UA_VALUERANK_SCALAR_OR_ONE_DIMENSION) { |
| 39164 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 39165 | "The ValueRank is invalid (< -3)"); |
| 39166 | return false; |
| 39167 | } |
| 39168 | |
| 39169 | /* case -3, UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: the value can be a scalar |
| 39170 | * or a one dimensional array |
| 39171 | * case -2, UA_VALUERANK_ANY: the value can be a scalar or an array with any |
| 39172 | * number of dimensions |
| 39173 | * case -1, UA_VALUERANK_SCALAR: the value is a scalar |
| 39174 | * case 0, UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: the value is an array with |
| 39175 | * one or more dimensions */ |
| 39176 | if(valueRank <= UA_VALUERANK_ONE_OR_MORE_DIMENSIONS) { |
| 39177 | if(arrayDimensionsSize > 0) { |
| 39178 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 39179 | "No ArrayDimensions can be defined for a ValueRank <= 0"); |
| 39180 | return false; |
| 39181 | } |
| 39182 | return true; |
| 39183 | } |
| 39184 | |
| 39185 | /* case >= 1, UA_VALUERANK_ONE_DIMENSION: the value is an array with the |
| 39186 | specified number of dimensions */ |
| 39187 | if(arrayDimensionsSize != (size_t)valueRank) { |
| 39188 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 39189 | "The number of ArrayDimensions is not equal to " |
| 39190 | "the (positive) ValueRank"); |
| 39191 | return false; |
| 39192 | } |
| 39193 | return true; |
| 39194 | } |
| 39195 | |
| 39196 | UA_Boolean |
| 39197 | compatibleValueRanks(UA_Int32 valueRank, UA_Int32 constraintValueRank) { |
| 39198 | /* Check if the valuerank of the variabletype allows the change. */ |
| 39199 | switch(constraintValueRank) { |
| 39200 | case UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: /* the value can be a scalar or a |
| 39201 | one dimensional array */ |
| 39202 | if(valueRank != UA_VALUERANK_SCALAR && valueRank != UA_VALUERANK_ONE_DIMENSION) |
| 39203 | return false; |
| 39204 | break; |
| 39205 | case UA_VALUERANK_ANY: /* the value can be a scalar or an array with any |
| 39206 | number of dimensions */ |
| 39207 | break; |
| 39208 | case UA_VALUERANK_SCALAR: /* the value is a scalar */ |
| 39209 | if(valueRank != UA_VALUERANK_SCALAR) |
| 39210 | return false; |
| 39211 | break; |
| 39212 | case UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: /* the value is an array with one |
| 39213 | or more dimensions */ |
| 39214 | if(valueRank < (UA_Int32) UA_VALUERANK_ONE_OR_MORE_DIMENSIONS) |
| 39215 | return false; |
| 39216 | break; |
| 39217 | default: /* >= 1: the value is an array with the specified number of |
| 39218 | dimensions */ |
| 39219 | if(valueRank != constraintValueRank) |
| 39220 | return false; |
| 39221 | break; |
| 39222 | } |
| 39223 | return true; |
| 39224 | } |
| 39225 | |
| 39226 | /* Check if the ValueRank allows for the value dimension. This is more |
| 39227 | * permissive than checking for the ArrayDimensions attribute. Because the value |
| 39228 | * can have dimensions if the ValueRank < 0 */ |
| 39229 | static UA_Boolean |
| 39230 | compatibleValueRankValue(UA_Int32 valueRank, const UA_Variant *value) { |
| 39231 | /* Invalid ValueRank */ |
| 39232 | if(valueRank < UA_VALUERANK_SCALAR_OR_ONE_DIMENSION) |
| 39233 | return false; |
| 39234 | |
| 39235 | /* Empty arrays (-1) always match */ |
| 39236 | if(!value->data) |
| 39237 | return true; |
| 39238 | |
| 39239 | size_t arrayDims = value->arrayDimensionsSize; |
| 39240 | if(arrayDims == 0 && !UA_Variant_isScalar(v: value)) |
| 39241 | arrayDims = 1; /* array but no arraydimensions -> implicit array dimension 1 */ |
| 39242 | |
| 39243 | /* We cannot simply use compatibleValueRankArrayDimensions since we can have |
| 39244 | * defined ArrayDimensions for the value if the ValueRank is -2 */ |
| 39245 | switch(valueRank) { |
| 39246 | case UA_VALUERANK_SCALAR_OR_ONE_DIMENSION: /* The value can be a scalar or a |
| 39247 | one dimensional array */ |
| 39248 | return (arrayDims <= 1); |
| 39249 | case UA_VALUERANK_ANY: /* The value can be a scalar or an array with any |
| 39250 | number of dimensions */ |
| 39251 | return true; |
| 39252 | case UA_VALUERANK_SCALAR: /* The value is a scalar */ |
| 39253 | return (arrayDims == 0); |
| 39254 | case UA_VALUERANK_ONE_OR_MORE_DIMENSIONS: |
| 39255 | return (arrayDims >= 1); |
| 39256 | default: |
| 39257 | break; |
| 39258 | } |
| 39259 | |
| 39260 | UA_assert(valueRank >= UA_VALUERANK_ONE_OR_MORE_DIMENSIONS); |
| 39261 | |
| 39262 | /* case 0: the value is an array with one or more dimensions */ |
| 39263 | return (arrayDims == (UA_UInt32)valueRank); |
| 39264 | } |
| 39265 | |
| 39266 | UA_Boolean |
| 39267 | compatibleArrayDimensions(size_t constraintArrayDimensionsSize, |
| 39268 | const UA_UInt32 *constraintArrayDimensions, |
| 39269 | size_t testArrayDimensionsSize, |
| 39270 | const UA_UInt32 *testArrayDimensions) { |
| 39271 | /* No array dimensions defined -> everything is permitted if the value rank fits */ |
| 39272 | if(constraintArrayDimensionsSize == 0) |
| 39273 | return true; |
| 39274 | |
| 39275 | /* Dimension count must match */ |
| 39276 | if(testArrayDimensionsSize != constraintArrayDimensionsSize) |
| 39277 | return false; |
| 39278 | |
| 39279 | /* Dimension lengths must not be larger than the constraint. Zero in the |
| 39280 | * constraint indicates a wildcard. */ |
| 39281 | for(size_t i = 0; i < constraintArrayDimensionsSize; ++i) { |
| 39282 | if(constraintArrayDimensions[i] < testArrayDimensions[i] && |
| 39283 | constraintArrayDimensions[i] != 0) |
| 39284 | return false; |
| 39285 | } |
| 39286 | return true; |
| 39287 | } |
| 39288 | |
| 39289 | UA_Boolean |
| 39290 | compatibleValueArrayDimensions(const UA_Variant *value, size_t targetArrayDimensionsSize, |
| 39291 | const UA_UInt32 *targetArrayDimensions) { |
| 39292 | size_t valueArrayDimensionsSize = value->arrayDimensionsSize; |
| 39293 | UA_UInt32 const *valueArrayDimensions = value->arrayDimensions; |
| 39294 | UA_UInt32 tempArrayDimensions; |
| 39295 | if(!valueArrayDimensions && !UA_Variant_isScalar(v: value)) { |
| 39296 | /* An empty array implicitly has array dimensions [0,0,...] with the |
| 39297 | * correct number of dimensions. So it always matches. */ |
| 39298 | if(value->arrayLength == 0) |
| 39299 | return true; |
| 39300 | |
| 39301 | /* Arrays with content and without array dimensions have one implicit dimension */ |
| 39302 | valueArrayDimensionsSize = 1; |
| 39303 | tempArrayDimensions = (UA_UInt32)value->arrayLength; |
| 39304 | valueArrayDimensions = &tempArrayDimensions; |
| 39305 | } |
| 39306 | UA_assert(valueArrayDimensionsSize == 0 || valueArrayDimensions != NULL); |
| 39307 | return compatibleArrayDimensions(constraintArrayDimensionsSize: targetArrayDimensionsSize, constraintArrayDimensions: targetArrayDimensions, |
| 39308 | testArrayDimensionsSize: valueArrayDimensionsSize, testArrayDimensions: valueArrayDimensions); |
| 39309 | } |
| 39310 | |
| 39311 | const char *reason_EmptyType = "Empty value only allowed for BaseDataType"; |
| 39312 | const char *reason_ValueDataType = "DataType of the value is incompatible"; |
| 39313 | const char *reason_ValueArrayDimensions = "ArrayDimensions of the value are incompatible"; |
| 39314 | const char *reason_ValueValueRank = "ValueRank of the value is incompatible"; |
| 39315 | |
| 39316 | UA_Boolean |
| 39317 | compatibleValue(UA_Server *server, UA_Session *session, const UA_NodeId *targetDataTypeId, |
| 39318 | UA_Int32 targetValueRank, size_t targetArrayDimensionsSize, |
| 39319 | const UA_UInt32 *targetArrayDimensions, const UA_Variant *value, |
| 39320 | const UA_NumericRange *range, const char **reason) { |
| 39321 | /* Empty value */ |
| 39322 | if(UA_Variant_isEmpty(v: value)) { |
| 39323 | /* Empty value is allowed for BaseDataType */ |
| 39324 | if(UA_NodeId_equal(p1: targetDataTypeId, p2: &UA_TYPES[UA_TYPES_VARIANT].typeId) || |
| 39325 | UA_NodeId_equal(p1: targetDataTypeId, p2: &UA_NODEID_NULL)) |
| 39326 | return true; |
| 39327 | |
| 39328 | /* Ignore if that is configured */ |
| 39329 | if(server->bootstrapNS0 || |
| 39330 | server->config.allowEmptyVariables == UA_RULEHANDLING_ACCEPT) |
| 39331 | return true; |
| 39332 | |
| 39333 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 39334 | "Only Variables with data type BaseDataType " |
| 39335 | "can contain an empty value"); |
| 39336 | |
| 39337 | /* Ignore if that is configured */ |
| 39338 | if(server->config.allowEmptyVariables == UA_RULEHANDLING_WARN) |
| 39339 | return true; |
| 39340 | |
| 39341 | /* Default handling is to abort */ |
| 39342 | *reason = reason_EmptyType; |
| 39343 | return false; |
| 39344 | } |
| 39345 | |
| 39346 | /* Empty array of ExtensionObjects */ |
| 39347 | if(UA_Variant_hasArrayType(v: value, type: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]) && |
| 39348 | value->arrayLength == 0) { |
| 39349 | /* There is no way to check type compatibility here. Leave it for the upper layers to |
| 39350 | * decide, if empty array is okay. */ |
| 39351 | return true; |
| 39352 | } |
| 39353 | |
| 39354 | /* Is the datatype compatible? */ |
| 39355 | if(!compatibleValueDataType(server, dataType: value->type, constraintDataType: targetDataTypeId)) { |
| 39356 | *reason = reason_ValueDataType; |
| 39357 | return false; |
| 39358 | } |
| 39359 | |
| 39360 | /* Array dimensions are checked later when writing the range */ |
| 39361 | if(range) |
| 39362 | return true; |
| 39363 | |
| 39364 | /* See if the array dimensions match. */ |
| 39365 | if(!compatibleValueArrayDimensions(value, targetArrayDimensionsSize, |
| 39366 | targetArrayDimensions)) { |
| 39367 | *reason = reason_ValueArrayDimensions; |
| 39368 | return false; |
| 39369 | } |
| 39370 | |
| 39371 | /* Check if the valuerank allows for the value dimension */ |
| 39372 | if(!compatibleValueRankValue(valueRank: targetValueRank, value)) { |
| 39373 | *reason = reason_ValueValueRank; |
| 39374 | return false; |
| 39375 | } |
| 39376 | |
| 39377 | return true; |
| 39378 | } |
| 39379 | |
| 39380 | /*****************/ |
| 39381 | /* Write Service */ |
| 39382 | /*****************/ |
| 39383 | |
| 39384 | static void |
| 39385 | freeWrapperArray(void *app, void *context) { |
| 39386 | UA_free(ptr: context); |
| 39387 | } |
| 39388 | |
| 39389 | static void |
| 39390 | unwrapEOArray(UA_Server *server, UA_Variant *value) { |
| 39391 | /* Only works on arrays of ExtensionObjects */ |
| 39392 | if(!UA_Variant_hasArrayType(v: value, type: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]) || |
| 39393 | value->arrayLength == 0) |
| 39394 | return; |
| 39395 | |
| 39396 | /* All eo need to be already decoded and have the same wrapped type */ |
| 39397 | UA_ExtensionObject *eo = (UA_ExtensionObject*)value->data; |
| 39398 | const UA_DataType *innerType = eo[0].content.decoded.type; |
| 39399 | for(size_t i = 0; i < value->arrayLength; i++) { |
| 39400 | if(eo[i].encoding != UA_EXTENSIONOBJECT_DECODED && |
| 39401 | eo[i].encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) |
| 39402 | return; |
| 39403 | if(eo[i].content.decoded.type != innerType) |
| 39404 | return; |
| 39405 | } |
| 39406 | |
| 39407 | /* Allocate the array for the unwrapped data. Since the adjusted value is |
| 39408 | * not cleaned up (only the original value), this memory is being cleaned up |
| 39409 | * by a delayed callback in the server after the method call has |
| 39410 | * finished. */ |
| 39411 | UA_DelayedCallback *dc = (UA_DelayedCallback*) |
| 39412 | UA_malloc(size: sizeof(UA_DelayedCallback) + (value->arrayLength * innerType->memSize)); |
| 39413 | if(!dc) |
| 39414 | return; |
| 39415 | |
| 39416 | /* Move the content */ |
| 39417 | uintptr_t pos = ((uintptr_t)dc) + sizeof(UA_DelayedCallback); |
| 39418 | void *unwrappedArray = (void*)pos; |
| 39419 | for(size_t i = 0; i < value->arrayLength; i++) { |
| 39420 | memcpy(dest: (void*)pos, src: eo[i].content.decoded.data, n: innerType->memSize); |
| 39421 | pos += innerType->memSize; |
| 39422 | } |
| 39423 | |
| 39424 | /* Adjust the value */ |
| 39425 | value->type = innerType; |
| 39426 | value->data = unwrappedArray; |
| 39427 | |
| 39428 | /* Add the delayed callback to free the memory of the unwrapped array */ |
| 39429 | dc->callback = freeWrapperArray; |
| 39430 | dc->application = NULL; |
| 39431 | dc->context = dc; |
| 39432 | UA_EventLoop *el = server->config.eventLoop; |
| 39433 | el->addDelayedCallback(el, dc); |
| 39434 | } |
| 39435 | |
| 39436 | void |
| 39437 | adjustValueType(UA_Server *server, UA_Variant *value, |
| 39438 | const UA_NodeId *targetDataTypeId) { |
| 39439 | /* If the value is empty, there is nothing we can do here */ |
| 39440 | const UA_DataType *type = value->type; |
| 39441 | if(!type) |
| 39442 | return; |
| 39443 | |
| 39444 | /* The target type is already achieved. No adjustment needed. */ |
| 39445 | if(UA_NodeId_equal(p1: &type->typeId, p2: targetDataTypeId)) |
| 39446 | return; |
| 39447 | |
| 39448 | /* Unwrap ExtensionObject arrays if they all contain the same DataType */ |
| 39449 | unwrapEOArray(server, value); |
| 39450 | |
| 39451 | /* Find the target type */ |
| 39452 | const UA_DataType *targetType = |
| 39453 | UA_findDataTypeWithCustom(typeId: targetDataTypeId, customTypes: server->config.customDataTypes); |
| 39454 | if(!targetType) |
| 39455 | return; |
| 39456 | |
| 39457 | /* Use the generic functionality shared by client and server */ |
| 39458 | adjustType(value, targetType); |
| 39459 | } |
| 39460 | |
| 39461 | static UA_StatusCode |
| 39462 | writeArrayDimensionsAttribute(UA_Server *server, UA_Session *session, |
| 39463 | UA_VariableNode *node, const UA_VariableTypeNode *type, |
| 39464 | size_t arrayDimensionsSize, UA_UInt32 *arrayDimensions) { |
| 39465 | UA_assert(node != NULL); |
| 39466 | UA_assert(type != NULL); |
| 39467 | |
| 39468 | /* If this is a variabletype, there must be no instances or subtypes of it |
| 39469 | * when we do the change */ |
| 39470 | if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE && |
| 39471 | UA_Node_hasSubTypeOrInstances(head: &node->head)) { |
| 39472 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 39473 | msg: "Cannot change a variable type with existing instances"); |
| 39474 | return UA_STATUSCODE_BADINTERNALERROR; |
| 39475 | } |
| 39476 | |
| 39477 | /* Check that the array dimensions match with the valuerank */ |
| 39478 | if(!compatibleValueRankArrayDimensions(server, session, valueRank: node->valueRank, |
| 39479 | arrayDimensionsSize)) { |
| 39480 | UA_LOG_DEBUG(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 39481 | msg: "Cannot write the ArrayDimensions. The ValueRank does not match."); |
| 39482 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 39483 | } |
| 39484 | |
| 39485 | /* Check if the array dimensions match with the wildcards in the |
| 39486 | * variabletype (dimension length 0) */ |
| 39487 | if(type->arrayDimensions && |
| 39488 | !compatibleArrayDimensions(constraintArrayDimensionsSize: type->arrayDimensionsSize, constraintArrayDimensions: type->arrayDimensions, |
| 39489 | testArrayDimensionsSize: arrayDimensionsSize, testArrayDimensions: arrayDimensions)) { |
| 39490 | UA_LOG_DEBUG(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 39491 | msg: "Array dimensions in the variable type do not match"); |
| 39492 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 39493 | } |
| 39494 | |
| 39495 | /* Check if the current value is compatible with the array dimensions */ |
| 39496 | UA_DataValue value; |
| 39497 | UA_DataValue_init(p: &value); |
| 39498 | UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value); |
| 39499 | if(retval != UA_STATUSCODE_GOOD) |
| 39500 | return retval; |
| 39501 | if(value.hasValue) { |
| 39502 | if(!compatibleValueArrayDimensions(value: &value.value, targetArrayDimensionsSize: arrayDimensionsSize, |
| 39503 | targetArrayDimensions: arrayDimensions)) |
| 39504 | retval = UA_STATUSCODE_BADTYPEMISMATCH; |
| 39505 | UA_DataValue_clear(p: &value); |
| 39506 | if(retval != UA_STATUSCODE_GOOD) { |
| 39507 | UA_LOG_DEBUG(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 39508 | msg: "Array dimensions in the current value do not match"); |
| 39509 | return retval; |
| 39510 | } |
| 39511 | } |
| 39512 | |
| 39513 | /* Ok, apply */ |
| 39514 | UA_UInt32 *oldArrayDimensions = node->arrayDimensions; |
| 39515 | size_t oldArrayDimensionsSize = node->arrayDimensionsSize; |
| 39516 | retval = UA_Array_copy(src: arrayDimensions, size: arrayDimensionsSize, |
| 39517 | dst: (void**)&node->arrayDimensions, |
| 39518 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 39519 | if(retval != UA_STATUSCODE_GOOD) |
| 39520 | return retval; |
| 39521 | UA_Array_delete(p: oldArrayDimensions, size: oldArrayDimensionsSize, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 39522 | node->arrayDimensionsSize = arrayDimensionsSize; |
| 39523 | return UA_STATUSCODE_GOOD; |
| 39524 | } |
| 39525 | |
| 39526 | /* Stack layout: ... | node | type */ |
| 39527 | static UA_StatusCode |
| 39528 | writeValueRank(UA_Server *server, UA_Session *session, |
| 39529 | UA_VariableNode *node, const UA_VariableTypeNode *type, |
| 39530 | UA_Int32 valueRank) { |
| 39531 | UA_assert(node != NULL); |
| 39532 | UA_assert(type != NULL); |
| 39533 | |
| 39534 | UA_Int32 constraintValueRank = type->valueRank; |
| 39535 | |
| 39536 | /* If this is a variabletype, there must be no instances or subtypes of it |
| 39537 | * when we do the change */ |
| 39538 | if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE && |
| 39539 | UA_Node_hasSubTypeOrInstances(head: &node->head)) |
| 39540 | return UA_STATUSCODE_BADINTERNALERROR; |
| 39541 | |
| 39542 | /* Check if the valuerank of the variabletype allows the change. */ |
| 39543 | if(!compatibleValueRanks(valueRank, constraintValueRank)) |
| 39544 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 39545 | |
| 39546 | /* Check if the new valuerank is compatible with the array dimensions. Use |
| 39547 | * the read service to handle data sources. */ |
| 39548 | size_t arrayDims = node->arrayDimensionsSize; |
| 39549 | if(arrayDims == 0) { |
| 39550 | /* the value could be an array with no arrayDimensions defined. |
| 39551 | dimensions zero indicate a scalar for compatibleValueRankArrayDimensions. */ |
| 39552 | UA_DataValue value; |
| 39553 | UA_DataValue_init(p: &value); |
| 39554 | UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value); |
| 39555 | if(retval != UA_STATUSCODE_GOOD) |
| 39556 | return retval; |
| 39557 | if(!value.hasValue || !value.value.type) { |
| 39558 | /* no value -> apply */ |
| 39559 | node->valueRank = valueRank; |
| 39560 | return UA_STATUSCODE_GOOD; |
| 39561 | } |
| 39562 | if(!UA_Variant_isScalar(v: &value.value)) |
| 39563 | arrayDims = 1; |
| 39564 | UA_DataValue_clear(p: &value); |
| 39565 | } |
| 39566 | if(!compatibleValueRankArrayDimensions(server, session, valueRank, arrayDimensionsSize: arrayDims)) |
| 39567 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 39568 | |
| 39569 | /* All good, apply the change */ |
| 39570 | node->valueRank = valueRank; |
| 39571 | return UA_STATUSCODE_GOOD; |
| 39572 | } |
| 39573 | |
| 39574 | static UA_StatusCode |
| 39575 | writeDataTypeAttribute(UA_Server *server, UA_Session *session, |
| 39576 | UA_VariableNode *node, const UA_VariableTypeNode *type, |
| 39577 | const UA_NodeId *dataType) { |
| 39578 | UA_assert(node != NULL); |
| 39579 | UA_assert(type != NULL); |
| 39580 | |
| 39581 | /* If this is a variabletype, there must be no instances or subtypes of it |
| 39582 | when we do the change */ |
| 39583 | if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE && |
| 39584 | UA_Node_hasSubTypeOrInstances(head: &node->head)) |
| 39585 | return UA_STATUSCODE_BADINTERNALERROR; |
| 39586 | |
| 39587 | /* Does the new type match the constraints of the variabletype? */ |
| 39588 | if(!compatibleDataTypes(server, dataType, constraintDataType: &type->dataType)) |
| 39589 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 39590 | |
| 39591 | /* Check if the current value would match the new type */ |
| 39592 | UA_DataValue value; |
| 39593 | UA_DataValue_init(p: &value); |
| 39594 | UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value); |
| 39595 | if(retval != UA_STATUSCODE_GOOD) |
| 39596 | return retval; |
| 39597 | if(value.hasValue) { |
| 39598 | const char *reason; /* temp value */ |
| 39599 | if(!compatibleValue(server, session, targetDataTypeId: dataType, targetValueRank: node->valueRank, |
| 39600 | targetArrayDimensionsSize: node->arrayDimensionsSize, targetArrayDimensions: node->arrayDimensions, |
| 39601 | value: &value.value, NULL, reason: &reason)) |
| 39602 | retval = UA_STATUSCODE_BADTYPEMISMATCH; |
| 39603 | UA_DataValue_clear(p: &value); |
| 39604 | if(retval != UA_STATUSCODE_GOOD) { |
| 39605 | UA_LOG_DEBUG(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 39606 | msg: "The current value does not match the new data type"); |
| 39607 | return retval; |
| 39608 | } |
| 39609 | } |
| 39610 | |
| 39611 | /* Replace the datatype nodeid */ |
| 39612 | UA_NodeId dtCopy = node->dataType; |
| 39613 | retval = UA_NodeId_copy(src: dataType, dst: &node->dataType); |
| 39614 | if(retval != UA_STATUSCODE_GOOD) { |
| 39615 | node->dataType = dtCopy; |
| 39616 | return retval; |
| 39617 | } |
| 39618 | UA_NodeId_clear(p: &dtCopy); |
| 39619 | return UA_STATUSCODE_GOOD; |
| 39620 | } |
| 39621 | |
| 39622 | static UA_StatusCode |
| 39623 | writeValueAttributeWithoutRange(UA_VariableNode *node, const UA_DataValue *value) { |
| 39624 | UA_DataValue *oldValue = &node->value.data.value; |
| 39625 | UA_DataValue tmpValue = *value; |
| 39626 | |
| 39627 | /* If possible memcpy the new value over the old value without |
| 39628 | * a malloc. For this the value needs to be "pointerfree". */ |
| 39629 | if(oldValue->hasValue && oldValue->value.type && oldValue->value.type->pointerFree && |
| 39630 | value->hasValue && value->value.type && value->value.type->pointerFree && |
| 39631 | oldValue->value.type->memSize == value->value.type->memSize) { |
| 39632 | size_t oSize = 1; |
| 39633 | size_t vSize = 1; |
| 39634 | if(!UA_Variant_isScalar(v: &oldValue->value)) |
| 39635 | oSize = oldValue->value.arrayLength; |
| 39636 | if(!UA_Variant_isScalar(v: &value->value)) |
| 39637 | vSize = value->value.arrayLength; |
| 39638 | |
| 39639 | if(oSize == vSize && |
| 39640 | oldValue->value.arrayDimensionsSize == value->value.arrayDimensionsSize) { |
| 39641 | /* Keep the old pointers, but adjust type and array length */ |
| 39642 | tmpValue.value = oldValue->value; |
| 39643 | tmpValue.value.type = value->value.type; |
| 39644 | tmpValue.value.arrayLength = value->value.arrayLength; |
| 39645 | |
| 39646 | /* Copy the data over the old memory */ |
| 39647 | memcpy(dest: tmpValue.value.data, src: value->value.data, |
| 39648 | n: oSize * oldValue->value.type->memSize); |
| 39649 | memcpy(dest: tmpValue.value.arrayDimensions, src: value->value.arrayDimensions, |
| 39650 | n: sizeof(UA_UInt32) * oldValue->value.arrayDimensionsSize); |
| 39651 | |
| 39652 | /* Set the value */ |
| 39653 | node->value.data.value = tmpValue; |
| 39654 | return UA_STATUSCODE_GOOD; |
| 39655 | } |
| 39656 | } |
| 39657 | |
| 39658 | /* Make a deep copy of the value and replace when this succeeds */ |
| 39659 | UA_StatusCode retval = UA_Variant_copy(src: &value->value, dst: &tmpValue.value); |
| 39660 | if(retval != UA_STATUSCODE_GOOD) |
| 39661 | return retval; |
| 39662 | UA_DataValue_clear(p: &node->value.data.value); |
| 39663 | node->value.data.value = tmpValue; |
| 39664 | return UA_STATUSCODE_GOOD; |
| 39665 | } |
| 39666 | |
| 39667 | static UA_StatusCode |
| 39668 | writeValueAttributeWithRange(UA_VariableNode *node, const UA_DataValue *value, |
| 39669 | const UA_NumericRange *rangeptr) { |
| 39670 | /* Value on both sides? */ |
| 39671 | if(value->status != node->value.data.value.status || |
| 39672 | !value->hasValue || !node->value.data.value.hasValue) |
| 39673 | return UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 39674 | |
| 39675 | /* Make scalar a one-entry array for range matching */ |
| 39676 | UA_Variant editableValue; |
| 39677 | const UA_Variant *v = &value->value; |
| 39678 | if(UA_Variant_isScalar(v: &value->value)) { |
| 39679 | editableValue = value->value; |
| 39680 | editableValue.arrayLength = 1; |
| 39681 | v = &editableValue; |
| 39682 | } |
| 39683 | |
| 39684 | /* Check that the type is an exact match and not only "compatible" */ |
| 39685 | if(!node->value.data.value.value.type || !v->type || |
| 39686 | !UA_NodeId_equal(p1: &node->value.data.value.value.type->typeId, |
| 39687 | p2: &v->type->typeId)) |
| 39688 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 39689 | |
| 39690 | /* Write the value */ |
| 39691 | UA_StatusCode retval = |
| 39692 | UA_Variant_setRangeCopy(v: &node->value.data.value.value, |
| 39693 | array: v->data, arraySize: v->arrayLength, range: *rangeptr); |
| 39694 | if(retval != UA_STATUSCODE_GOOD) |
| 39695 | return retval; |
| 39696 | |
| 39697 | /* Write the status and timestamps */ |
| 39698 | node->value.data.value.hasStatus = value->hasStatus; |
| 39699 | node->value.data.value.status = value->status; |
| 39700 | node->value.data.value.hasSourceTimestamp = value->hasSourceTimestamp; |
| 39701 | node->value.data.value.sourceTimestamp = value->sourceTimestamp; |
| 39702 | node->value.data.value.hasSourcePicoseconds = value->hasSourcePicoseconds; |
| 39703 | node->value.data.value.sourcePicoseconds = value->sourcePicoseconds; |
| 39704 | return UA_STATUSCODE_GOOD; |
| 39705 | } |
| 39706 | |
| 39707 | static UA_StatusCode |
| 39708 | writeNodeValueAttribute(UA_Server *server, UA_Session *session, |
| 39709 | UA_VariableNode *node, const UA_DataValue *value, |
| 39710 | const UA_String *indexRange) { |
| 39711 | UA_assert(node != NULL); |
| 39712 | UA_assert(session != NULL); |
| 39713 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 39714 | |
| 39715 | /* Parse the range */ |
| 39716 | UA_NumericRange range; |
| 39717 | range.dimensions = NULL; |
| 39718 | UA_NumericRange *rangeptr = NULL; |
| 39719 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 39720 | if(indexRange && indexRange->length > 0) { |
| 39721 | retval = UA_NumericRange_parse(range: &range, str: *indexRange); |
| 39722 | if(retval != UA_STATUSCODE_GOOD) |
| 39723 | return retval; |
| 39724 | rangeptr = ⦥ |
| 39725 | } |
| 39726 | |
| 39727 | /* Created an editable version. The data is not touched. Only the variant |
| 39728 | * "container". */ |
| 39729 | UA_DataValue adjustedValue = *value; |
| 39730 | |
| 39731 | /* Type checking. May change the type of adjustedValue */ |
| 39732 | const char *reason; |
| 39733 | if(value->hasValue && value->value.type) { |
| 39734 | /* Try to correct the type */ |
| 39735 | adjustValueType(server, value: &adjustedValue.value, targetDataTypeId: &node->dataType); |
| 39736 | |
| 39737 | /* Check the type */ |
| 39738 | if(!compatibleValue(server, session, targetDataTypeId: &node->dataType, targetValueRank: node->valueRank, |
| 39739 | targetArrayDimensionsSize: node->arrayDimensionsSize, targetArrayDimensions: node->arrayDimensions, |
| 39740 | value: &adjustedValue.value, range: rangeptr, reason: &reason)) { |
| 39741 | UA_LOG_NODEID_WARNING(&node->head.nodeId, |
| 39742 | if(session == &server->adminSession) { |
| 39743 | /* If the value is written via the local API, log a warning */ |
| 39744 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 39745 | "Writing the value of Node %.*s failed with the " |
| 39746 | "following reason: %s", |
| 39747 | (int)nodeIdStr.length, nodeIdStr.data, reason); |
| 39748 | } else { |
| 39749 | /* Don't spam the logs if writing from remote failed */ |
| 39750 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 39751 | "Writing the value of Node %.*s failed with the " |
| 39752 | "following reason: %s", |
| 39753 | (int)nodeIdStr.length, nodeIdStr.data, reason); |
| 39754 | }); |
| 39755 | if(rangeptr && rangeptr->dimensions != NULL) |
| 39756 | UA_free(ptr: rangeptr->dimensions); |
| 39757 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 39758 | } |
| 39759 | } |
| 39760 | |
| 39761 | /* If no source timestamp is defined create one here. |
| 39762 | * It should be created as close to the source as possible. */ |
| 39763 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE && !node->isDynamic) { |
| 39764 | adjustedValue.hasSourceTimestamp = false; |
| 39765 | adjustedValue.hasSourcePicoseconds = false; |
| 39766 | } |
| 39767 | |
| 39768 | /* Call into the different value storage backends. |
| 39769 | * |
| 39770 | * TODO: Clean up this mess with duplicated possibilities for external |
| 39771 | * callbacks */ |
| 39772 | retval = UA_STATUSCODE_BADWRITENOTSUPPORTED; /* default */ |
| 39773 | switch(node->valueBackend.backendType) { |
| 39774 | case UA_VALUEBACKENDTYPE_NONE: |
| 39775 | if(node->valueSource == UA_VALUESOURCE_DATA) { |
| 39776 | /* Write into the in-situ DataValue */ |
| 39777 | if(!rangeptr) |
| 39778 | retval = writeValueAttributeWithoutRange(node, value: &adjustedValue); |
| 39779 | else |
| 39780 | retval = writeValueAttributeWithRange(node, value: &adjustedValue, rangeptr); |
| 39781 | |
| 39782 | /* Callback after writing */ |
| 39783 | if(retval == UA_STATUSCODE_GOOD && |
| 39784 | node->value.data.callback.onWrite) { |
| 39785 | node->value.data.callback. |
| 39786 | onWrite(server, &session->sessionId, session->sessionHandle, |
| 39787 | &node->head.nodeId, node->head.context, |
| 39788 | rangeptr, &adjustedValue); |
| 39789 | } |
| 39790 | } else if(node->value.dataSource.write) { |
| 39791 | /* Write via the datasource callback */ |
| 39792 | retval = node->value.dataSource. |
| 39793 | write(server, &session->sessionId, session->sessionHandle, |
| 39794 | &node->head.nodeId, node->head.context, |
| 39795 | rangeptr, &adjustedValue); |
| 39796 | } |
| 39797 | break; |
| 39798 | |
| 39799 | case UA_VALUEBACKENDTYPE_EXTERNAL: |
| 39800 | retval = UA_STATUSCODE_GOOD; |
| 39801 | if(node->valueBackend.backend.external.callback.userWrite) { |
| 39802 | retval = node->valueBackend.backend.external.callback. |
| 39803 | userWrite(server, &session->sessionId, session->sessionHandle, |
| 39804 | &node->head.nodeId, node->head.context, |
| 39805 | rangeptr, &adjustedValue); |
| 39806 | } else { |
| 39807 | if(node->valueBackend.backend.external.value) { |
| 39808 | UA_DataValue_clear(p: *node->valueBackend.backend.external.value); |
| 39809 | retval = UA_DataValue_copy(src: &adjustedValue, |
| 39810 | dst: *node->valueBackend.backend.external.value); |
| 39811 | } |
| 39812 | } |
| 39813 | break; |
| 39814 | |
| 39815 | case UA_VALUEBACKENDTYPE_INTERNAL: |
| 39816 | case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK: |
| 39817 | default: |
| 39818 | break; |
| 39819 | } |
| 39820 | |
| 39821 | /* Write into the historical data backend. Not that the historical data |
| 39822 | * backend can be configured to "poll" data like a MonitoredItem also. */ |
| 39823 | #ifdef UA_ENABLE_HISTORIZING |
| 39824 | if(retval == UA_STATUSCODE_GOOD && |
| 39825 | node->head.nodeClass == UA_NODECLASS_VARIABLE && |
| 39826 | server->config.historyDatabase.setValue) { |
| 39827 | server->config.historyDatabase. |
| 39828 | setValue(server, server->config.historyDatabase.context, |
| 39829 | &session->sessionId, session->sessionHandle, |
| 39830 | &node->head.nodeId, node->historizing, &adjustedValue); |
| 39831 | } |
| 39832 | #endif |
| 39833 | |
| 39834 | /* Clean up */ |
| 39835 | if(rangeptr && rangeptr->dimensions != NULL) |
| 39836 | UA_free(ptr: rangeptr->dimensions); |
| 39837 | return retval; |
| 39838 | } |
| 39839 | |
| 39840 | static UA_StatusCode |
| 39841 | writeIsAbstract(UA_Node *node, UA_Boolean value) { |
| 39842 | switch(node->head.nodeClass) { |
| 39843 | case UA_NODECLASS_OBJECTTYPE: |
| 39844 | node->objectTypeNode.isAbstract = value; |
| 39845 | break; |
| 39846 | case UA_NODECLASS_REFERENCETYPE: |
| 39847 | node->referenceTypeNode.isAbstract = value; |
| 39848 | break; |
| 39849 | case UA_NODECLASS_VARIABLETYPE: |
| 39850 | node->variableTypeNode.isAbstract = value; |
| 39851 | break; |
| 39852 | case UA_NODECLASS_DATATYPE: |
| 39853 | node->dataTypeNode.isAbstract = value; |
| 39854 | break; |
| 39855 | default: |
| 39856 | return UA_STATUSCODE_BADNODECLASSINVALID; |
| 39857 | } |
| 39858 | return UA_STATUSCODE_GOOD; |
| 39859 | } |
| 39860 | |
| 39861 | /*****************/ |
| 39862 | /* Write Service */ |
| 39863 | /*****************/ |
| 39864 | |
| 39865 | #define CHECK_DATATYPE_SCALAR(EXP_DT) \ |
| 39866 | if(!wvalue->value.hasValue || \ |
| 39867 | &UA_TYPES[UA_TYPES_##EXP_DT] != wvalue->value.value.type || \ |
| 39868 | !UA_Variant_isScalar(&wvalue->value.value)) { \ |
| 39869 | retval = UA_STATUSCODE_BADTYPEMISMATCH; \ |
| 39870 | break; \ |
| 39871 | } |
| 39872 | |
| 39873 | #define CHECK_DATATYPE_ARRAY(EXP_DT) \ |
| 39874 | if(!wvalue->value.hasValue || \ |
| 39875 | &UA_TYPES[UA_TYPES_##EXP_DT] != wvalue->value.value.type || \ |
| 39876 | UA_Variant_isScalar(&wvalue->value.value)) { \ |
| 39877 | retval = UA_STATUSCODE_BADTYPEMISMATCH; \ |
| 39878 | break; \ |
| 39879 | } |
| 39880 | |
| 39881 | #define CHECK_NODECLASS_WRITE(CLASS) \ |
| 39882 | if((node->head.nodeClass & (CLASS)) == 0) { \ |
| 39883 | retval = UA_STATUSCODE_BADNODECLASSINVALID; \ |
| 39884 | break; \ |
| 39885 | } |
| 39886 | |
| 39887 | #define CHECK_USERWRITEMASK(mask) \ |
| 39888 | if(!(userWriteMask & (mask))) { \ |
| 39889 | retval = UA_STATUSCODE_BADUSERACCESSDENIED; \ |
| 39890 | break; \ |
| 39891 | } |
| 39892 | |
| 39893 | #define GET_NODETYPE \ |
| 39894 | type = (const UA_VariableTypeNode*) \ |
| 39895 | getNodeType(server, &node->head); \ |
| 39896 | if(!type) { \ |
| 39897 | retval = UA_STATUSCODE_BADTYPEMISMATCH; \ |
| 39898 | break; \ |
| 39899 | } |
| 39900 | |
| 39901 | /* Update a localized text. Don't touch the target if copying fails |
| 39902 | * (maybe due to BadOutOfMemory). */ |
| 39903 | static UA_StatusCode |
| 39904 | updateLocalizedText(const UA_LocalizedText *source, UA_LocalizedText *target) { |
| 39905 | UA_LocalizedText tmp; |
| 39906 | UA_StatusCode retval = UA_LocalizedText_copy(src: source, dst: &tmp); |
| 39907 | if(retval != UA_STATUSCODE_GOOD) |
| 39908 | return retval; |
| 39909 | UA_LocalizedText_clear(p: target); |
| 39910 | *target = tmp; |
| 39911 | return UA_STATUSCODE_GOOD; |
| 39912 | } |
| 39913 | |
| 39914 | /* Trigger sampling if a MonitoredItem surveils the attribute with no sampling |
| 39915 | * interval */ |
| 39916 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 39917 | static void |
| 39918 | triggerImmediateDataChange(UA_Server *server, UA_Session *session, |
| 39919 | UA_Node *node, const UA_WriteValue *wvalue) { |
| 39920 | UA_MonitoredItem *mon = node->head.monitoredItems; |
| 39921 | for(; mon != NULL; mon = mon->sampling.nodeListNext) { |
| 39922 | if(mon->itemToMonitor.attributeId != wvalue->attributeId) |
| 39923 | continue; |
| 39924 | UA_DataValue value; |
| 39925 | UA_DataValue_init(p: &value); |
| 39926 | ReadWithNode(node, server, session, timestampsToReturn: mon->timestampsToReturn, |
| 39927 | id: &mon->itemToMonitor, v: &value); |
| 39928 | UA_MonitoredItem_processSampledValue(server, mon, value: &value); |
| 39929 | } |
| 39930 | } |
| 39931 | #endif |
| 39932 | |
| 39933 | /* This function implements the main part of the write service and operates on a |
| 39934 | copy of the node (not in single-threaded mode). */ |
| 39935 | static UA_StatusCode |
| 39936 | copyAttributeIntoNode(UA_Server *server, UA_Session *session, |
| 39937 | UA_Node *node, const UA_WriteValue *wvalue) { |
| 39938 | UA_assert(session != NULL); |
| 39939 | const void *value = wvalue->value.value.data; |
| 39940 | UA_UInt32 userWriteMask = getUserWriteMask(server, session, head: &node->head); |
| 39941 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 39942 | |
| 39943 | UA_LOG_NODEID_TRACE(&node->head.nodeId, |
| 39944 | UA_LOG_TRACE_SESSION(server->config.logging, session, |
| 39945 | "Write attribute %"PRIi32 " of Node %.*s", |
| 39946 | wvalue->attributeId, (int)nodeIdStr.length, |
| 39947 | nodeIdStr.data)); |
| 39948 | |
| 39949 | const UA_VariableTypeNode *type; |
| 39950 | |
| 39951 | switch(wvalue->attributeId) { |
| 39952 | case UA_ATTRIBUTEID_NODEID: |
| 39953 | case UA_ATTRIBUTEID_NODECLASS: |
| 39954 | case UA_ATTRIBUTEID_USERWRITEMASK: |
| 39955 | case UA_ATTRIBUTEID_USERACCESSLEVEL: |
| 39956 | case UA_ATTRIBUTEID_USEREXECUTABLE: |
| 39957 | case UA_ATTRIBUTEID_BROWSENAME: /* BrowseName is tracked in a binary tree |
| 39958 | for fast lookup */ |
| 39959 | retval = UA_STATUSCODE_BADWRITENOTSUPPORTED; |
| 39960 | break; |
| 39961 | case UA_ATTRIBUTEID_DISPLAYNAME: |
| 39962 | CHECK_USERWRITEMASK(UA_WRITEMASK_DISPLAYNAME); |
| 39963 | CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT); |
| 39964 | retval = UA_Node_insertOrUpdateDisplayName(head: &node->head, |
| 39965 | value: (const UA_LocalizedText *)value); |
| 39966 | break; |
| 39967 | case UA_ATTRIBUTEID_DESCRIPTION: |
| 39968 | CHECK_USERWRITEMASK(UA_WRITEMASK_DESCRIPTION); |
| 39969 | CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT); |
| 39970 | retval = UA_Node_insertOrUpdateDescription(head: &node->head, |
| 39971 | value: (const UA_LocalizedText *)value); |
| 39972 | break; |
| 39973 | case UA_ATTRIBUTEID_WRITEMASK: |
| 39974 | CHECK_USERWRITEMASK(UA_WRITEMASK_WRITEMASK); |
| 39975 | CHECK_DATATYPE_SCALAR(UINT32); |
| 39976 | node->head.writeMask = *(const UA_UInt32*)value; |
| 39977 | break; |
| 39978 | case UA_ATTRIBUTEID_ISABSTRACT: |
| 39979 | CHECK_USERWRITEMASK(UA_WRITEMASK_ISABSTRACT); |
| 39980 | CHECK_DATATYPE_SCALAR(BOOLEAN); |
| 39981 | retval = writeIsAbstract(node, value: *(const UA_Boolean*)value); |
| 39982 | break; |
| 39983 | case UA_ATTRIBUTEID_SYMMETRIC: |
| 39984 | CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE); |
| 39985 | CHECK_USERWRITEMASK(UA_WRITEMASK_SYMMETRIC); |
| 39986 | CHECK_DATATYPE_SCALAR(BOOLEAN); |
| 39987 | node->referenceTypeNode.symmetric = *(const UA_Boolean*)value; |
| 39988 | break; |
| 39989 | case UA_ATTRIBUTEID_INVERSENAME: |
| 39990 | CHECK_NODECLASS_WRITE(UA_NODECLASS_REFERENCETYPE); |
| 39991 | CHECK_USERWRITEMASK(UA_WRITEMASK_INVERSENAME); |
| 39992 | CHECK_DATATYPE_SCALAR(LOCALIZEDTEXT); |
| 39993 | retval = updateLocalizedText(source: (const UA_LocalizedText *)value, |
| 39994 | target: &node->referenceTypeNode.inverseName); |
| 39995 | break; |
| 39996 | case UA_ATTRIBUTEID_CONTAINSNOLOOPS: |
| 39997 | CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW); |
| 39998 | CHECK_USERWRITEMASK(UA_WRITEMASK_CONTAINSNOLOOPS); |
| 39999 | CHECK_DATATYPE_SCALAR(BOOLEAN); |
| 40000 | node->viewNode.containsNoLoops = *(const UA_Boolean*)value; |
| 40001 | break; |
| 40002 | case UA_ATTRIBUTEID_EVENTNOTIFIER: |
| 40003 | CHECK_NODECLASS_WRITE(UA_NODECLASS_VIEW | UA_NODECLASS_OBJECT); |
| 40004 | CHECK_USERWRITEMASK(UA_WRITEMASK_EVENTNOTIFIER); |
| 40005 | CHECK_DATATYPE_SCALAR(BYTE); |
| 40006 | if(node->head.nodeClass == UA_NODECLASS_VIEW) { |
| 40007 | node->viewNode.eventNotifier = *(const UA_Byte*)value; |
| 40008 | } else { |
| 40009 | node->objectNode.eventNotifier = *(const UA_Byte*)value; |
| 40010 | } |
| 40011 | break; |
| 40012 | case UA_ATTRIBUTEID_VALUE: |
| 40013 | CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE); |
| 40014 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE) { |
| 40015 | /* The access to a value variable is granted via the AccessLevel |
| 40016 | * and UserAccessLevel attributes */ |
| 40017 | UA_Byte accessLevel = getAccessLevel(server, session, node: &node->variableNode); |
| 40018 | if(!(accessLevel & (UA_ACCESSLEVELMASK_WRITE))) { |
| 40019 | retval = UA_STATUSCODE_BADNOTWRITABLE; |
| 40020 | break; |
| 40021 | } |
| 40022 | accessLevel = getUserAccessLevel(server, session, node: &node->variableNode); |
| 40023 | if(!(accessLevel & (UA_ACCESSLEVELMASK_WRITE))) { |
| 40024 | retval = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 40025 | break; |
| 40026 | } |
| 40027 | } else { /* UA_NODECLASS_VARIABLETYPE */ |
| 40028 | CHECK_USERWRITEMASK(UA_WRITEMASK_VALUEFORVARIABLETYPE); |
| 40029 | } |
| 40030 | retval = writeNodeValueAttribute(server, session, node: &node->variableNode, |
| 40031 | value: &wvalue->value, indexRange: &wvalue->indexRange); |
| 40032 | break; |
| 40033 | case UA_ATTRIBUTEID_DATATYPE: |
| 40034 | CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE); |
| 40035 | CHECK_USERWRITEMASK(UA_WRITEMASK_DATATYPE); |
| 40036 | CHECK_DATATYPE_SCALAR(NODEID); |
| 40037 | GET_NODETYPE; |
| 40038 | retval = writeDataTypeAttribute(server, session, node: &node->variableNode, |
| 40039 | type, dataType: (const UA_NodeId*)value); |
| 40040 | UA_NODESTORE_RELEASE(server, (const UA_Node*)type); |
| 40041 | break; |
| 40042 | case UA_ATTRIBUTEID_VALUERANK: |
| 40043 | CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE); |
| 40044 | CHECK_USERWRITEMASK(UA_WRITEMASK_VALUERANK); |
| 40045 | CHECK_DATATYPE_SCALAR(INT32); |
| 40046 | GET_NODETYPE; |
| 40047 | retval = writeValueRank(server, session, node: &node->variableNode, |
| 40048 | type, valueRank: *(const UA_Int32*)value); |
| 40049 | UA_NODESTORE_RELEASE(server, (const UA_Node*)type); |
| 40050 | break; |
| 40051 | case UA_ATTRIBUTEID_ARRAYDIMENSIONS: |
| 40052 | CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE | UA_NODECLASS_VARIABLETYPE); |
| 40053 | CHECK_USERWRITEMASK(UA_WRITEMASK_ARRRAYDIMENSIONS); |
| 40054 | CHECK_DATATYPE_ARRAY(UINT32); |
| 40055 | GET_NODETYPE; |
| 40056 | retval = writeArrayDimensionsAttribute(server, session, node: &node->variableNode, |
| 40057 | type, arrayDimensionsSize: wvalue->value.value.arrayLength, |
| 40058 | arrayDimensions: (UA_UInt32 *)wvalue->value.value.data); |
| 40059 | UA_NODESTORE_RELEASE(server, (const UA_Node*)type); |
| 40060 | break; |
| 40061 | case UA_ATTRIBUTEID_ACCESSLEVEL: |
| 40062 | CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE); |
| 40063 | CHECK_USERWRITEMASK(UA_WRITEMASK_ACCESSLEVEL); |
| 40064 | CHECK_DATATYPE_SCALAR(BYTE); |
| 40065 | node->variableNode.accessLevel = *(const UA_Byte*)value; |
| 40066 | break; |
| 40067 | case UA_ATTRIBUTEID_ACCESSLEVELEX: |
| 40068 | CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE); |
| 40069 | CHECK_USERWRITEMASK(UA_WRITEMASK_ACCESSLEVELEX); |
| 40070 | CHECK_DATATYPE_SCALAR(UINT32); |
| 40071 | node->variableNode.accessLevel = (UA_Byte)(*(const UA_UInt32*)value & 0xFF); |
| 40072 | break; |
| 40073 | case UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL: |
| 40074 | CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE); |
| 40075 | CHECK_USERWRITEMASK(UA_WRITEMASK_MINIMUMSAMPLINGINTERVAL); |
| 40076 | CHECK_DATATYPE_SCALAR(DOUBLE); |
| 40077 | node->variableNode.minimumSamplingInterval = *(const UA_Double*)value; |
| 40078 | break; |
| 40079 | case UA_ATTRIBUTEID_HISTORIZING: |
| 40080 | CHECK_NODECLASS_WRITE(UA_NODECLASS_VARIABLE); |
| 40081 | CHECK_USERWRITEMASK(UA_WRITEMASK_HISTORIZING); |
| 40082 | CHECK_DATATYPE_SCALAR(BOOLEAN); |
| 40083 | node->variableNode.historizing = *(const UA_Boolean*)value; |
| 40084 | break; |
| 40085 | case UA_ATTRIBUTEID_EXECUTABLE: |
| 40086 | CHECK_NODECLASS_WRITE(UA_NODECLASS_METHOD); |
| 40087 | CHECK_USERWRITEMASK(UA_WRITEMASK_EXECUTABLE); |
| 40088 | CHECK_DATATYPE_SCALAR(BOOLEAN); |
| 40089 | node->methodNode.executable = *(const UA_Boolean*)value; |
| 40090 | break; |
| 40091 | default: |
| 40092 | retval = UA_STATUSCODE_BADATTRIBUTEIDINVALID; |
| 40093 | break; |
| 40094 | } |
| 40095 | |
| 40096 | /* Check if writing succeeded */ |
| 40097 | if(retval != UA_STATUSCODE_GOOD) { |
| 40098 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 40099 | "WriteRequest returned status code %s", |
| 40100 | UA_StatusCode_name(retval)); |
| 40101 | return retval; |
| 40102 | } |
| 40103 | |
| 40104 | /* Trigger MonitoredItems with no SamplingInterval */ |
| 40105 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 40106 | triggerImmediateDataChange(server, session, node, wvalue); |
| 40107 | #endif |
| 40108 | |
| 40109 | return UA_STATUSCODE_GOOD; |
| 40110 | } |
| 40111 | |
| 40112 | void |
| 40113 | Operation_Write(UA_Server *server, UA_Session *session, void *context, |
| 40114 | const UA_WriteValue *wv, UA_StatusCode *result) { |
| 40115 | UA_assert(session != NULL); |
| 40116 | *result = UA_Server_editNode(server, session, nodeId: &wv->nodeId, |
| 40117 | callback: (UA_EditNodeCallback)copyAttributeIntoNode, |
| 40118 | data: (void*)(uintptr_t)wv); |
| 40119 | } |
| 40120 | |
| 40121 | void |
| 40122 | Service_Write(UA_Server *server, UA_Session *session, |
| 40123 | const UA_WriteRequest *request, |
| 40124 | UA_WriteResponse *response) { |
| 40125 | UA_assert(session != NULL); |
| 40126 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 40127 | "Processing WriteRequest"); |
| 40128 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 40129 | |
| 40130 | if(server->config.maxNodesPerWrite != 0 && |
| 40131 | request->nodesToWriteSize > server->config.maxNodesPerWrite) { |
| 40132 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 40133 | return; |
| 40134 | } |
| 40135 | |
| 40136 | response->responseHeader.serviceResult = |
| 40137 | UA_Server_processServiceOperations(server, session, |
| 40138 | operationCallback: (UA_ServiceOperation)Operation_Write, NULL, |
| 40139 | requestOperations: &request->nodesToWriteSize, |
| 40140 | requestOperationsType: &UA_TYPES[UA_TYPES_WRITEVALUE], |
| 40141 | responseOperations: &response->resultsSize, |
| 40142 | responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 40143 | } |
| 40144 | |
| 40145 | UA_StatusCode |
| 40146 | UA_Server_write(UA_Server *server, const UA_WriteValue *value) { |
| 40147 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 40148 | lockServer(server); |
| 40149 | Operation_Write(server, session: &server->adminSession, NULL, wv: value, result: &res); |
| 40150 | unlockServer(server); |
| 40151 | return res; |
| 40152 | } |
| 40153 | |
| 40154 | /* Convenience function to be wrapped into inline functions */ |
| 40155 | UA_StatusCode |
| 40156 | __UA_Server_write(UA_Server *server, const UA_NodeId *nodeId, |
| 40157 | const UA_AttributeId attributeId, |
| 40158 | const UA_DataType *attr_type, const void *attr) { |
| 40159 | lockServer(server); |
| 40160 | UA_StatusCode res = writeAttribute(server, session: &server->adminSession, |
| 40161 | nodeId, attributeId, attr, attr_type); |
| 40162 | unlockServer(server); |
| 40163 | return res; |
| 40164 | } |
| 40165 | |
| 40166 | /* Internal convenience function */ |
| 40167 | UA_StatusCode |
| 40168 | writeAttribute(UA_Server *server, UA_Session *session, |
| 40169 | const UA_NodeId *nodeId, const UA_AttributeId attributeId, |
| 40170 | const void *attr, const UA_DataType *attr_type) { |
| 40171 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 40172 | |
| 40173 | UA_WriteValue wvalue; |
| 40174 | UA_WriteValue_init(p: &wvalue); |
| 40175 | wvalue.nodeId = *nodeId; |
| 40176 | wvalue.attributeId = attributeId; |
| 40177 | wvalue.value.hasValue = true; |
| 40178 | if(attr_type == &UA_TYPES[UA_TYPES_VARIANT]) { |
| 40179 | wvalue.value.value = *(const UA_Variant*)attr; |
| 40180 | } else if(attr_type == &UA_TYPES[UA_TYPES_DATAVALUE]) { |
| 40181 | wvalue.value = *(const UA_DataValue*)attr; |
| 40182 | } else { |
| 40183 | /* hacked cast. the target WriteValue is used as const anyway */ |
| 40184 | UA_Variant_setScalar(v: &wvalue.value.value, |
| 40185 | p: (void*)(uintptr_t)attr, type: attr_type); |
| 40186 | } |
| 40187 | |
| 40188 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 40189 | Operation_Write(server, session, NULL, wv: &wvalue, result: &res); |
| 40190 | return res; |
| 40191 | } |
| 40192 | |
| 40193 | #ifdef UA_ENABLE_HISTORIZING |
| 40194 | typedef void |
| 40195 | (*UA_HistoryDatabase_readFunc)(UA_Server *server, void *hdbContext, |
| 40196 | const UA_NodeId *sessionId, void *sessionContext, |
| 40197 | const UA_RequestHeader *requestHeader, |
| 40198 | const void *historyReadDetails, |
| 40199 | UA_TimestampsToReturn timestampsToReturn, |
| 40200 | UA_Boolean releaseContinuationPoints, |
| 40201 | size_t nodesToReadSize, |
| 40202 | const UA_HistoryReadValueId *nodesToRead, |
| 40203 | UA_HistoryReadResponse *response, |
| 40204 | void * const * const historyData); |
| 40205 | |
| 40206 | void |
| 40207 | Service_HistoryRead(UA_Server *server, UA_Session *session, |
| 40208 | const UA_HistoryReadRequest *request, |
| 40209 | UA_HistoryReadResponse *response) { |
| 40210 | UA_assert(session != NULL); |
| 40211 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 40212 | if(server->config.historyDatabase.context == NULL) { |
| 40213 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTSUPPORTED; |
| 40214 | return; |
| 40215 | } |
| 40216 | |
| 40217 | if(request->historyReadDetails.encoding != UA_EXTENSIONOBJECT_DECODED) { |
| 40218 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTSUPPORTED; |
| 40219 | return; |
| 40220 | } |
| 40221 | |
| 40222 | const UA_DataType *historyDataType = &UA_TYPES[UA_TYPES_HISTORYDATA]; |
| 40223 | UA_HistoryDatabase_readFunc readHistory = NULL; |
| 40224 | if(request->historyReadDetails.content.decoded.type == |
| 40225 | &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS]) { |
| 40226 | UA_ReadRawModifiedDetails *details = (UA_ReadRawModifiedDetails*) |
| 40227 | request->historyReadDetails.content.decoded.data; |
| 40228 | if(!details->isReadModified) { |
| 40229 | readHistory = (UA_HistoryDatabase_readFunc) |
| 40230 | server->config.historyDatabase.readRaw; |
| 40231 | } else { |
| 40232 | historyDataType = &UA_TYPES[UA_TYPES_HISTORYMODIFIEDDATA]; |
| 40233 | readHistory = (UA_HistoryDatabase_readFunc) |
| 40234 | server->config.historyDatabase.readModified; |
| 40235 | } |
| 40236 | } else if(request->historyReadDetails.content.decoded.type == |
| 40237 | &UA_TYPES[UA_TYPES_READEVENTDETAILS]) { |
| 40238 | historyDataType = &UA_TYPES[UA_TYPES_HISTORYEVENT]; |
| 40239 | readHistory = (UA_HistoryDatabase_readFunc) |
| 40240 | server->config.historyDatabase.readEvent; |
| 40241 | } else if(request->historyReadDetails.content.decoded.type == |
| 40242 | &UA_TYPES[UA_TYPES_READPROCESSEDDETAILS]) { |
| 40243 | readHistory = (UA_HistoryDatabase_readFunc) |
| 40244 | server->config.historyDatabase.readProcessed; |
| 40245 | } else if(request->historyReadDetails.content.decoded.type == |
| 40246 | &UA_TYPES[UA_TYPES_READATTIMEDETAILS]) { |
| 40247 | readHistory = (UA_HistoryDatabase_readFunc) |
| 40248 | server->config.historyDatabase.readAtTime; |
| 40249 | } else { |
| 40250 | /* TODO handle more request->historyReadDetails.content.decoded.type types */ |
| 40251 | response->responseHeader.serviceResult = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED; |
| 40252 | return; |
| 40253 | } |
| 40254 | |
| 40255 | /* Check if the configured History-Backend supports the requested history type */ |
| 40256 | if(!readHistory) { |
| 40257 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 40258 | "The configured HistoryBackend does not support the selected history-type."); |
| 40259 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTSUPPORTED; |
| 40260 | return; |
| 40261 | } |
| 40262 | |
| 40263 | /* Something to do? */ |
| 40264 | if(request->nodesToReadSize == 0) { |
| 40265 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO; |
| 40266 | return; |
| 40267 | } |
| 40268 | |
| 40269 | /* Check if there are too many operations */ |
| 40270 | if(server->config.maxNodesPerRead != 0 && |
| 40271 | request->nodesToReadSize > server->config.maxNodesPerRead) { |
| 40272 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 40273 | return; |
| 40274 | } |
| 40275 | |
| 40276 | /* Allocate a temporary array to forward the result pointers to the |
| 40277 | * backend */ |
| 40278 | void **historyData = (void **) |
| 40279 | UA_calloc(nmemb: request->nodesToReadSize, size: sizeof(void*)); |
| 40280 | if(!historyData) { |
| 40281 | response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 40282 | return; |
| 40283 | } |
| 40284 | |
| 40285 | /* Allocate the results array */ |
| 40286 | response->results = (UA_HistoryReadResult*) |
| 40287 | UA_Array_new(size: request->nodesToReadSize, type: &UA_TYPES[UA_TYPES_HISTORYREADRESULT]); |
| 40288 | if(!response->results) { |
| 40289 | UA_free(ptr: historyData); |
| 40290 | response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 40291 | return; |
| 40292 | } |
| 40293 | response->resultsSize = request->nodesToReadSize; |
| 40294 | |
| 40295 | for(size_t i = 0; i < response->resultsSize; ++i) { |
| 40296 | void * data = UA_new(type: historyDataType); |
| 40297 | UA_ExtensionObject_setValue(eo: &response->results[i].historyData, |
| 40298 | p: data, type: historyDataType); |
| 40299 | historyData[i] = data; |
| 40300 | } |
| 40301 | readHistory(server, server->config.historyDatabase.context, |
| 40302 | &session->sessionId, session->sessionHandle, |
| 40303 | &request->requestHeader, |
| 40304 | request->historyReadDetails.content.decoded.data, |
| 40305 | request->timestampsToReturn, |
| 40306 | request->releaseContinuationPoints, |
| 40307 | request->nodesToReadSize, request->nodesToRead, |
| 40308 | response, historyData); |
| 40309 | UA_free(ptr: historyData); |
| 40310 | } |
| 40311 | |
| 40312 | void |
| 40313 | Service_HistoryUpdate(UA_Server *server, UA_Session *session, |
| 40314 | const UA_HistoryUpdateRequest *request, |
| 40315 | UA_HistoryUpdateResponse *response) { |
| 40316 | UA_assert(session != NULL); |
| 40317 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 40318 | |
| 40319 | response->resultsSize = request->historyUpdateDetailsSize; |
| 40320 | response->results = (UA_HistoryUpdateResult*) |
| 40321 | UA_Array_new(size: response->resultsSize, type: &UA_TYPES[UA_TYPES_HISTORYUPDATERESULT]); |
| 40322 | if(!response->results) { |
| 40323 | response->resultsSize = 0; |
| 40324 | response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 40325 | return; |
| 40326 | } |
| 40327 | |
| 40328 | for(size_t i = 0; i < request->historyUpdateDetailsSize; ++i) { |
| 40329 | UA_HistoryUpdateResult_init(p: &response->results[i]); |
| 40330 | if(request->historyUpdateDetails[i].encoding != UA_EXTENSIONOBJECT_DECODED) { |
| 40331 | response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED; |
| 40332 | continue; |
| 40333 | } |
| 40334 | |
| 40335 | const UA_DataType *updateDetailsType = |
| 40336 | request->historyUpdateDetails[i].content.decoded.type; |
| 40337 | void *updateDetailsData = request->historyUpdateDetails[i].content.decoded.data; |
| 40338 | |
| 40339 | if(updateDetailsType == &UA_TYPES[UA_TYPES_UPDATEDATADETAILS]) { |
| 40340 | if(!server->config.historyDatabase.updateData) { |
| 40341 | response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED; |
| 40342 | continue; |
| 40343 | } |
| 40344 | server->config.historyDatabase. |
| 40345 | updateData(server, server->config.historyDatabase.context, |
| 40346 | &session->sessionId, session->sessionHandle, |
| 40347 | &request->requestHeader, |
| 40348 | (UA_UpdateDataDetails*)updateDetailsData, |
| 40349 | &response->results[i]); |
| 40350 | continue; |
| 40351 | } |
| 40352 | |
| 40353 | if(updateDetailsType == &UA_TYPES[UA_TYPES_DELETERAWMODIFIEDDETAILS]) { |
| 40354 | if(!server->config.historyDatabase.deleteRawModified) { |
| 40355 | response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED; |
| 40356 | continue; |
| 40357 | } |
| 40358 | server->config.historyDatabase. |
| 40359 | deleteRawModified(server, server->config.historyDatabase.context, |
| 40360 | &session->sessionId, session->sessionHandle, |
| 40361 | &request->requestHeader, |
| 40362 | (UA_DeleteRawModifiedDetails*)updateDetailsData, |
| 40363 | &response->results[i]); |
| 40364 | continue; |
| 40365 | } |
| 40366 | |
| 40367 | response->results[i].statusCode = UA_STATUSCODE_BADNOTSUPPORTED; |
| 40368 | } |
| 40369 | } |
| 40370 | |
| 40371 | #endif |
| 40372 | |
| 40373 | UA_StatusCode |
| 40374 | UA_Server_writeObjectProperty(UA_Server *server, const UA_NodeId objectId, |
| 40375 | const UA_QualifiedName propertyName, |
| 40376 | const UA_Variant value) { |
| 40377 | lockServer(server); |
| 40378 | UA_StatusCode retVal = writeObjectProperty(server, objectId, propertyName, value); |
| 40379 | unlockServer(server); |
| 40380 | return retVal; |
| 40381 | } |
| 40382 | |
| 40383 | UA_StatusCode |
| 40384 | writeObjectProperty(UA_Server *server, const UA_NodeId objectId, |
| 40385 | const UA_QualifiedName propertyName, |
| 40386 | const UA_Variant value) { |
| 40387 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 40388 | UA_RelativePathElement rpe; |
| 40389 | UA_RelativePathElement_init(p: &rpe); |
| 40390 | rpe.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY); |
| 40391 | rpe.isInverse = false; |
| 40392 | rpe.includeSubtypes = false; |
| 40393 | rpe.targetName = propertyName; |
| 40394 | |
| 40395 | UA_BrowsePath bp; |
| 40396 | UA_BrowsePath_init(p: &bp); |
| 40397 | bp.startingNode = objectId; |
| 40398 | bp.relativePath.elementsSize = 1; |
| 40399 | bp.relativePath.elements = &rpe; |
| 40400 | |
| 40401 | UA_StatusCode retval; |
| 40402 | UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp); |
| 40403 | if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { |
| 40404 | retval = bpr.statusCode; |
| 40405 | UA_BrowsePathResult_clear(p: &bpr); |
| 40406 | return retval; |
| 40407 | } |
| 40408 | |
| 40409 | retval = writeValueAttribute(server, nodeId: bpr.targets[0].targetId.nodeId, value: &value); |
| 40410 | |
| 40411 | UA_BrowsePathResult_clear(p: &bpr); |
| 40412 | return retval; |
| 40413 | } |
| 40414 | |
| 40415 | UA_StatusCode |
| 40416 | writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId, |
| 40417 | const UA_QualifiedName propertyName, |
| 40418 | const void *value, const UA_DataType *type) { |
| 40419 | UA_Variant var; |
| 40420 | UA_Variant_init(p: &var); |
| 40421 | UA_Variant_setScalar(v: &var, p: (void*)(uintptr_t)value, type); |
| 40422 | return writeObjectProperty(server, objectId, propertyName, value: var); |
| 40423 | } |
| 40424 | |
| 40425 | UA_StatusCode UA_EXPORT |
| 40426 | UA_Server_writeObjectProperty_scalar(UA_Server *server, const UA_NodeId objectId, |
| 40427 | const UA_QualifiedName propertyName, |
| 40428 | const void *value, const UA_DataType *type) { |
| 40429 | lockServer(server); |
| 40430 | UA_StatusCode retval = |
| 40431 | writeObjectProperty_scalar(server, objectId, propertyName, value, type); |
| 40432 | unlockServer(server); |
| 40433 | return retval; |
| 40434 | } |
| 40435 | |
| 40436 | static UA_LocalizedText |
| 40437 | getLocalizedForSession(const UA_Session *session, |
| 40438 | const UA_LocalizedTextListEntry *root) { |
| 40439 | const UA_LocalizedTextListEntry *lt; |
| 40440 | UA_LocalizedText result; |
| 40441 | UA_LocalizedText_init(p: &result); |
| 40442 | |
| 40443 | /* No session. Return the first */ |
| 40444 | if(!session) |
| 40445 | goto not_found; |
| 40446 | |
| 40447 | /* Exact match? */ |
| 40448 | for(size_t i = 0; i < session->localeIdsSize; ++i) { |
| 40449 | for(lt = root; lt != NULL; lt = lt->next) { |
| 40450 | if(UA_String_equal(p1: &session->localeIds[i], p2: <->localizedText.locale)) |
| 40451 | return lt->localizedText; |
| 40452 | } |
| 40453 | } |
| 40454 | |
| 40455 | /* Partial match, e.g. de-DE instead of de-CH */ |
| 40456 | for(size_t i = 0; i < session->localeIdsSize; ++i) { |
| 40457 | if(session->localeIds[i].length < 2 || |
| 40458 | (session->localeIdsSize > 2 && |
| 40459 | session->localeIds[i].data[2] != '-')) |
| 40460 | continue; |
| 40461 | |
| 40462 | UA_String requestedPrefix; |
| 40463 | requestedPrefix.data = session->localeIds[i].data; |
| 40464 | requestedPrefix.length = 2; |
| 40465 | |
| 40466 | for(lt = root; lt != NULL; lt = lt->next) { |
| 40467 | if(lt->localizedText.locale.length < 2 || |
| 40468 | (lt->localizedText.locale.length > 2 && |
| 40469 | lt->localizedText.locale.data[2] != '-')) |
| 40470 | continue; |
| 40471 | |
| 40472 | UA_String currentPrefix; |
| 40473 | currentPrefix.data = lt->localizedText.locale.data; |
| 40474 | currentPrefix.length = 2; |
| 40475 | |
| 40476 | if(UA_String_equal(p1: &requestedPrefix, p2: ¤tPrefix)) |
| 40477 | return lt->localizedText; |
| 40478 | } |
| 40479 | } |
| 40480 | |
| 40481 | /* Not found. Return the first localized text that was added (last in the |
| 40482 | * linked list). Return an empty result if the list is empty. */ |
| 40483 | not_found: |
| 40484 | if(!root) |
| 40485 | return result; |
| 40486 | while(root->next) |
| 40487 | root = root->next; |
| 40488 | return root->localizedText; |
| 40489 | } |
| 40490 | |
| 40491 | UA_LocalizedText |
| 40492 | UA_Session_getNodeDisplayName(const UA_Session *session, |
| 40493 | const UA_NodeHead *head) { |
| 40494 | return getLocalizedForSession(session, root: head->displayName); |
| 40495 | } |
| 40496 | |
| 40497 | UA_LocalizedText |
| 40498 | UA_Session_getNodeDescription(const UA_Session *session, |
| 40499 | const UA_NodeHead *head) { |
| 40500 | return getLocalizedForSession(session, root: head->description); |
| 40501 | } |
| 40502 | |
| 40503 | /**** amalgamated original file "/src/server/ua_services_discovery.c" ****/ |
| 40504 | |
| 40505 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 40506 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 40507 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 40508 | * |
| 40509 | * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 40510 | * Copyright 2014-2016 (c) Sten Grüner |
| 40511 | * Copyright 2014, 2017 (c) Florian Palm |
| 40512 | * Copyright 2016 (c) Oleksiy Vasylyev |
| 40513 | * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH |
| 40514 | * Copyright 2017 (c) frax2222 |
| 40515 | * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB |
| 40516 | */ |
| 40517 | |
| 40518 | |
| 40519 | #ifdef UA_ENABLE_DISCOVERY |
| 40520 | |
| 40521 | |
| 40522 | static UA_StatusCode |
| 40523 | setApplicationDescriptionFromRegisteredServer(const UA_FindServersRequest *request, |
| 40524 | UA_ApplicationDescription *target, |
| 40525 | const UA_RegisteredServer *registeredServer) { |
| 40526 | UA_ApplicationDescription_init(p: target); |
| 40527 | UA_StatusCode retval = |
| 40528 | UA_String_copy(src: ®isteredServer->serverUri, dst: &target->applicationUri); |
| 40529 | if(retval != UA_STATUSCODE_GOOD) |
| 40530 | return retval; |
| 40531 | |
| 40532 | retval = UA_String_copy(src: ®isteredServer->productUri, dst: &target->productUri); |
| 40533 | if(retval != UA_STATUSCODE_GOOD) |
| 40534 | return retval; |
| 40535 | |
| 40536 | // if the client requests a specific locale, select the corresponding server name |
| 40537 | if(request->localeIdsSize) { |
| 40538 | UA_Boolean appNameFound = false; |
| 40539 | for(size_t i =0; i<request->localeIdsSize && !appNameFound; i++) { |
| 40540 | for(size_t j =0; j<registeredServer->serverNamesSize; j++) { |
| 40541 | if(UA_String_equal(p1: &request->localeIds[i], |
| 40542 | p2: ®isteredServer->serverNames[j].locale)) { |
| 40543 | retval = UA_LocalizedText_copy(src: ®isteredServer->serverNames[j], |
| 40544 | dst: &target->applicationName); |
| 40545 | if(retval != UA_STATUSCODE_GOOD) |
| 40546 | return retval; |
| 40547 | appNameFound = true; |
| 40548 | break; |
| 40549 | } |
| 40550 | } |
| 40551 | } |
| 40552 | |
| 40553 | // server does not have the requested local, therefore we can select the |
| 40554 | // most suitable one |
| 40555 | if(!appNameFound && registeredServer->serverNamesSize) { |
| 40556 | retval = UA_LocalizedText_copy(src: ®isteredServer->serverNames[0], |
| 40557 | dst: &target->applicationName); |
| 40558 | if(retval != UA_STATUSCODE_GOOD) |
| 40559 | return retval; |
| 40560 | } |
| 40561 | } else if(registeredServer->serverNamesSize) { |
| 40562 | // just take the first name |
| 40563 | retval = UA_LocalizedText_copy(src: ®isteredServer->serverNames[0], |
| 40564 | dst: &target->applicationName); |
| 40565 | if(retval != UA_STATUSCODE_GOOD) |
| 40566 | return retval; |
| 40567 | } |
| 40568 | |
| 40569 | target->applicationType = registeredServer->serverType; |
| 40570 | retval = UA_String_copy(src: ®isteredServer->gatewayServerUri, dst: &target->gatewayServerUri); |
| 40571 | if(retval != UA_STATUSCODE_GOOD) |
| 40572 | return retval; |
| 40573 | // TODO where do we get the discoveryProfileUri for application data? |
| 40574 | |
| 40575 | target->discoveryUrlsSize = registeredServer->discoveryUrlsSize; |
| 40576 | if(registeredServer->discoveryUrlsSize) { |
| 40577 | size_t duSize = sizeof(UA_String) * registeredServer->discoveryUrlsSize; |
| 40578 | target->discoveryUrls = (UA_String *)UA_malloc(size: duSize); |
| 40579 | if(!target->discoveryUrls) |
| 40580 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 40581 | for(size_t i = 0; i < registeredServer->discoveryUrlsSize; i++) { |
| 40582 | retval = UA_String_copy(src: ®isteredServer->discoveryUrls[i], |
| 40583 | dst: &target->discoveryUrls[i]); |
| 40584 | if(retval != UA_STATUSCODE_GOOD) |
| 40585 | return retval; |
| 40586 | } |
| 40587 | } |
| 40588 | |
| 40589 | return retval; |
| 40590 | } |
| 40591 | #endif |
| 40592 | |
| 40593 | void Service_FindServers(UA_Server *server, UA_Session *session, |
| 40594 | const UA_FindServersRequest *request, |
| 40595 | UA_FindServersResponse *response) { |
| 40596 | UA_LOG_DEBUG_SESSION(server->config.logging, session, "Processing FindServersRequest"); |
| 40597 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 40598 | |
| 40599 | /* Return the server itself? */ |
| 40600 | UA_Boolean foundSelf = false; |
| 40601 | if(request->serverUrisSize) { |
| 40602 | for(size_t i = 0; i < request->serverUrisSize; i++) { |
| 40603 | if(UA_String_equal(p1: &request->serverUris[i], |
| 40604 | p2: &server->config.applicationDescription.applicationUri)) { |
| 40605 | foundSelf = true; |
| 40606 | break; |
| 40607 | } |
| 40608 | } |
| 40609 | } else { |
| 40610 | foundSelf = true; |
| 40611 | } |
| 40612 | |
| 40613 | #ifndef UA_ENABLE_DISCOVERY |
| 40614 | if(!foundSelf) |
| 40615 | return; |
| 40616 | |
| 40617 | response->responseHeader.serviceResult = |
| 40618 | UA_Array_copy(&server->config.applicationDescription, 1, |
| 40619 | (void**)&response->servers, |
| 40620 | &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]); |
| 40621 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) |
| 40622 | return; |
| 40623 | |
| 40624 | response->serversSize = 1; |
| 40625 | #else |
| 40626 | UA_DiscoveryManager *dm = (UA_DiscoveryManager*) |
| 40627 | getServerComponentByName(server, name: UA_STRING(chars: "discovery")); |
| 40628 | if(!dm) { |
| 40629 | response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; |
| 40630 | return; |
| 40631 | } |
| 40632 | |
| 40633 | /* Allocate enough memory, including memory for the "self" response */ |
| 40634 | size_t maxResults = dm->registeredServersSize + 1; |
| 40635 | response->servers = (UA_ApplicationDescription*) |
| 40636 | UA_Array_new(size: maxResults, type: &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]); |
| 40637 | if(!response->servers) { |
| 40638 | response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 40639 | return; |
| 40640 | } |
| 40641 | |
| 40642 | /* Copy into the response. TODO: Evaluate return codes */ |
| 40643 | size_t pos = 0; |
| 40644 | if(foundSelf) |
| 40645 | UA_ApplicationDescription_copy(src: &server->config.applicationDescription, |
| 40646 | dst: &response->servers[pos++]); |
| 40647 | |
| 40648 | registeredServer_list_entry* current; |
| 40649 | LIST_FOREACH(current, &dm->registeredServers, pointers) { |
| 40650 | UA_Boolean usable = (request->serverUrisSize == 0); |
| 40651 | if(!usable) { |
| 40652 | /* If client only requested a specific set of servers */ |
| 40653 | for(size_t i = 0; i < request->serverUrisSize; i++) { |
| 40654 | if(UA_String_equal(p1: ¤t->registeredServer.serverUri, |
| 40655 | p2: &request->serverUris[i])) { |
| 40656 | usable = true; |
| 40657 | break; |
| 40658 | } |
| 40659 | } |
| 40660 | } |
| 40661 | |
| 40662 | if(usable) |
| 40663 | setApplicationDescriptionFromRegisteredServer(request, target: &response->servers[pos++], |
| 40664 | registeredServer: ¤t->registeredServer); |
| 40665 | } |
| 40666 | |
| 40667 | /* Set the final size */ |
| 40668 | if(pos > 0) { |
| 40669 | response->serversSize = pos; |
| 40670 | } else { |
| 40671 | UA_free(ptr: response->servers); |
| 40672 | response->servers = NULL; |
| 40673 | } |
| 40674 | #endif |
| 40675 | |
| 40676 | if(request->endpointUrl.length > 0 && response->servers != NULL) { |
| 40677 | for(size_t i = 0; i < response->serversSize; i++) { |
| 40678 | UA_Array_delete(p: response->servers[i].discoveryUrls, |
| 40679 | size: response->servers[i].discoveryUrlsSize, |
| 40680 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 40681 | response->servers[i].discoveryUrls = NULL; |
| 40682 | response->servers[i].discoveryUrlsSize = 0; |
| 40683 | response->responseHeader.serviceResult |= |
| 40684 | UA_Array_appendCopy(p: (void**)&response->servers[i].discoveryUrls, |
| 40685 | size: &response->servers[i].discoveryUrlsSize, |
| 40686 | newElem: &request->endpointUrl, type: &UA_TYPES[UA_TYPES_STRING]); |
| 40687 | } |
| 40688 | } |
| 40689 | } |
| 40690 | |
| 40691 | #if defined(UA_ENABLE_DISCOVERY) && defined(UA_ENABLE_DISCOVERY_MULTICAST) |
| 40692 | /* All filter criteria must be fulfilled in the list entry. The comparison is |
| 40693 | * case insensitive. Returns true if the entry matches the filter. */ |
| 40694 | static UA_Boolean |
| 40695 | entryMatchesCapabilityFilter(size_t serverCapabilityFilterSize, |
| 40696 | UA_String *serverCapabilityFilter, |
| 40697 | serverOnNetwork_list_entry* current) { |
| 40698 | /* If the entry has less capabilities defined than the filter, there's no match */ |
| 40699 | if(serverCapabilityFilterSize > current->serverOnNetwork.serverCapabilitiesSize) |
| 40700 | return false; |
| 40701 | for(size_t i = 0; i < serverCapabilityFilterSize; i++) { |
| 40702 | UA_Boolean capabilityFound = false; |
| 40703 | for(size_t j = 0; j < current->serverOnNetwork.serverCapabilitiesSize; j++) { |
| 40704 | if(UA_String_equal_ignorecase(&serverCapabilityFilter[i], |
| 40705 | ¤t->serverOnNetwork.serverCapabilities[j])) { |
| 40706 | capabilityFound = true; |
| 40707 | break; |
| 40708 | } |
| 40709 | } |
| 40710 | if(!capabilityFound) |
| 40711 | return false; |
| 40712 | } |
| 40713 | return true; |
| 40714 | } |
| 40715 | |
| 40716 | void |
| 40717 | Service_FindServersOnNetwork(UA_Server *server, UA_Session *session, |
| 40718 | const UA_FindServersOnNetworkRequest *request, |
| 40719 | UA_FindServersOnNetworkResponse *response) { |
| 40720 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 40721 | |
| 40722 | UA_DiscoveryManager *dm = (UA_DiscoveryManager*) |
| 40723 | getServerComponentByName(server, UA_STRING("discovery")); |
| 40724 | if(!dm) { |
| 40725 | response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; |
| 40726 | return; |
| 40727 | } |
| 40728 | |
| 40729 | if(!server->config.mdnsEnabled) { |
| 40730 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 40731 | return; |
| 40732 | } |
| 40733 | |
| 40734 | /* Set LastCounterResetTime */ |
| 40735 | response->lastCounterResetTime = |
| 40736 | dm->serverOnNetworkRecordIdLastReset; |
| 40737 | |
| 40738 | /* Compute the max number of records to return */ |
| 40739 | UA_UInt32 recordCount = 0; |
| 40740 | if(request->startingRecordId < dm->serverOnNetworkRecordIdCounter) |
| 40741 | recordCount = dm->serverOnNetworkRecordIdCounter - request->startingRecordId; |
| 40742 | if(request->maxRecordsToReturn && recordCount > request->maxRecordsToReturn) |
| 40743 | recordCount = UA_MIN(recordCount, request->maxRecordsToReturn); |
| 40744 | if(recordCount == 0) { |
| 40745 | response->serversSize = 0; |
| 40746 | return; |
| 40747 | } |
| 40748 | |
| 40749 | /* Iterate over all records and add to filtered list */ |
| 40750 | UA_UInt32 filteredCount = 0; |
| 40751 | UA_STACKARRAY(UA_ServerOnNetwork*, filtered, recordCount); |
| 40752 | serverOnNetwork_list_entry* current; |
| 40753 | LIST_FOREACH(current, &dm->serverOnNetwork, pointers) { |
| 40754 | if(filteredCount >= recordCount) |
| 40755 | break; |
| 40756 | if(current->serverOnNetwork.recordId < request->startingRecordId) |
| 40757 | continue; |
| 40758 | if(!entryMatchesCapabilityFilter(request->serverCapabilityFilterSize, |
| 40759 | request->serverCapabilityFilter, current)) |
| 40760 | continue; |
| 40761 | filtered[filteredCount++] = ¤t->serverOnNetwork; |
| 40762 | } |
| 40763 | |
| 40764 | if(filteredCount == 0) |
| 40765 | return; |
| 40766 | |
| 40767 | /* Allocate the array for the response */ |
| 40768 | response->servers = (UA_ServerOnNetwork*) |
| 40769 | UA_malloc(sizeof(UA_ServerOnNetwork)*filteredCount); |
| 40770 | if(!response->servers) { |
| 40771 | response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 40772 | return; |
| 40773 | } |
| 40774 | response->serversSize = filteredCount; |
| 40775 | |
| 40776 | /* Copy the server names */ |
| 40777 | for(size_t i = 0; i < filteredCount; i++) |
| 40778 | UA_ServerOnNetwork_copy(filtered[i], &response->servers[filteredCount-i-1]); |
| 40779 | } |
| 40780 | #endif |
| 40781 | |
| 40782 | static const UA_String UA_SECURITY_POLICY_BASIC256SHA256_URI = |
| 40783 | UA_STRING_STATIC("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"); |
| 40784 | |
| 40785 | UA_SecurityPolicy * |
| 40786 | getDefaultEncryptedSecurityPolicy(UA_Server *server) { |
| 40787 | for(size_t i = 0; i < server->config.securityPoliciesSize; i++) { |
| 40788 | UA_SecurityPolicy *sp = &server->config.securityPolicies[i]; |
| 40789 | if(UA_String_equal(p1: &UA_SECURITY_POLICY_BASIC256SHA256_URI, p2: &sp->policyUri)) |
| 40790 | return sp; |
| 40791 | } |
| 40792 | for(size_t i = server->config.securityPoliciesSize; i > 0; i--) { |
| 40793 | UA_SecurityPolicy *sp = &server->config.securityPolicies[i-1]; |
| 40794 | if(!UA_String_equal(p1: &UA_SECURITY_POLICY_NONE_URI, p2: &sp->policyUri)) |
| 40795 | return sp; |
| 40796 | } |
| 40797 | return NULL; /* No encrypted policy found */ |
| 40798 | } |
| 40799 | |
| 40800 | const char *securityModeStrs[4] = {"-invalid", "-none", "-sign", "-sign+encrypt"}; |
| 40801 | |
| 40802 | UA_String |
| 40803 | securityPolicyUriPostfix(const UA_String uri) { |
| 40804 | for(UA_Byte *b = uri.data + uri.length - 1; b >= uri.data; b--) { |
| 40805 | if(*b != '#') |
| 40806 | continue; |
| 40807 | UA_String postfix = {uri.length - (size_t)(b - uri.data), b}; |
| 40808 | return postfix; |
| 40809 | } |
| 40810 | return uri; |
| 40811 | } |
| 40812 | |
| 40813 | static UA_StatusCode |
| 40814 | updateEndpointUserIdentityToken(UA_Server *server, UA_EndpointDescription *ed) { |
| 40815 | /* Don't change the UserIdentityTokens if there are manually configured |
| 40816 | * entries */ |
| 40817 | if(ed->userIdentityTokensSize > 0) |
| 40818 | return UA_STATUSCODE_GOOD; |
| 40819 | |
| 40820 | /* Copy the UserTokenPolicies from the AccessControl plugin, but only the matching ones to the securityPolicyUri. |
| 40821 | * TODO: Different instances of the AccessControl plugin per Endpoint */ |
| 40822 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 40823 | UA_ServerConfig *sc = &server->config; |
| 40824 | for(size_t i = 0; i < sc->accessControl.userTokenPoliciesSize; i++) { |
| 40825 | UA_UserTokenPolicy *utp = &sc->accessControl.userTokenPolicies[i]; |
| 40826 | res = UA_Array_appendCopy(p: (void**)&ed->userIdentityTokens, |
| 40827 | size: &ed->userIdentityTokensSize, newElem: utp, |
| 40828 | type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY]); |
| 40829 | if(res != UA_STATUSCODE_GOOD) |
| 40830 | return res; |
| 40831 | |
| 40832 | /* Select the SecurityPolicy for the UserTokenType. |
| 40833 | * If not set, the SecurityPolicy of the SecureChannel is used. */ |
| 40834 | utp = &ed->userIdentityTokens[ed->userIdentityTokensSize - 1]; |
| 40835 | UA_String_clear(p: &utp->securityPolicyUri); |
| 40836 | #ifdef UA_ENABLE_ENCRYPTION |
| 40837 | /* Anonymous tokens don't need encryption. All other tokens require |
| 40838 | * encryption with the exception of Username/Password if also the |
| 40839 | * allowNonePolicyPassword option has been set. The same logic is used |
| 40840 | * in selectEndpointAndTokenPolicy (ua_services_session.c). */ |
| 40841 | if(utp->tokenType != UA_USERTOKENTYPE_ANONYMOUS && |
| 40842 | !(sc->allowNonePolicyPassword && utp->tokenType == UA_USERTOKENTYPE_USERNAME) && |
| 40843 | UA_String_equal(p1: &ed->securityPolicyUri, p2: &UA_SECURITY_POLICY_NONE_URI)) { |
| 40844 | UA_SecurityPolicy *encSP = getDefaultEncryptedSecurityPolicy(server); |
| 40845 | if(!encSP) { |
| 40846 | /* No encrypted SecurityPolicy available */ |
| 40847 | UA_LOG_WARNING(logger: sc->logging, category: UA_LOGCATEGORY_CLIENT, |
| 40848 | msg: "Removing a UserTokenPolicy that would allow the " |
| 40849 | "password to be transmitted without encryption " |
| 40850 | "(Can be enabled via config->allowNonePolicyPassword)"); |
| 40851 | UA_StatusCode res2 = |
| 40852 | UA_Array_resize(p: (void **)&ed->userIdentityTokens, |
| 40853 | size: &ed->userIdentityTokensSize, |
| 40854 | newSize: ed->userIdentityTokensSize - 1, |
| 40855 | type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY]); |
| 40856 | (void)res2; |
| 40857 | continue; |
| 40858 | } |
| 40859 | res |= UA_String_copy(src: &encSP->policyUri, dst: &utp->securityPolicyUri); |
| 40860 | } |
| 40861 | #endif |
| 40862 | |
| 40863 | /* Append the SecurityMode and SecurityPolicy postfix to the PolicyId to |
| 40864 | * make it unique */ |
| 40865 | UA_String postfix; |
| 40866 | if(utp->securityPolicyUri.length > 0) |
| 40867 | postfix = securityPolicyUriPostfix(uri: utp->securityPolicyUri); |
| 40868 | else |
| 40869 | postfix = securityPolicyUriPostfix(uri: ed->securityPolicyUri); |
| 40870 | size_t newLen = utp->policyId.length + postfix.length + |
| 40871 | strlen(s: securityModeStrs[ed->securityMode]); |
| 40872 | UA_Byte *newString = (UA_Byte*)UA_realloc(ptr: utp->policyId.data, size: newLen); |
| 40873 | if(!newString) |
| 40874 | continue; |
| 40875 | size_t pos = utp->policyId.length; |
| 40876 | memcpy(dest: &newString[pos], src: securityModeStrs[ed->securityMode], |
| 40877 | n: strlen(s: securityModeStrs[ed->securityMode])); |
| 40878 | pos += strlen(s: securityModeStrs[ed->securityMode]); |
| 40879 | memcpy(dest: &newString[pos], src: postfix.data, n: postfix.length); |
| 40880 | utp->policyId.data = newString; |
| 40881 | utp->policyId.length = newLen; |
| 40882 | } |
| 40883 | |
| 40884 | return res; |
| 40885 | } |
| 40886 | |
| 40887 | /* Also reused to create the EndpointDescription array in the CreateSessionResponse */ |
| 40888 | UA_StatusCode |
| 40889 | setCurrentEndPointsArray(UA_Server *server, const UA_String endpointUrl, |
| 40890 | UA_String *profileUris, size_t profileUrisSize, |
| 40891 | UA_EndpointDescription **arr, size_t *arrSize) { |
| 40892 | /* Clone the endpoint for each discoveryURL? */ |
| 40893 | size_t clone_times = 1; |
| 40894 | if(endpointUrl.length == 0) |
| 40895 | clone_times = server->config.applicationDescription.discoveryUrlsSize; |
| 40896 | |
| 40897 | /* Allocate the array */ |
| 40898 | *arr = (UA_EndpointDescription*) |
| 40899 | UA_Array_new(size: server->config.endpointsSize * clone_times, |
| 40900 | type: &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); |
| 40901 | if(!*arr) |
| 40902 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 40903 | |
| 40904 | size_t pos = 0; |
| 40905 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 40906 | for(size_t j = 0; j < server->config.endpointsSize; ++j) { |
| 40907 | /* Test if the supported binary profile shall be returned */ |
| 40908 | UA_Boolean usable = (profileUrisSize == 0); |
| 40909 | if(!usable) { |
| 40910 | for(size_t i = 0; i < profileUrisSize; ++i) { |
| 40911 | if(!UA_String_equal(p1: &profileUris[i], p2: &server->config.endpoints[j].transportProfileUri)) |
| 40912 | continue; |
| 40913 | usable = true; |
| 40914 | break; |
| 40915 | } |
| 40916 | } |
| 40917 | if(!usable) |
| 40918 | continue; |
| 40919 | |
| 40920 | /* Copy into the results */ |
| 40921 | for(size_t i = 0; i < clone_times; ++i) { |
| 40922 | /* Copy the endpoint with a current ApplicationDescription */ |
| 40923 | UA_EndpointDescription *ed = &(*arr)[pos]; |
| 40924 | retval |= UA_EndpointDescription_copy(src: &server->config.endpoints[j], dst: ed); |
| 40925 | UA_ApplicationDescription_clear(p: &ed->server); |
| 40926 | retval |= UA_ApplicationDescription_copy(src: &server->config.applicationDescription, |
| 40927 | dst: &ed->server); |
| 40928 | |
| 40929 | /* Return the certificate for the SecurityPolicy. If the |
| 40930 | * SecureChannel is unencrypted, select the default encrypted |
| 40931 | * SecurityPolicy. */ |
| 40932 | UA_SecurityPolicy *sp = getSecurityPolicyByUri(server, securityPolicyUri: &ed->securityPolicyUri); |
| 40933 | if(!sp || UA_String_equal(p1: &UA_SECURITY_POLICY_NONE_URI, p2: &sp->policyUri)) |
| 40934 | sp = getDefaultEncryptedSecurityPolicy(server); |
| 40935 | if(sp) { |
| 40936 | UA_ByteString_clear(p: &ed->serverCertificate); |
| 40937 | retval |= UA_String_copy(src: &sp->localCertificate, dst: &ed->serverCertificate); |
| 40938 | } |
| 40939 | |
| 40940 | /* Set the User Identity Token list fromt the AccessControl plugin */ |
| 40941 | retval |= updateEndpointUserIdentityToken(server, ed); |
| 40942 | |
| 40943 | /* Set the EndpointURL */ |
| 40944 | UA_String_clear(p: &ed->endpointUrl); |
| 40945 | if(endpointUrl.length == 0) { |
| 40946 | retval |= UA_String_copy(src: &server->config.applicationDescription. |
| 40947 | discoveryUrls[i], dst: &ed->endpointUrl); |
| 40948 | } else { |
| 40949 | /* Mirror back the requested EndpointUrl and also add it to the |
| 40950 | * array of discovery urls */ |
| 40951 | retval |= UA_String_copy(src: &endpointUrl, dst: &ed->endpointUrl); |
| 40952 | |
| 40953 | /* Check if the ServerUrl is already present in the DiscoveryUrl array */ |
| 40954 | size_t k = 0; |
| 40955 | for(; k < ed->server.discoveryUrlsSize; k++) { |
| 40956 | if(UA_String_equal(p1: &ed->endpointUrl, p2: &ed->server.discoveryUrls[k])) |
| 40957 | break; |
| 40958 | } |
| 40959 | if(k == ed->server.discoveryUrlsSize) { |
| 40960 | retval |= UA_Array_appendCopy( |
| 40961 | p: (void **)&ed->server.discoveryUrls, size: &ed->server.discoveryUrlsSize, |
| 40962 | newElem: &endpointUrl, type: &UA_TYPES[UA_TYPES_STRING]); |
| 40963 | } |
| 40964 | } |
| 40965 | if(retval != UA_STATUSCODE_GOOD) |
| 40966 | goto error; |
| 40967 | |
| 40968 | pos++; |
| 40969 | } |
| 40970 | } |
| 40971 | |
| 40972 | *arrSize = pos; |
| 40973 | return UA_STATUSCODE_GOOD; |
| 40974 | |
| 40975 | error: |
| 40976 | UA_Array_delete(p: *arr, size: server->config.endpointsSize * clone_times, |
| 40977 | type: &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); |
| 40978 | *arr = NULL; |
| 40979 | return retval; |
| 40980 | } |
| 40981 | |
| 40982 | void |
| 40983 | Service_GetEndpoints(UA_Server *server, UA_Session *session, |
| 40984 | const UA_GetEndpointsRequest *request, |
| 40985 | UA_GetEndpointsResponse *response) { |
| 40986 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 40987 | |
| 40988 | /* If the client expects to see a specific endpointurl, mirror it back. If |
| 40989 | * not, clone the endpoints with the discovery url of all networklayers. */ |
| 40990 | if(request->endpointUrl.length > 0) { |
| 40991 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 40992 | "Processing GetEndpointsRequest with endpointUrl " |
| 40993 | UA_PRINTF_STRING_FORMAT, UA_PRINTF_STRING_DATA(request->endpointUrl)); |
| 40994 | } else { |
| 40995 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 40996 | "Processing GetEndpointsRequest with an empty endpointUrl"); |
| 40997 | } |
| 40998 | |
| 40999 | response->responseHeader.serviceResult = |
| 41000 | setCurrentEndPointsArray(server, endpointUrl: request->endpointUrl, |
| 41001 | profileUris: request->profileUris, profileUrisSize: request->profileUrisSize, |
| 41002 | arr: &response->endpoints, arrSize: &response->endpointsSize); |
| 41003 | } |
| 41004 | |
| 41005 | #ifdef UA_ENABLE_DISCOVERY |
| 41006 | |
| 41007 | static void |
| 41008 | process_RegisterServer(UA_Server *server, UA_Session *session, |
| 41009 | const UA_RequestHeader* requestHeader, |
| 41010 | const UA_RegisteredServer *requestServer, |
| 41011 | const size_t requestDiscoveryConfigurationSize, |
| 41012 | const UA_ExtensionObject *requestDiscoveryConfiguration, |
| 41013 | UA_ResponseHeader* responseHeader, |
| 41014 | size_t *responseConfigurationResultsSize, |
| 41015 | UA_StatusCode **responseConfigurationResults, |
| 41016 | size_t *responseDiagnosticInfosSize, |
| 41017 | UA_DiagnosticInfo *responseDiagnosticInfos) { |
| 41018 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41019 | |
| 41020 | UA_DiscoveryManager *dm = (UA_DiscoveryManager*) |
| 41021 | getServerComponentByName(server, name: UA_STRING(chars: "discovery")); |
| 41022 | if(!dm) |
| 41023 | return; |
| 41024 | |
| 41025 | if(dm->serverConfig->applicationDescription.applicationType != UA_APPLICATIONTYPE_DISCOVERYSERVER) { |
| 41026 | responseHeader->serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED; |
| 41027 | return; |
| 41028 | } |
| 41029 | |
| 41030 | /* Find the server from the request in the registered list */ |
| 41031 | registeredServer_list_entry* current; |
| 41032 | registeredServer_list_entry *registeredServer_entry = NULL; |
| 41033 | LIST_FOREACH(current, &dm->registeredServers, pointers) { |
| 41034 | if(UA_String_equal(p1: ¤t->registeredServer.serverUri, p2: &requestServer->serverUri)) { |
| 41035 | registeredServer_entry = current; |
| 41036 | break; |
| 41037 | } |
| 41038 | } |
| 41039 | |
| 41040 | UA_MdnsDiscoveryConfiguration *mdnsConfig = NULL; |
| 41041 | |
| 41042 | const UA_String* mdnsServerName = NULL; |
| 41043 | if(requestDiscoveryConfigurationSize) { |
| 41044 | *responseConfigurationResults = |
| 41045 | (UA_StatusCode *)UA_Array_new(size: requestDiscoveryConfigurationSize, |
| 41046 | type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 41047 | if(!(*responseConfigurationResults)) { |
| 41048 | responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 41049 | return; |
| 41050 | } |
| 41051 | *responseConfigurationResultsSize = requestDiscoveryConfigurationSize; |
| 41052 | |
| 41053 | for(size_t i = 0; i < requestDiscoveryConfigurationSize; i++) { |
| 41054 | const UA_ExtensionObject *object = &requestDiscoveryConfiguration[i]; |
| 41055 | if(!mdnsConfig && (object->encoding == UA_EXTENSIONOBJECT_DECODED || |
| 41056 | object->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) && |
| 41057 | (object->content.decoded.type == &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION])) { |
| 41058 | mdnsConfig = (UA_MdnsDiscoveryConfiguration *)object->content.decoded.data; |
| 41059 | mdnsServerName = &mdnsConfig->mdnsServerName; |
| 41060 | (*responseConfigurationResults)[i] = UA_STATUSCODE_GOOD; |
| 41061 | } else { |
| 41062 | (*responseConfigurationResults)[i] = UA_STATUSCODE_BADNOTSUPPORTED; |
| 41063 | } |
| 41064 | } |
| 41065 | } |
| 41066 | |
| 41067 | if(!mdnsServerName && requestServer->serverNamesSize) |
| 41068 | mdnsServerName = &requestServer->serverNames[0].text; |
| 41069 | |
| 41070 | if(!mdnsServerName) { |
| 41071 | responseHeader->serviceResult = UA_STATUSCODE_BADSERVERNAMEMISSING; |
| 41072 | return; |
| 41073 | } |
| 41074 | |
| 41075 | if(requestServer->discoveryUrlsSize == 0) { |
| 41076 | responseHeader->serviceResult = UA_STATUSCODE_BADDISCOVERYURLMISSING; |
| 41077 | return; |
| 41078 | } |
| 41079 | |
| 41080 | if(requestServer->semaphoreFilePath.length) { |
| 41081 | #ifdef UA_ENABLE_DISCOVERY_SEMAPHORE |
| 41082 | char* filePath = (char*) |
| 41083 | UA_malloc(size: sizeof(char)*requestServer->semaphoreFilePath.length+1); |
| 41084 | if(!filePath) { |
| 41085 | UA_LOG_ERROR_SESSION(server->config.logging, session, |
| 41086 | "Cannot allocate memory for semaphore path. Out of memory."); |
| 41087 | responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 41088 | return; |
| 41089 | } |
| 41090 | memcpy(dest: filePath, src: requestServer->semaphoreFilePath.data, n: requestServer->semaphoreFilePath.length ); |
| 41091 | filePath[requestServer->semaphoreFilePath.length] = '\0'; |
| 41092 | if(!UA_fileExists( filePath )) { |
| 41093 | responseHeader->serviceResult = UA_STATUSCODE_BADSEMPAHOREFILEMISSING; |
| 41094 | UA_free(ptr: filePath); |
| 41095 | return; |
| 41096 | } |
| 41097 | UA_free(ptr: filePath); |
| 41098 | #else |
| 41099 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_CLIENT, |
| 41100 | "Ignoring semaphore file path. open62541 not compiled " |
| 41101 | "with UA_ENABLE_DISCOVERY_SEMAPHORE=ON"); |
| 41102 | #endif |
| 41103 | } |
| 41104 | |
| 41105 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 41106 | if(server->config.mdnsEnabled) { |
| 41107 | for(size_t i = 0; i < requestServer->discoveryUrlsSize; i++) { |
| 41108 | /* create TXT if is online and first index, delete TXT if is offline and last index */ |
| 41109 | UA_Boolean updateTxt = (requestServer->isOnline && i==0) || |
| 41110 | (!requestServer->isOnline && i==requestServer->discoveryUrlsSize); |
| 41111 | UA_Discovery_updateMdnsForDiscoveryUrl(dm, mdnsServerName, mdnsConfig, |
| 41112 | &requestServer->discoveryUrls[i], |
| 41113 | requestServer->isOnline, updateTxt); |
| 41114 | } |
| 41115 | } |
| 41116 | #endif |
| 41117 | |
| 41118 | if(!requestServer->isOnline) { |
| 41119 | // server is shutting down. Remove it from the registered servers list |
| 41120 | if(!registeredServer_entry) { |
| 41121 | // server not found, show warning |
| 41122 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 41123 | "Could not unregister server %.*s. Not registered.", |
| 41124 | (int)requestServer->serverUri.length, requestServer->serverUri.data); |
| 41125 | responseHeader->serviceResult = UA_STATUSCODE_BADNOTHINGTODO; |
| 41126 | return; |
| 41127 | } |
| 41128 | |
| 41129 | if(dm->registerServerCallback) |
| 41130 | dm->registerServerCallback(requestServer, dm->registerServerCallbackData); |
| 41131 | |
| 41132 | // server found, remove from list |
| 41133 | LIST_REMOVE(registeredServer_entry, pointers); |
| 41134 | UA_RegisteredServer_clear(p: ®isteredServer_entry->registeredServer); |
| 41135 | UA_free(ptr: registeredServer_entry); |
| 41136 | dm->registeredServersSize--; |
| 41137 | responseHeader->serviceResult = UA_STATUSCODE_GOOD; |
| 41138 | return; |
| 41139 | } |
| 41140 | |
| 41141 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 41142 | if(!registeredServer_entry) { |
| 41143 | // server not yet registered, register it by adding it to the list |
| 41144 | UA_LOG_DEBUG_SESSION(server->config.logging, session, "Registering new server: %.*s", |
| 41145 | (int)requestServer->serverUri.length, requestServer->serverUri.data); |
| 41146 | |
| 41147 | registeredServer_entry = |
| 41148 | (registeredServer_list_entry *)UA_malloc(size: sizeof(registeredServer_list_entry)); |
| 41149 | if(!registeredServer_entry) { |
| 41150 | responseHeader->serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 41151 | return; |
| 41152 | } |
| 41153 | |
| 41154 | LIST_INSERT_HEAD(&dm->registeredServers, |
| 41155 | registeredServer_entry, pointers); |
| 41156 | dm->registeredServersSize++; |
| 41157 | } else { |
| 41158 | UA_RegisteredServer_clear(p: ®isteredServer_entry->registeredServer); |
| 41159 | } |
| 41160 | |
| 41161 | // Always call the callback, if it is set. |
| 41162 | // Previously we only called it if it was a new register call. It may be the case that this endpoint |
| 41163 | // registered before, then crashed, restarts and registeres again. In that case the entry is not deleted |
| 41164 | // and the callback would not be called. |
| 41165 | if(dm->registerServerCallback) |
| 41166 | dm->registerServerCallback(requestServer, dm->registerServerCallbackData); |
| 41167 | |
| 41168 | // copy the data from the request into the list |
| 41169 | UA_RegisteredServer_copy(src: requestServer, dst: ®isteredServer_entry->registeredServer); |
| 41170 | registeredServer_entry->lastSeen = UA_DateTime_nowMonotonic(); |
| 41171 | responseHeader->serviceResult = retval; |
| 41172 | } |
| 41173 | |
| 41174 | void Service_RegisterServer(UA_Server *server, UA_Session *session, |
| 41175 | const UA_RegisterServerRequest *request, |
| 41176 | UA_RegisterServerResponse *response) { |
| 41177 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41178 | "Processing RegisterServerRequest"); |
| 41179 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41180 | process_RegisterServer(server, session, requestHeader: &request->requestHeader, requestServer: &request->server, requestDiscoveryConfigurationSize: 0, |
| 41181 | NULL, responseHeader: &response->responseHeader, responseConfigurationResultsSize: 0, NULL, responseDiagnosticInfosSize: 0, NULL); |
| 41182 | } |
| 41183 | |
| 41184 | void Service_RegisterServer2(UA_Server *server, UA_Session *session, |
| 41185 | const UA_RegisterServer2Request *request, |
| 41186 | UA_RegisterServer2Response *response) { |
| 41187 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41188 | "Processing RegisterServer2Request"); |
| 41189 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41190 | process_RegisterServer(server, session, requestHeader: &request->requestHeader, requestServer: &request->server, |
| 41191 | requestDiscoveryConfigurationSize: request->discoveryConfigurationSize, requestDiscoveryConfiguration: request->discoveryConfiguration, |
| 41192 | responseHeader: &response->responseHeader, responseConfigurationResultsSize: &response->configurationResultsSize, |
| 41193 | responseConfigurationResults: &response->configurationResults, responseDiagnosticInfosSize: &response->diagnosticInfosSize, |
| 41194 | responseDiagnosticInfos: response->diagnosticInfos); |
| 41195 | } |
| 41196 | |
| 41197 | #endif /* UA_ENABLE_DISCOVERY */ |
| 41198 | |
| 41199 | /**** amalgamated original file "/src/server/ua_services_subscription.c" ****/ |
| 41200 | |
| 41201 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 41202 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 41203 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 41204 | * |
| 41205 | * Copyright 2014-2018, 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 41206 | * Copyright 2016-2017 (c) Florian Palm |
| 41207 | * Copyright 2015 (c) Chris Iatrou |
| 41208 | * Copyright 2015-2016 (c) Sten Grüner |
| 41209 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 41210 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 41211 | * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH |
| 41212 | * Copyright 2017 (c) Mattias Bornhager |
| 41213 | * Copyright 2017 (c) Henrik Norrman |
| 41214 | * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA |
| 41215 | * Copyright 2018 (c) Fabian Arndt, Root-Core |
| 41216 | * Copyright 2017-2019 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 41217 | */ |
| 41218 | |
| 41219 | |
| 41220 | #ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */ |
| 41221 | |
| 41222 | static void |
| 41223 | setSubscriptionSettings(UA_Server *server, UA_Subscription *subscription, |
| 41224 | UA_Double requestedPublishingInterval, |
| 41225 | UA_UInt32 requestedLifetimeCount, |
| 41226 | UA_UInt32 requestedMaxKeepAliveCount, |
| 41227 | UA_UInt32 maxNotificationsPerPublish, |
| 41228 | UA_Byte priority) { |
| 41229 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41230 | |
| 41231 | /* re-parameterize the subscription */ |
| 41232 | UA_BOUNDEDVALUE_SETWBOUNDS(server->config.publishingIntervalLimits, |
| 41233 | requestedPublishingInterval, |
| 41234 | subscription->publishingInterval); |
| 41235 | /* check for nan*/ |
| 41236 | if(requestedPublishingInterval != requestedPublishingInterval) |
| 41237 | subscription->publishingInterval = server->config.publishingIntervalLimits.min; |
| 41238 | UA_BOUNDEDVALUE_SETWBOUNDS(server->config.keepAliveCountLimits, |
| 41239 | requestedMaxKeepAliveCount, subscription->maxKeepAliveCount); |
| 41240 | UA_BOUNDEDVALUE_SETWBOUNDS(server->config.lifeTimeCountLimits, |
| 41241 | requestedLifetimeCount, subscription->lifeTimeCount); |
| 41242 | if(subscription->lifeTimeCount < 3 * subscription->maxKeepAliveCount) |
| 41243 | subscription->lifeTimeCount = 3 * subscription->maxKeepAliveCount; |
| 41244 | subscription->notificationsPerPublish = maxNotificationsPerPublish; |
| 41245 | if(maxNotificationsPerPublish == 0 || |
| 41246 | maxNotificationsPerPublish > server->config.maxNotificationsPerPublish) |
| 41247 | subscription->notificationsPerPublish = server->config.maxNotificationsPerPublish; |
| 41248 | subscription->priority = priority; |
| 41249 | } |
| 41250 | |
| 41251 | void |
| 41252 | Service_CreateSubscription(UA_Server *server, UA_Session *session, |
| 41253 | const UA_CreateSubscriptionRequest *request, |
| 41254 | UA_CreateSubscriptionResponse *response) { |
| 41255 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41256 | |
| 41257 | /* Check limits for the number of subscriptions */ |
| 41258 | if(((server->config.maxSubscriptions != 0) && |
| 41259 | (server->subscriptionsSize >= server->config.maxSubscriptions)) || |
| 41260 | ((server->config.maxSubscriptionsPerSession != 0) && |
| 41261 | (session->subscriptionsSize >= server->config.maxSubscriptionsPerSession))) { |
| 41262 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS; |
| 41263 | return; |
| 41264 | } |
| 41265 | |
| 41266 | /* Create the subscription */ |
| 41267 | UA_Subscription *sub = UA_Subscription_new(); |
| 41268 | if(!sub) { |
| 41269 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41270 | "Processing CreateSubscriptionRequest failed"); |
| 41271 | response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 41272 | return; |
| 41273 | } |
| 41274 | |
| 41275 | /* Set the subscription parameters */ |
| 41276 | setSubscriptionSettings(server, subscription: sub, requestedPublishingInterval: request->requestedPublishingInterval, |
| 41277 | requestedLifetimeCount: request->requestedLifetimeCount, |
| 41278 | requestedMaxKeepAliveCount: request->requestedMaxKeepAliveCount, |
| 41279 | maxNotificationsPerPublish: request->maxNotificationsPerPublish, priority: request->priority); |
| 41280 | sub->subscriptionId = ++server->lastSubscriptionId; /* Assign the SubscriptionId */ |
| 41281 | |
| 41282 | /* Register the subscription in the server */ |
| 41283 | LIST_INSERT_HEAD(&server->subscriptions, sub, serverListEntry); |
| 41284 | server->subscriptionsSize++; |
| 41285 | |
| 41286 | /* Update the server statistics */ |
| 41287 | server->serverDiagnosticsSummary.currentSubscriptionCount++; |
| 41288 | server->serverDiagnosticsSummary.cumulatedSubscriptionCount++; |
| 41289 | |
| 41290 | /* Attach the Subscription to the session */ |
| 41291 | UA_Session_attachSubscription(session, sub); |
| 41292 | |
| 41293 | /* Create representation in the Session object */ |
| 41294 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 41295 | createSubscriptionObject(server, session, sub); |
| 41296 | #endif |
| 41297 | |
| 41298 | /* Set the subscription state. This also registers the callback. |
| 41299 | * Note that also a disabled subscription publishes keepalives. */ |
| 41300 | UA_SubscriptionState sState = (request->publishingEnabled) ? |
| 41301 | UA_SUBSCRIPTIONSTATE_ENABLED : UA_SUBSCRIPTIONSTATE_ENABLED_NOPUBLISH; |
| 41302 | UA_StatusCode res = Subscription_setState(server, sub, state: sState); |
| 41303 | if(res != UA_STATUSCODE_GOOD) { |
| 41304 | UA_LOG_DEBUG_SESSION(server->config.logging, sub->session, |
| 41305 | "Subscription %"PRIu32 " | Could not register " |
| 41306 | "publish callback with error code %s", |
| 41307 | sub->subscriptionId, UA_StatusCode_name(res)); |
| 41308 | response->responseHeader.serviceResult = res; |
| 41309 | UA_Subscription_delete(server, sub); |
| 41310 | return; |
| 41311 | } |
| 41312 | |
| 41313 | UA_LOG_INFO_SUBSCRIPTION(server->config.logging, sub, |
| 41314 | "Subscription created (Publishing interval %.2fms, " |
| 41315 | "max %lu notifications per publish)", |
| 41316 | sub->publishingInterval, |
| 41317 | (long unsigned)sub->notificationsPerPublish); |
| 41318 | |
| 41319 | /* Prepare the response */ |
| 41320 | response->subscriptionId = sub->subscriptionId; |
| 41321 | response->revisedPublishingInterval = sub->publishingInterval; |
| 41322 | response->revisedLifetimeCount = sub->lifeTimeCount; |
| 41323 | response->revisedMaxKeepAliveCount = sub->maxKeepAliveCount; |
| 41324 | } |
| 41325 | |
| 41326 | void |
| 41327 | Service_ModifySubscription(UA_Server *server, UA_Session *session, |
| 41328 | const UA_ModifySubscriptionRequest *request, |
| 41329 | UA_ModifySubscriptionResponse *response) { |
| 41330 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41331 | "Processing ModifySubscriptionRequest"); |
| 41332 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41333 | |
| 41334 | UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId); |
| 41335 | if(!sub) { |
| 41336 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 41337 | return; |
| 41338 | } |
| 41339 | |
| 41340 | /* Store the old publishing interval */ |
| 41341 | UA_Double oldPublishingInterval = sub->publishingInterval; |
| 41342 | UA_Byte oldPriority = sub->priority; |
| 41343 | |
| 41344 | /* Change the Subscription settings */ |
| 41345 | setSubscriptionSettings(server, subscription: sub, requestedPublishingInterval: request->requestedPublishingInterval, |
| 41346 | requestedLifetimeCount: request->requestedLifetimeCount, |
| 41347 | requestedMaxKeepAliveCount: request->requestedMaxKeepAliveCount, |
| 41348 | maxNotificationsPerPublish: request->maxNotificationsPerPublish, priority: request->priority); |
| 41349 | |
| 41350 | /* Reset the subscription lifetime */ |
| 41351 | Subscription_resetLifetime(sub); |
| 41352 | |
| 41353 | /* The publish interval has changed */ |
| 41354 | if(sub->publishingInterval != oldPublishingInterval) { |
| 41355 | /* Change the repeated callback to the new interval. This cannot fail as |
| 41356 | * memory is reused. */ |
| 41357 | if(sub->publishCallbackId > 0) |
| 41358 | changeRepeatedCallbackInterval(server, callbackId: sub->publishCallbackId, |
| 41359 | interval_ms: sub->publishingInterval); |
| 41360 | |
| 41361 | /* For each MonitoredItem check if it was/shall be attached to the |
| 41362 | * publish interval. This ensures that we have less cyclic callbacks |
| 41363 | * registered and that the notifications are fresh. */ |
| 41364 | UA_MonitoredItem *mon; |
| 41365 | LIST_FOREACH(mon, &sub->monitoredItems, listEntry) { |
| 41366 | if(mon->parameters.samplingInterval == sub->publishingInterval || |
| 41367 | mon->parameters.samplingInterval == oldPublishingInterval) { |
| 41368 | UA_MonitoredItem_unregisterSampling(server, mon); |
| 41369 | UA_MonitoredItem_registerSampling(server, mon); |
| 41370 | } |
| 41371 | } |
| 41372 | } |
| 41373 | |
| 41374 | /* If the priority has changed, re-enter the subscription to the |
| 41375 | * priority-ordered queue in the session. */ |
| 41376 | if(oldPriority != sub->priority) { |
| 41377 | UA_Session_detachSubscription(server, session, sub, false); |
| 41378 | UA_Session_attachSubscription(session, sub); |
| 41379 | } |
| 41380 | |
| 41381 | /* Set the response */ |
| 41382 | response->revisedPublishingInterval = sub->publishingInterval; |
| 41383 | response->revisedLifetimeCount = sub->lifeTimeCount; |
| 41384 | response->revisedMaxKeepAliveCount = sub->maxKeepAliveCount; |
| 41385 | |
| 41386 | /* Update the diagnostics statistics */ |
| 41387 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 41388 | sub->modifyCount++; |
| 41389 | #endif |
| 41390 | } |
| 41391 | |
| 41392 | static void |
| 41393 | Operation_SetPublishingMode(UA_Server *server, UA_Session *session, |
| 41394 | const UA_Boolean *publishingEnabled, |
| 41395 | const UA_UInt32 *subscriptionId, |
| 41396 | UA_StatusCode *result) { |
| 41397 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41398 | UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: *subscriptionId); |
| 41399 | if(!sub) { |
| 41400 | *result = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 41401 | return; |
| 41402 | } |
| 41403 | |
| 41404 | /* Enable/disable */ |
| 41405 | UA_SubscriptionState sState = (*publishingEnabled) ? |
| 41406 | UA_SUBSCRIPTIONSTATE_ENABLED : UA_SUBSCRIPTIONSTATE_ENABLED_NOPUBLISH; |
| 41407 | *result = Subscription_setState(server, sub, state: sState); |
| 41408 | |
| 41409 | /* Reset the lifetime counter */ |
| 41410 | Subscription_resetLifetime(sub); |
| 41411 | } |
| 41412 | |
| 41413 | void |
| 41414 | Service_SetPublishingMode(UA_Server *server, UA_Session *session, |
| 41415 | const UA_SetPublishingModeRequest *request, |
| 41416 | UA_SetPublishingModeResponse *response) { |
| 41417 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41418 | "Processing SetPublishingModeRequest"); |
| 41419 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41420 | |
| 41421 | UA_Boolean publishingEnabled = request->publishingEnabled; /* request is const */ |
| 41422 | response->responseHeader.serviceResult = |
| 41423 | UA_Server_processServiceOperations(server, session, |
| 41424 | operationCallback: (UA_ServiceOperation)Operation_SetPublishingMode, |
| 41425 | context: &publishingEnabled, |
| 41426 | requestOperations: &request->subscriptionIdsSize, |
| 41427 | requestOperationsType: &UA_TYPES[UA_TYPES_UINT32], |
| 41428 | responseOperations: &response->resultsSize, |
| 41429 | responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 41430 | } |
| 41431 | |
| 41432 | UA_StatusCode |
| 41433 | Service_Publish(UA_Server *server, UA_Session *session, |
| 41434 | const UA_PublishRequest *request, UA_UInt32 requestId) { |
| 41435 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41436 | "Processing PublishRequest with RequestId %u", requestId); |
| 41437 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41438 | |
| 41439 | /* Return an error if the session has no subscription */ |
| 41440 | if(TAILQ_EMPTY(&session->subscriptions)) { |
| 41441 | sendServiceFault(channel: session->header.channel, requestId, |
| 41442 | requestHandle: request->requestHeader.requestHandle, |
| 41443 | UA_STATUSCODE_BADNOSUBSCRIPTION); |
| 41444 | return UA_STATUSCODE_BADNOSUBSCRIPTION; |
| 41445 | } |
| 41446 | |
| 41447 | /* Handle too many subscriptions to free resources before trying to allocate |
| 41448 | * resources for the new publish request. If the limit has been reached the |
| 41449 | * oldest publish request are returned with an error message. */ |
| 41450 | UA_Session_ensurePublishQueueSpace(server, session); |
| 41451 | |
| 41452 | /* Allocate the response to store it in the retransmission queue */ |
| 41453 | UA_PublishResponseEntry *entry = (UA_PublishResponseEntry *) |
| 41454 | UA_malloc(size: sizeof(UA_PublishResponseEntry)); |
| 41455 | if(!entry) { |
| 41456 | sendServiceFault(channel: session->header.channel, requestId, |
| 41457 | requestHandle: request->requestHeader.requestHandle, |
| 41458 | UA_STATUSCODE_BADOUTOFMEMORY); |
| 41459 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 41460 | } |
| 41461 | |
| 41462 | /* Prepare the response */ |
| 41463 | entry->requestId = requestId; |
| 41464 | UA_PublishResponse *response = &entry->response; |
| 41465 | UA_PublishResponse_init(p: response); |
| 41466 | response->responseHeader.requestHandle = request->requestHeader.requestHandle; |
| 41467 | |
| 41468 | /* Allocate the results array to acknowledge the acknowledge */ |
| 41469 | if(request->subscriptionAcknowledgementsSize > 0) { |
| 41470 | response->results = (UA_StatusCode *) |
| 41471 | UA_Array_new(size: request->subscriptionAcknowledgementsSize, |
| 41472 | type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 41473 | if(!response->results) { |
| 41474 | UA_free(ptr: entry); |
| 41475 | sendServiceFault(channel: session->header.channel, requestId, |
| 41476 | requestHandle: request->requestHeader.requestHandle, |
| 41477 | UA_STATUSCODE_BADOUTOFMEMORY); |
| 41478 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 41479 | } |
| 41480 | response->resultsSize = request->subscriptionAcknowledgementsSize; |
| 41481 | } |
| 41482 | |
| 41483 | /* <--- A good StatusCode is returned from here on ---> */ |
| 41484 | |
| 41485 | /* Delete Acknowledged Subscription Messages */ |
| 41486 | for(size_t i = 0; i < request->subscriptionAcknowledgementsSize; ++i) { |
| 41487 | UA_SubscriptionAcknowledgement *ack = &request->subscriptionAcknowledgements[i]; |
| 41488 | UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: ack->subscriptionId); |
| 41489 | if(!sub) { |
| 41490 | response->results[i] = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 41491 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41492 | "Cannot process acknowledgements subscription %u"PRIu32, |
| 41493 | ack->subscriptionId); |
| 41494 | continue; |
| 41495 | } |
| 41496 | /* Remove the acked transmission from the retransmission queue */ |
| 41497 | response->results[i] = |
| 41498 | UA_Subscription_removeRetransmissionMessage(sub, sequenceNumber: ack->sequenceNumber); |
| 41499 | } |
| 41500 | |
| 41501 | /* Set the maxTime if a timeout hint is defined */ |
| 41502 | entry->maxTime = UA_INT64_MAX; |
| 41503 | if(request->requestHeader.timeoutHint > 0) { |
| 41504 | UA_EventLoop *el = server->config.eventLoop; |
| 41505 | entry->maxTime = el->dateTime_nowMonotonic(el) + |
| 41506 | (request->requestHeader.timeoutHint * UA_DATETIME_MSEC); |
| 41507 | } |
| 41508 | |
| 41509 | /* Queue the publish response. It will be dequeued in a repeated publish |
| 41510 | * callback. This can also be triggered right now for a late |
| 41511 | * subscription. */ |
| 41512 | UA_Session_queuePublishReq(session, entry, false); |
| 41513 | UA_LOG_DEBUG_SESSION(server->config.logging, session, "Queued a publication message"); |
| 41514 | |
| 41515 | /* If there are late subscriptions, the new publish request is used to |
| 41516 | * answer them immediately. Late subscriptions with higher priority are |
| 41517 | * considered earlier. However, a single subscription that generates many |
| 41518 | * notifications must not "starve" other late subscriptions. Hence we move |
| 41519 | * it to the end of the queue for the subscriptions of that priority. */ |
| 41520 | UA_Subscription *late, *late_tmp; |
| 41521 | TAILQ_FOREACH_SAFE(late, &session->subscriptions, sessionListEntry, late_tmp) { |
| 41522 | /* Skip non-late subscriptions */ |
| 41523 | if(!late->late) |
| 41524 | continue; |
| 41525 | |
| 41526 | /* Call publish on the late subscription */ |
| 41527 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, late, |
| 41528 | "Send PublishResponse on a late subscription"); |
| 41529 | UA_Subscription_publish(server, sub: late); |
| 41530 | |
| 41531 | /* Skip re-insert if the subscription was deleted or deactivated during |
| 41532 | * _publish */ |
| 41533 | if(late->state >= UA_SUBSCRIPTIONSTATE_ENABLED_NOPUBLISH) { |
| 41534 | /* Find the first element with smaller priority and insert before |
| 41535 | * that. If there is none, insert at the end of the queue. */ |
| 41536 | UA_Subscription *after = TAILQ_NEXT(late, sessionListEntry); |
| 41537 | while(after && after->priority >= late->priority) |
| 41538 | after = TAILQ_NEXT(after, sessionListEntry); |
| 41539 | TAILQ_REMOVE(&session->subscriptions, late, sessionListEntry); |
| 41540 | if(after) |
| 41541 | TAILQ_INSERT_BEFORE(after, late, sessionListEntry); |
| 41542 | else |
| 41543 | TAILQ_INSERT_TAIL(&session->subscriptions, late, sessionListEntry); |
| 41544 | } |
| 41545 | |
| 41546 | /* Responses left in the queue? */ |
| 41547 | if(session->responseQueueSize == 0) |
| 41548 | break; |
| 41549 | } |
| 41550 | |
| 41551 | return UA_STATUSCODE_GOOD; |
| 41552 | } |
| 41553 | |
| 41554 | static void |
| 41555 | Operation_DeleteSubscription(UA_Server *server, UA_Session *session, void *_, |
| 41556 | const UA_UInt32 *subscriptionId, UA_StatusCode *result) { |
| 41557 | UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: *subscriptionId); |
| 41558 | if(!sub) { |
| 41559 | *result = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 41560 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41561 | "Deleting Subscription with Id %"PRIu32 |
| 41562 | " failed with error code %s", |
| 41563 | *subscriptionId, UA_StatusCode_name(*result)); |
| 41564 | return; |
| 41565 | } |
| 41566 | |
| 41567 | UA_Subscription_delete(server, sub); |
| 41568 | *result = UA_STATUSCODE_GOOD; |
| 41569 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41570 | "Subscription %"PRIu32 " | Subscription deleted", |
| 41571 | *subscriptionId); |
| 41572 | } |
| 41573 | |
| 41574 | void |
| 41575 | Service_DeleteSubscriptions(UA_Server *server, UA_Session *session, |
| 41576 | const UA_DeleteSubscriptionsRequest *request, |
| 41577 | UA_DeleteSubscriptionsResponse *response) { |
| 41578 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41579 | "Processing DeleteSubscriptionsRequest"); |
| 41580 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41581 | |
| 41582 | response->responseHeader.serviceResult = |
| 41583 | UA_Server_processServiceOperations(server, session, |
| 41584 | operationCallback: (UA_ServiceOperation)Operation_DeleteSubscription, NULL, |
| 41585 | requestOperations: &request->subscriptionIdsSize, requestOperationsType: &UA_TYPES[UA_TYPES_UINT32], |
| 41586 | responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 41587 | } |
| 41588 | |
| 41589 | void |
| 41590 | Service_Republish(UA_Server *server, UA_Session *session, |
| 41591 | const UA_RepublishRequest *request, |
| 41592 | UA_RepublishResponse *response) { |
| 41593 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41594 | "Processing RepublishRequest"); |
| 41595 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41596 | |
| 41597 | /* Get the subscription */ |
| 41598 | UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId); |
| 41599 | if(!sub) { |
| 41600 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 41601 | return; |
| 41602 | } |
| 41603 | |
| 41604 | /* Reset the lifetime counter */ |
| 41605 | Subscription_resetLifetime(sub); |
| 41606 | |
| 41607 | /* Update the subscription statistics */ |
| 41608 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 41609 | sub->republishRequestCount++; |
| 41610 | #endif |
| 41611 | |
| 41612 | /* Find the notification in the retransmission queue */ |
| 41613 | UA_NotificationMessageEntry *entry; |
| 41614 | TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) { |
| 41615 | if(entry->message.sequenceNumber == request->retransmitSequenceNumber) |
| 41616 | break; |
| 41617 | } |
| 41618 | if(!entry) { |
| 41619 | response->responseHeader.serviceResult = UA_STATUSCODE_BADMESSAGENOTAVAILABLE; |
| 41620 | return; |
| 41621 | } |
| 41622 | |
| 41623 | response->responseHeader.serviceResult = |
| 41624 | UA_NotificationMessage_copy(src: &entry->message, dst: &response->notificationMessage); |
| 41625 | |
| 41626 | /* Update the subscription statistics for the case where we return a message */ |
| 41627 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 41628 | sub->republishMessageCount++; |
| 41629 | #endif |
| 41630 | } |
| 41631 | |
| 41632 | static UA_StatusCode |
| 41633 | setTransferredSequenceNumbers(const UA_Subscription *sub, UA_TransferResult *result) { |
| 41634 | /* Allocate memory */ |
| 41635 | result->availableSequenceNumbers = (UA_UInt32*) |
| 41636 | UA_Array_new(size: sub->retransmissionQueueSize, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 41637 | if(!result->availableSequenceNumbers) |
| 41638 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 41639 | result->availableSequenceNumbersSize = sub->retransmissionQueueSize; |
| 41640 | |
| 41641 | /* Copy over the sequence numbers */ |
| 41642 | UA_NotificationMessageEntry *entry; |
| 41643 | size_t i = 0; |
| 41644 | TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) { |
| 41645 | result->availableSequenceNumbers[i] = entry->message.sequenceNumber; |
| 41646 | i++; |
| 41647 | } |
| 41648 | |
| 41649 | UA_assert(i == result->availableSequenceNumbersSize); |
| 41650 | |
| 41651 | return UA_STATUSCODE_GOOD; |
| 41652 | } |
| 41653 | |
| 41654 | static void |
| 41655 | Operation_TransferSubscription(UA_Server *server, UA_Session *session, |
| 41656 | const UA_Boolean *sendInitialValues, |
| 41657 | const UA_UInt32 *subscriptionId, |
| 41658 | UA_TransferResult *result) { |
| 41659 | /* Get the subscription. This requires a server-wide lookup instead of the |
| 41660 | * usual session-wide lookup. */ |
| 41661 | UA_Subscription *sub = getSubscriptionById(server, subscriptionId: *subscriptionId); |
| 41662 | if(!sub) { |
| 41663 | result->statusCode = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 41664 | return; |
| 41665 | } |
| 41666 | |
| 41667 | /* Update the diagnostics statistics */ |
| 41668 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 41669 | sub->transferRequestCount++; |
| 41670 | #endif |
| 41671 | |
| 41672 | /* Is this the same session? Return the sequence numbers and do nothing else. */ |
| 41673 | UA_Session *oldSession = sub->session; |
| 41674 | if(oldSession == session) { |
| 41675 | result->statusCode = setTransferredSequenceNumbers(sub, result); |
| 41676 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 41677 | sub->transferredToSameClientCount++; |
| 41678 | #endif |
| 41679 | return; |
| 41680 | } |
| 41681 | |
| 41682 | /* Check with AccessControl if the transfer is allowed */ |
| 41683 | if(server->config.accessControl.allowTransferSubscription) { |
| 41684 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41685 | if(!server->config.accessControl. |
| 41686 | allowTransferSubscription(server, &server->config.accessControl, |
| 41687 | oldSession ? &oldSession->sessionId : NULL, |
| 41688 | oldSession ? oldSession->sessionHandle : NULL, |
| 41689 | &session->sessionId, session->sessionHandle)) { |
| 41690 | result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 41691 | return; |
| 41692 | } |
| 41693 | } else { |
| 41694 | result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 41695 | return; |
| 41696 | } |
| 41697 | |
| 41698 | /* Check limits for the number of subscriptions for this Session */ |
| 41699 | if((server->config.maxSubscriptionsPerSession != 0) && |
| 41700 | (session->subscriptionsSize >= server->config.maxSubscriptionsPerSession)) { |
| 41701 | result->statusCode = UA_STATUSCODE_BADTOOMANYSUBSCRIPTIONS; |
| 41702 | return; |
| 41703 | } |
| 41704 | |
| 41705 | /* Allocate memory for the new subscription */ |
| 41706 | UA_Subscription *newSub = (UA_Subscription*)UA_malloc(size: sizeof(UA_Subscription)); |
| 41707 | if(!newSub) { |
| 41708 | result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY; |
| 41709 | return; |
| 41710 | } |
| 41711 | |
| 41712 | /* Set the available sequence numbers */ |
| 41713 | result->statusCode = setTransferredSequenceNumbers(sub, result); |
| 41714 | if(result->statusCode != UA_STATUSCODE_GOOD) { |
| 41715 | UA_free(ptr: newSub); |
| 41716 | return; |
| 41717 | } |
| 41718 | |
| 41719 | /* Create an identical copy of the Subscription struct. The original |
| 41720 | * subscription remains in place until a StatusChange notification has been |
| 41721 | * sent. The elements for lists and queues are moved over manually to ensure |
| 41722 | * that all backpointers are set correctly. */ |
| 41723 | memcpy(dest: newSub, src: sub, n: sizeof(UA_Subscription)); |
| 41724 | |
| 41725 | /* Set to the same state as the original subscription */ |
| 41726 | newSub->publishCallbackId = 0; |
| 41727 | result->statusCode = Subscription_setState(server, sub: newSub, state: sub->state); |
| 41728 | if(result->statusCode != UA_STATUSCODE_GOOD) { |
| 41729 | UA_Array_delete(p: result->availableSequenceNumbers, |
| 41730 | size: sub->retransmissionQueueSize, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 41731 | result->availableSequenceNumbers = NULL; |
| 41732 | result->availableSequenceNumbersSize = 0; |
| 41733 | UA_free(ptr: newSub); |
| 41734 | return; |
| 41735 | } |
| 41736 | |
| 41737 | /* <-- The point of no return --> */ |
| 41738 | |
| 41739 | /* Move over the MonitoredItems and adjust the backpointers */ |
| 41740 | LIST_INIT(&newSub->monitoredItems); |
| 41741 | UA_MonitoredItem *mon, *mon_tmp; |
| 41742 | LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, mon_tmp) { |
| 41743 | LIST_REMOVE(mon, listEntry); |
| 41744 | mon->subscription = newSub; |
| 41745 | LIST_INSERT_HEAD(&newSub->monitoredItems, mon, listEntry); |
| 41746 | } |
| 41747 | sub->monitoredItemsSize = 0; |
| 41748 | |
| 41749 | /* Move over the notification queue */ |
| 41750 | TAILQ_INIT(&newSub->notificationQueue); |
| 41751 | UA_Notification *nn, *nn_tmp; |
| 41752 | TAILQ_FOREACH_SAFE(nn, &sub->notificationQueue, globalEntry, nn_tmp) { |
| 41753 | TAILQ_REMOVE(&sub->notificationQueue, nn, globalEntry); |
| 41754 | TAILQ_INSERT_TAIL(&newSub->notificationQueue, nn, globalEntry); |
| 41755 | } |
| 41756 | sub->notificationQueueSize = 0; |
| 41757 | sub->dataChangeNotifications = 0; |
| 41758 | sub->eventNotifications = 0; |
| 41759 | |
| 41760 | TAILQ_INIT(&newSub->retransmissionQueue); |
| 41761 | UA_NotificationMessageEntry *nme, *nme_tmp; |
| 41762 | TAILQ_FOREACH_SAFE(nme, &sub->retransmissionQueue, listEntry, nme_tmp) { |
| 41763 | TAILQ_REMOVE(&sub->retransmissionQueue, nme, listEntry); |
| 41764 | TAILQ_INSERT_TAIL(&newSub->retransmissionQueue, nme, listEntry); |
| 41765 | if(oldSession) |
| 41766 | oldSession->totalRetransmissionQueueSize -= 1; |
| 41767 | sub->retransmissionQueueSize -= 1; |
| 41768 | } |
| 41769 | UA_assert(sub->retransmissionQueueSize == 0); |
| 41770 | sub->retransmissionQueueSize = 0; |
| 41771 | |
| 41772 | /* Add to the server */ |
| 41773 | UA_assert(newSub->subscriptionId == sub->subscriptionId); |
| 41774 | LIST_INSERT_HEAD(&server->subscriptions, newSub, serverListEntry); |
| 41775 | server->subscriptionsSize++; |
| 41776 | |
| 41777 | /* Attach to the session */ |
| 41778 | UA_Session_attachSubscription(session, sub: newSub); |
| 41779 | |
| 41780 | UA_LOG_INFO_SUBSCRIPTION(server->config.logging, newSub, "Transferred to this Session"); |
| 41781 | |
| 41782 | /* Set StatusChange in the original subscription and force publish. This |
| 41783 | * also removes the Subscription, even if there was no PublishResponse |
| 41784 | * queued to send a StatusChangeNotification. */ |
| 41785 | sub->statusChange = UA_STATUSCODE_GOODSUBSCRIPTIONTRANSFERRED; |
| 41786 | UA_Subscription_publish(server, sub); |
| 41787 | |
| 41788 | /* Re-create notifications with the current values for the new subscription */ |
| 41789 | if(*sendInitialValues) |
| 41790 | UA_Subscription_resendData(server, sub: newSub); |
| 41791 | |
| 41792 | /* Do not update the statistics for the number of Subscriptions here. The |
| 41793 | * fact that we duplicate the subscription and move over the content is just |
| 41794 | * an implementtion detail. |
| 41795 | * server->serverDiagnosticsSummary.currentSubscriptionCount++; |
| 41796 | * server->serverDiagnosticsSummary.cumulatedSubscriptionCount++; |
| 41797 | * |
| 41798 | * Update the diagnostics statistics: */ |
| 41799 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 41800 | if(oldSession && |
| 41801 | UA_equal(p1: &oldSession->clientDescription, p2: &session->clientDescription, |
| 41802 | type: &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION])) |
| 41803 | sub->transferredToSameClientCount++; |
| 41804 | else |
| 41805 | sub->transferredToAltClientCount++; |
| 41806 | #endif |
| 41807 | } |
| 41808 | |
| 41809 | void Service_TransferSubscriptions(UA_Server *server, UA_Session *session, |
| 41810 | const UA_TransferSubscriptionsRequest *request, |
| 41811 | UA_TransferSubscriptionsResponse *response) { |
| 41812 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 41813 | "Processing TransferSubscriptionsRequest"); |
| 41814 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41815 | |
| 41816 | response->responseHeader.serviceResult = |
| 41817 | UA_Server_processServiceOperations(server, session, |
| 41818 | operationCallback: (UA_ServiceOperation)Operation_TransferSubscription, |
| 41819 | context: &request->sendInitialValues, |
| 41820 | requestOperations: &request->subscriptionIdsSize, requestOperationsType: &UA_TYPES[UA_TYPES_UINT32], |
| 41821 | responseOperations: &response->resultsSize, responseOperationsType: &UA_TYPES[UA_TYPES_TRANSFERRESULT]); |
| 41822 | } |
| 41823 | |
| 41824 | #endif /* UA_ENABLE_SUBSCRIPTIONS */ |
| 41825 | |
| 41826 | /**** amalgamated original file "/src/server/ua_services_monitoreditem.c" ****/ |
| 41827 | |
| 41828 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 41829 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 41830 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 41831 | * |
| 41832 | * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 41833 | * Copyright 2016-2017 (c) Florian Palm |
| 41834 | * Copyright 2015 (c) Chris Iatrou |
| 41835 | * Copyright 2015-2016 (c) Sten Grüner |
| 41836 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 41837 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 41838 | * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH |
| 41839 | * Copyright 2017 (c) Mattias Bornhager |
| 41840 | * Copyright 2017 (c) Henrik Norrman |
| 41841 | * Copyright 2017-2023 (c) Thomas Stalder, Blue Time Concept SA |
| 41842 | * Copyright 2018 (c) Fabian Arndt, Root-Core |
| 41843 | * Copyright 2020 (c) Kalycito Infotech Private Limited |
| 41844 | * Copyright 2021 (c) Uranik, Berisha |
| 41845 | * Copyright 2021 (c) Ammar, Morshed |
| 41846 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
| 41847 | */ |
| 41848 | |
| 41849 | |
| 41850 | #ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */ |
| 41851 | |
| 41852 | #ifdef UA_ENABLE_DA |
| 41853 | |
| 41854 | /* Translate a percentage deadband into an absolute deadband based on the |
| 41855 | * UARange property of the variable */ |
| 41856 | static UA_StatusCode |
| 41857 | setAbsoluteFromPercentageDeadband(UA_Server *server, UA_Session *session, |
| 41858 | const UA_MonitoredItem *mon, UA_DataChangeFilter *filter) { |
| 41859 | /* A valid deadband? */ |
| 41860 | if(filter->deadbandValue < 0.0 || filter->deadbandValue > 100.0) |
| 41861 | return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED; |
| 41862 | |
| 41863 | /* Browse for the percent range */ |
| 41864 | UA_QualifiedName qn = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EURange"); |
| 41865 | UA_BrowsePathResult bpr = |
| 41866 | browseSimplifiedBrowsePath(server, origin: mon->itemToMonitor.nodeId, browsePathSize: 1, browsePath: &qn); |
| 41867 | if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { |
| 41868 | UA_BrowsePathResult_clear(p: &bpr); |
| 41869 | return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED; |
| 41870 | } |
| 41871 | |
| 41872 | /* Read the range */ |
| 41873 | UA_ReadValueId rvi; |
| 41874 | UA_ReadValueId_init(p: &rvi); |
| 41875 | rvi.nodeId = bpr.targets->targetId.nodeId; |
| 41876 | rvi.attributeId = UA_ATTRIBUTEID_VALUE; |
| 41877 | UA_DataValue rangeVal = readWithSession(server, session, item: &rvi, |
| 41878 | timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER); |
| 41879 | UA_BrowsePathResult_clear(p: &bpr); |
| 41880 | if(!UA_Variant_isScalar(v: &rangeVal.value) || |
| 41881 | rangeVal.value.type != &UA_TYPES[UA_TYPES_RANGE]) { |
| 41882 | UA_DataValue_clear(p: &rangeVal); |
| 41883 | return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED; |
| 41884 | } |
| 41885 | |
| 41886 | /* Compute the abs deadband */ |
| 41887 | UA_Range *euRange = (UA_Range*)rangeVal.value.data; |
| 41888 | UA_Double absDeadband = (filter->deadbandValue/100.0) * (euRange->high - euRange->low); |
| 41889 | |
| 41890 | UA_DataValue_clear(p: &rangeVal); |
| 41891 | |
| 41892 | /* EURange invalid or NaN? */ |
| 41893 | if(absDeadband < 0.0 || absDeadband != absDeadband) { |
| 41894 | UA_DataValue_clear(p: &rangeVal); |
| 41895 | return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED; |
| 41896 | } |
| 41897 | |
| 41898 | /* Adjust the original filter */ |
| 41899 | filter->deadbandType = UA_DEADBANDTYPE_ABSOLUTE; |
| 41900 | filter->deadbandValue = absDeadband; |
| 41901 | return UA_STATUSCODE_GOOD; |
| 41902 | } |
| 41903 | |
| 41904 | #endif /* UA_ENABLE_DA */ |
| 41905 | |
| 41906 | void |
| 41907 | Service_SetTriggering(UA_Server *server, UA_Session *session, |
| 41908 | const UA_SetTriggeringRequest *request, |
| 41909 | UA_SetTriggeringResponse *response) { |
| 41910 | /* Nothing to do? */ |
| 41911 | if(request->linksToRemoveSize == 0 && |
| 41912 | request->linksToAddSize == 0) { |
| 41913 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNOTHINGTODO; |
| 41914 | return; |
| 41915 | } |
| 41916 | |
| 41917 | /* Get the Subscription */ |
| 41918 | UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId); |
| 41919 | if(!sub) { |
| 41920 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 41921 | return; |
| 41922 | } |
| 41923 | |
| 41924 | /* Reset the lifetime counter of the Subscription */ |
| 41925 | Subscription_resetLifetime(sub); |
| 41926 | |
| 41927 | /* Get the MonitoredItem */ |
| 41928 | UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, monitoredItemId: request->triggeringItemId); |
| 41929 | if(!mon) { |
| 41930 | response->responseHeader.serviceResult = UA_STATUSCODE_BADMONITOREDITEMIDINVALID; |
| 41931 | return; |
| 41932 | } |
| 41933 | |
| 41934 | /* Allocate the results arrays */ |
| 41935 | if(request->linksToRemoveSize > 0) { |
| 41936 | response->removeResults = (UA_StatusCode*) |
| 41937 | UA_Array_new(size: request->linksToRemoveSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 41938 | if(!response->removeResults) { |
| 41939 | response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 41940 | return; |
| 41941 | } |
| 41942 | response->removeResultsSize = request->linksToRemoveSize; |
| 41943 | } |
| 41944 | |
| 41945 | if(request->linksToAddSize> 0) { |
| 41946 | response->addResults = (UA_StatusCode*) |
| 41947 | UA_Array_new(size: request->linksToAddSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 41948 | if(!response->addResults) { |
| 41949 | UA_Array_delete(p: response->removeResults, |
| 41950 | size: request->linksToAddSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 41951 | response->removeResults = NULL; |
| 41952 | response->removeResultsSize = 0; |
| 41953 | response->responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 41954 | return; |
| 41955 | } |
| 41956 | response->addResultsSize = request->linksToAddSize; |
| 41957 | } |
| 41958 | |
| 41959 | /* Apply the changes */ |
| 41960 | for(size_t i = 0; i < request->linksToRemoveSize; i++) |
| 41961 | response->removeResults[i] = |
| 41962 | UA_MonitoredItem_removeLink(sub, mon, linkId: request->linksToRemove[i]); |
| 41963 | |
| 41964 | for(size_t i = 0; i < request->linksToAddSize; i++) |
| 41965 | response->addResults[i] = |
| 41966 | UA_MonitoredItem_addLink(sub, mon, linkId: request->linksToAdd[i]); |
| 41967 | } |
| 41968 | |
| 41969 | /* Verify and adjust the parameters of a MonitoredItem */ |
| 41970 | static UA_StatusCode |
| 41971 | checkAdjustMonitoredItemParams(UA_Server *server, UA_Session *session, |
| 41972 | const UA_MonitoredItem *mon, |
| 41973 | const UA_DataType* valueType, |
| 41974 | UA_MonitoringParameters *params) { |
| 41975 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 41976 | |
| 41977 | /* Check the filter */ |
| 41978 | if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) { |
| 41979 | /* Event MonitoredItems need a filter */ |
| 41980 | #ifndef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 41981 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 41982 | #else |
| 41983 | if(params->filter.encoding != UA_EXTENSIONOBJECT_DECODED && |
| 41984 | params->filter.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) |
| 41985 | return UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 41986 | if(params->filter.content.decoded.type != &UA_TYPES[UA_TYPES_EVENTFILTER]) |
| 41987 | return UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 41988 | #endif |
| 41989 | } else { |
| 41990 | /* DataChange MonitoredItem. Can be "no filter" which defaults to |
| 41991 | * triggering on Status and Value. */ |
| 41992 | if(params->filter.encoding != UA_EXTENSIONOBJECT_DECODED && |
| 41993 | params->filter.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE && |
| 41994 | params->filter.encoding != UA_EXTENSIONOBJECT_ENCODED_NOBODY) |
| 41995 | return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED; |
| 41996 | |
| 41997 | /* If the filter ExtensionObject has a body, then it must be a |
| 41998 | * DataChangeFilter */ |
| 41999 | if(params->filter.encoding != UA_EXTENSIONOBJECT_ENCODED_NOBODY && |
| 42000 | params->filter.content.decoded.type != &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) |
| 42001 | return UA_STATUSCODE_BADFILTERNOTALLOWED; |
| 42002 | |
| 42003 | /* Check the deadband and adjust if necessary. */ |
| 42004 | if(params->filter.content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) { |
| 42005 | UA_DataChangeFilter *filter = (UA_DataChangeFilter *) |
| 42006 | params->filter.content.decoded.data; |
| 42007 | switch(filter->deadbandType) { |
| 42008 | case UA_DEADBANDTYPE_NONE: |
| 42009 | break; |
| 42010 | case UA_DEADBANDTYPE_ABSOLUTE: |
| 42011 | if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE || |
| 42012 | !valueType || !UA_DataType_isNumeric(type: valueType)) |
| 42013 | return UA_STATUSCODE_BADFILTERNOTALLOWED; |
| 42014 | break; |
| 42015 | #ifdef UA_ENABLE_DA |
| 42016 | case UA_DEADBANDTYPE_PERCENT: { |
| 42017 | if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE || |
| 42018 | !valueType || !UA_DataType_isNumeric(type: valueType)) |
| 42019 | return UA_STATUSCODE_BADFILTERNOTALLOWED; |
| 42020 | /* If percentage deadband is supported, look up the range values |
| 42021 | * and precompute as if it was an absolute deadband. */ |
| 42022 | UA_StatusCode res = |
| 42023 | setAbsoluteFromPercentageDeadband(server, session, mon, filter); |
| 42024 | if(res != UA_STATUSCODE_GOOD) |
| 42025 | return res; |
| 42026 | break; |
| 42027 | } |
| 42028 | #endif |
| 42029 | default: |
| 42030 | return UA_STATUSCODE_BADMONITOREDITEMFILTERUNSUPPORTED; |
| 42031 | } |
| 42032 | } |
| 42033 | } |
| 42034 | |
| 42035 | /* Read the minimum sampling interval for the variable. The sampling |
| 42036 | * interval of the MonitoredItem must not be less than that. */ |
| 42037 | if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_VALUE) { |
| 42038 | const UA_Node *node = UA_NODESTORE_GET(server, nodeId: &mon->itemToMonitor.nodeId); |
| 42039 | if(node) { |
| 42040 | const UA_VariableNode *vn = &node->variableNode; |
| 42041 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE) { |
| 42042 | /* Take into account if the publishing interval is used for sampling */ |
| 42043 | UA_Double samplingInterval = params->samplingInterval; |
| 42044 | if(samplingInterval < 0 && mon->subscription) |
| 42045 | samplingInterval = mon->subscription->publishingInterval; |
| 42046 | /* Adjust if smaller than the allowed minimum for the variable */ |
| 42047 | if(samplingInterval < vn->minimumSamplingInterval) |
| 42048 | params->samplingInterval = vn->minimumSamplingInterval; |
| 42049 | } |
| 42050 | UA_NODESTORE_RELEASE(server, node); |
| 42051 | } |
| 42052 | } |
| 42053 | |
| 42054 | |
| 42055 | /* A negative number indicates that the sampling interval is the publishing |
| 42056 | * interval of the Subscription. Note that the sampling interval selected |
| 42057 | * here remains also when the Subscription's publish interval is adjusted |
| 42058 | * afterwards. */ |
| 42059 | if(mon->subscription && params->samplingInterval < 0.0) |
| 42060 | params->samplingInterval = mon->subscription->publishingInterval; |
| 42061 | |
| 42062 | /* Adjust non-null sampling interval to lie within the configured limits */ |
| 42063 | if(params->samplingInterval != 0.0) { |
| 42064 | UA_BOUNDEDVALUE_SETWBOUNDS(server->config.samplingIntervalLimits, |
| 42065 | params->samplingInterval, params->samplingInterval); |
| 42066 | /* Check for NaN */ |
| 42067 | if(mon->parameters.samplingInterval != mon->parameters.samplingInterval) |
| 42068 | params->samplingInterval = server->config.samplingIntervalLimits.min; |
| 42069 | } |
| 42070 | |
| 42071 | /* Adjust the maximum queue size */ |
| 42072 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 42073 | if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) { |
| 42074 | /* 0 => Set to the configured maximum. Otherwise adjust with configured limits */ |
| 42075 | if(params->queueSize == 0) { |
| 42076 | params->queueSize = server->config.queueSizeLimits.max; |
| 42077 | } else { |
| 42078 | UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits, |
| 42079 | params->queueSize, params->queueSize); |
| 42080 | } |
| 42081 | } else |
| 42082 | #endif |
| 42083 | { |
| 42084 | /* 0 or 1 => queue-size 1. Otherwise adjust with configured limits */ |
| 42085 | if(params->queueSize == 0) |
| 42086 | params->queueSize = 1; |
| 42087 | if(params->queueSize != 1) |
| 42088 | UA_BOUNDEDVALUE_SETWBOUNDS(server->config.queueSizeLimits, |
| 42089 | params->queueSize, params->queueSize); |
| 42090 | } |
| 42091 | |
| 42092 | return UA_STATUSCODE_GOOD; |
| 42093 | } |
| 42094 | |
| 42095 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 42096 | static UA_StatusCode |
| 42097 | checkEventFilterParam(UA_Server *server, UA_Session *session, |
| 42098 | const UA_MonitoredItem *mon, |
| 42099 | const UA_MonitoringParameters *params, |
| 42100 | UA_ExtensionObject *filterResult) { |
| 42101 | /* Is an Event MonitoredItem? */ |
| 42102 | if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER) |
| 42103 | return UA_STATUSCODE_GOOD; |
| 42104 | |
| 42105 | /* Correct data type? */ |
| 42106 | if(params->filter.encoding != UA_EXTENSIONOBJECT_DECODED && |
| 42107 | params->filter.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) |
| 42108 | return UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 42109 | if(params->filter.content.decoded.type != &UA_TYPES[UA_TYPES_EVENTFILTER]) |
| 42110 | return UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 42111 | |
| 42112 | UA_EventFilter *eventFilter = (UA_EventFilter *)params->filter.content.decoded.data; |
| 42113 | |
| 42114 | /* Correct number of elements? */ |
| 42115 | if(eventFilter->selectClausesSize == 0 || |
| 42116 | eventFilter->selectClausesSize > UA_EVENTFILTER_MAXSELECT) |
| 42117 | return UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 42118 | |
| 42119 | /* Allow empty where clauses --> select every event */ |
| 42120 | if(eventFilter->whereClause.elementsSize > UA_EVENTFILTER_MAXELEMENTS) |
| 42121 | return UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 42122 | |
| 42123 | /* Check where-clause */ |
| 42124 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 42125 | const UA_ContentFilter *cf = &eventFilter->whereClause; |
| 42126 | UA_ContentFilterElementResult whereRes[UA_EVENTFILTER_MAXELEMENTS]; |
| 42127 | for(size_t i = 0; i < cf->elementsSize; ++i) { |
| 42128 | UA_ContentFilterElement *ef = &cf->elements[i]; |
| 42129 | whereRes[i] = UA_ContentFilterElementValidation(server, operatorIndex: i, operatorsCount: cf->elementsSize, ef); |
| 42130 | if(whereRes[i].statusCode != UA_STATUSCODE_GOOD && res == UA_STATUSCODE_GOOD) |
| 42131 | res = whereRes[i].statusCode; |
| 42132 | } |
| 42133 | |
| 42134 | /* Check select clause */ |
| 42135 | UA_StatusCode selectRes[UA_EVENTFILTER_MAXSELECT]; |
| 42136 | for(size_t i = 0; i < eventFilter->selectClausesSize; i++) { |
| 42137 | const UA_SimpleAttributeOperand *sao = &eventFilter->selectClauses[i]; |
| 42138 | selectRes[i] = UA_SimpleAttributeOperandValidation(server, sao); |
| 42139 | if(selectRes[i] != UA_STATUSCODE_GOOD && res == UA_STATUSCODE_GOOD) |
| 42140 | res = selectRes[i]; |
| 42141 | } |
| 42142 | |
| 42143 | /* Filter bad, return details */ |
| 42144 | if(res != UA_STATUSCODE_GOOD) { |
| 42145 | UA_EventFilterResult *efr = UA_EventFilterResult_new(); |
| 42146 | if(!efr) { |
| 42147 | res = UA_STATUSCODE_BADOUTOFMEMORY; |
| 42148 | } else { |
| 42149 | UA_EventFilterResult tmp_efr; |
| 42150 | UA_EventFilterResult_init(p: &tmp_efr); |
| 42151 | tmp_efr.selectClauseResultsSize = eventFilter->selectClausesSize; |
| 42152 | tmp_efr.selectClauseResults = selectRes; |
| 42153 | tmp_efr.whereClauseResult.elementResultsSize = cf->elementsSize; |
| 42154 | tmp_efr.whereClauseResult.elementResults = whereRes; |
| 42155 | UA_EventFilterResult_copy(src: &tmp_efr, dst: efr); |
| 42156 | UA_ExtensionObject_setValue(eo: filterResult, p: efr, |
| 42157 | type: &UA_TYPES[UA_TYPES_EVENTFILTERRESULT]); |
| 42158 | } |
| 42159 | } |
| 42160 | |
| 42161 | for(size_t i = 0; i < cf->elementsSize; ++i) |
| 42162 | UA_ContentFilterElementResult_clear(p: &whereRes[i]); |
| 42163 | return res; |
| 42164 | } |
| 42165 | #endif |
| 42166 | |
| 42167 | static const UA_String |
| 42168 | binaryEncoding = {sizeof("Default Binary") - 1, (UA_Byte *) "Default Binary"}; |
| 42169 | |
| 42170 | /* Structure to pass additional arguments into the operation */ |
| 42171 | struct createMonContext { |
| 42172 | UA_Subscription *sub; |
| 42173 | UA_TimestampsToReturn timestampsToReturn; |
| 42174 | |
| 42175 | /* If sub is NULL, use local callbacks */ |
| 42176 | UA_Server_DataChangeNotificationCallback dataChangeCallback; |
| 42177 | void *context; |
| 42178 | }; |
| 42179 | |
| 42180 | static void |
| 42181 | Operation_CreateMonitoredItem(UA_Server *server, UA_Session *session, |
| 42182 | struct createMonContext *cmc, |
| 42183 | const UA_MonitoredItemCreateRequest *request, |
| 42184 | UA_MonitoredItemCreateResult *result) { |
| 42185 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 42186 | |
| 42187 | /* Check available capacity */ |
| 42188 | if(cmc->sub && |
| 42189 | (((server->config.maxMonitoredItems != 0) && |
| 42190 | (server->monitoredItemsSize >= server->config.maxMonitoredItems)) || |
| 42191 | ((server->config.maxMonitoredItemsPerSubscription != 0) && |
| 42192 | (cmc->sub->monitoredItemsSize >= server->config.maxMonitoredItemsPerSubscription)))) { |
| 42193 | result->statusCode = UA_STATUSCODE_BADTOOMANYMONITOREDITEMS; |
| 42194 | return; |
| 42195 | } |
| 42196 | |
| 42197 | /* Check if the encoding is supported */ |
| 42198 | if(request->itemToMonitor.dataEncoding.name.length > 0 && |
| 42199 | (!UA_String_equal(p1: &binaryEncoding, p2: &request->itemToMonitor.dataEncoding.name) || |
| 42200 | request->itemToMonitor.dataEncoding.namespaceIndex != 0)) { |
| 42201 | result->statusCode = UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED; |
| 42202 | return; |
| 42203 | } |
| 42204 | |
| 42205 | /* Check if the encoding is set for a value */ |
| 42206 | if(request->itemToMonitor.attributeId != UA_ATTRIBUTEID_VALUE && |
| 42207 | request->itemToMonitor.dataEncoding.name.length > 0) { |
| 42208 | result->statusCode = UA_STATUSCODE_BADDATAENCODINGINVALID; |
| 42209 | return; |
| 42210 | } |
| 42211 | |
| 42212 | /* Make an example read to check the itemToMonitor. The DataSource itself |
| 42213 | * could return a (temporary) error. This should still result in a valid |
| 42214 | * MonitoredItem. Only a few StatusCodes are considered unrecoverable and |
| 42215 | * lead to an abort: |
| 42216 | * - The Node does not exist |
| 42217 | * - The AttributeId does not match the NodeClass |
| 42218 | * - The Session does not have sufficient access rights |
| 42219 | * - The indicated encoding is not supported or not valid */ |
| 42220 | UA_DataValue v = readWithSession(server, session, item: &request->itemToMonitor, |
| 42221 | timestampsToReturn: cmc->timestampsToReturn); |
| 42222 | if(v.hasStatus && |
| 42223 | (v.status == UA_STATUSCODE_BADNODEIDUNKNOWN || |
| 42224 | v.status == UA_STATUSCODE_BADATTRIBUTEIDINVALID || |
| 42225 | v.status == UA_STATUSCODE_BADDATAENCODINGUNSUPPORTED || |
| 42226 | v.status == UA_STATUSCODE_BADDATAENCODINGINVALID || |
| 42227 | v.status == UA_STATUSCODE_BADINDEXRANGEINVALID |
| 42228 | /* Part 4, 5.12.2 CreateMonitoredItems: When a user adds a monitored |
| 42229 | * item that the user is denied read access to, the add operation for |
| 42230 | * the item shall succeed and the bad status Bad_NotReadable or |
| 42231 | * Bad_UserAccessDenied shall be returned in the Publish response. |
| 42232 | * v.status == UA_STATUSCODE_BADNOTREADABLE |
| 42233 | * v.status == UA_STATUSCODE_BADUSERACCESSDENIED |
| 42234 | * |
| 42235 | * The IndexRange error can change depending on the value. |
| 42236 | * v.status == UA_STATUSCODE_BADINDEXRANGENODATA */ |
| 42237 | )) { |
| 42238 | result->statusCode = v.status; |
| 42239 | UA_DataValue_clear(p: &v); |
| 42240 | return; |
| 42241 | } |
| 42242 | |
| 42243 | /* Adding an Event MonitoredItem */ |
| 42244 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 42245 | if(request->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) { |
| 42246 | /* TODO: Only remote clients can add Event-MonitoredItems at the moment */ |
| 42247 | if(!cmc->sub) { |
| 42248 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 42249 | msg: "Only remote clients can add Event-MonitoredItems"); |
| 42250 | result->statusCode = UA_STATUSCODE_BADNOTSUPPORTED; |
| 42251 | UA_DataValue_clear(p: &v); |
| 42252 | return; |
| 42253 | } |
| 42254 | |
| 42255 | /* If the 'SubscribeToEvents' bit of EventNotifier attribute is |
| 42256 | * zero, then the object cannot be subscribed to monitor events */ |
| 42257 | if(!v.hasValue || !v.value.data) { |
| 42258 | result->statusCode = UA_STATUSCODE_BADINTERNALERROR; |
| 42259 | UA_DataValue_clear(p: &v); |
| 42260 | return; |
| 42261 | } |
| 42262 | UA_Byte eventNotifierValue = *((UA_Byte *)v.value.data); |
| 42263 | if((eventNotifierValue & 0x01) != 1) { |
| 42264 | result->statusCode = UA_STATUSCODE_BADNOTSUPPORTED; |
| 42265 | UA_LOG_INFO_SUBSCRIPTION(server->config.logging, cmc->sub, |
| 42266 | "Could not create a MonitoredItem as the " |
| 42267 | "'SubscribeToEvents' bit of the EventNotifier " |
| 42268 | "attribute is not set"); |
| 42269 | UA_DataValue_clear(p: &v); |
| 42270 | return; |
| 42271 | } |
| 42272 | } |
| 42273 | #endif |
| 42274 | |
| 42275 | const UA_DataType *valueType = v.value.type; |
| 42276 | UA_DataValue_clear(p: &v); |
| 42277 | |
| 42278 | /* Allocate the MonitoredItem */ |
| 42279 | UA_MonitoredItem *newMon = NULL; |
| 42280 | if(cmc->sub) { |
| 42281 | newMon = (UA_MonitoredItem*)UA_malloc(size: sizeof(UA_MonitoredItem)); |
| 42282 | } else { |
| 42283 | UA_LocalMonitoredItem *localMon = (UA_LocalMonitoredItem*) |
| 42284 | UA_malloc(size: sizeof(UA_LocalMonitoredItem)); |
| 42285 | if(localMon) { |
| 42286 | /* Set special values only for the LocalMonitoredItem */ |
| 42287 | localMon->context = cmc->context; |
| 42288 | localMon->callback.dataChangeCallback = cmc->dataChangeCallback; |
| 42289 | } |
| 42290 | newMon = &localMon->monitoredItem; |
| 42291 | } |
| 42292 | if(!newMon) { |
| 42293 | result->statusCode = UA_STATUSCODE_BADOUTOFMEMORY; |
| 42294 | return; |
| 42295 | } |
| 42296 | |
| 42297 | /* Initialize the MonitoredItem */ |
| 42298 | UA_MonitoredItem_init(mon: newMon); |
| 42299 | newMon->subscription = cmc->sub; /* Can be NULL for local MonitoredItems */ |
| 42300 | newMon->timestampsToReturn = cmc->timestampsToReturn; |
| 42301 | result->statusCode |= UA_ReadValueId_copy(src: &request->itemToMonitor, |
| 42302 | dst: &newMon->itemToMonitor); |
| 42303 | result->statusCode |= UA_MonitoringParameters_copy(src: &request->requestedParameters, |
| 42304 | dst: &newMon->parameters); |
| 42305 | result->statusCode |= checkAdjustMonitoredItemParams(server, session, mon: newMon, |
| 42306 | valueType, params: &newMon->parameters); |
| 42307 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 42308 | const UA_StatusCode eventFilterStatus = checkEventFilterParam(server, session, mon: newMon, |
| 42309 | params: &newMon->parameters, |
| 42310 | filterResult: &result->filterResult); |
| 42311 | |
| 42312 | if(eventFilterStatus != UA_STATUSCODE_GOOD) { |
| 42313 | result->statusCode = UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 42314 | } |
| 42315 | #endif |
| 42316 | if(result->statusCode != UA_STATUSCODE_GOOD) { |
| 42317 | UA_LOG_INFO_SUBSCRIPTION(server->config.logging, cmc->sub, |
| 42318 | "Could not create a MonitoredItem " |
| 42319 | "with StatusCode %s", |
| 42320 | UA_StatusCode_name(result->statusCode)); |
| 42321 | UA_MonitoredItem_delete(server, mon: newMon); |
| 42322 | return; |
| 42323 | } |
| 42324 | |
| 42325 | /* Initialize the value status so the first sample always passes the filter */ |
| 42326 | newMon->lastValue.hasStatus = true; |
| 42327 | newMon->lastValue.status = ~(UA_StatusCode)0; |
| 42328 | |
| 42329 | /* Register the Monitoreditem in the server and subscription */ |
| 42330 | UA_Server_registerMonitoredItem(server, mon: newMon); |
| 42331 | |
| 42332 | /* Activate the MonitoredItem */ |
| 42333 | result->statusCode |= |
| 42334 | UA_MonitoredItem_setMonitoringMode(server, mon: newMon, monitoringMode: request->monitoringMode); |
| 42335 | if(result->statusCode != UA_STATUSCODE_GOOD) { |
| 42336 | UA_MonitoredItem_delete(server, mon: newMon); |
| 42337 | return; |
| 42338 | } |
| 42339 | |
| 42340 | /* Prepare the response */ |
| 42341 | result->revisedSamplingInterval = newMon->parameters.samplingInterval; |
| 42342 | result->revisedQueueSize = newMon->parameters.queueSize; |
| 42343 | result->monitoredItemId = newMon->monitoredItemId; |
| 42344 | |
| 42345 | /* If the sampling interval is negative (the sampling callback is called |
| 42346 | * from within the publishing callback), return the publishing interval of |
| 42347 | * the Subscription. Note that we only use the cyclic callback of the |
| 42348 | * Subscription. So if the Subscription publishing interval is modified, |
| 42349 | * this also impacts this MonitoredItem. */ |
| 42350 | if(result->revisedSamplingInterval < 0.0 && cmc->sub) |
| 42351 | result->revisedSamplingInterval = cmc->sub->publishingInterval; |
| 42352 | |
| 42353 | UA_LOG_INFO_SUBSCRIPTION(server->config.logging, cmc->sub, |
| 42354 | "MonitoredItem %"PRIi32 " | " |
| 42355 | "Created the MonitoredItem " |
| 42356 | "(Sampling Interval: %.2fms, Queue Size: %lu)", |
| 42357 | newMon->monitoredItemId, |
| 42358 | newMon->parameters.samplingInterval, |
| 42359 | (unsigned long)newMon->parameters.queueSize); |
| 42360 | } |
| 42361 | |
| 42362 | void |
| 42363 | Service_CreateMonitoredItems(UA_Server *server, UA_Session *session, |
| 42364 | const UA_CreateMonitoredItemsRequest *request, |
| 42365 | UA_CreateMonitoredItemsResponse *response) { |
| 42366 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 42367 | "Processing CreateMonitoredItemsRequest"); |
| 42368 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 42369 | |
| 42370 | if(server->config.maxMonitoredItemsPerCall != 0 && |
| 42371 | request->itemsToCreateSize > server->config.maxMonitoredItemsPerCall) { |
| 42372 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 42373 | return; |
| 42374 | } |
| 42375 | |
| 42376 | /* Check if the timestampstoreturn is valid */ |
| 42377 | struct createMonContext cmc; |
| 42378 | cmc.timestampsToReturn = request->timestampsToReturn; |
| 42379 | if(cmc.timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) { |
| 42380 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID; |
| 42381 | return; |
| 42382 | } |
| 42383 | |
| 42384 | /* Find the subscription */ |
| 42385 | cmc.sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId); |
| 42386 | if(!cmc.sub) { |
| 42387 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 42388 | return; |
| 42389 | } |
| 42390 | |
| 42391 | /* Reset the lifetime counter of the Subscription */ |
| 42392 | Subscription_resetLifetime(sub: cmc.sub); |
| 42393 | |
| 42394 | response->responseHeader.serviceResult = |
| 42395 | UA_Server_processServiceOperations(server, session, |
| 42396 | operationCallback: (UA_ServiceOperation)Operation_CreateMonitoredItem, |
| 42397 | context: &cmc, requestOperations: &request->itemsToCreateSize, |
| 42398 | requestOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMCREATEREQUEST], |
| 42399 | responseOperations: &response->resultsSize, |
| 42400 | responseOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMCREATERESULT]); |
| 42401 | } |
| 42402 | |
| 42403 | UA_MonitoredItemCreateResult |
| 42404 | UA_Server_createDataChangeMonitoredItem(UA_Server *server, |
| 42405 | UA_TimestampsToReturn timestampsToReturn, |
| 42406 | const UA_MonitoredItemCreateRequest item, |
| 42407 | void *monitoredItemContext, |
| 42408 | UA_Server_DataChangeNotificationCallback callback) { |
| 42409 | struct createMonContext cmc; |
| 42410 | cmc.sub = NULL; |
| 42411 | cmc.context = monitoredItemContext; |
| 42412 | cmc.dataChangeCallback = callback; |
| 42413 | cmc.timestampsToReturn = timestampsToReturn; |
| 42414 | |
| 42415 | UA_MonitoredItemCreateResult result; |
| 42416 | UA_MonitoredItemCreateResult_init(p: &result); |
| 42417 | lockServer(server); |
| 42418 | Operation_CreateMonitoredItem(server, session: &server->adminSession, cmc: &cmc, request: &item, result: &result); |
| 42419 | unlockServer(server); |
| 42420 | return result; |
| 42421 | } |
| 42422 | |
| 42423 | static void |
| 42424 | Operation_ModifyMonitoredItem(UA_Server *server, UA_Session *session, UA_Subscription *sub, |
| 42425 | const UA_MonitoredItemModifyRequest *request, |
| 42426 | UA_MonitoredItemModifyResult *result) { |
| 42427 | /* Get the MonitoredItem */ |
| 42428 | UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, monitoredItemId: request->monitoredItemId); |
| 42429 | if(!mon) { |
| 42430 | result->statusCode = UA_STATUSCODE_BADMONITOREDITEMIDINVALID; |
| 42431 | return; |
| 42432 | } |
| 42433 | |
| 42434 | /* Make local copy of the settings */ |
| 42435 | UA_MonitoringParameters params; |
| 42436 | result->statusCode = |
| 42437 | UA_MonitoringParameters_copy(src: &request->requestedParameters, dst: ¶ms); |
| 42438 | if(result->statusCode != UA_STATUSCODE_GOOD) |
| 42439 | return; |
| 42440 | |
| 42441 | /* Read the current value to test if filters are possible. |
| 42442 | * Can return an empty value (v.value.type == NULL). */ |
| 42443 | UA_DataValue v = readWithSession(server, session, item: &mon->itemToMonitor, |
| 42444 | timestampsToReturn: mon->timestampsToReturn); |
| 42445 | |
| 42446 | /* Verify and adjust the new parameters. This still leaves the original |
| 42447 | * MonitoredItem untouched. */ |
| 42448 | result->statusCode = |
| 42449 | checkAdjustMonitoredItemParams(server, session, mon, |
| 42450 | valueType: v.value.type, params: ¶ms); |
| 42451 | UA_DataValue_clear(p: &v); |
| 42452 | if(result->statusCode != UA_STATUSCODE_GOOD) { |
| 42453 | UA_MonitoringParameters_clear(p: ¶ms); |
| 42454 | return; |
| 42455 | } |
| 42456 | |
| 42457 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 42458 | const UA_StatusCode eventFilterStatus = checkEventFilterParam(server, session, mon, |
| 42459 | params: &request->requestedParameters, |
| 42460 | filterResult: &result->filterResult); |
| 42461 | if(eventFilterStatus != UA_STATUSCODE_GOOD) { |
| 42462 | result->statusCode = UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 42463 | UA_MonitoringParameters_clear(p: ¶ms); |
| 42464 | return; |
| 42465 | } |
| 42466 | #endif |
| 42467 | |
| 42468 | /* Store the old sampling interval */ |
| 42469 | UA_Double oldSamplingInterval = mon->parameters.samplingInterval; |
| 42470 | |
| 42471 | /* Move over the new settings */ |
| 42472 | UA_MonitoringParameters_clear(p: &mon->parameters); |
| 42473 | mon->parameters = params; |
| 42474 | |
| 42475 | /* Re-register the callback if necessary */ |
| 42476 | if(oldSamplingInterval != mon->parameters.samplingInterval) { |
| 42477 | UA_MonitoredItem_unregisterSampling(server, mon); |
| 42478 | result->statusCode = |
| 42479 | UA_MonitoredItem_setMonitoringMode(server, mon, monitoringMode: mon->monitoringMode); |
| 42480 | } |
| 42481 | |
| 42482 | result->revisedSamplingInterval = mon->parameters.samplingInterval; |
| 42483 | result->revisedQueueSize = mon->parameters.queueSize; |
| 42484 | |
| 42485 | /* If the sampling interval is negative (the sampling callback is called |
| 42486 | * from within the publishing callback), return the publishing interval of |
| 42487 | * the Subscription. Note that we only use the cyclic callback of the |
| 42488 | * Subscription. So if the Subscription publishing interval is modified, |
| 42489 | * this also impacts this MonitoredItem. */ |
| 42490 | if(result->revisedSamplingInterval < 0.0 && mon->subscription) |
| 42491 | result->revisedSamplingInterval = mon->subscription->publishingInterval; |
| 42492 | |
| 42493 | /* Remove some notifications if the queue is now too small */ |
| 42494 | UA_MonitoredItem_ensureQueueSpace(server, mon); |
| 42495 | |
| 42496 | /* Remove the overflow bits if the queue has now a size of 1 */ |
| 42497 | UA_MonitoredItem_removeOverflowInfoBits(mon); |
| 42498 | |
| 42499 | /* If the sampling interval is negative (the sampling callback is called |
| 42500 | * from within the publishing callback), return the publishing interval of |
| 42501 | * the Subscription. Note that we only use the cyclic callback of the |
| 42502 | * Subscription. So if the Subscription publishing interval is modified, |
| 42503 | * this also impacts this MonitoredItem. */ |
| 42504 | if(result->revisedSamplingInterval < 0.0 && mon->subscription) |
| 42505 | result->revisedSamplingInterval = mon->subscription->publishingInterval; |
| 42506 | |
| 42507 | UA_LOG_INFO_SUBSCRIPTION(server->config.logging, sub, |
| 42508 | "MonitoredItem %"PRIi32 " | " |
| 42509 | "Modified the MonitoredItem " |
| 42510 | "(Sampling Interval: %fms, Queue Size: %lu)", |
| 42511 | mon->monitoredItemId, |
| 42512 | mon->parameters.samplingInterval, |
| 42513 | (unsigned long)mon->queueSize); |
| 42514 | } |
| 42515 | |
| 42516 | void |
| 42517 | Service_ModifyMonitoredItems(UA_Server *server, UA_Session *session, |
| 42518 | const UA_ModifyMonitoredItemsRequest *request, |
| 42519 | UA_ModifyMonitoredItemsResponse *response) { |
| 42520 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 42521 | "Processing ModifyMonitoredItemsRequest"); |
| 42522 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 42523 | |
| 42524 | if(server->config.maxMonitoredItemsPerCall != 0 && |
| 42525 | request->itemsToModifySize > server->config.maxMonitoredItemsPerCall) { |
| 42526 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 42527 | return; |
| 42528 | } |
| 42529 | |
| 42530 | /* Check if the timestampstoreturn is valid */ |
| 42531 | if(request->timestampsToReturn > UA_TIMESTAMPSTORETURN_NEITHER) { |
| 42532 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTIMESTAMPSTORETURNINVALID; |
| 42533 | return; |
| 42534 | } |
| 42535 | |
| 42536 | /* Get the subscription */ |
| 42537 | UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId); |
| 42538 | if(!sub) { |
| 42539 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 42540 | return; |
| 42541 | } |
| 42542 | |
| 42543 | /* Reset the lifetime counter of the Subscription */ |
| 42544 | Subscription_resetLifetime(sub); |
| 42545 | |
| 42546 | response->responseHeader.serviceResult = |
| 42547 | UA_Server_processServiceOperations(server, session, |
| 42548 | operationCallback: (UA_ServiceOperation)Operation_ModifyMonitoredItem, |
| 42549 | context: sub, requestOperations: &request->itemsToModifySize, |
| 42550 | requestOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYREQUEST], |
| 42551 | responseOperations: &response->resultsSize, |
| 42552 | responseOperationsType: &UA_TYPES[UA_TYPES_MONITOREDITEMMODIFYRESULT]); |
| 42553 | } |
| 42554 | |
| 42555 | struct setMonitoringContext { |
| 42556 | UA_Subscription *sub; |
| 42557 | UA_MonitoringMode monitoringMode; |
| 42558 | }; |
| 42559 | |
| 42560 | static void |
| 42561 | Operation_SetMonitoringMode(UA_Server *server, UA_Session *session, |
| 42562 | struct setMonitoringContext *smc, |
| 42563 | const UA_UInt32 *monitoredItemId, UA_StatusCode *result) { |
| 42564 | UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub: smc->sub, monitoredItemId: *monitoredItemId); |
| 42565 | if(!mon) { |
| 42566 | *result = UA_STATUSCODE_BADMONITOREDITEMIDINVALID; |
| 42567 | return; |
| 42568 | } |
| 42569 | *result = UA_MonitoredItem_setMonitoringMode(server, mon, monitoringMode: smc->monitoringMode); |
| 42570 | } |
| 42571 | |
| 42572 | void |
| 42573 | Service_SetMonitoringMode(UA_Server *server, UA_Session *session, |
| 42574 | const UA_SetMonitoringModeRequest *request, |
| 42575 | UA_SetMonitoringModeResponse *response) { |
| 42576 | UA_LOG_DEBUG_SESSION(server->config.logging, session, "Processing SetMonitoringMode"); |
| 42577 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 42578 | |
| 42579 | if(server->config.maxMonitoredItemsPerCall != 0 && |
| 42580 | request->monitoredItemIdsSize > server->config.maxMonitoredItemsPerCall) { |
| 42581 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 42582 | return; |
| 42583 | } |
| 42584 | |
| 42585 | /* Get the subscription */ |
| 42586 | struct setMonitoringContext smc; |
| 42587 | smc.sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId); |
| 42588 | if(!smc.sub) { |
| 42589 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 42590 | return; |
| 42591 | } |
| 42592 | |
| 42593 | /* Reset the lifetime counter of the Subscription */ |
| 42594 | Subscription_resetLifetime(sub: smc.sub); |
| 42595 | |
| 42596 | smc.monitoringMode = request->monitoringMode; |
| 42597 | response->responseHeader.serviceResult = |
| 42598 | UA_Server_processServiceOperations(server, session, |
| 42599 | operationCallback: (UA_ServiceOperation)Operation_SetMonitoringMode, |
| 42600 | context: &smc, requestOperations: &request->monitoredItemIdsSize, |
| 42601 | requestOperationsType: &UA_TYPES[UA_TYPES_UINT32], |
| 42602 | responseOperations: &response->resultsSize, |
| 42603 | responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 42604 | } |
| 42605 | |
| 42606 | static void |
| 42607 | Operation_DeleteMonitoredItem(UA_Server *server, UA_Session *session, UA_Subscription *sub, |
| 42608 | const UA_UInt32 *monitoredItemId, UA_StatusCode *result) { |
| 42609 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 42610 | UA_MonitoredItem *mon = UA_Subscription_getMonitoredItem(sub, monitoredItemId: *monitoredItemId); |
| 42611 | if(!mon) { |
| 42612 | *result = UA_STATUSCODE_BADMONITOREDITEMIDINVALID; |
| 42613 | return; |
| 42614 | } |
| 42615 | UA_MonitoredItem_delete(server, mon); |
| 42616 | } |
| 42617 | |
| 42618 | void |
| 42619 | Service_DeleteMonitoredItems(UA_Server *server, UA_Session *session, |
| 42620 | const UA_DeleteMonitoredItemsRequest *request, |
| 42621 | UA_DeleteMonitoredItemsResponse *response) { |
| 42622 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 42623 | "Processing DeleteMonitoredItemsRequest"); |
| 42624 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 42625 | |
| 42626 | if(server->config.maxMonitoredItemsPerCall != 0 && |
| 42627 | request->monitoredItemIdsSize > server->config.maxMonitoredItemsPerCall) { |
| 42628 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 42629 | return; |
| 42630 | } |
| 42631 | |
| 42632 | /* Get the subscription */ |
| 42633 | UA_Subscription *sub = UA_Session_getSubscriptionById(session, subscriptionId: request->subscriptionId); |
| 42634 | if(!sub) { |
| 42635 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 42636 | return; |
| 42637 | } |
| 42638 | |
| 42639 | /* Reset the lifetime counter of the Subscription */ |
| 42640 | Subscription_resetLifetime(sub); |
| 42641 | |
| 42642 | response->responseHeader.serviceResult = |
| 42643 | UA_Server_processServiceOperations(server, session, |
| 42644 | operationCallback: (UA_ServiceOperation)Operation_DeleteMonitoredItem, |
| 42645 | context: sub, requestOperations: &request->monitoredItemIdsSize, |
| 42646 | requestOperationsType: &UA_TYPES[UA_TYPES_UINT32], |
| 42647 | responseOperations: &response->resultsSize, |
| 42648 | responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 42649 | } |
| 42650 | |
| 42651 | UA_StatusCode |
| 42652 | UA_Server_deleteMonitoredItem(UA_Server *server, UA_UInt32 monitoredItemId) { |
| 42653 | lockServer(server); |
| 42654 | UA_MonitoredItem *mon, *mon_tmp; |
| 42655 | LIST_FOREACH_SAFE(mon, &server->localMonitoredItems, listEntry, mon_tmp) { |
| 42656 | if(mon->monitoredItemId != monitoredItemId) |
| 42657 | continue; |
| 42658 | UA_MonitoredItem_delete(server, mon); |
| 42659 | unlockServer(server); |
| 42660 | return UA_STATUSCODE_GOOD; |
| 42661 | } |
| 42662 | unlockServer(server); |
| 42663 | return UA_STATUSCODE_BADMONITOREDITEMIDINVALID; |
| 42664 | } |
| 42665 | |
| 42666 | #endif /* UA_ENABLE_SUBSCRIPTIONS */ |
| 42667 | |
| 42668 | /**** amalgamated original file "/src/server/ua_services_securechannel.c" ****/ |
| 42669 | |
| 42670 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 42671 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 42672 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 42673 | * |
| 42674 | * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 42675 | * Copyright 2014, 2017 (c) Florian Palm |
| 42676 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 42677 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 42678 | * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB |
| 42679 | * Copyright 2023 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Phuong Nguyen) |
| 42680 | */ |
| 42681 | |
| 42682 | |
| 42683 | /* This contains the SecureChannel Services to be called after validation and |
| 42684 | * decoding of the message. The main SecureChannel logic is handled in |
| 42685 | * /src/ua_securechannel.* and /src/server/ua_server_binary.c. */ |
| 42686 | |
| 42687 | void |
| 42688 | Service_OpenSecureChannel(UA_Server *server, UA_SecureChannel *channel, |
| 42689 | UA_OpenSecureChannelRequest *request, |
| 42690 | UA_OpenSecureChannelResponse *response) { |
| 42691 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 42692 | |
| 42693 | switch(request->requestType) { |
| 42694 | /* Open the channel */ |
| 42695 | case UA_SECURITYTOKENREQUESTTYPE_ISSUE: |
| 42696 | /* We must expect an OPN handshake */ |
| 42697 | if(channel->state != UA_SECURECHANNELSTATE_ACK_SENT) { |
| 42698 | UA_LOG_ERROR_CHANNEL(server->config.logging, channel, |
| 42699 | "Called open on already open or closed channel"); |
| 42700 | response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; |
| 42701 | goto error; |
| 42702 | } |
| 42703 | |
| 42704 | /* Set the SecurityMode */ |
| 42705 | if(request->securityMode != UA_MESSAGESECURITYMODE_NONE && |
| 42706 | UA_ByteString_equal(p1: &sp->policyUri, p2: &UA_SECURITY_POLICY_NONE_URI)) { |
| 42707 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURITYMODEREJECTED; |
| 42708 | goto error; |
| 42709 | } |
| 42710 | channel->securityMode = request->securityMode; |
| 42711 | break; |
| 42712 | |
| 42713 | /* Renew the channel */ |
| 42714 | case UA_SECURITYTOKENREQUESTTYPE_RENEW: |
| 42715 | /* The channel must be open to be renewed */ |
| 42716 | if(channel->state != UA_SECURECHANNELSTATE_OPEN) { |
| 42717 | UA_LOG_ERROR_CHANNEL(server->config.logging, channel, |
| 42718 | "Called renew on channel which is not open"); |
| 42719 | response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; |
| 42720 | goto error; |
| 42721 | } |
| 42722 | |
| 42723 | /* Check whether the nonce was reused */ |
| 42724 | if(channel->securityMode != UA_MESSAGESECURITYMODE_NONE && |
| 42725 | UA_ByteString_equal(p1: &channel->remoteNonce, p2: &request->clientNonce)) { |
| 42726 | UA_LOG_ERROR_CHANNEL(server->config.logging, channel, |
| 42727 | "The client reused the last nonce"); |
| 42728 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 42729 | goto error; |
| 42730 | } |
| 42731 | |
| 42732 | break; |
| 42733 | |
| 42734 | /* Unknown request type */ |
| 42735 | default: |
| 42736 | response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; |
| 42737 | return; |
| 42738 | } |
| 42739 | |
| 42740 | /* Create a new SecurityToken. It will be switched over when the first |
| 42741 | * message is received. The ChannelId is left unchanged. */ |
| 42742 | channel->altSecurityToken.channelId = channel->securityToken.channelId; |
| 42743 | channel->altSecurityToken.tokenId = generateSecureChannelTokenId(server); |
| 42744 | channel->altSecurityToken.createdAt = UA_DateTime_nowMonotonic(); |
| 42745 | channel->altSecurityToken.revisedLifetime = |
| 42746 | (request->requestedLifetime > server->config.maxSecurityTokenLifetime) ? |
| 42747 | server->config.maxSecurityTokenLifetime : request->requestedLifetime; |
| 42748 | if(channel->altSecurityToken.revisedLifetime == 0) |
| 42749 | channel->altSecurityToken.revisedLifetime = server->config.maxSecurityTokenLifetime; |
| 42750 | |
| 42751 | /* Set the nonces. The remote nonce will be "rotated in" when it is first used. */ |
| 42752 | UA_ByteString_clear(p: &channel->remoteNonce); |
| 42753 | channel->remoteNonce = request->clientNonce; |
| 42754 | UA_ByteString_init(p: &request->clientNonce); |
| 42755 | |
| 42756 | response->responseHeader.serviceResult = UA_SecureChannel_generateLocalNonce(channel); |
| 42757 | UA_CHECK_STATUS(response->responseHeader.serviceResult, goto error); |
| 42758 | |
| 42759 | /* Update the channel state */ |
| 42760 | channel->renewState = UA_SECURECHANNELRENEWSTATE_NEWTOKEN_SERVER; |
| 42761 | channel->state = UA_SECURECHANNELSTATE_OPEN; |
| 42762 | |
| 42763 | /* Set the response */ |
| 42764 | response->securityToken = channel->altSecurityToken; |
| 42765 | response->securityToken.createdAt = UA_DateTime_now(); /* only for sending */ |
| 42766 | response->responseHeader.timestamp = response->securityToken.createdAt; |
| 42767 | response->responseHeader.requestHandle = request->requestHeader.requestHandle; |
| 42768 | response->responseHeader.serviceResult = |
| 42769 | UA_ByteString_copy(src: &channel->localNonce, dst: &response->serverNonce); |
| 42770 | UA_CHECK_STATUS(response->responseHeader.serviceResult, goto error); |
| 42771 | |
| 42772 | /* Success */ |
| 42773 | if(request->requestType == UA_SECURITYTOKENREQUESTTYPE_ISSUE) { |
| 42774 | UA_LOG_INFO_CHANNEL(server->config.logging, channel, |
| 42775 | "SecureChannel opened with SecurityPolicy %.*s " |
| 42776 | "and a revised lifetime of %.2fs", |
| 42777 | (int)channel->securityPolicy->policyUri.length, |
| 42778 | channel->securityPolicy->policyUri.data, |
| 42779 | (UA_Float)response->securityToken.revisedLifetime / 1000); |
| 42780 | } else { |
| 42781 | UA_LOG_INFO_CHANNEL(server->config.logging, channel, "SecureChannel renewed " |
| 42782 | "with a revised lifetime of %.2fs", |
| 42783 | (UA_Float)response->securityToken.revisedLifetime / 1000); |
| 42784 | } |
| 42785 | |
| 42786 | return; |
| 42787 | |
| 42788 | error: |
| 42789 | if(request->requestType == UA_SECURITYTOKENREQUESTTYPE_ISSUE) { |
| 42790 | UA_LOG_INFO_CHANNEL(server->config.logging, channel, |
| 42791 | "Opening a SecureChannel failed"); |
| 42792 | } else { |
| 42793 | UA_LOG_DEBUG_CHANNEL(server->config.logging, channel, |
| 42794 | "Renewing SecureChannel failed"); |
| 42795 | } |
| 42796 | } |
| 42797 | |
| 42798 | /* The server does not send a CloseSecureChannel response */ |
| 42799 | void |
| 42800 | Service_CloseSecureChannel(UA_Server *server, UA_SecureChannel *channel) { |
| 42801 | UA_SecureChannel_shutdown(channel, shutdownReason: UA_SHUTDOWNREASON_CLOSE); |
| 42802 | } |
| 42803 | |
| 42804 | /**** amalgamated original file "/src/server/ua_services_nodemanagement.c" ****/ |
| 42805 | |
| 42806 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 42807 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 42808 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 42809 | * |
| 42810 | * Copyright 2014-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 42811 | * Copyright 2014-2017 (c) Florian Palm |
| 42812 | * Copyright 2015-2016 (c) Sten Grüner |
| 42813 | * Copyright 2015-2016 (c) Chris Iatrou |
| 42814 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 42815 | * Copyright 2017 (c) Julian Grothoff |
| 42816 | * Copyright 2016 (c) LEvertz |
| 42817 | * Copyright 2016 (c) Lorenz Haas |
| 42818 | * Copyright 2017 (c) frax2222 |
| 42819 | * Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH |
| 42820 | * Copyright 2017 (c) Christian von Arnim |
| 42821 | * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 42822 | * Copyright 2017 (c) Henrik Norrman |
| 42823 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
| 42824 | */ |
| 42825 | |
| 42826 | |
| 42827 | /*********************/ |
| 42828 | /* Edit Node Context */ |
| 42829 | /*********************/ |
| 42830 | |
| 42831 | UA_StatusCode |
| 42832 | UA_Server_getNodeContext(UA_Server *server, UA_NodeId nodeId, |
| 42833 | void **nodeContext) { |
| 42834 | lockServer(server); |
| 42835 | UA_StatusCode retval = getNodeContext(server, nodeId, nodeContext); |
| 42836 | unlockServer(server); |
| 42837 | return retval; |
| 42838 | } |
| 42839 | |
| 42840 | UA_StatusCode |
| 42841 | getNodeContext(UA_Server *server, UA_NodeId nodeId, |
| 42842 | void **nodeContext) { |
| 42843 | const UA_Node *node = UA_NODESTORE_GET(server, nodeId: &nodeId); |
| 42844 | if(!node) |
| 42845 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 42846 | *nodeContext = node->head.context; |
| 42847 | UA_NODESTORE_RELEASE(server, node); |
| 42848 | return UA_STATUSCODE_GOOD; |
| 42849 | } |
| 42850 | |
| 42851 | static UA_StatusCode |
| 42852 | setDeconstructedNode(UA_Server *server, UA_Session *session, |
| 42853 | UA_NodeHead *head, void *context) { |
| 42854 | head->constructed = false; |
| 42855 | return UA_STATUSCODE_GOOD; |
| 42856 | } |
| 42857 | |
| 42858 | static UA_StatusCode |
| 42859 | setConstructedNodeContext(UA_Server *server, UA_Session *session, |
| 42860 | UA_NodeHead *head, void *context) { |
| 42861 | head->context = context; |
| 42862 | head->constructed = true; |
| 42863 | return UA_STATUSCODE_GOOD; |
| 42864 | } |
| 42865 | |
| 42866 | static UA_StatusCode |
| 42867 | editNodeContext(UA_Server *server, UA_Session* session, |
| 42868 | UA_NodeHead *head, void *context) { |
| 42869 | head->context = context; |
| 42870 | return UA_STATUSCODE_GOOD; |
| 42871 | } |
| 42872 | |
| 42873 | UA_StatusCode |
| 42874 | setNodeContext(UA_Server *server, UA_NodeId nodeId, |
| 42875 | void *nodeContext) { |
| 42876 | return UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId, |
| 42877 | callback: (UA_EditNodeCallback)editNodeContext, data: nodeContext); |
| 42878 | } |
| 42879 | |
| 42880 | UA_StatusCode |
| 42881 | UA_Server_setNodeContext(UA_Server *server, UA_NodeId nodeId, |
| 42882 | void *nodeContext) { |
| 42883 | lockServer(server); |
| 42884 | UA_StatusCode retval = setNodeContext(server, nodeId, nodeContext); |
| 42885 | unlockServer(server); |
| 42886 | return retval; |
| 42887 | } |
| 42888 | |
| 42889 | static UA_StatusCode |
| 42890 | checkSetIsDynamicVariable(UA_Server *server, UA_Session *session, |
| 42891 | const UA_NodeId *nodeId); |
| 42892 | |
| 42893 | /**********************/ |
| 42894 | /* Consistency Checks */ |
| 42895 | /**********************/ |
| 42896 | |
| 42897 | #define UA_PARENT_REFERENCES_COUNT 2 |
| 42898 | |
| 42899 | const UA_NodeId parentReferences[UA_PARENT_REFERENCES_COUNT] = { |
| 42900 | {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}}, |
| 42901 | {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}} |
| 42902 | }; |
| 42903 | |
| 42904 | static void |
| 42905 | logAddNode(const UA_Logger *logger, UA_Session *session, |
| 42906 | const UA_NodeId *nodeId, const char *msg) { |
| 42907 | UA_LOG_NODEID_INFO(nodeId, |
| 42908 | UA_LOG_INFO_SESSION(logger, session, "AddNode (%.*s): %s", |
| 42909 | (int)nodeIdStr.length, nodeIdStr.data, msg)); |
| 42910 | } |
| 42911 | |
| 42912 | /* Check if the requested parent node exists, has the right node class and is |
| 42913 | * referenced with an allowed (hierarchical) reference type. For "type" nodes, |
| 42914 | * only hasSubType references are allowed. */ |
| 42915 | static UA_StatusCode |
| 42916 | checkParentReference(UA_Server *server, UA_Session *session, const UA_NodeHead *head, |
| 42917 | const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId) { |
| 42918 | /* Objects do not need a parent (e.g. mandatory/optional modellingrules). |
| 42919 | * Also, there are some variables which do not have parents, e.g. |
| 42920 | * EnumStrings, EnumValues */ |
| 42921 | if((head->nodeClass == UA_NODECLASS_OBJECT || |
| 42922 | head->nodeClass == UA_NODECLASS_VARIABLE) && |
| 42923 | UA_NodeId_isNull(p: parentNodeId) && UA_NodeId_isNull(p: referenceTypeId)) |
| 42924 | return UA_STATUSCODE_GOOD; |
| 42925 | |
| 42926 | /* See if the parent exists */ |
| 42927 | const UA_Node *parent = UA_NODESTORE_GET(server, nodeId: parentNodeId); |
| 42928 | if(!parent) { |
| 42929 | logAddNode(logger: server->config.logging, session, nodeId: &head->nodeId, |
| 42930 | msg: "Parent node not found"); |
| 42931 | return UA_STATUSCODE_BADPARENTNODEIDINVALID; |
| 42932 | } |
| 42933 | |
| 42934 | UA_NodeClass parentNodeClass = parent->head.nodeClass; |
| 42935 | UA_NODESTORE_RELEASE(server, parent); |
| 42936 | |
| 42937 | /* Check the referencetype exists */ |
| 42938 | const UA_Node *referenceType = UA_NODESTORE_GET(server, nodeId: referenceTypeId); |
| 42939 | if(!referenceType) { |
| 42940 | logAddNode(logger: server->config.logging, session, nodeId: &head->nodeId, |
| 42941 | msg: "Reference type to the parent not found"); |
| 42942 | return UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 42943 | } |
| 42944 | |
| 42945 | /* Check if the referencetype is a reference type node */ |
| 42946 | if(referenceType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) { |
| 42947 | logAddNode(logger: server->config.logging, session, nodeId: &head->nodeId, |
| 42948 | msg: "Reference type to the parent is not a ReferenceTypeNode"); |
| 42949 | UA_NODESTORE_RELEASE(server, referenceType); |
| 42950 | return UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 42951 | } |
| 42952 | |
| 42953 | /* Check that the reference type is not abstract */ |
| 42954 | UA_Boolean referenceTypeIsAbstract = referenceType->referenceTypeNode.isAbstract; |
| 42955 | UA_NODESTORE_RELEASE(server, referenceType); |
| 42956 | if(referenceTypeIsAbstract == true) { |
| 42957 | logAddNode(logger: server->config.logging, session, nodeId: &head->nodeId, |
| 42958 | msg: "Abstract reference type to the parent not allowed"); |
| 42959 | return UA_STATUSCODE_BADREFERENCENOTALLOWED; |
| 42960 | } |
| 42961 | |
| 42962 | /* Check hassubtype relation for type nodes */ |
| 42963 | if(head->nodeClass == UA_NODECLASS_DATATYPE || |
| 42964 | head->nodeClass == UA_NODECLASS_VARIABLETYPE || |
| 42965 | head->nodeClass == UA_NODECLASS_OBJECTTYPE || |
| 42966 | head->nodeClass == UA_NODECLASS_REFERENCETYPE) { |
| 42967 | /* Type needs hassubtype reference to the supertype */ |
| 42968 | if(referenceType->referenceTypeNode.referenceTypeIndex != |
| 42969 | UA_REFERENCETYPEINDEX_HASSUBTYPE) { |
| 42970 | logAddNode(logger: server->config.logging, session, nodeId: &head->nodeId, |
| 42971 | msg: "Type nodes need to have a HasSubType reference to the parent"); |
| 42972 | return UA_STATUSCODE_BADREFERENCENOTALLOWED; |
| 42973 | } |
| 42974 | /* Supertype needs to be of the same node type */ |
| 42975 | if(parentNodeClass != head->nodeClass) { |
| 42976 | logAddNode(logger: server->config.logging, session, nodeId: &head->nodeId, |
| 42977 | msg: "Type nodes needs to be of the same node " |
| 42978 | "type as their parent"); |
| 42979 | return UA_STATUSCODE_BADPARENTNODEIDINVALID; |
| 42980 | } |
| 42981 | return UA_STATUSCODE_GOOD; |
| 42982 | } |
| 42983 | |
| 42984 | /* Test if the referencetype is hierarchical */ |
| 42985 | const UA_NodeId hierarchRefs = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES); |
| 42986 | if(!isNodeInTree_singleRef(server, leafNode: referenceTypeId, nodeToFind: &hierarchRefs, |
| 42987 | UA_REFERENCETYPEINDEX_HASSUBTYPE)) { |
| 42988 | logAddNode(logger: server->config.logging, session, nodeId: &head->nodeId, |
| 42989 | msg: "Reference type to the parent is not hierarchical"); |
| 42990 | return UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 42991 | } |
| 42992 | |
| 42993 | return UA_STATUSCODE_GOOD; |
| 42994 | } |
| 42995 | |
| 42996 | /* Only BaseDataType can have empty values. Generate a default value. */ |
| 42997 | static UA_StatusCode |
| 42998 | setDefaultValue(UA_Server *server, const UA_VariableNode *node) { |
| 42999 | /* Get the DataType */ |
| 43000 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 43001 | const UA_DataType *type = UA_Server_findDataType(server, typeId: &node->dataType); |
| 43002 | if(!type) { |
| 43003 | /* No description for the DataType found. It is possible that an |
| 43004 | * abstract DataType is used, e.g. UInteger. Browse to see if there is a |
| 43005 | * non-abstract subtype that can be used for the default value. |
| 43006 | * |
| 43007 | * Look up and downwards in the hierarchy. Some data types (e.g. |
| 43008 | * UtcTime) are derived from a non-abstract data type. This is then used |
| 43009 | * for the actual value, Use the first match. */ |
| 43010 | UA_ReferenceTypeSet refs = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE); |
| 43011 | UA_ExpandedNodeId *typeCandidates = NULL; |
| 43012 | size_t typeCandidatesSize = 0; |
| 43013 | res = browseRecursive(server, startNodesSize: 1, startNodes: &node->dataType, |
| 43014 | browseDirection: UA_BROWSEDIRECTION_BOTH, refTypes: &refs, |
| 43015 | nodeClassMask: UA_NODECLASS_DATATYPE, false, |
| 43016 | resultsSize: &typeCandidatesSize, results: &typeCandidates); |
| 43017 | if(res != UA_STATUSCODE_GOOD) |
| 43018 | return res; |
| 43019 | |
| 43020 | for(size_t i = 0; i < typeCandidatesSize; i++) { |
| 43021 | /* Skip BaseDataType (Variant). This is the root of the DataType |
| 43022 | * hierarchy. Variables of BaseDataType can be empty. */ |
| 43023 | if(UA_NodeId_equal(p1: &UA_TYPES[UA_TYPES_VARIANT].typeId, |
| 43024 | p2: &typeCandidates[i].nodeId)) |
| 43025 | continue; |
| 43026 | |
| 43027 | /* Skip ExtensionObject. Even though we can encode the type it is |
| 43028 | * abstract and nodes should not contain them as value. */ |
| 43029 | if(UA_NodeId_equal(p1: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT].typeId, |
| 43030 | p2: &typeCandidates[i].nodeId)) |
| 43031 | continue; |
| 43032 | |
| 43033 | /* Get the type encoding information */ |
| 43034 | type = UA_Server_findDataType(server, typeId: &typeCandidates[i].nodeId); |
| 43035 | if(type) |
| 43036 | break; |
| 43037 | } |
| 43038 | |
| 43039 | UA_Array_delete(p: typeCandidates, size: typeCandidatesSize, |
| 43040 | type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 43041 | if(!type) |
| 43042 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 43043 | } |
| 43044 | |
| 43045 | /* Set up the value with the default content */ |
| 43046 | UA_Variant val; |
| 43047 | UA_Variant_init(p: &val); |
| 43048 | if(node->valueRank < 0) { |
| 43049 | /* Set a scalar */ |
| 43050 | void *data = UA_new(type); |
| 43051 | if(!data) |
| 43052 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 43053 | UA_Variant_setScalar(v: &val, p: data, type); |
| 43054 | } else { |
| 43055 | /* Set an array |
| 43056 | * |
| 43057 | * https://reference.opcfoundation.org/v104/Core/docs/Part3/5.6.2/#Table13 |
| 43058 | * specifies ArrayDimensions as follows: This Attribute specifies the |
| 43059 | * maximum supported length of each dimension. If the maximum is unknown |
| 43060 | * the value shall be 0. The number of elements shall be equal to the |
| 43061 | * value of the ValueRank Attribute. This Attribute shall be null if |
| 43062 | * ValueRank <= 0. |
| 43063 | * |
| 43064 | * The (variant) values themselves cannot have ArrayDimensions with a |
| 43065 | * dimension length of zero. We however consider that empty arrays |
| 43066 | * (null-array or length zero) have implicit array dimensions [0,0,...]. |
| 43067 | * With the appropriate number of dimensions. So they always match. |
| 43068 | * |
| 43069 | * We automatically create a null array during the node creation when |
| 43070 | * required for the type-checking.. |
| 43071 | * |
| 43072 | * Also see the method 'compatibleValueArrayDimensions' where the |
| 43073 | * compatibility of the ArrayDimensions is checked. */ |
| 43074 | UA_Variant_setArray(v: &val, NULL, arraySize: 0, type); |
| 43075 | } |
| 43076 | |
| 43077 | /* Write the value */ |
| 43078 | res = writeAttribute(server, session: &server->adminSession, nodeId: &node->head.nodeId, |
| 43079 | attributeId: UA_ATTRIBUTEID_VALUE, attr: &val, attr_type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 43080 | |
| 43081 | /* Clean up */ |
| 43082 | UA_Variant_clear(p: &val); |
| 43083 | return res; |
| 43084 | } |
| 43085 | |
| 43086 | static UA_StatusCode |
| 43087 | typeCheckVariableNode(UA_Server *server, UA_Session *session, |
| 43088 | const UA_VariableNode *node, |
| 43089 | const UA_VariableTypeNode *vt) { |
| 43090 | /* Check the datatype against the vt */ |
| 43091 | if(!compatibleDataTypes(server, dataType: &node->dataType, constraintDataType: &vt->dataType)) { |
| 43092 | logAddNode(logger: server->config.logging, session, nodeId: &node->head.nodeId, |
| 43093 | msg: "The value of is incompatible with " |
| 43094 | "the datatype of the VariableType"); |
| 43095 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 43096 | } |
| 43097 | |
| 43098 | /* Check valueRank against array dimensions */ |
| 43099 | if(!compatibleValueRankArrayDimensions(server, session, valueRank: node->valueRank, |
| 43100 | arrayDimensionsSize: node->arrayDimensionsSize)) { |
| 43101 | logAddNode(logger: server->config.logging, session, nodeId: &node->head.nodeId, |
| 43102 | msg: "The value rank of is incompatible with its array dimensions"); |
| 43103 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 43104 | } |
| 43105 | |
| 43106 | /* Check valueRank against the vt */ |
| 43107 | if(!compatibleValueRanks(valueRank: node->valueRank, constraintValueRank: vt->valueRank)) { |
| 43108 | logAddNode(logger: server->config.logging, session, nodeId: &node->head.nodeId, |
| 43109 | msg: "The value rank is incompatible " |
| 43110 | "with the value rank of the VariableType"); |
| 43111 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 43112 | } |
| 43113 | |
| 43114 | /* Check array dimensions against the vt */ |
| 43115 | if(!compatibleArrayDimensions(constraintArrayDimensionsSize: vt->arrayDimensionsSize, constraintArrayDimensions: vt->arrayDimensions, |
| 43116 | testArrayDimensionsSize: node->arrayDimensionsSize, testArrayDimensions: node->arrayDimensions)) { |
| 43117 | logAddNode(logger: server->config.logging, session, nodeId: &node->head.nodeId, |
| 43118 | msg: "The array dimensions are incompatible with the " |
| 43119 | "array dimensions of the VariableType"); |
| 43120 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 43121 | } |
| 43122 | |
| 43123 | /* Typecheck the value. Less strict for NS0 -- we adjust nodes after loading |
| 43124 | * the generated definitions. */ |
| 43125 | if(server->bootstrapNS0) |
| 43126 | return UA_STATUSCODE_GOOD; |
| 43127 | |
| 43128 | /* The value might come from a datasource, so we perform a |
| 43129 | * regular read. */ |
| 43130 | UA_DataValue value; |
| 43131 | UA_DataValue_init(p: &value); |
| 43132 | UA_StatusCode retval = readValueAttribute(server, session, vn: node, v: &value); |
| 43133 | if(retval != UA_STATUSCODE_GOOD) |
| 43134 | return retval; |
| 43135 | |
| 43136 | /* We have a value. Write it back to perform checks and adjustments. */ |
| 43137 | const char *reason; |
| 43138 | if(node->valueSource == UA_VALUESOURCE_DATA && value.hasValue) { |
| 43139 | if(!compatibleValue(server, session, targetDataTypeId: &node->dataType, targetValueRank: node->valueRank, |
| 43140 | targetArrayDimensionsSize: node->arrayDimensionsSize, targetArrayDimensions: node->arrayDimensions, |
| 43141 | value: &value.value, NULL, reason: &reason)) { |
| 43142 | retval = writeAttribute(server, session, nodeId: &node->head.nodeId, |
| 43143 | attributeId: UA_ATTRIBUTEID_VALUE, attr: &value.value, |
| 43144 | attr_type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 43145 | } |
| 43146 | UA_DataValue_clear(p: &value); |
| 43147 | return retval; |
| 43148 | } |
| 43149 | |
| 43150 | /* Only BaseDataType (Variant) can have empty values */ |
| 43151 | if(!value.hasValue && |
| 43152 | !UA_NodeId_equal(p1: &node->dataType, p2: &UA_TYPES[UA_TYPES_VARIANT].typeId)) { |
| 43153 | /* Warn if that is configured */ |
| 43154 | if(server->config.allowEmptyVariables != UA_RULEHANDLING_ACCEPT) |
| 43155 | UA_LOG_NODEID_DEBUG(&node->head.nodeId, |
| 43156 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 43157 | "AddNode (%.*s): The value is empty. " |
| 43158 | "But this is only allowed for BaseDataType. " |
| 43159 | "Create a matching default value.", |
| 43160 | (int)nodeIdStr.length, nodeIdStr.data)); |
| 43161 | |
| 43162 | /* Abort if that is configured */ |
| 43163 | if(server->config.allowEmptyVariables == UA_RULEHANDLING_ABORT) |
| 43164 | retval = UA_STATUSCODE_BADTYPEMISMATCH; |
| 43165 | |
| 43166 | /* Try to generate and write a default value */ |
| 43167 | if(server->config.allowEmptyVariables == UA_RULEHANDLING_DEFAULT) { |
| 43168 | retval = setDefaultValue(server, node); |
| 43169 | if(retval != UA_STATUSCODE_GOOD) { |
| 43170 | UA_LOG_NODEID_INFO(&node->head.nodeId, |
| 43171 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 43172 | "AddNode (%.*s): Could not create a default value " |
| 43173 | "with StatusCode %s", (int)nodeIdStr.length, |
| 43174 | nodeIdStr.data, UA_StatusCode_name(retval))); |
| 43175 | } |
| 43176 | } |
| 43177 | return retval; |
| 43178 | } |
| 43179 | |
| 43180 | /* Type-check the value */ |
| 43181 | UA_Boolean compatible = |
| 43182 | compatibleValue(server, session, targetDataTypeId: &node->dataType, |
| 43183 | targetValueRank: node->valueRank, targetArrayDimensionsSize: node->arrayDimensionsSize, |
| 43184 | targetArrayDimensions: node->arrayDimensions, value: &value.value, NULL, reason: &reason); |
| 43185 | if(!compatible) { |
| 43186 | UA_LOG_NODEID_INFO(&node->head.nodeId, |
| 43187 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 43188 | "AddNode (%.*s): The VariableNode value has " |
| 43189 | "failed the type check with reason %s. ", |
| 43190 | (int)nodeIdStr.length, nodeIdStr.data, reason)); |
| 43191 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 43192 | } |
| 43193 | |
| 43194 | UA_DataValue_clear(p: &value); |
| 43195 | return retval; |
| 43196 | } |
| 43197 | |
| 43198 | /********************/ |
| 43199 | /* Instantiate Node */ |
| 43200 | /********************/ |
| 43201 | |
| 43202 | static const UA_NodeId baseDataVariableType = |
| 43203 | {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_BASEDATAVARIABLETYPE}}; |
| 43204 | static const UA_NodeId baseObjectType = |
| 43205 | {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_BASEOBJECTTYPE}}; |
| 43206 | static const UA_NodeId hasTypeDefinition = |
| 43207 | {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASTYPEDEFINITION}}; |
| 43208 | |
| 43209 | /* Use attributes from the variable type wherever required. Reload the node if |
| 43210 | * changes were made. */ |
| 43211 | static UA_StatusCode |
| 43212 | useVariableTypeAttributes(UA_Server *server, UA_Session *session, |
| 43213 | const UA_VariableNode *node, |
| 43214 | const UA_VariableTypeNode *vt) { |
| 43215 | /* If no value is set, see if the vt provides one and copy it. This needs to |
| 43216 | * be done before copying the datatype from the vt, as setting the datatype |
| 43217 | * triggers a typecheck. */ |
| 43218 | UA_Variant orig; |
| 43219 | UA_StatusCode retval = |
| 43220 | readWithReadValue(server, nodeId: &node->head.nodeId, attributeId: UA_ATTRIBUTEID_VALUE, v: &orig); |
| 43221 | if(retval != UA_STATUSCODE_GOOD) |
| 43222 | return retval; |
| 43223 | |
| 43224 | if(orig.type) { |
| 43225 | /* A value is present */ |
| 43226 | UA_Variant_clear(p: &orig); |
| 43227 | } else { |
| 43228 | UA_DataValue v; |
| 43229 | UA_DataValue_init(p: &v); |
| 43230 | retval = readValueAttribute(server, session, vn: (const UA_VariableNode*)vt, v: &v); |
| 43231 | if(retval == UA_STATUSCODE_GOOD && v.hasValue) { |
| 43232 | retval = writeAttribute(server, session, nodeId: &node->head.nodeId, |
| 43233 | attributeId: UA_ATTRIBUTEID_VALUE, attr: &v.value, |
| 43234 | attr_type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 43235 | } |
| 43236 | UA_DataValue_clear(p: &v); |
| 43237 | |
| 43238 | if(retval != UA_STATUSCODE_GOOD) { |
| 43239 | logAddNode(logger: server->config.logging, session, nodeId: &node->head.nodeId, |
| 43240 | msg: "The default content of the VariableType could " |
| 43241 | "not be used. This may happen if the VariableNode " |
| 43242 | "makes additional restrictions."); |
| 43243 | retval = UA_STATUSCODE_GOOD; |
| 43244 | } |
| 43245 | } |
| 43246 | |
| 43247 | /* If no datatype is given, use the datatype of the vt */ |
| 43248 | if(UA_NodeId_isNull(p: &node->dataType)) { |
| 43249 | logAddNode(logger: server->config.logging, session, nodeId: &node->head.nodeId, |
| 43250 | msg: "No datatype given; Copy the datatype attribute " |
| 43251 | "from the TypeDefinition"); |
| 43252 | retval = writeAttribute(server, session, nodeId: &node->head.nodeId, |
| 43253 | attributeId: UA_ATTRIBUTEID_DATATYPE, attr: &vt->dataType, |
| 43254 | attr_type: &UA_TYPES[UA_TYPES_NODEID]); |
| 43255 | if(retval != UA_STATUSCODE_GOOD) |
| 43256 | return retval; |
| 43257 | } |
| 43258 | |
| 43259 | /* Use the ArrayDimensions of the vt */ |
| 43260 | if(node->arrayDimensionsSize == 0 && vt->arrayDimensionsSize > 0) { |
| 43261 | UA_Variant v; |
| 43262 | UA_Variant_init(p: &v); |
| 43263 | UA_Variant_setArray(v: &v, array: vt->arrayDimensions, arraySize: vt->arrayDimensionsSize, |
| 43264 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 43265 | retval = writeAttribute(server, session, nodeId: &node->head.nodeId, |
| 43266 | attributeId: UA_ATTRIBUTEID_ARRAYDIMENSIONS, attr: &v, |
| 43267 | attr_type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 43268 | } |
| 43269 | |
| 43270 | return retval; |
| 43271 | } |
| 43272 | |
| 43273 | /* Search for an instance of "browseName" in node searchInstance. Used during |
| 43274 | * copyChildNodes to find overwritable/mergable nodes. Does not touch |
| 43275 | * outInstanceNodeId if no child is found. */ |
| 43276 | static UA_StatusCode |
| 43277 | findChildByBrowsename(UA_Server *server, UA_Session *session, |
| 43278 | const UA_NodeId *searchInstance, |
| 43279 | const UA_QualifiedName *browseName, |
| 43280 | UA_NodeId *outInstanceNodeId) { |
| 43281 | UA_BrowseDescription bd; |
| 43282 | UA_BrowseDescription_init(p: &bd); |
| 43283 | bd.nodeId = *searchInstance; |
| 43284 | bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES); |
| 43285 | bd.includeSubtypes = true; |
| 43286 | bd.browseDirection = UA_BROWSEDIRECTION_FORWARD; |
| 43287 | bd.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD; |
| 43288 | bd.resultMask = UA_BROWSERESULTMASK_BROWSENAME; |
| 43289 | |
| 43290 | UA_BrowseResult br; |
| 43291 | UA_BrowseResult_init(p: &br); |
| 43292 | UA_UInt32 maxrefs = 0; |
| 43293 | Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br); |
| 43294 | if(br.statusCode != UA_STATUSCODE_GOOD) |
| 43295 | return br.statusCode; |
| 43296 | |
| 43297 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 43298 | for(size_t i = 0; i < br.referencesSize; ++i) { |
| 43299 | UA_ReferenceDescription *rd = &br.references[i]; |
| 43300 | if(rd->browseName.namespaceIndex == browseName->namespaceIndex && |
| 43301 | UA_String_equal(p1: &rd->browseName.name, p2: &browseName->name)) { |
| 43302 | retval = UA_NodeId_copy(src: &rd->nodeId.nodeId, dst: outInstanceNodeId); |
| 43303 | break; |
| 43304 | } |
| 43305 | } |
| 43306 | |
| 43307 | UA_BrowseResult_clear(p: &br); |
| 43308 | return retval; |
| 43309 | } |
| 43310 | |
| 43311 | static const UA_ExpandedNodeId mandatoryId = |
| 43312 | {{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_MODELLINGRULE_MANDATORY}}, {0, NULL}, 0}; |
| 43313 | |
| 43314 | static UA_Boolean |
| 43315 | isMandatoryChild(UA_Server *server, UA_Session *session, |
| 43316 | const UA_NodeId *childNodeId) { |
| 43317 | /* Get the child */ |
| 43318 | const UA_Node *child = UA_NODESTORE_GET(server, nodeId: childNodeId); |
| 43319 | if(!child) |
| 43320 | return false; |
| 43321 | |
| 43322 | /* Look for the reference making the child mandatory */ |
| 43323 | UA_Boolean found = false; |
| 43324 | for(size_t i = 0; i < child->head.referencesSize; ++i) { |
| 43325 | UA_NodeReferenceKind *rk = &child->head.references[i]; |
| 43326 | if(rk->referenceTypeIndex != UA_REFERENCETYPEINDEX_HASMODELLINGRULE) |
| 43327 | continue; |
| 43328 | if(rk->isInverse) |
| 43329 | continue; |
| 43330 | |
| 43331 | if(UA_NodeReferenceKind_findTarget(rk, targetId: &mandatoryId)) { |
| 43332 | found = true; |
| 43333 | break; |
| 43334 | } |
| 43335 | } |
| 43336 | |
| 43337 | UA_NODESTORE_RELEASE(server, child); |
| 43338 | return found; |
| 43339 | } |
| 43340 | |
| 43341 | static UA_StatusCode |
| 43342 | copyAllChildren(UA_Server *server, UA_Session *session, |
| 43343 | const UA_NodeId *source, const UA_NodeId *destination); |
| 43344 | |
| 43345 | static void |
| 43346 | Operation_addReference(UA_Server *server, UA_Session *session, void *context, |
| 43347 | const UA_AddReferencesItem *item, UA_StatusCode *retval); |
| 43348 | |
| 43349 | UA_StatusCode |
| 43350 | addRefWithSession(UA_Server *server, UA_Session *session, const UA_NodeId *sourceId, |
| 43351 | const UA_NodeId *referenceTypeId, const UA_NodeId *targetId, |
| 43352 | UA_Boolean forward) { |
| 43353 | UA_AddReferencesItem ref_item; |
| 43354 | UA_AddReferencesItem_init(p: &ref_item); |
| 43355 | ref_item.sourceNodeId = *sourceId; |
| 43356 | ref_item.referenceTypeId = *referenceTypeId; |
| 43357 | ref_item.isForward = forward; |
| 43358 | ref_item.targetNodeId.nodeId = *targetId; |
| 43359 | |
| 43360 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 43361 | Operation_addReference(server, session, NULL, item: &ref_item, retval: &retval); |
| 43362 | return retval; |
| 43363 | } |
| 43364 | |
| 43365 | UA_StatusCode |
| 43366 | addRef(UA_Server *server, const UA_NodeId sourceId, |
| 43367 | const UA_NodeId referenceTypeId, const UA_NodeId targetId, |
| 43368 | UA_Boolean forward) { |
| 43369 | return addRefWithSession(server, session: &server->adminSession, sourceId: &sourceId, |
| 43370 | referenceTypeId: &referenceTypeId, targetId: &targetId, forward); |
| 43371 | } |
| 43372 | |
| 43373 | static UA_StatusCode |
| 43374 | addInterfaceChildren(UA_Server *server, UA_Session *session, |
| 43375 | const UA_NodeId *nodeId, const UA_NodeId *typeId) { |
| 43376 | /* Get the hierarchy of the type and all its supertypes */ |
| 43377 | UA_NodeId *hierarchy = NULL; |
| 43378 | size_t hierarchySize = 0; |
| 43379 | UA_StatusCode retval = getAllInterfaceChildNodeIds(server, objectNode: nodeId, objectTypeNode: typeId, |
| 43380 | interfaceChildNodes: &hierarchy, interfaceChildNodesSize: &hierarchySize); |
| 43381 | if(retval != UA_STATUSCODE_GOOD) |
| 43382 | return retval; |
| 43383 | |
| 43384 | /* Copy members of the type and supertypes (and instantiate them) */ |
| 43385 | for(size_t i = 0; i < hierarchySize; ++i) { |
| 43386 | retval = copyAllChildren(server, session, source: &hierarchy[i], destination: nodeId); |
| 43387 | if(retval != UA_STATUSCODE_GOOD) { |
| 43388 | UA_Array_delete(p: hierarchy, size: hierarchySize, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 43389 | return retval; |
| 43390 | } |
| 43391 | } |
| 43392 | |
| 43393 | for(size_t i = 0; i < hierarchySize; ++i) { |
| 43394 | UA_NodeId refId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASINTERFACE); |
| 43395 | retval = addRef(server, sourceId: *nodeId, referenceTypeId: refId, targetId: hierarchy[i], true); |
| 43396 | |
| 43397 | /* Don't add the original HasInterface reference to ObjectType sub nodes */ |
| 43398 | if(retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) { |
| 43399 | retval = UA_STATUSCODE_GOOD; |
| 43400 | } else if(retval != UA_STATUSCODE_GOOD) { |
| 43401 | break; |
| 43402 | } |
| 43403 | } |
| 43404 | |
| 43405 | UA_Array_delete(p: hierarchy, size: hierarchySize, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 43406 | return retval; |
| 43407 | } |
| 43408 | |
| 43409 | static UA_StatusCode |
| 43410 | copyChild(UA_Server *server, UA_Session *session, |
| 43411 | const UA_NodeId *destinationNodeId, |
| 43412 | const UA_ReferenceDescription *rd) { |
| 43413 | UA_assert(session); |
| 43414 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 43415 | |
| 43416 | /* Is there an existing child with the browsename? */ |
| 43417 | UA_NodeId existingChild = UA_NODEID_NULL; |
| 43418 | UA_StatusCode retval = findChildByBrowsename(server, session, searchInstance: destinationNodeId, |
| 43419 | browseName: &rd->browseName, outInstanceNodeId: &existingChild); |
| 43420 | if(retval != UA_STATUSCODE_GOOD) |
| 43421 | return retval; |
| 43422 | |
| 43423 | /* Have a child with that browseName. Deep-copy missing members. */ |
| 43424 | if(!UA_NodeId_isNull(p: &existingChild)) { |
| 43425 | if(rd->nodeClass == UA_NODECLASS_VARIABLE || |
| 43426 | rd->nodeClass == UA_NODECLASS_OBJECT) |
| 43427 | retval = copyAllChildren(server, session, source: &rd->nodeId.nodeId, destination: &existingChild); |
| 43428 | UA_NodeId_clear(p: &existingChild); |
| 43429 | return retval; |
| 43430 | } |
| 43431 | |
| 43432 | /* Is the child mandatory? If not, ask callback whether child should be instantiated. |
| 43433 | * If not, skip. */ |
| 43434 | if(!isMandatoryChild(server, session, childNodeId: &rd->nodeId.nodeId)) { |
| 43435 | if(!server->config.nodeLifecycle.createOptionalChild) |
| 43436 | return UA_STATUSCODE_GOOD; |
| 43437 | UA_Boolean createChild = server->config.nodeLifecycle. |
| 43438 | createOptionalChild(server, &session->sessionId, session->sessionHandle, |
| 43439 | &rd->nodeId.nodeId, destinationNodeId, &rd->referenceTypeId); |
| 43440 | if(!createChild) |
| 43441 | return UA_STATUSCODE_GOOD; |
| 43442 | } |
| 43443 | |
| 43444 | /* Child is a method -> create a reference */ |
| 43445 | if(rd->nodeClass == UA_NODECLASS_METHOD) { |
| 43446 | UA_AddReferencesItem newItem; |
| 43447 | UA_AddReferencesItem_init(p: &newItem); |
| 43448 | newItem.sourceNodeId = *destinationNodeId; |
| 43449 | newItem.referenceTypeId = rd->referenceTypeId; |
| 43450 | newItem.isForward = true; |
| 43451 | newItem.targetNodeId = rd->nodeId; |
| 43452 | newItem.targetNodeClass = UA_NODECLASS_METHOD; |
| 43453 | Operation_addReference(server, session, NULL, item: &newItem, retval: &retval); |
| 43454 | return retval; |
| 43455 | } |
| 43456 | |
| 43457 | /* Child is a variable or object */ |
| 43458 | if(rd->nodeClass == UA_NODECLASS_VARIABLE || |
| 43459 | rd->nodeClass == UA_NODECLASS_OBJECT) { |
| 43460 | /* Make a copy of the node */ |
| 43461 | UA_Node *node; |
| 43462 | retval = UA_NODESTORE_GETCOPY(server, &rd->nodeId.nodeId, &node); |
| 43463 | if(retval != UA_STATUSCODE_GOOD) |
| 43464 | return retval; |
| 43465 | |
| 43466 | /* Remove the context of the copied node */ |
| 43467 | node->head.context = NULL; |
| 43468 | node->head.constructed = false; |
| 43469 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 43470 | node->head.monitoredItems = NULL; |
| 43471 | #endif |
| 43472 | |
| 43473 | /* The value backend is copied by default. But we don't want to keep it |
| 43474 | * here. */ |
| 43475 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE || |
| 43476 | node->head.nodeClass == UA_NODECLASS_VARIABLETYPE) { |
| 43477 | if(node->variableNode.valueSource != UA_VALUESOURCE_DATA) |
| 43478 | memset(s: &node->variableNode.value, c: 0, n: sizeof(node->variableNode.value)); |
| 43479 | node->variableNode.valueSource = UA_VALUESOURCE_DATA; |
| 43480 | memset(s: &node->variableNode.valueBackend, c: 0, n: sizeof(UA_ValueBackend)); |
| 43481 | } |
| 43482 | |
| 43483 | /* Reset the NodeId (random numeric id will be assigned in the nodestore) */ |
| 43484 | UA_NodeId_clear(p: &node->head.nodeId); |
| 43485 | node->head.nodeId.namespaceIndex = destinationNodeId->namespaceIndex; |
| 43486 | |
| 43487 | if(server->config.nodeLifecycle.generateChildNodeId) { |
| 43488 | retval = server->config.nodeLifecycle. |
| 43489 | generateChildNodeId(server, &session->sessionId, session->sessionHandle, |
| 43490 | &rd->nodeId.nodeId, destinationNodeId, |
| 43491 | &rd->referenceTypeId, &node->head.nodeId); |
| 43492 | if(retval != UA_STATUSCODE_GOOD) { |
| 43493 | UA_NODESTORE_DELETE(server, node); |
| 43494 | return retval; |
| 43495 | } |
| 43496 | } |
| 43497 | |
| 43498 | /* Remove references, they are re-created from scratch in addnode_finish */ |
| 43499 | /* TODO: Be more clever in removing references that are re-added during |
| 43500 | * addnode_finish. That way, we can call addnode_finish also on children that were |
| 43501 | * manually added by the user during addnode_begin and addnode_finish. */ |
| 43502 | /* For now we keep all the modelling rule references and delete all others */ |
| 43503 | const UA_NodeId nodeId_typesFolder= UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_TYPESFOLDER); |
| 43504 | const UA_ReferenceTypeSet reftypes_aggregates = |
| 43505 | UA_REFTYPESET(UA_REFERENCETYPEINDEX_AGGREGATES); |
| 43506 | UA_ReferenceTypeSet reftypes_skipped; |
| 43507 | /* Check if the hasModellingRule-reference is required (configured or node in an |
| 43508 | instance declaration) */ |
| 43509 | if(server->config.modellingRulesOnInstances || |
| 43510 | isNodeInTree(server, leafNode: destinationNodeId, |
| 43511 | nodeToFind: &nodeId_typesFolder, relevantRefs: &reftypes_aggregates)) { |
| 43512 | reftypes_skipped = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASMODELLINGRULE); |
| 43513 | } else { |
| 43514 | UA_ReferenceTypeSet_init(set: &reftypes_skipped); |
| 43515 | } |
| 43516 | reftypes_skipped = UA_ReferenceTypeSet_union(setA: reftypes_skipped, setB: UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE)); |
| 43517 | UA_Node_deleteReferencesSubset(node, keepSet: &reftypes_skipped); |
| 43518 | |
| 43519 | /* Add the node to the nodestore */ |
| 43520 | UA_NodeId newNodeId = UA_NODEID_NULL; |
| 43521 | retval = UA_NODESTORE_INSERT(server, node, &newNodeId); |
| 43522 | /* node = NULL; The pointer is no longer valid */ |
| 43523 | if(retval != UA_STATUSCODE_GOOD) |
| 43524 | return retval; |
| 43525 | |
| 43526 | /* Add the node references */ |
| 43527 | retval = addNode_addRefs(server, session, nodeId: &newNodeId, parentNodeId: destinationNodeId, |
| 43528 | referenceTypeId: &rd->referenceTypeId, typeDefinitionId: &rd->typeDefinition.nodeId); |
| 43529 | if(retval != UA_STATUSCODE_GOOD) { |
| 43530 | UA_NODESTORE_REMOVE(server, &newNodeId); |
| 43531 | UA_NodeId_clear(p: &newNodeId); |
| 43532 | return retval; |
| 43533 | } |
| 43534 | |
| 43535 | if (rd->nodeClass == UA_NODECLASS_VARIABLE) { |
| 43536 | retval = checkSetIsDynamicVariable(server, session, nodeId: &newNodeId); |
| 43537 | |
| 43538 | if(retval != UA_STATUSCODE_GOOD) { |
| 43539 | UA_NODESTORE_REMOVE(server, &newNodeId); |
| 43540 | return retval; |
| 43541 | } |
| 43542 | } |
| 43543 | |
| 43544 | /* For the new child, recursively copy the members of the original. No |
| 43545 | * typechecking is performed here. Assuming that the original is |
| 43546 | * consistent. */ |
| 43547 | retval = copyAllChildren(server, session, source: &rd->nodeId.nodeId, destination: &newNodeId); |
| 43548 | if(retval != UA_STATUSCODE_GOOD) { |
| 43549 | deleteNode(server, nodeId: newNodeId, true); |
| 43550 | return retval; |
| 43551 | } |
| 43552 | |
| 43553 | /* Check if its a dynamic variable, add all type and/or interface |
| 43554 | * children and call the constructor */ |
| 43555 | retval = addNode_finish(server, session, nodeId: &newNodeId); |
| 43556 | if(retval != UA_STATUSCODE_GOOD) { |
| 43557 | deleteNode(server, nodeId: newNodeId, true); |
| 43558 | return retval; |
| 43559 | } |
| 43560 | |
| 43561 | /* Clean up. Because it can happen that a string is assigned as ID at |
| 43562 | * generateChildNodeId. */ |
| 43563 | UA_NodeId_clear(p: &newNodeId); |
| 43564 | } |
| 43565 | |
| 43566 | return retval; |
| 43567 | } |
| 43568 | |
| 43569 | /* Copy any children of Node sourceNodeId to another node destinationNodeId. */ |
| 43570 | static UA_StatusCode |
| 43571 | copyAllChildren(UA_Server *server, UA_Session *session, |
| 43572 | const UA_NodeId *source, const UA_NodeId *destination) { |
| 43573 | /* Browse to get all children of the source */ |
| 43574 | UA_BrowseDescription bd; |
| 43575 | UA_BrowseDescription_init(p: &bd); |
| 43576 | bd.nodeId = *source; |
| 43577 | bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES); |
| 43578 | bd.includeSubtypes = true; |
| 43579 | bd.browseDirection = UA_BROWSEDIRECTION_FORWARD; |
| 43580 | bd.nodeClassMask = UA_NODECLASS_OBJECT | UA_NODECLASS_VARIABLE | UA_NODECLASS_METHOD; |
| 43581 | bd.resultMask = UA_BROWSERESULTMASK_REFERENCETYPEID | UA_BROWSERESULTMASK_NODECLASS | |
| 43582 | UA_BROWSERESULTMASK_BROWSENAME | UA_BROWSERESULTMASK_TYPEDEFINITION; |
| 43583 | |
| 43584 | UA_BrowseResult br; |
| 43585 | UA_BrowseResult_init(p: &br); |
| 43586 | UA_UInt32 maxrefs = 0; |
| 43587 | Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br); |
| 43588 | if(br.statusCode != UA_STATUSCODE_GOOD) |
| 43589 | return br.statusCode; |
| 43590 | |
| 43591 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 43592 | for(size_t i = 0; i < br.referencesSize; ++i) { |
| 43593 | UA_ReferenceDescription *rd = &br.references[i]; |
| 43594 | retval = copyChild(server, session, destinationNodeId: destination, rd); |
| 43595 | if(retval != UA_STATUSCODE_GOOD) |
| 43596 | break; |
| 43597 | } |
| 43598 | |
| 43599 | UA_BrowseResult_clear(p: &br); |
| 43600 | return retval; |
| 43601 | } |
| 43602 | |
| 43603 | static UA_StatusCode |
| 43604 | addTypeChildren(UA_Server *server, UA_Session *session, |
| 43605 | const UA_NodeId *nodeId, const UA_NodeId *typeId) { |
| 43606 | /* Get the hierarchy of the type and all its supertypes */ |
| 43607 | UA_NodeId *hierarchy = NULL; |
| 43608 | size_t hierarchySize = 0; |
| 43609 | UA_StatusCode retval = getParentTypeAndInterfaceHierarchy(server, typeNode: typeId, |
| 43610 | typeHierarchy: &hierarchy, typeHierarchySize: &hierarchySize); |
| 43611 | if(retval != UA_STATUSCODE_GOOD) |
| 43612 | return retval; |
| 43613 | UA_assert(hierarchySize < 1000); |
| 43614 | |
| 43615 | /* Copy members of the type and supertypes (and instantiate them) */ |
| 43616 | for(size_t i = 0; i < hierarchySize; ++i) { |
| 43617 | retval = copyAllChildren(server, session, source: &hierarchy[i], destination: nodeId); |
| 43618 | if(retval != UA_STATUSCODE_GOOD) |
| 43619 | break; |
| 43620 | } |
| 43621 | |
| 43622 | UA_Array_delete(p: hierarchy, size: hierarchySize, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 43623 | return retval; |
| 43624 | } |
| 43625 | |
| 43626 | /************/ |
| 43627 | /* Add Node */ |
| 43628 | /************/ |
| 43629 | |
| 43630 | static const UA_NodeId hasSubtype = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASSUBTYPE}}; |
| 43631 | |
| 43632 | UA_StatusCode |
| 43633 | addNode_addRefs(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId, |
| 43634 | const UA_NodeId *parentNodeId, const UA_NodeId *referenceTypeId, |
| 43635 | const UA_NodeId *typeDefinitionId) { |
| 43636 | /* Get the node */ |
| 43637 | const UA_Node *type = NULL; |
| 43638 | const UA_Node *node = UA_NODESTORE_GET(server, nodeId); |
| 43639 | if(!node) |
| 43640 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 43641 | |
| 43642 | /* Use the typeDefinition as parent for type-nodes */ |
| 43643 | const UA_NodeHead *head = &node->head; |
| 43644 | if(head->nodeClass == UA_NODECLASS_VARIABLETYPE || |
| 43645 | head->nodeClass == UA_NODECLASS_OBJECTTYPE || |
| 43646 | head->nodeClass == UA_NODECLASS_REFERENCETYPE || |
| 43647 | head->nodeClass == UA_NODECLASS_DATATYPE) { |
| 43648 | if(UA_NodeId_equal(p1: referenceTypeId, p2: &UA_NODEID_NULL)) |
| 43649 | referenceTypeId = &hasSubtype; |
| 43650 | const UA_Node *parentNode = UA_NODESTORE_GET(server, nodeId: parentNodeId); |
| 43651 | if(parentNode) { |
| 43652 | if(parentNode->head.nodeClass == head->nodeClass) |
| 43653 | typeDefinitionId = parentNodeId; |
| 43654 | UA_NODESTORE_RELEASE(server, parentNode); |
| 43655 | } |
| 43656 | } |
| 43657 | |
| 43658 | UA_StatusCode retval; |
| 43659 | /* Make sure newly created node does not have itself as parent */ |
| 43660 | if(UA_NodeId_equal(p1: nodeId, p2: parentNodeId)) { |
| 43661 | logAddNode(logger: server->config.logging, session, nodeId, |
| 43662 | msg: "A node cannot have itself as parent"); |
| 43663 | retval = UA_STATUSCODE_BADINVALIDARGUMENT; |
| 43664 | goto cleanup; |
| 43665 | } |
| 43666 | |
| 43667 | |
| 43668 | /* Check parent reference. Objects may have no parent. */ |
| 43669 | retval = checkParentReference(server, session, head, parentNodeId, referenceTypeId); |
| 43670 | if(retval != UA_STATUSCODE_GOOD) { |
| 43671 | logAddNode(logger: server->config.logging, session, nodeId, |
| 43672 | msg: "The parent reference for is invalid"); |
| 43673 | goto cleanup; |
| 43674 | } |
| 43675 | |
| 43676 | /* Replace empty typeDefinition with the most permissive default */ |
| 43677 | if((head->nodeClass == UA_NODECLASS_VARIABLE || |
| 43678 | head->nodeClass == UA_NODECLASS_OBJECT) && |
| 43679 | UA_NodeId_isNull(p: typeDefinitionId)) { |
| 43680 | logAddNode(logger: server->config.logging, session, nodeId, |
| 43681 | msg: "No TypeDefinition. Use the default " |
| 43682 | "TypeDefinition for the Variable/Object"); |
| 43683 | if(head->nodeClass == UA_NODECLASS_VARIABLE) |
| 43684 | typeDefinitionId = &baseDataVariableType; |
| 43685 | else |
| 43686 | typeDefinitionId = &baseObjectType; |
| 43687 | } |
| 43688 | |
| 43689 | /* Get the node type. There must be a typedefinition for variables, objects |
| 43690 | * and type-nodes. See the above checks. */ |
| 43691 | if(!UA_NodeId_isNull(p: typeDefinitionId)) { |
| 43692 | /* Get the type node */ |
| 43693 | type = UA_NODESTORE_GET(server, nodeId: typeDefinitionId); |
| 43694 | if(!type) { |
| 43695 | logAddNode(logger: server->config.logging, session, nodeId, msg: "Node type not found"); |
| 43696 | retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; |
| 43697 | goto cleanup; |
| 43698 | } |
| 43699 | |
| 43700 | UA_Boolean typeOk = false; |
| 43701 | const UA_NodeHead *typeHead = &type->head; |
| 43702 | switch(head->nodeClass) { |
| 43703 | case UA_NODECLASS_DATATYPE: |
| 43704 | typeOk = typeHead->nodeClass == UA_NODECLASS_DATATYPE; |
| 43705 | break; |
| 43706 | case UA_NODECLASS_METHOD: |
| 43707 | typeOk = typeHead->nodeClass == UA_NODECLASS_METHOD; |
| 43708 | break; |
| 43709 | case UA_NODECLASS_OBJECT: |
| 43710 | case UA_NODECLASS_OBJECTTYPE: |
| 43711 | typeOk = typeHead->nodeClass == UA_NODECLASS_OBJECTTYPE; |
| 43712 | break; |
| 43713 | case UA_NODECLASS_REFERENCETYPE: |
| 43714 | typeOk = typeHead->nodeClass == UA_NODECLASS_REFERENCETYPE; |
| 43715 | break; |
| 43716 | case UA_NODECLASS_VARIABLE: |
| 43717 | case UA_NODECLASS_VARIABLETYPE: |
| 43718 | typeOk = typeHead->nodeClass == UA_NODECLASS_VARIABLETYPE; |
| 43719 | break; |
| 43720 | case UA_NODECLASS_VIEW: |
| 43721 | typeOk = typeHead->nodeClass == UA_NODECLASS_VIEW; |
| 43722 | break; |
| 43723 | default: |
| 43724 | typeOk = false; |
| 43725 | } |
| 43726 | if(!typeOk) { |
| 43727 | logAddNode(logger: server->config.logging, session, nodeId, |
| 43728 | msg: "Type does not match the NodeClass"); |
| 43729 | retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; |
| 43730 | goto cleanup; |
| 43731 | } |
| 43732 | |
| 43733 | /* See if the type has the correct node class. For type-nodes, we know |
| 43734 | * that type has the same nodeClass from checkParentReference. */ |
| 43735 | if(head->nodeClass == UA_NODECLASS_VARIABLE && |
| 43736 | type->variableTypeNode.isAbstract) { |
| 43737 | /* Get subtypes of the parent reference types */ |
| 43738 | UA_ReferenceTypeSet refTypes1, refTypes2; |
| 43739 | retval |= referenceTypeIndices(server, refType: &parentReferences[0], indices: &refTypes1, true); |
| 43740 | retval |= referenceTypeIndices(server, refType: &parentReferences[1], indices: &refTypes2, true); |
| 43741 | UA_ReferenceTypeSet refTypes = UA_ReferenceTypeSet_union(setA: refTypes1, setB: refTypes2); |
| 43742 | if(retval != UA_STATUSCODE_GOOD) |
| 43743 | goto cleanup; |
| 43744 | |
| 43745 | /* Abstract variable is allowed if parent is a children of a |
| 43746 | * base data variable. An abstract variable may be part of an |
| 43747 | * object type which again is below BaseObjectType */ |
| 43748 | const UA_NodeId variableTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATAVARIABLETYPE); |
| 43749 | const UA_NodeId objectTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE); |
| 43750 | if(!isNodeInTree(server, leafNode: parentNodeId, nodeToFind: &variableTypes, relevantRefs: &refTypes) && |
| 43751 | !isNodeInTree(server, leafNode: parentNodeId, nodeToFind: &objectTypes, relevantRefs: &refTypes)) { |
| 43752 | logAddNode(logger: server->config.logging, session, nodeId, |
| 43753 | msg: "Type of variable node must be a " |
| 43754 | "VariableType and not cannot be abstract"); |
| 43755 | retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; |
| 43756 | goto cleanup; |
| 43757 | } |
| 43758 | } |
| 43759 | |
| 43760 | if(head->nodeClass == UA_NODECLASS_OBJECT && |
| 43761 | type->objectTypeNode.isAbstract) { |
| 43762 | /* Get subtypes of the parent reference types */ |
| 43763 | UA_ReferenceTypeSet refTypes1, refTypes2; |
| 43764 | retval |= referenceTypeIndices(server, refType: &parentReferences[0], indices: &refTypes1, true); |
| 43765 | retval |= referenceTypeIndices(server, refType: &parentReferences[1], indices: &refTypes2, true); |
| 43766 | UA_ReferenceTypeSet refTypes = UA_ReferenceTypeSet_union(setA: refTypes1, setB: refTypes2); |
| 43767 | if(retval != UA_STATUSCODE_GOOD) |
| 43768 | goto cleanup; |
| 43769 | |
| 43770 | |
| 43771 | /* Object node created of an abstract ObjectType. Only allowed if |
| 43772 | * within BaseObjectType folder or if it's an event (subType of |
| 43773 | * BaseEventType) */ |
| 43774 | const UA_NodeId objectTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE); |
| 43775 | UA_Boolean isInBaseObjectType = |
| 43776 | isNodeInTree(server, leafNode: parentNodeId, nodeToFind: &objectTypes, relevantRefs: &refTypes); |
| 43777 | |
| 43778 | const UA_NodeId eventTypes = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE); |
| 43779 | UA_Boolean isInBaseEventType = |
| 43780 | isNodeInTree_singleRef(server, leafNode: &type->head.nodeId, nodeToFind: &eventTypes, |
| 43781 | UA_REFERENCETYPEINDEX_HASSUBTYPE); |
| 43782 | |
| 43783 | if(!isInBaseObjectType && |
| 43784 | !(isInBaseEventType && UA_NodeId_isNull(p: parentNodeId))) { |
| 43785 | logAddNode(logger: server->config.logging, session, nodeId, |
| 43786 | msg: "Type of ObjectNode must be ObjectType and not be abstract"); |
| 43787 | retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; |
| 43788 | goto cleanup; |
| 43789 | } |
| 43790 | } |
| 43791 | } |
| 43792 | |
| 43793 | /* Add reference to the parent */ |
| 43794 | if(!UA_NodeId_isNull(p: parentNodeId)) { |
| 43795 | if(UA_NodeId_isNull(p: referenceTypeId)) { |
| 43796 | logAddNode(logger: server->config.logging, session, nodeId, |
| 43797 | msg: "Reference to parent cannot be null"); |
| 43798 | retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; |
| 43799 | goto cleanup; |
| 43800 | } |
| 43801 | |
| 43802 | retval = addRefWithSession(server, session, sourceId: &head->nodeId, referenceTypeId, |
| 43803 | targetId: parentNodeId, false); |
| 43804 | if(retval != UA_STATUSCODE_GOOD) { |
| 43805 | logAddNode(logger: server->config.logging, session, nodeId, |
| 43806 | msg: "Adding reference to parent failed"); |
| 43807 | goto cleanup; |
| 43808 | } |
| 43809 | } |
| 43810 | |
| 43811 | /* Add a hasTypeDefinition reference */ |
| 43812 | if(head->nodeClass == UA_NODECLASS_VARIABLE || |
| 43813 | head->nodeClass == UA_NODECLASS_OBJECT) { |
| 43814 | UA_assert(type != NULL); /* see above */ |
| 43815 | retval = addRefWithSession(server, session, sourceId: &head->nodeId, referenceTypeId: &hasTypeDefinition, |
| 43816 | targetId: &type->head.nodeId, true); |
| 43817 | if(retval != UA_STATUSCODE_GOOD) { |
| 43818 | logAddNode(logger: server->config.logging, session, nodeId, |
| 43819 | msg: "Adding a reference to the type definition failed"); |
| 43820 | } |
| 43821 | } |
| 43822 | |
| 43823 | cleanup: |
| 43824 | UA_NODESTORE_RELEASE(server, node); |
| 43825 | if(type) |
| 43826 | UA_NODESTORE_RELEASE(server, type); |
| 43827 | return retval; |
| 43828 | } |
| 43829 | |
| 43830 | /* Create the node and add it to the nodestore. But don't typecheck and add |
| 43831 | * references so far */ |
| 43832 | UA_StatusCode |
| 43833 | addNode_raw(UA_Server *server, UA_Session *session, void *nodeContext, |
| 43834 | const UA_AddNodesItem *item, UA_NodeId *outNewNodeId) { |
| 43835 | /* Do not check access for server */ |
| 43836 | if(session != &server->adminSession && server->config.accessControl.allowAddNode) { |
| 43837 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 43838 | if(!server->config.accessControl. |
| 43839 | allowAddNode(server, &server->config.accessControl, |
| 43840 | &session->sessionId, session->sessionHandle, item)) { |
| 43841 | return UA_STATUSCODE_BADUSERACCESSDENIED; |
| 43842 | } |
| 43843 | } |
| 43844 | |
| 43845 | /* Check the namespaceindex */ |
| 43846 | if(item->requestedNewNodeId.nodeId.namespaceIndex >= server->namespacesSize) { |
| 43847 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 43848 | "AddNode: Namespace invalid"); |
| 43849 | return UA_STATUSCODE_BADNODEIDINVALID; |
| 43850 | } |
| 43851 | |
| 43852 | if(item->nodeAttributes.encoding != UA_EXTENSIONOBJECT_DECODED && |
| 43853 | item->nodeAttributes.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) { |
| 43854 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 43855 | "AddNode: Node attributes invalid"); |
| 43856 | return UA_STATUSCODE_BADINTERNALERROR; |
| 43857 | } |
| 43858 | |
| 43859 | /* Create a node */ |
| 43860 | UA_Node *node = UA_NODESTORE_NEW(server, item->nodeClass); |
| 43861 | if(!node) { |
| 43862 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 43863 | "AddNode: Node could not create a node " |
| 43864 | "in the nodestore"); |
| 43865 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 43866 | } |
| 43867 | |
| 43868 | UA_NodeId tmpOutId = UA_NODEID_NULL; |
| 43869 | /* Fill the node attributes */ |
| 43870 | node->head.context = nodeContext; |
| 43871 | UA_StatusCode retval = |
| 43872 | UA_NodeId_copy(src: &item->requestedNewNodeId.nodeId, dst: &node->head.nodeId); |
| 43873 | if(retval != UA_STATUSCODE_GOOD) |
| 43874 | goto create_error; |
| 43875 | |
| 43876 | retval = UA_QualifiedName_copy(src: &item->browseName, dst: &node->head.browseName); |
| 43877 | if(retval != UA_STATUSCODE_GOOD) |
| 43878 | goto create_error; |
| 43879 | |
| 43880 | retval = UA_Node_setAttributes(node, attributes: item->nodeAttributes.content.decoded.data, |
| 43881 | attributeType: item->nodeAttributes.content.decoded.type); |
| 43882 | if(retval != UA_STATUSCODE_GOOD) |
| 43883 | goto create_error; |
| 43884 | |
| 43885 | /* Create a current source timestamp for values that don't have any */ |
| 43886 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE && |
| 43887 | !node->variableNode.value.data.value.hasSourceTimestamp) { |
| 43888 | node->variableNode.value.data.value.hasSourceTimestamp = true; |
| 43889 | node->variableNode.value.data.value.sourceTimestamp = UA_DateTime_now(); |
| 43890 | } |
| 43891 | |
| 43892 | /* Add the node to the nodestore */ |
| 43893 | if(!outNewNodeId) |
| 43894 | outNewNodeId = &tmpOutId; |
| 43895 | retval = UA_NODESTORE_INSERT(server, node, outNewNodeId); |
| 43896 | if(retval != UA_STATUSCODE_GOOD) { |
| 43897 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 43898 | "AddNode: Node could not add the new node " |
| 43899 | "to the nodestore with error code %s", |
| 43900 | UA_StatusCode_name(retval)); |
| 43901 | return retval; |
| 43902 | } |
| 43903 | |
| 43904 | if(outNewNodeId == &tmpOutId) |
| 43905 | UA_NodeId_clear(p: &tmpOutId); |
| 43906 | |
| 43907 | return UA_STATUSCODE_GOOD; |
| 43908 | |
| 43909 | create_error: |
| 43910 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 43911 | "AddNode: Node could not create a node " |
| 43912 | "with error code %s", UA_StatusCode_name(retval)); |
| 43913 | UA_NODESTORE_DELETE(server, node); |
| 43914 | return retval; |
| 43915 | } |
| 43916 | |
| 43917 | static UA_StatusCode |
| 43918 | findDefaultInstanceBrowseNameNode(UA_Server *server, UA_NodeId startingNode, |
| 43919 | UA_NodeId *foundId) { |
| 43920 | UA_NodeId_init(p: foundId); |
| 43921 | UA_RelativePathElement rpe; |
| 43922 | UA_RelativePathElement_init(p: &rpe); |
| 43923 | rpe.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY); |
| 43924 | rpe.targetName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "DefaultInstanceBrowseName"); |
| 43925 | UA_BrowsePath bp; |
| 43926 | UA_BrowsePath_init(p: &bp); |
| 43927 | bp.startingNode = startingNode; |
| 43928 | bp.relativePath.elementsSize = 1; |
| 43929 | bp.relativePath.elements = &rpe; |
| 43930 | UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp); |
| 43931 | UA_StatusCode retval = bpr.statusCode; |
| 43932 | if(retval == UA_STATUSCODE_GOOD && bpr.targetsSize > 0) |
| 43933 | retval = UA_NodeId_copy(src: &bpr.targets[0].targetId.nodeId, dst: foundId); |
| 43934 | UA_BrowsePathResult_clear(p: &bpr); |
| 43935 | return retval; |
| 43936 | } |
| 43937 | |
| 43938 | /* Check if we got a valid browse name for the new node. For object nodes the |
| 43939 | * BrowseName may only be null if the parent type has a |
| 43940 | * 'DefaultInstanceBrowseName' property. */ |
| 43941 | static UA_StatusCode |
| 43942 | checkSetBrowseName(UA_Server *server, UA_Session *session, UA_AddNodesItem *item) { |
| 43943 | /* If the object node already has a browse name we are done here. */ |
| 43944 | if(!UA_QualifiedName_isNull(q: &item->browseName)) |
| 43945 | return UA_STATUSCODE_GOOD; |
| 43946 | |
| 43947 | /* Nodes other than Objects must have a BrowseName */ |
| 43948 | if(item->nodeClass != UA_NODECLASS_OBJECT) |
| 43949 | return UA_STATUSCODE_BADBROWSENAMEINVALID; |
| 43950 | |
| 43951 | /* At this point we have an object with an empty browse name. Check the type |
| 43952 | * node if it has a DefaultInstanceBrowseName property. */ |
| 43953 | UA_NodeId defaultBrowseNameNode; |
| 43954 | UA_StatusCode retval = |
| 43955 | findDefaultInstanceBrowseNameNode(server, startingNode: item->typeDefinition.nodeId, |
| 43956 | foundId: &defaultBrowseNameNode); |
| 43957 | if(retval != UA_STATUSCODE_GOOD) |
| 43958 | return UA_STATUSCODE_BADBROWSENAMEINVALID; |
| 43959 | |
| 43960 | UA_Variant defaultBrowseName; |
| 43961 | retval = readWithReadValue(server, nodeId: &defaultBrowseNameNode, |
| 43962 | attributeId: UA_ATTRIBUTEID_VALUE, v: &defaultBrowseName); |
| 43963 | UA_NodeId_clear(p: &defaultBrowseNameNode); |
| 43964 | if(retval != UA_STATUSCODE_GOOD) |
| 43965 | return UA_STATUSCODE_BADBROWSENAMEINVALID; |
| 43966 | |
| 43967 | if(UA_Variant_hasScalarType(v: &defaultBrowseName, type: &UA_TYPES[UA_TYPES_QUALIFIEDNAME])) { |
| 43968 | item->browseName = *(UA_QualifiedName*)defaultBrowseName.data; |
| 43969 | UA_QualifiedName_init(p: (UA_QualifiedName*)defaultBrowseName.data); |
| 43970 | } else { |
| 43971 | retval = UA_STATUSCODE_BADBROWSENAMEINVALID; |
| 43972 | } |
| 43973 | |
| 43974 | UA_Variant_clear(p: &defaultBrowseName); |
| 43975 | return retval; |
| 43976 | } |
| 43977 | |
| 43978 | /* Prepare the node, then add it to the nodestore */ |
| 43979 | static UA_StatusCode |
| 43980 | Operation_addNode_begin(UA_Server *server, UA_Session *session, void *nodeContext, |
| 43981 | const UA_AddNodesItem *item, const UA_NodeId *parentNodeId, |
| 43982 | const UA_NodeId *referenceTypeId, UA_NodeId *outNewNodeId) { |
| 43983 | /* Create a temporary NodeId if none is returned */ |
| 43984 | UA_NodeId newId; |
| 43985 | if(!outNewNodeId) { |
| 43986 | UA_NodeId_init(p: &newId); |
| 43987 | outNewNodeId = &newId; |
| 43988 | } |
| 43989 | |
| 43990 | /* Set the BrowsenName before adding to the Nodestore. The BrowseName is |
| 43991 | * immutable afterwards. */ |
| 43992 | UA_Boolean noBrowseName = UA_QualifiedName_isNull(q: &item->browseName); |
| 43993 | UA_StatusCode retval = |
| 43994 | checkSetBrowseName(server, session, item: (UA_AddNodesItem*)(uintptr_t)item); |
| 43995 | if(retval != UA_STATUSCODE_GOOD) |
| 43996 | return retval; |
| 43997 | |
| 43998 | /* Create the node and add it to the nodestore */ |
| 43999 | retval = addNode_raw(server, session, nodeContext, item, outNewNodeId); |
| 44000 | if(retval != UA_STATUSCODE_GOOD) |
| 44001 | goto cleanup; |
| 44002 | |
| 44003 | /* Typecheck and add references to parent and type definition */ |
| 44004 | retval = addNode_addRefs(server, session, nodeId: outNewNodeId, parentNodeId, |
| 44005 | referenceTypeId, typeDefinitionId: &item->typeDefinition.nodeId); |
| 44006 | if(retval != UA_STATUSCODE_GOOD) |
| 44007 | deleteNode(server, nodeId: *outNewNodeId, true); |
| 44008 | |
| 44009 | if(outNewNodeId == &newId) |
| 44010 | UA_NodeId_clear(p: &newId); |
| 44011 | |
| 44012 | cleanup: |
| 44013 | if(noBrowseName) |
| 44014 | UA_QualifiedName_clear(p: (UA_QualifiedName*)(uintptr_t)&item->browseName); |
| 44015 | return retval; |
| 44016 | } |
| 44017 | |
| 44018 | /* Construct children first */ |
| 44019 | static UA_StatusCode |
| 44020 | recursiveCallConstructors(UA_Server *server, UA_Session *session, |
| 44021 | const UA_NodeId *nodeId, const UA_Node *type) { |
| 44022 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 44023 | |
| 44024 | /* Browse the children */ |
| 44025 | UA_BrowseDescription bd; |
| 44026 | UA_BrowseDescription_init(p: &bd); |
| 44027 | bd.nodeId = *nodeId; |
| 44028 | bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES); |
| 44029 | bd.includeSubtypes = true; |
| 44030 | bd.browseDirection = UA_BROWSEDIRECTION_FORWARD; |
| 44031 | |
| 44032 | UA_BrowseResult br; |
| 44033 | UA_BrowseResult_init(p: &br); |
| 44034 | UA_UInt32 maxrefs = 0; |
| 44035 | Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br); |
| 44036 | if(br.statusCode != UA_STATUSCODE_GOOD) |
| 44037 | return br.statusCode; |
| 44038 | |
| 44039 | /* Call the constructor for every unconstructed child node */ |
| 44040 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 44041 | for(size_t i = 0; i < br.referencesSize; ++i) { |
| 44042 | UA_ReferenceDescription *rd = &br.references[i]; |
| 44043 | if(!UA_ExpandedNodeId_isLocal(n: &rd->nodeId)) |
| 44044 | continue; |
| 44045 | const UA_Node *target = UA_NODESTORE_GET(server, nodeId: &rd->nodeId.nodeId); |
| 44046 | if(!target) |
| 44047 | continue; |
| 44048 | if(target->head.constructed) { |
| 44049 | UA_NODESTORE_RELEASE(server, target); |
| 44050 | continue; |
| 44051 | } |
| 44052 | |
| 44053 | const UA_Node *targetType = NULL; |
| 44054 | if(target->head.nodeClass == UA_NODECLASS_VARIABLE || |
| 44055 | target->head.nodeClass == UA_NODECLASS_OBJECT) { |
| 44056 | targetType = getNodeType(server, head: &target->head); |
| 44057 | if(!targetType) { |
| 44058 | UA_NODESTORE_RELEASE(server, target); |
| 44059 | retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; |
| 44060 | break; |
| 44061 | } |
| 44062 | } |
| 44063 | |
| 44064 | UA_NODESTORE_RELEASE(server, target); |
| 44065 | retval = recursiveCallConstructors(server, session, nodeId: &rd->nodeId.nodeId, type: targetType); |
| 44066 | |
| 44067 | if(targetType) |
| 44068 | UA_NODESTORE_RELEASE(server, targetType); |
| 44069 | if(retval != UA_STATUSCODE_GOOD) |
| 44070 | break; |
| 44071 | } |
| 44072 | |
| 44073 | UA_BrowseResult_clear(p: &br); |
| 44074 | |
| 44075 | /* If a child could not be constructed or the node is already constructed */ |
| 44076 | if(retval != UA_STATUSCODE_GOOD) |
| 44077 | return retval; |
| 44078 | |
| 44079 | /* Get the node context */ |
| 44080 | const UA_Node *node = UA_NODESTORE_GET(server, nodeId); |
| 44081 | if(!node) |
| 44082 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 44083 | void *context = node->head.context; |
| 44084 | UA_NODESTORE_RELEASE(server, node); |
| 44085 | |
| 44086 | /* Call the global constructor */ |
| 44087 | if(server->config.nodeLifecycle.constructor) { |
| 44088 | retval = server->config.nodeLifecycle. |
| 44089 | constructor(server, &session->sessionId, |
| 44090 | session->sessionHandle, nodeId, &context); |
| 44091 | if(retval != UA_STATUSCODE_GOOD) |
| 44092 | return retval; |
| 44093 | } |
| 44094 | |
| 44095 | /* Call the local (per-type) constructor */ |
| 44096 | const UA_NodeTypeLifecycle *lifecycle = NULL; |
| 44097 | if(type && node->head.nodeClass == UA_NODECLASS_OBJECT) |
| 44098 | lifecycle = &type->objectTypeNode.lifecycle; |
| 44099 | else if(type && node->head.nodeClass == UA_NODECLASS_VARIABLE) |
| 44100 | lifecycle = &type->variableTypeNode.lifecycle; |
| 44101 | if(lifecycle && lifecycle->constructor) { |
| 44102 | retval = lifecycle->constructor(server, &session->sessionId, |
| 44103 | session->sessionHandle, &type->head.nodeId, |
| 44104 | type->head.context, nodeId, &context); |
| 44105 | if(retval != UA_STATUSCODE_GOOD) |
| 44106 | goto global_destructor; |
| 44107 | } |
| 44108 | |
| 44109 | /* Set the context *and* mark the node as constructed */ |
| 44110 | retval = UA_Server_editNode(server, session: &server->adminSession, nodeId, |
| 44111 | callback: (UA_EditNodeCallback)setConstructedNodeContext, data: context); |
| 44112 | if(retval != UA_STATUSCODE_GOOD) |
| 44113 | goto local_destructor; |
| 44114 | |
| 44115 | /* All good, return */ |
| 44116 | return retval; |
| 44117 | |
| 44118 | /* Fail. Call the destructors. */ |
| 44119 | local_destructor: |
| 44120 | if(lifecycle && lifecycle->destructor) { |
| 44121 | lifecycle->destructor(server, &session->sessionId, session->sessionHandle, |
| 44122 | &type->head.nodeId, type->head.context, nodeId, &context); |
| 44123 | } |
| 44124 | |
| 44125 | global_destructor: |
| 44126 | if(server->config.nodeLifecycle.destructor) { |
| 44127 | server->config.nodeLifecycle.destructor(server, &session->sessionId, |
| 44128 | session->sessionHandle, |
| 44129 | nodeId, context); |
| 44130 | } |
| 44131 | return retval; |
| 44132 | } |
| 44133 | |
| 44134 | /* Add new ReferenceType to the subtypes bitfield */ |
| 44135 | static UA_StatusCode |
| 44136 | addReferenceTypeSubtype(UA_Server *server, UA_Session *session, |
| 44137 | UA_Node *node, void *context) { |
| 44138 | node->referenceTypeNode.subTypes = |
| 44139 | UA_ReferenceTypeSet_union(setA: node->referenceTypeNode.subTypes, |
| 44140 | setB: *(UA_ReferenceTypeSet*)context); |
| 44141 | return UA_STATUSCODE_GOOD; |
| 44142 | } |
| 44143 | |
| 44144 | static UA_StatusCode |
| 44145 | setReferenceTypeSubtypes(UA_Server *server, const UA_ReferenceTypeNode *node) { |
| 44146 | /* Get the ReferenceTypes upwards in the hierarchy */ |
| 44147 | size_t parentsSize = 0; |
| 44148 | UA_ExpandedNodeId *parents = NULL; |
| 44149 | UA_ReferenceTypeSet reftypes_subtype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE); |
| 44150 | UA_StatusCode res = |
| 44151 | browseRecursive(server, startNodesSize: 1, startNodes: &node->head.nodeId, browseDirection: UA_BROWSEDIRECTION_INVERSE, |
| 44152 | refTypes: &reftypes_subtype, nodeClassMask: UA_NODECLASS_UNSPECIFIED, |
| 44153 | false, resultsSize: &parentsSize, results: &parents); |
| 44154 | if(res != UA_STATUSCODE_GOOD) |
| 44155 | return res; |
| 44156 | |
| 44157 | /* Add the ReferenceTypeIndex of this node */ |
| 44158 | const UA_ReferenceTypeSet *newRefSet = &node->subTypes; |
| 44159 | for(size_t i = 0; i < parentsSize; i++) { |
| 44160 | UA_Server_editNode(server, session: &server->adminSession, nodeId: &parents[i].nodeId, |
| 44161 | callback: addReferenceTypeSubtype, data: (void*)(uintptr_t)newRefSet); |
| 44162 | } |
| 44163 | |
| 44164 | UA_Array_delete(p: parents, size: parentsSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 44165 | return UA_STATUSCODE_GOOD; |
| 44166 | } |
| 44167 | |
| 44168 | static UA_StatusCode |
| 44169 | setVariableNodeDynamic(UA_Server *server, UA_Session *session, |
| 44170 | UA_Node *node, const void *ctx) { |
| 44171 | if(node->head.nodeClass != UA_NODECLASS_VARIABLE) |
| 44172 | return UA_STATUSCODE_BADINTERNALERROR; |
| 44173 | ((UA_VariableNode*)node)->isDynamic = *(const UA_Boolean*)ctx; |
| 44174 | return UA_STATUSCODE_GOOD; |
| 44175 | } |
| 44176 | |
| 44177 | static UA_StatusCode |
| 44178 | checkSetIsDynamicVariable(UA_Server *server, UA_Session *session, |
| 44179 | const UA_NodeId *nodeId) { |
| 44180 | /* Get all hierarchical reference types */ |
| 44181 | UA_ReferenceTypeSet reftypes_hierarchical; |
| 44182 | UA_ReferenceTypeSet_init(set: &reftypes_hierarchical); |
| 44183 | UA_NodeId hierarchicalRefs = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES); |
| 44184 | UA_StatusCode res = |
| 44185 | referenceTypeIndices(server, refType: &hierarchicalRefs, indices: &reftypes_hierarchical, true); |
| 44186 | if(res != UA_STATUSCODE_GOOD) |
| 44187 | return res; |
| 44188 | |
| 44189 | /* Is the variable under the server object? */ |
| 44190 | UA_NodeId serverNodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER); |
| 44191 | if(isNodeInTree(server, leafNode: nodeId, nodeToFind: &serverNodeId, relevantRefs: &reftypes_hierarchical)) |
| 44192 | return UA_STATUSCODE_GOOD; |
| 44193 | |
| 44194 | /* Is the variable in the type hierarchy? */ |
| 44195 | UA_NodeId typesNodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_TYPESFOLDER); |
| 44196 | if(isNodeInTree(server, leafNode: nodeId, nodeToFind: &typesNodeId, relevantRefs: &reftypes_hierarchical)) |
| 44197 | return UA_STATUSCODE_GOOD; |
| 44198 | |
| 44199 | /* Is the variable a property of a method node (InputArguments / |
| 44200 | * OutputArguments)? */ |
| 44201 | UA_BrowseDescription bd; |
| 44202 | UA_BrowseDescription_init(p: &bd); |
| 44203 | bd.nodeId = *nodeId; |
| 44204 | bd.browseDirection = UA_BROWSEDIRECTION_INVERSE; |
| 44205 | bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY); |
| 44206 | bd.includeSubtypes = false; |
| 44207 | bd.nodeClassMask = UA_NODECLASS_METHOD; |
| 44208 | UA_BrowseResult br; |
| 44209 | UA_BrowseResult_init(p: &br); |
| 44210 | UA_UInt32 maxrefs = 0; |
| 44211 | Operation_Browse(server, session, maxrefs: &maxrefs, descr: &bd, result: &br); |
| 44212 | UA_Boolean hasParentMethod = (br.referencesSize > 0); |
| 44213 | UA_BrowseResult_clear(p: &br); |
| 44214 | if(hasParentMethod) |
| 44215 | return UA_STATUSCODE_GOOD; |
| 44216 | |
| 44217 | /* Set the variable to "dynamic" */ |
| 44218 | UA_Boolean isDynamic = true; |
| 44219 | UA_Server_editNode(server, session, nodeId, |
| 44220 | callback: (UA_EditNodeCallback)setVariableNodeDynamic, data: &isDynamic); |
| 44221 | |
| 44222 | return UA_STATUSCODE_GOOD; |
| 44223 | } |
| 44224 | |
| 44225 | UA_StatusCode |
| 44226 | UA_Server_setVariableNodeDynamic(UA_Server *server, const UA_NodeId nodeId, |
| 44227 | UA_Boolean isDynamic) { |
| 44228 | lockServer(server); |
| 44229 | UA_StatusCode res = |
| 44230 | UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId, |
| 44231 | callback: (UA_EditNodeCallback)setVariableNodeDynamic, data: &isDynamic); |
| 44232 | unlockServer(server); |
| 44233 | return res; |
| 44234 | } |
| 44235 | |
| 44236 | /* Children, references, type-checking, constructors. */ |
| 44237 | UA_StatusCode |
| 44238 | addNode_finish(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId) { |
| 44239 | /* Get the node */ |
| 44240 | const UA_Node *type = NULL; |
| 44241 | const UA_Node *node = UA_NODESTORE_GET(server, nodeId); |
| 44242 | if(!node) |
| 44243 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 44244 | |
| 44245 | /* Set the ReferenceTypesSet of subtypes in the ReferenceTypeNode */ |
| 44246 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 44247 | if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) { |
| 44248 | retval = setReferenceTypeSubtypes(server, node: &node->referenceTypeNode); |
| 44249 | if(retval != UA_STATUSCODE_GOOD) |
| 44250 | goto cleanup; |
| 44251 | } |
| 44252 | |
| 44253 | /* Check NodeClass for 'hasSubtype'. UA_NODECLASS_VARIABLE not allowed |
| 44254 | * to have subtype */ |
| 44255 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE) { |
| 44256 | for(size_t i = 0; i < node->head.referencesSize; i++) { |
| 44257 | if(node->head.references[i].referenceTypeIndex == |
| 44258 | UA_REFERENCETYPEINDEX_HASSUBTYPE) { |
| 44259 | UA_LOG_NODEID_INFO(&node->head.nodeId, |
| 44260 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 44261 | "AddNode (%.*s): Variable not allowed " |
| 44262 | "to have HasSubType reference", |
| 44263 | (int)nodeIdStr.length, nodeIdStr.data)); |
| 44264 | retval = UA_STATUSCODE_BADREFERENCENOTALLOWED; |
| 44265 | goto cleanup; |
| 44266 | } |
| 44267 | } |
| 44268 | } |
| 44269 | |
| 44270 | /* Set variables to dynamic (source and server timestamps are meaningful) if |
| 44271 | * they fulfill some conditions. (Do this before replacing the default value |
| 44272 | * in a VariableNode. So that the sourceTimestamp is set in the Write service.) */ |
| 44273 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE) { |
| 44274 | retval = checkSetIsDynamicVariable(server, session, nodeId); |
| 44275 | if(retval != UA_STATUSCODE_GOOD) |
| 44276 | goto cleanup; |
| 44277 | } |
| 44278 | |
| 44279 | /* Get the type node */ |
| 44280 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE || |
| 44281 | node->head.nodeClass == UA_NODECLASS_VARIABLETYPE || |
| 44282 | node->head.nodeClass == UA_NODECLASS_OBJECT) { |
| 44283 | type = getNodeType(server, head: &node->head); |
| 44284 | if(!type) { |
| 44285 | if(server->bootstrapNS0) |
| 44286 | goto constructor; |
| 44287 | logAddNode(logger: server->config.logging, session, nodeId: &node->head.nodeId, |
| 44288 | msg: "Node type not found"); |
| 44289 | retval = UA_STATUSCODE_BADTYPEDEFINITIONINVALID; |
| 44290 | goto cleanup; |
| 44291 | } |
| 44292 | } |
| 44293 | |
| 44294 | /* Initialize and typecheck the variable */ |
| 44295 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE || |
| 44296 | node->head.nodeClass == UA_NODECLASS_VARIABLETYPE) { |
| 44297 | /* Use attributes from the type. The value and value constraints are the |
| 44298 | * same for the variable and variabletype attribute structs. */ |
| 44299 | retval = useVariableTypeAttributes(server, session, |
| 44300 | node: &node->variableNode, |
| 44301 | vt: &type->variableTypeNode); |
| 44302 | if(retval != UA_STATUSCODE_GOOD) { |
| 44303 | UA_LOG_NODEID_INFO(&node->head.nodeId, |
| 44304 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 44305 | "AddNode (%.*s): Using attributes for from " |
| 44306 | "the variable type failed with error code %s", |
| 44307 | (int)nodeIdStr.length, nodeIdStr.data, |
| 44308 | UA_StatusCode_name(retval))); |
| 44309 | goto cleanup; |
| 44310 | } |
| 44311 | |
| 44312 | /* Get a new pointer to the node. It might have been switched out */ |
| 44313 | #ifdef UA_ENABLE_IMMUTABLE_NODES |
| 44314 | UA_NODESTORE_RELEASE(server, node); |
| 44315 | node = UA_NODESTORE_GET(server, nodeId); |
| 44316 | if(!node || (node->head.nodeClass != UA_NODECLASS_VARIABLE && |
| 44317 | node->head.nodeClass != UA_NODECLASS_VARIABLETYPE)) { |
| 44318 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 44319 | goto cleanup; |
| 44320 | } |
| 44321 | #endif |
| 44322 | |
| 44323 | /* Check if all attributes hold the constraints of the type now. The initial |
| 44324 | * attributes must type-check. The constructor might change the attributes |
| 44325 | * again. Then, the changes are type-checked by the normal write service. */ |
| 44326 | retval = typeCheckVariableNode(server, session, node: &node->variableNode, |
| 44327 | vt: &type->variableTypeNode); |
| 44328 | if(retval != UA_STATUSCODE_GOOD) { |
| 44329 | UA_LOG_NODEID_INFO(&node->head.nodeId, |
| 44330 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 44331 | "AddNode (%.*s): Type-checking " |
| 44332 | "failed with error code %s", (int)nodeIdStr.length, |
| 44333 | nodeIdStr.data, UA_StatusCode_name(retval))); |
| 44334 | goto cleanup; |
| 44335 | } |
| 44336 | } |
| 44337 | |
| 44338 | /* Add (mandatory) child nodes from the type definition */ |
| 44339 | if(node->head.nodeClass == UA_NODECLASS_VARIABLE || |
| 44340 | node->head.nodeClass == UA_NODECLASS_OBJECT) { |
| 44341 | retval = addTypeChildren(server, session, nodeId, typeId: &type->head.nodeId); |
| 44342 | if(retval != UA_STATUSCODE_GOOD) { |
| 44343 | UA_LOG_NODEID_INFO(&node->head.nodeId, |
| 44344 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 44345 | "AddNode (%.*s): Adding child nodes " |
| 44346 | "failed with error code %s", (int)nodeIdStr.length, |
| 44347 | nodeIdStr.data, UA_StatusCode_name(retval))); |
| 44348 | goto cleanup; |
| 44349 | } |
| 44350 | } |
| 44351 | |
| 44352 | /* Add (mandatory) child nodes from the HasInterface references */ |
| 44353 | if(node->head.nodeClass == UA_NODECLASS_OBJECT) { |
| 44354 | retval = addInterfaceChildren(server, session, nodeId, typeId: &type->head.nodeId); |
| 44355 | if(retval != UA_STATUSCODE_GOOD) { |
| 44356 | UA_LOG_NODEID_INFO(&node->head.nodeId, |
| 44357 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 44358 | "AddNode (%.*s): Adding child nodes " |
| 44359 | "interface failed with error code %s", |
| 44360 | (int)nodeIdStr.length, nodeIdStr.data, |
| 44361 | UA_StatusCode_name(retval))); |
| 44362 | goto cleanup; |
| 44363 | } |
| 44364 | } |
| 44365 | |
| 44366 | /* Call the constructor(s) */ |
| 44367 | constructor: |
| 44368 | if(!node->head.constructed) |
| 44369 | retval = recursiveCallConstructors(server, session, nodeId, type); |
| 44370 | if(retval != UA_STATUSCODE_GOOD) { |
| 44371 | UA_LOG_NODEID_INFO(&node->head.nodeId, |
| 44372 | UA_LOG_INFO_SESSION(server->config.logging, session, |
| 44373 | "AddNode (%.*s): Calling the node constructor(s) " |
| 44374 | "failed with status code %s", (int)nodeIdStr.length, |
| 44375 | nodeIdStr.data, UA_StatusCode_name(retval))); |
| 44376 | } |
| 44377 | |
| 44378 | cleanup: |
| 44379 | UA_NODESTORE_RELEASE(server, node); |
| 44380 | if(type) |
| 44381 | UA_NODESTORE_RELEASE(server, type); |
| 44382 | if(retval != UA_STATUSCODE_GOOD) |
| 44383 | deleteNode(server, nodeId: *nodeId, true); |
| 44384 | return retval; |
| 44385 | } |
| 44386 | |
| 44387 | static void |
| 44388 | Operation_addNode(UA_Server *server, UA_Session *session, void *nodeContext, |
| 44389 | const UA_AddNodesItem *item, UA_AddNodesResult *result) { |
| 44390 | result->statusCode = |
| 44391 | Operation_addNode_begin(server, session, nodeContext, |
| 44392 | item, parentNodeId: &item->parentNodeId.nodeId, |
| 44393 | referenceTypeId: &item->referenceTypeId, outNewNodeId: &result->addedNodeId); |
| 44394 | if(result->statusCode != UA_STATUSCODE_GOOD) |
| 44395 | return; |
| 44396 | |
| 44397 | /* AddNodes_finish */ |
| 44398 | result->statusCode = addNode_finish(server, session, nodeId: &result->addedNodeId); |
| 44399 | |
| 44400 | /* If finishing failed, the node was deleted */ |
| 44401 | if(result->statusCode != UA_STATUSCODE_GOOD) |
| 44402 | UA_NodeId_clear(p: &result->addedNodeId); |
| 44403 | } |
| 44404 | |
| 44405 | void |
| 44406 | Service_AddNodes(UA_Server *server, UA_Session *session, |
| 44407 | const UA_AddNodesRequest *request, |
| 44408 | UA_AddNodesResponse *response) { |
| 44409 | UA_LOG_DEBUG_SESSION(server->config.logging, session, "Processing AddNodesRequest"); |
| 44410 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 44411 | |
| 44412 | if(server->config.maxNodesPerNodeManagement != 0 && |
| 44413 | request->nodesToAddSize > server->config.maxNodesPerNodeManagement) { |
| 44414 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 44415 | return; |
| 44416 | } |
| 44417 | |
| 44418 | response->responseHeader.serviceResult = |
| 44419 | UA_Server_processServiceOperations(server, session, |
| 44420 | operationCallback: (UA_ServiceOperation)Operation_addNode, NULL, |
| 44421 | requestOperations: &request->nodesToAddSize, |
| 44422 | requestOperationsType: &UA_TYPES[UA_TYPES_ADDNODESITEM], |
| 44423 | responseOperations: &response->resultsSize, |
| 44424 | responseOperationsType: &UA_TYPES[UA_TYPES_ADDNODESRESULT]); |
| 44425 | } |
| 44426 | |
| 44427 | UA_StatusCode |
| 44428 | addNode(UA_Server *server, const UA_NodeClass nodeClass, const UA_NodeId requestedNewNodeId, |
| 44429 | const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, |
| 44430 | const UA_QualifiedName browseName, const UA_NodeId typeDefinition, |
| 44431 | const void *attr, const UA_DataType *attributeType, |
| 44432 | void *nodeContext, UA_NodeId *outNewNodeId) { |
| 44433 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 44434 | |
| 44435 | /* Create the AddNodesItem */ |
| 44436 | UA_AddNodesItem item; |
| 44437 | UA_AddNodesItem_init(p: &item); |
| 44438 | item.nodeClass = nodeClass; |
| 44439 | item.requestedNewNodeId.nodeId = requestedNewNodeId; |
| 44440 | item.browseName = browseName; |
| 44441 | item.parentNodeId.nodeId = parentNodeId; |
| 44442 | item.referenceTypeId = referenceTypeId; |
| 44443 | item.typeDefinition.nodeId = typeDefinition; |
| 44444 | UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes, |
| 44445 | p: (void*)(uintptr_t)attr, type: attributeType); |
| 44446 | |
| 44447 | /* Call the normal addnodes service */ |
| 44448 | UA_AddNodesResult result; |
| 44449 | UA_AddNodesResult_init(p: &result); |
| 44450 | Operation_addNode(server, session: &server->adminSession, nodeContext, item: &item, result: &result); |
| 44451 | if(outNewNodeId) |
| 44452 | *outNewNodeId = result.addedNodeId; |
| 44453 | else |
| 44454 | UA_NodeId_clear(p: &result.addedNodeId); |
| 44455 | return result.statusCode; |
| 44456 | } |
| 44457 | |
| 44458 | UA_StatusCode |
| 44459 | __UA_Server_addNode(UA_Server *server, const UA_NodeClass nodeClass, |
| 44460 | const UA_NodeId *requestedNewNodeId, |
| 44461 | const UA_NodeId *parentNodeId, |
| 44462 | const UA_NodeId *referenceTypeId, |
| 44463 | const UA_QualifiedName browseName, |
| 44464 | const UA_NodeId *typeDefinition, |
| 44465 | const UA_NodeAttributes *attr, |
| 44466 | const UA_DataType *attributeType, |
| 44467 | void *nodeContext, UA_NodeId *outNewNodeId) { |
| 44468 | lockServer(server); |
| 44469 | UA_StatusCode reval = |
| 44470 | addNode(server, nodeClass, requestedNewNodeId: *requestedNewNodeId, parentNodeId: *parentNodeId, |
| 44471 | referenceTypeId: *referenceTypeId, browseName, typeDefinition: *typeDefinition, attr, |
| 44472 | attributeType, nodeContext, outNewNodeId); |
| 44473 | unlockServer(server); |
| 44474 | return reval; |
| 44475 | } |
| 44476 | |
| 44477 | UA_StatusCode |
| 44478 | addNode_begin(UA_Server *server, const UA_NodeClass nodeClass, |
| 44479 | const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, |
| 44480 | const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, |
| 44481 | const UA_NodeId typeDefinition, const void *attr, |
| 44482 | const UA_DataType *attributeType, void *nodeContext, |
| 44483 | UA_NodeId *outNewNodeId) { |
| 44484 | UA_AddNodesItem item; |
| 44485 | UA_AddNodesItem_init(p: &item); |
| 44486 | item.nodeClass = nodeClass; |
| 44487 | item.requestedNewNodeId.nodeId = requestedNewNodeId; |
| 44488 | item.browseName = browseName; |
| 44489 | item.typeDefinition.nodeId = typeDefinition; |
| 44490 | UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes, |
| 44491 | p: (void*)(uintptr_t)attr, type: attributeType); |
| 44492 | return Operation_addNode_begin(server, session: &server->adminSession, nodeContext, item: &item, |
| 44493 | parentNodeId: &parentNodeId, referenceTypeId: &referenceTypeId, outNewNodeId); |
| 44494 | } |
| 44495 | |
| 44496 | UA_StatusCode |
| 44497 | UA_Server_addNode_begin(UA_Server *server, const UA_NodeClass nodeClass, |
| 44498 | const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, |
| 44499 | const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, |
| 44500 | const UA_NodeId typeDefinition, const void *attr, |
| 44501 | const UA_DataType *attributeType, void *nodeContext, |
| 44502 | UA_NodeId *outNewNodeId) { |
| 44503 | lockServer(server); |
| 44504 | UA_StatusCode res = |
| 44505 | addNode_begin(server, nodeClass, requestedNewNodeId, parentNodeId, |
| 44506 | referenceTypeId, browseName, typeDefinition, attr, |
| 44507 | attributeType, nodeContext, outNewNodeId); |
| 44508 | unlockServer(server); |
| 44509 | return res; |
| 44510 | } |
| 44511 | |
| 44512 | UA_StatusCode |
| 44513 | UA_Server_addNode_finish(UA_Server *server, const UA_NodeId nodeId) { |
| 44514 | lockServer(server); |
| 44515 | UA_StatusCode retval = addNode_finish(server, session: &server->adminSession, nodeId: &nodeId); |
| 44516 | unlockServer(server); |
| 44517 | return retval; |
| 44518 | } |
| 44519 | |
| 44520 | /****************/ |
| 44521 | /* Delete Nodes */ |
| 44522 | /****************/ |
| 44523 | |
| 44524 | static void |
| 44525 | Operation_deleteReference(UA_Server *server, UA_Session *session, void *context, |
| 44526 | const UA_DeleteReferencesItem *item, UA_StatusCode *retval); |
| 44527 | |
| 44528 | struct RemoveIncomingContext { |
| 44529 | UA_Server *server; |
| 44530 | UA_Session *session; |
| 44531 | UA_DeleteReferencesItem *item; |
| 44532 | }; |
| 44533 | |
| 44534 | static void * |
| 44535 | removeIncomingReferencesCallback(void *context, UA_ReferenceTarget *t) { |
| 44536 | struct RemoveIncomingContext *ctx = (struct RemoveIncomingContext *)context; |
| 44537 | if(!UA_NodePointer_isLocal(np: t->targetId)) |
| 44538 | return NULL; |
| 44539 | UA_StatusCode dummy; |
| 44540 | ctx->item->sourceNodeId = UA_NodePointer_toNodeId(np: t->targetId); |
| 44541 | Operation_deleteReference(server: ctx->server, session: ctx->session, NULL, item: ctx->item, retval: &dummy); |
| 44542 | return NULL; |
| 44543 | } |
| 44544 | |
| 44545 | /* Remove references to this node (in the other nodes) */ |
| 44546 | static void |
| 44547 | removeIncomingReferences(UA_Server *server, UA_Session *session, |
| 44548 | const UA_NodeHead *head) { |
| 44549 | UA_DeleteReferencesItem item; |
| 44550 | UA_DeleteReferencesItem_init(p: &item); |
| 44551 | item.targetNodeId.nodeId = head->nodeId; |
| 44552 | item.deleteBidirectional = false; |
| 44553 | |
| 44554 | struct RemoveIncomingContext ctx; |
| 44555 | ctx.server = server; |
| 44556 | ctx.session = session; |
| 44557 | ctx.item = &item; |
| 44558 | |
| 44559 | for(size_t i = 0; i < head->referencesSize; ++i) { |
| 44560 | UA_NodeReferenceKind *rk = &head->references[i]; |
| 44561 | item.isForward = rk->isInverse; |
| 44562 | item.referenceTypeId = |
| 44563 | *UA_NODESTORE_GETREFERENCETYPEID(server, rk->referenceTypeIndex); |
| 44564 | UA_NodeReferenceKind_iterate(rk, callback: removeIncomingReferencesCallback, context: &ctx); |
| 44565 | } |
| 44566 | } |
| 44567 | |
| 44568 | static void * |
| 44569 | checkTargetInRefTree(void *context, UA_ReferenceTarget *t) { |
| 44570 | RefTree *refTree = (RefTree*)context; |
| 44571 | if(!UA_NodePointer_isLocal(np: t->targetId)) |
| 44572 | return NULL; |
| 44573 | UA_NodeId tmpId = UA_NodePointer_toNodeId(np: t->targetId); |
| 44574 | if(!RefTree_containsNodeId(rt: refTree, target: &tmpId)) |
| 44575 | return (void*)0x1; |
| 44576 | return NULL; |
| 44577 | } |
| 44578 | |
| 44579 | /* A node is auto-deleted if all its hierarchical parents are being deleted */ |
| 44580 | static UA_Boolean |
| 44581 | hasParentRef(const UA_NodeHead *head, const UA_ReferenceTypeSet *refSet, |
| 44582 | RefTree *refTree) { |
| 44583 | for(size_t i = 0; i < head->referencesSize; i++) { |
| 44584 | UA_NodeReferenceKind *rk = &head->references[i]; |
| 44585 | if(!rk->isInverse) |
| 44586 | continue; |
| 44587 | if(!UA_ReferenceTypeSet_contains(set: refSet, index: rk->referenceTypeIndex)) |
| 44588 | continue; |
| 44589 | if(UA_NodeReferenceKind_iterate(rk, callback: checkTargetInRefTree, context: refTree) != NULL) |
| 44590 | return true; |
| 44591 | } |
| 44592 | return false; |
| 44593 | } |
| 44594 | |
| 44595 | static void |
| 44596 | deconstructNodeSet(UA_Server *server, UA_Session *session, |
| 44597 | UA_ReferenceTypeSet *hierarchRefsSet, RefTree *refTree) { |
| 44598 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 44599 | |
| 44600 | /* Deconstruct the nodes based on the RefTree entries, parent nodes first */ |
| 44601 | for(size_t i = 0; i < refTree->size; i++) { |
| 44602 | const UA_Node *member = UA_NODESTORE_GET(server, nodeId: &refTree->targets[i].nodeId); |
| 44603 | if(!member) |
| 44604 | continue; |
| 44605 | |
| 44606 | /* Call the type-level destructor */ |
| 44607 | void *context = member->head.context; /* No longer needed after this function */ |
| 44608 | if(member->head.nodeClass == UA_NODECLASS_OBJECT || |
| 44609 | member->head.nodeClass == UA_NODECLASS_VARIABLE) { |
| 44610 | const UA_Node *type = getNodeType(server, head: &member->head); |
| 44611 | if(type) { |
| 44612 | /* Get the lifecycle */ |
| 44613 | const UA_NodeTypeLifecycle *lifecycle; |
| 44614 | if(member->head.nodeClass == UA_NODECLASS_OBJECT) |
| 44615 | lifecycle = &type->objectTypeNode.lifecycle; |
| 44616 | else |
| 44617 | lifecycle = &type->variableTypeNode.lifecycle; |
| 44618 | |
| 44619 | /* Call the destructor */ |
| 44620 | if(lifecycle->destructor) { |
| 44621 | lifecycle->destructor(server, |
| 44622 | &session->sessionId, session->sessionHandle, |
| 44623 | &type->head.nodeId, type->head.context, |
| 44624 | &member->head.nodeId, &context); |
| 44625 | } |
| 44626 | |
| 44627 | /* Release the type node */ |
| 44628 | UA_NODESTORE_RELEASE(server, type); |
| 44629 | } |
| 44630 | } |
| 44631 | |
| 44632 | /* Call the global destructor */ |
| 44633 | if(server->config.nodeLifecycle.destructor) { |
| 44634 | server->config.nodeLifecycle.destructor(server, &session->sessionId, |
| 44635 | session->sessionHandle, |
| 44636 | &member->head.nodeId, context); |
| 44637 | } |
| 44638 | |
| 44639 | /* Release the node. Don't access the node context from here on. */ |
| 44640 | UA_NODESTORE_RELEASE(server, member); |
| 44641 | |
| 44642 | /* Set the constructed flag to false */ |
| 44643 | UA_Server_editNode(server, session: &server->adminSession, nodeId: &refTree->targets[i].nodeId, |
| 44644 | callback: (UA_EditNodeCallback)setDeconstructedNode, NULL); |
| 44645 | } |
| 44646 | } |
| 44647 | |
| 44648 | struct DeleteChildrenContext { |
| 44649 | UA_Server *server; |
| 44650 | const UA_ReferenceTypeSet *hierarchRefsSet; |
| 44651 | RefTree *refTree; |
| 44652 | UA_StatusCode res; |
| 44653 | }; |
| 44654 | |
| 44655 | static void * |
| 44656 | deleteChildrenCallback(void *context, UA_ReferenceTarget *t) { |
| 44657 | struct DeleteChildrenContext *ctx = (struct DeleteChildrenContext*)context; |
| 44658 | |
| 44659 | /* Get the child */ |
| 44660 | const UA_Node *child = UA_NODESTORE_GETFROMREF(server: ctx->server, target: t->targetId); |
| 44661 | if(!child) |
| 44662 | return NULL; |
| 44663 | |
| 44664 | /* Only delete child nodes that have no other parent */ |
| 44665 | if(!hasParentRef(head: &child->head, refSet: ctx->hierarchRefsSet, refTree: ctx->refTree)) |
| 44666 | ctx->res = RefTree_addNodeId(rt: ctx->refTree, target: &child->head.nodeId, NULL); |
| 44667 | |
| 44668 | UA_NODESTORE_RELEASE(ctx->server, child); |
| 44669 | return (ctx->res == UA_STATUSCODE_GOOD) ? NULL : (void*)0x01; |
| 44670 | } |
| 44671 | |
| 44672 | /* The processNodeLayer function searches all children's of the head node and |
| 44673 | * adds the children node to the RefTree if all incoming references sources are |
| 44674 | * contained in the RefTree (No external references to this node --> node can be |
| 44675 | * deleted) */ |
| 44676 | static UA_StatusCode |
| 44677 | autoDeleteChildren(UA_Server *server, UA_Session *session, RefTree *refTree, |
| 44678 | const UA_ReferenceTypeSet *hierarchRefsSet, const UA_NodeHead *head){ |
| 44679 | struct DeleteChildrenContext ctx; |
| 44680 | ctx.server = server; |
| 44681 | ctx.hierarchRefsSet = hierarchRefsSet; |
| 44682 | ctx.refTree = refTree; |
| 44683 | ctx.res = UA_STATUSCODE_GOOD; |
| 44684 | |
| 44685 | for(size_t i = 0; i < head->referencesSize; ++i) { |
| 44686 | /* Check if the ReferenceType is hierarchical */ |
| 44687 | UA_NodeReferenceKind *rk = &head->references[i]; |
| 44688 | if(!UA_ReferenceTypeSet_contains(set: hierarchRefsSet, index: rk->referenceTypeIndex)) |
| 44689 | continue; |
| 44690 | |
| 44691 | /* Check if the references are forward (to a child) */ |
| 44692 | if(rk->isInverse) |
| 44693 | continue; |
| 44694 | |
| 44695 | /* Loop over the references */ |
| 44696 | UA_NodeReferenceKind_iterate(rk, callback: deleteChildrenCallback, context: &ctx); |
| 44697 | if(ctx.res != UA_STATUSCODE_GOOD) |
| 44698 | return ctx.res; |
| 44699 | } |
| 44700 | return UA_STATUSCODE_GOOD; |
| 44701 | } |
| 44702 | |
| 44703 | /* Build up an ordered set (tree) of all nodes that can be deleted. Step through |
| 44704 | * the ordered set in order to avoid recursion. */ |
| 44705 | static UA_StatusCode |
| 44706 | buildDeleteNodeSet(UA_Server *server, UA_Session *session, |
| 44707 | const UA_ReferenceTypeSet *hierarchRefsSet, |
| 44708 | const UA_NodeId *initial, UA_Boolean removeTargetRefs, |
| 44709 | RefTree *refTree) { |
| 44710 | /* Add the initial node to delete */ |
| 44711 | UA_StatusCode res = RefTree_addNodeId(rt: refTree, target: initial, NULL); |
| 44712 | if(res != UA_STATUSCODE_GOOD) |
| 44713 | return res; |
| 44714 | |
| 44715 | /* Find out which hierarchical children should also be deleted. We know |
| 44716 | * there are no "external" ExpandedNodeId in the RefTree. */ |
| 44717 | size_t pos = 0; |
| 44718 | while(pos < refTree->size) { |
| 44719 | const UA_Node *member = UA_NODESTORE_GET(server, nodeId: &refTree->targets[pos].nodeId); |
| 44720 | pos++; |
| 44721 | if(!member) |
| 44722 | continue; |
| 44723 | res |= autoDeleteChildren(server, session, refTree, hierarchRefsSet, head: &member->head); |
| 44724 | UA_NODESTORE_RELEASE(server, member); |
| 44725 | } |
| 44726 | return res; |
| 44727 | } |
| 44728 | |
| 44729 | static void |
| 44730 | deleteNodeSet(UA_Server *server, UA_Session *session, |
| 44731 | const UA_ReferenceTypeSet *hierarchRefsSet, |
| 44732 | UA_Boolean removeTargetRefs, RefTree *refTree) { |
| 44733 | /* Delete the nodes based on the RefTree entries */ |
| 44734 | for(size_t i = refTree->size; i > 0; --i) { |
| 44735 | const UA_Node *member = UA_NODESTORE_GET(server, nodeId: &refTree->targets[i-1].nodeId); |
| 44736 | if(!member) |
| 44737 | continue; |
| 44738 | UA_NODESTORE_RELEASE(server, member); |
| 44739 | if(removeTargetRefs) |
| 44740 | removeIncomingReferences(server, session, head: &member->head); |
| 44741 | UA_NODESTORE_REMOVE(server, &member->head.nodeId); |
| 44742 | } |
| 44743 | } |
| 44744 | |
| 44745 | static void |
| 44746 | deleteNodeOperation(UA_Server *server, UA_Session *session, void *context, |
| 44747 | const UA_DeleteNodesItem *item, UA_StatusCode *result) { |
| 44748 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 44749 | |
| 44750 | /* Do not check access for server */ |
| 44751 | if(session != &server->adminSession && server->config.accessControl.allowDeleteNode) { |
| 44752 | if(!server->config.accessControl. |
| 44753 | allowDeleteNode(server, &server->config.accessControl, |
| 44754 | &session->sessionId, session->sessionHandle, item)) { |
| 44755 | *result = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 44756 | return; |
| 44757 | } |
| 44758 | } |
| 44759 | |
| 44760 | const UA_Node *node = UA_NODESTORE_GET(server, nodeId: &item->nodeId); |
| 44761 | if(!node) { |
| 44762 | *result = UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 44763 | return; |
| 44764 | } |
| 44765 | |
| 44766 | if(UA_Node_hasSubTypeOrInstances(head: &node->head)) { |
| 44767 | UA_LOG_NODEID_INFO(&node->head.nodeId, |
| 44768 | UA_LOG_INFO_SESSION(server->config.logging, session, "DeleteNode (%.*s): " |
| 44769 | "Cannot delete a type node with active instances or " |
| 44770 | "subtypes", (int)nodeIdStr.length, nodeIdStr.data)); |
| 44771 | UA_NODESTORE_RELEASE(server, node); |
| 44772 | *result = UA_STATUSCODE_BADINTERNALERROR; |
| 44773 | return; |
| 44774 | } |
| 44775 | |
| 44776 | /* TODO: Check if the information model consistency is violated */ |
| 44777 | /* TODO: Check if the node is a mandatory child of a parent */ |
| 44778 | |
| 44779 | /* Relase the node. Don't access the pointer after this! */ |
| 44780 | UA_NODESTORE_RELEASE(server, node); |
| 44781 | |
| 44782 | /* A node can be referenced with hierarchical references from several |
| 44783 | * parents in the information model. (But not in a circular way.) The |
| 44784 | * hierarchical references are checked to see if a node can be deleted. |
| 44785 | * Getting the type hierarchy can fail in case of low RAM. In that case the |
| 44786 | * nodes are always deleted. */ |
| 44787 | UA_ReferenceTypeSet hierarchRefsSet; |
| 44788 | UA_NodeId hr = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES); |
| 44789 | *result = referenceTypeIndices(server, refType: &hr, indices: &hierarchRefsSet, true); |
| 44790 | if(*result != UA_STATUSCODE_GOOD) |
| 44791 | return; |
| 44792 | |
| 44793 | /* The list of childs is needed for the deconstructing and deleting phase. |
| 44794 | * Within the processNodeLayer we generate a RefTree based set of childs |
| 44795 | * which can be deleted beside the parent node. */ |
| 44796 | RefTree refTree; |
| 44797 | *result = RefTree_init(rt: &refTree); |
| 44798 | if(*result != UA_STATUSCODE_GOOD) |
| 44799 | return; |
| 44800 | *result = buildDeleteNodeSet(server, session, hierarchRefsSet: &hierarchRefsSet, initial: &item->nodeId, |
| 44801 | removeTargetRefs: item->deleteTargetReferences, refTree: &refTree); |
| 44802 | if(*result != UA_STATUSCODE_GOOD) { |
| 44803 | UA_LOG_WARNING_SESSION(server->config.logging, session, |
| 44804 | "DeleteNode: Incomplete lookup of nodes. " |
| 44805 | "Still deleting what we have."); |
| 44806 | /* Continue, so the RefTree is cleaned up. Return the error message |
| 44807 | * anyway. */ |
| 44808 | } |
| 44809 | |
| 44810 | /* Deconstruct, then delete, then clean up the set */ |
| 44811 | deconstructNodeSet(server, session, hierarchRefsSet: &hierarchRefsSet, refTree: &refTree); |
| 44812 | deleteNodeSet(server, session, hierarchRefsSet: &hierarchRefsSet, |
| 44813 | removeTargetRefs: item->deleteTargetReferences, refTree: &refTree); |
| 44814 | RefTree_clear(rt: &refTree); |
| 44815 | } |
| 44816 | |
| 44817 | void |
| 44818 | Service_DeleteNodes(UA_Server *server, UA_Session *session, |
| 44819 | const UA_DeleteNodesRequest *request, |
| 44820 | UA_DeleteNodesResponse *response) { |
| 44821 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 44822 | "Processing DeleteNodesRequest"); |
| 44823 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 44824 | |
| 44825 | if(server->config.maxNodesPerNodeManagement != 0 && |
| 44826 | request->nodesToDeleteSize > server->config.maxNodesPerNodeManagement) { |
| 44827 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 44828 | return; |
| 44829 | } |
| 44830 | |
| 44831 | response->responseHeader.serviceResult = |
| 44832 | UA_Server_processServiceOperations(server, session, |
| 44833 | operationCallback: (UA_ServiceOperation)deleteNodeOperation, |
| 44834 | NULL, requestOperations: &request->nodesToDeleteSize, |
| 44835 | requestOperationsType: &UA_TYPES[UA_TYPES_DELETENODESITEM], |
| 44836 | responseOperations: &response->resultsSize, |
| 44837 | responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 44838 | } |
| 44839 | |
| 44840 | UA_StatusCode |
| 44841 | UA_Server_deleteNode(UA_Server *server, const UA_NodeId nodeId, |
| 44842 | UA_Boolean deleteReferences) { |
| 44843 | lockServer(server); |
| 44844 | UA_StatusCode retval = deleteNode(server, nodeId, deleteReferences); |
| 44845 | unlockServer(server); |
| 44846 | return retval; |
| 44847 | } |
| 44848 | |
| 44849 | UA_StatusCode |
| 44850 | deleteNode(UA_Server *server, const UA_NodeId nodeId, |
| 44851 | UA_Boolean deleteReferences) { |
| 44852 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 44853 | UA_DeleteNodesItem item; |
| 44854 | item.deleteTargetReferences = deleteReferences; |
| 44855 | item.nodeId = nodeId; |
| 44856 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 44857 | deleteNodeOperation(server, session: &server->adminSession, NULL, item: &item, result: &retval); |
| 44858 | return retval; |
| 44859 | } |
| 44860 | |
| 44861 | /******************/ |
| 44862 | /* Add References */ |
| 44863 | /******************/ |
| 44864 | |
| 44865 | struct AddNodeInfo { |
| 44866 | UA_Byte refTypeIndex; |
| 44867 | UA_Boolean isForward; |
| 44868 | const UA_ExpandedNodeId *targetNodeId; |
| 44869 | UA_UInt32 targetBrowseNameHash; |
| 44870 | }; |
| 44871 | |
| 44872 | static UA_StatusCode |
| 44873 | addOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node, |
| 44874 | const struct AddNodeInfo *info) { |
| 44875 | return UA_Node_addReference(node, refTypeIndex: info->refTypeIndex, isForward: info->isForward, |
| 44876 | targetNodeId: info->targetNodeId, targetBrowseNameHash: info->targetBrowseNameHash); |
| 44877 | } |
| 44878 | |
| 44879 | static UA_StatusCode |
| 44880 | deleteOneWayReference(UA_Server *server, UA_Session *session, UA_Node *node, |
| 44881 | const UA_DeleteReferencesItem *item) { |
| 44882 | const UA_Node *refType = UA_NODESTORE_GET(server, nodeId: &item->referenceTypeId); |
| 44883 | if(!refType) |
| 44884 | return UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 44885 | if(refType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) { |
| 44886 | UA_NODESTORE_RELEASE(server, refType); |
| 44887 | return UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 44888 | } |
| 44889 | UA_Byte refTypeIndex = refType->referenceTypeNode.referenceTypeIndex; |
| 44890 | UA_NODESTORE_RELEASE(server, refType); |
| 44891 | return UA_Node_deleteReference(node, refTypeIndex, isForward: item->isForward, targetNodeId: &item->targetNodeId); |
| 44892 | } |
| 44893 | |
| 44894 | static void |
| 44895 | Operation_addReference(UA_Server *server, UA_Session *session, void *context, |
| 44896 | const UA_AddReferencesItem *item, UA_StatusCode *retval) { |
| 44897 | (void)context; |
| 44898 | UA_assert(session); |
| 44899 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 44900 | |
| 44901 | /* Check access rights */ |
| 44902 | if(session != &server->adminSession && server->config.accessControl.allowAddReference) { |
| 44903 | if (!server->config.accessControl. |
| 44904 | allowAddReference(server, &server->config.accessControl, |
| 44905 | &session->sessionId, session->sessionHandle, item)) { |
| 44906 | *retval = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 44907 | return; |
| 44908 | } |
| 44909 | } |
| 44910 | |
| 44911 | /* TODO: Currently no expandednodeids are allowed */ |
| 44912 | if(item->targetServerUri.length > 0) { |
| 44913 | *retval = UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 44914 | return; |
| 44915 | } |
| 44916 | |
| 44917 | /* Check the ReferenceType and get the index */ |
| 44918 | const UA_Node *refType = UA_NODESTORE_GET(server, nodeId: &item->referenceTypeId); |
| 44919 | if(!refType) { |
| 44920 | UA_LOG_NODEID_DEBUG(&item->referenceTypeId, |
| 44921 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 44922 | "Cannot add reference - ReferenceType %.*s unknown", |
| 44923 | (int)nodeIdStr.length, nodeIdStr.data)); |
| 44924 | *retval = UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 44925 | return; |
| 44926 | } |
| 44927 | if(refType->head.nodeClass != UA_NODECLASS_REFERENCETYPE) { |
| 44928 | UA_LOG_NODEID_DEBUG(&item->referenceTypeId, |
| 44929 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 44930 | "Cannot add reference - ReferenceType %.*s with wrong NodeClass", |
| 44931 | (int)nodeIdStr.length, nodeIdStr.data)); |
| 44932 | UA_NODESTORE_RELEASE(server, refType); |
| 44933 | *retval = UA_STATUSCODE_BADREFERENCETYPEIDINVALID; |
| 44934 | return; |
| 44935 | } |
| 44936 | UA_Byte refTypeIndex = refType->referenceTypeNode.referenceTypeIndex; |
| 44937 | UA_NODESTORE_RELEASE(server, refType); |
| 44938 | |
| 44939 | /* Get the source and target node BrowseName hash */ |
| 44940 | const UA_Node *targetNode = UA_NODESTORE_GET(server, nodeId: &item->targetNodeId.nodeId); |
| 44941 | if(!targetNode) { |
| 44942 | UA_LOG_NODEID_DEBUG(&item->targetNodeId.nodeId, |
| 44943 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 44944 | "Cannot add reference - target %.*s does not exist", |
| 44945 | (int)nodeIdStr.length, nodeIdStr.data)); |
| 44946 | *retval = UA_STATUSCODE_BADTARGETNODEIDINVALID; |
| 44947 | return; |
| 44948 | } |
| 44949 | UA_UInt32 targetNameHash = UA_QualifiedName_hash(q: &targetNode->head.browseName); |
| 44950 | UA_NODESTORE_RELEASE(server, targetNode); |
| 44951 | |
| 44952 | const UA_Node *sourceNode = UA_NODESTORE_GET(server, nodeId: &item->sourceNodeId); |
| 44953 | if(!sourceNode) { |
| 44954 | *retval = UA_STATUSCODE_BADSOURCENODEIDINVALID; |
| 44955 | return; |
| 44956 | } |
| 44957 | UA_UInt32 sourceNameHash = UA_QualifiedName_hash(q: &sourceNode->head.browseName); |
| 44958 | UA_NODESTORE_RELEASE(server, sourceNode); |
| 44959 | |
| 44960 | /* Compute the BrowseName hash and release the target */ |
| 44961 | struct AddNodeInfo info; |
| 44962 | info.refTypeIndex = refTypeIndex; |
| 44963 | info.targetNodeId = &item->targetNodeId; |
| 44964 | info.isForward = item->isForward; |
| 44965 | info.targetBrowseNameHash = targetNameHash; |
| 44966 | |
| 44967 | /* Add the first direction */ |
| 44968 | *retval = UA_Server_editNode(server, session, nodeId: &item->sourceNodeId, |
| 44969 | callback: (UA_EditNodeCallback)addOneWayReference, data: &info); |
| 44970 | UA_Boolean firstExisted = false; |
| 44971 | if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) { |
| 44972 | *retval = UA_STATUSCODE_GOOD; |
| 44973 | firstExisted = true; |
| 44974 | } |
| 44975 | if(*retval != UA_STATUSCODE_GOOD) |
| 44976 | return; |
| 44977 | |
| 44978 | /* Add the second direction */ |
| 44979 | UA_ExpandedNodeId target2; |
| 44980 | UA_ExpandedNodeId_init(p: &target2); |
| 44981 | target2.nodeId = item->sourceNodeId; |
| 44982 | info.targetNodeId = &target2; |
| 44983 | info.isForward = !info.isForward; |
| 44984 | info.targetBrowseNameHash = sourceNameHash; |
| 44985 | *retval = UA_Server_editNode(server, session, nodeId: &item->targetNodeId.nodeId, |
| 44986 | callback: (UA_EditNodeCallback)addOneWayReference, data: &info); |
| 44987 | |
| 44988 | /* Second direction existed already */ |
| 44989 | if(*retval == UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED) { |
| 44990 | /* Calculate common duplicate reference not allowed result and set bad |
| 44991 | * result if BOTH directions already existed */ |
| 44992 | if(UA_NodeId_equal(p1: &item->sourceNodeId, p2: &item->targetNodeId.nodeId)) { |
| 44993 | *retval = UA_STATUSCODE_GOOD; |
| 44994 | UA_LOG_INFO_SESSION(server->config.logging, session, "The source node and the target node are identical. The check for duplicate references is skipped."); |
| 44995 | } |
| 44996 | else if(firstExisted) { |
| 44997 | *retval = UA_STATUSCODE_BADDUPLICATEREFERENCENOTALLOWED; |
| 44998 | return; |
| 44999 | } |
| 45000 | *retval = UA_STATUSCODE_GOOD; |
| 45001 | } |
| 45002 | |
| 45003 | /* Remove first direction if the second direction failed */ |
| 45004 | if(*retval != UA_STATUSCODE_GOOD && !firstExisted) { |
| 45005 | UA_DeleteReferencesItem deleteItem; |
| 45006 | deleteItem.sourceNodeId = item->sourceNodeId; |
| 45007 | deleteItem.referenceTypeId = item->referenceTypeId; |
| 45008 | deleteItem.isForward = item->isForward; |
| 45009 | deleteItem.targetNodeId = item->targetNodeId; |
| 45010 | deleteItem.deleteBidirectional = false; |
| 45011 | /* Ignore status code */ |
| 45012 | UA_Server_editNode(server, session, nodeId: &item->sourceNodeId, |
| 45013 | callback: (UA_EditNodeCallback)deleteOneWayReference, data: &deleteItem); |
| 45014 | } |
| 45015 | } |
| 45016 | |
| 45017 | void |
| 45018 | Service_AddReferences(UA_Server *server, UA_Session *session, |
| 45019 | const UA_AddReferencesRequest *request, |
| 45020 | UA_AddReferencesResponse *response) { |
| 45021 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 45022 | "Processing AddReferencesRequest"); |
| 45023 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 45024 | UA_assert(session); |
| 45025 | |
| 45026 | if(server->config.maxNodesPerNodeManagement != 0 && |
| 45027 | request->referencesToAddSize > server->config.maxNodesPerNodeManagement) { |
| 45028 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 45029 | return; |
| 45030 | } |
| 45031 | |
| 45032 | response->responseHeader.serviceResult = |
| 45033 | UA_Server_processServiceOperations(server, session, |
| 45034 | operationCallback: (UA_ServiceOperation)Operation_addReference, |
| 45035 | NULL, requestOperations: &request->referencesToAddSize, |
| 45036 | requestOperationsType: &UA_TYPES[UA_TYPES_ADDREFERENCESITEM], |
| 45037 | responseOperations: &response->resultsSize, |
| 45038 | responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 45039 | } |
| 45040 | |
| 45041 | UA_StatusCode |
| 45042 | UA_Server_addReference(UA_Server *server, const UA_NodeId sourceId, |
| 45043 | const UA_NodeId refTypeId, |
| 45044 | const UA_ExpandedNodeId targetId, |
| 45045 | UA_Boolean isForward) { |
| 45046 | UA_AddReferencesItem item; |
| 45047 | UA_AddReferencesItem_init(p: &item); |
| 45048 | item.sourceNodeId = sourceId; |
| 45049 | item.referenceTypeId = refTypeId; |
| 45050 | item.isForward = isForward; |
| 45051 | item.targetNodeId = targetId; |
| 45052 | |
| 45053 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 45054 | lockServer(server); |
| 45055 | Operation_addReference(server, session: &server->adminSession, NULL, item: &item, retval: &retval); |
| 45056 | unlockServer(server); |
| 45057 | return retval; |
| 45058 | } |
| 45059 | |
| 45060 | /*********************/ |
| 45061 | /* Delete References */ |
| 45062 | /*********************/ |
| 45063 | |
| 45064 | static void |
| 45065 | Operation_deleteReference(UA_Server *server, UA_Session *session, void *context, |
| 45066 | const UA_DeleteReferencesItem *item, UA_StatusCode *retval) { |
| 45067 | /* Do not check access for server */ |
| 45068 | if(session != &server->adminSession && |
| 45069 | server->config.accessControl.allowDeleteReference) { |
| 45070 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 45071 | if (!server->config.accessControl. |
| 45072 | allowDeleteReference(server, &server->config.accessControl, |
| 45073 | &session->sessionId, session->sessionHandle, item)){ |
| 45074 | *retval = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 45075 | return; |
| 45076 | } |
| 45077 | } |
| 45078 | |
| 45079 | // TODO: Check consistency constraints, remove the references. |
| 45080 | *retval = UA_Server_editNode(server, session, nodeId: &item->sourceNodeId, |
| 45081 | callback: (UA_EditNodeCallback)deleteOneWayReference, |
| 45082 | /* cast away const qualifier because callback |
| 45083 | * uses it anyway */ |
| 45084 | data: (UA_DeleteReferencesItem *)(uintptr_t)item); |
| 45085 | if(*retval != UA_STATUSCODE_GOOD) |
| 45086 | return; |
| 45087 | |
| 45088 | if(!item->deleteBidirectional || item->targetNodeId.serverIndex != 0) |
| 45089 | return; |
| 45090 | |
| 45091 | UA_DeleteReferencesItem secondItem; |
| 45092 | UA_DeleteReferencesItem_init(p: &secondItem); |
| 45093 | secondItem.isForward = !item->isForward; |
| 45094 | secondItem.sourceNodeId = item->targetNodeId.nodeId; |
| 45095 | secondItem.targetNodeId.nodeId = item->sourceNodeId; |
| 45096 | secondItem.referenceTypeId = item->referenceTypeId; |
| 45097 | *retval = UA_Server_editNode(server, session, nodeId: &secondItem.sourceNodeId, |
| 45098 | callback: (UA_EditNodeCallback)deleteOneWayReference, |
| 45099 | data: &secondItem); |
| 45100 | } |
| 45101 | |
| 45102 | void |
| 45103 | Service_DeleteReferences(UA_Server *server, UA_Session *session, |
| 45104 | const UA_DeleteReferencesRequest *request, |
| 45105 | UA_DeleteReferencesResponse *response) { |
| 45106 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 45107 | "Processing DeleteReferencesRequest"); |
| 45108 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 45109 | |
| 45110 | if(server->config.maxNodesPerNodeManagement != 0 && |
| 45111 | request->referencesToDeleteSize > server->config.maxNodesPerNodeManagement) { |
| 45112 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYOPERATIONS; |
| 45113 | return; |
| 45114 | } |
| 45115 | |
| 45116 | response->responseHeader.serviceResult = |
| 45117 | UA_Server_processServiceOperations(server, session, |
| 45118 | operationCallback: (UA_ServiceOperation)Operation_deleteReference, |
| 45119 | NULL, requestOperations: &request->referencesToDeleteSize, |
| 45120 | requestOperationsType: &UA_TYPES[UA_TYPES_DELETEREFERENCESITEM], |
| 45121 | responseOperations: &response->resultsSize, |
| 45122 | responseOperationsType: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 45123 | } |
| 45124 | |
| 45125 | UA_StatusCode |
| 45126 | deleteReference(UA_Server *server, const UA_NodeId sourceNodeId, |
| 45127 | const UA_NodeId referenceTypeId, UA_Boolean isForward, |
| 45128 | const UA_ExpandedNodeId targetNodeId, |
| 45129 | UA_Boolean deleteBidirectional) { |
| 45130 | UA_DeleteReferencesItem item; |
| 45131 | item.sourceNodeId = sourceNodeId; |
| 45132 | item.referenceTypeId = referenceTypeId; |
| 45133 | item.isForward = isForward; |
| 45134 | item.targetNodeId = targetNodeId; |
| 45135 | item.deleteBidirectional = deleteBidirectional; |
| 45136 | |
| 45137 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 45138 | Operation_deleteReference(server, session: &server->adminSession, NULL, item: &item, retval: &retval); |
| 45139 | return retval; |
| 45140 | } |
| 45141 | |
| 45142 | UA_StatusCode |
| 45143 | UA_Server_deleteReference(UA_Server *server, const UA_NodeId sourceNodeId, |
| 45144 | const UA_NodeId referenceTypeId, UA_Boolean isForward, |
| 45145 | const UA_ExpandedNodeId targetNodeId, |
| 45146 | UA_Boolean deleteBidirectional) { |
| 45147 | lockServer(server); |
| 45148 | UA_StatusCode res = deleteReference(server, sourceNodeId, referenceTypeId, |
| 45149 | isForward, targetNodeId, deleteBidirectional); |
| 45150 | unlockServer(server); |
| 45151 | return res; |
| 45152 | } |
| 45153 | |
| 45154 | /**********************/ |
| 45155 | /* Set Value Callback */ |
| 45156 | /**********************/ |
| 45157 | |
| 45158 | static UA_StatusCode |
| 45159 | setValueCallback(UA_Server *server, UA_Session *session, |
| 45160 | UA_VariableNode *node, const UA_ValueCallback *callback) { |
| 45161 | if(node->head.nodeClass != UA_NODECLASS_VARIABLE) |
| 45162 | return UA_STATUSCODE_BADNODECLASSINVALID; |
| 45163 | node->value.data.callback = *callback; |
| 45164 | return UA_STATUSCODE_GOOD; |
| 45165 | } |
| 45166 | |
| 45167 | UA_StatusCode |
| 45168 | setVariableNode_valueCallback(UA_Server *server, const UA_NodeId nodeId, |
| 45169 | const UA_ValueCallback callback) { |
| 45170 | return UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId, |
| 45171 | callback: (UA_EditNodeCallback)setValueCallback, |
| 45172 | /* cast away const because |
| 45173 | * callback uses const anyway */ |
| 45174 | data: (UA_ValueCallback *)(uintptr_t) &callback); |
| 45175 | } |
| 45176 | |
| 45177 | UA_StatusCode |
| 45178 | UA_Server_setVariableNode_valueCallback(UA_Server *server, |
| 45179 | const UA_NodeId nodeId, |
| 45180 | const UA_ValueCallback callback) { |
| 45181 | lockServer(server); |
| 45182 | UA_StatusCode retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId, |
| 45183 | callback: (UA_EditNodeCallback)setValueCallback, |
| 45184 | /* cast away const because |
| 45185 | * callback uses const anyway */ |
| 45186 | data: (UA_ValueCallback *)(uintptr_t) &callback); |
| 45187 | unlockServer(server); |
| 45188 | return retval; |
| 45189 | } |
| 45190 | |
| 45191 | /***************************************************/ |
| 45192 | /* Special Handling of Variables with Data Sources */ |
| 45193 | /***************************************************/ |
| 45194 | |
| 45195 | UA_StatusCode |
| 45196 | UA_Server_addDataSourceVariableNode(UA_Server *server, const UA_NodeId requestedNewNodeId, |
| 45197 | const UA_NodeId parentNodeId, |
| 45198 | const UA_NodeId referenceTypeId, |
| 45199 | const UA_QualifiedName browseName, |
| 45200 | const UA_NodeId typeDefinition, |
| 45201 | const UA_VariableAttributes attr, |
| 45202 | const UA_DataSource dataSource, |
| 45203 | void *nodeContext, UA_NodeId *outNewNodeId) { |
| 45204 | UA_AddNodesItem item; |
| 45205 | UA_AddNodesItem_init(p: &item); |
| 45206 | item.nodeClass = UA_NODECLASS_VARIABLE; |
| 45207 | item.requestedNewNodeId.nodeId = requestedNewNodeId; |
| 45208 | item.browseName = browseName; |
| 45209 | UA_ExpandedNodeId typeDefinitionId; |
| 45210 | UA_ExpandedNodeId_init(p: &typeDefinitionId); |
| 45211 | typeDefinitionId.nodeId = typeDefinition; |
| 45212 | item.typeDefinition = typeDefinitionId; |
| 45213 | UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes, p: (void*)(uintptr_t)&attr, |
| 45214 | type: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES]); |
| 45215 | UA_NodeId newNodeId; |
| 45216 | if(!outNewNodeId) { |
| 45217 | newNodeId = UA_NODEID_NULL; |
| 45218 | outNewNodeId = &newNodeId; |
| 45219 | } |
| 45220 | |
| 45221 | lockServer(server); |
| 45222 | |
| 45223 | /* Create the node and add it to the nodestore */ |
| 45224 | UA_StatusCode retval = addNode_raw(server, session: &server->adminSession, nodeContext, |
| 45225 | item: &item, outNewNodeId); |
| 45226 | if(retval != UA_STATUSCODE_GOOD) |
| 45227 | goto cleanup; |
| 45228 | |
| 45229 | /* Set the data source */ |
| 45230 | retval = setVariableNode_dataSource(server, nodeId: *outNewNodeId, dataSource); |
| 45231 | if(retval != UA_STATUSCODE_GOOD) |
| 45232 | goto cleanup; |
| 45233 | |
| 45234 | /* Typecheck and add references to parent and type definition */ |
| 45235 | retval = addNode_addRefs(server, session: &server->adminSession, nodeId: outNewNodeId, parentNodeId: &parentNodeId, |
| 45236 | referenceTypeId: &referenceTypeId, typeDefinitionId: &typeDefinition); |
| 45237 | if(retval != UA_STATUSCODE_GOOD) |
| 45238 | goto cleanup; |
| 45239 | |
| 45240 | /* Call the constructors */ |
| 45241 | retval = addNode_finish(server, session: &server->adminSession, nodeId: outNewNodeId); |
| 45242 | |
| 45243 | cleanup: |
| 45244 | unlockServer(server); |
| 45245 | if(outNewNodeId == &newNodeId) |
| 45246 | UA_NodeId_clear(p: &newNodeId); |
| 45247 | |
| 45248 | return retval; |
| 45249 | } |
| 45250 | |
| 45251 | static UA_StatusCode |
| 45252 | setDataSource(UA_Server *server, UA_Session *session, |
| 45253 | UA_VariableNode *node, const UA_DataSource *dataSource) { |
| 45254 | if(node->head.nodeClass != UA_NODECLASS_VARIABLE) |
| 45255 | return UA_STATUSCODE_BADNODECLASSINVALID; |
| 45256 | if(node->valueSource == UA_VALUESOURCE_DATA) |
| 45257 | UA_DataValue_clear(p: &node->value.data.value); |
| 45258 | node->value.dataSource = *dataSource; |
| 45259 | node->valueSource = UA_VALUESOURCE_DATASOURCE; |
| 45260 | return UA_STATUSCODE_GOOD; |
| 45261 | } |
| 45262 | |
| 45263 | UA_StatusCode |
| 45264 | setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId, |
| 45265 | const UA_DataSource dataSource) { |
| 45266 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 45267 | return UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId, |
| 45268 | callback: (UA_EditNodeCallback)setDataSource, |
| 45269 | /* casting away const because callback casts it back anyway */ |
| 45270 | data: (UA_DataSource *) (uintptr_t)&dataSource); |
| 45271 | } |
| 45272 | |
| 45273 | UA_StatusCode |
| 45274 | UA_Server_setVariableNode_dataSource(UA_Server *server, const UA_NodeId nodeId, |
| 45275 | const UA_DataSource dataSource) { |
| 45276 | lockServer(server); |
| 45277 | UA_StatusCode retval = setVariableNode_dataSource(server, nodeId, dataSource); |
| 45278 | unlockServer(server); |
| 45279 | return retval; |
| 45280 | } |
| 45281 | |
| 45282 | /******************************/ |
| 45283 | /* Set External Value Source */ |
| 45284 | /******************************/ |
| 45285 | static UA_StatusCode |
| 45286 | setExternalValueSource(UA_Server *server, UA_Session *session, |
| 45287 | UA_VariableNode *node, const UA_ValueBackend *externalValueSource) { |
| 45288 | if(node->head.nodeClass != UA_NODECLASS_VARIABLE) |
| 45289 | return UA_STATUSCODE_BADNODECLASSINVALID; |
| 45290 | node->valueBackend.backendType = UA_VALUEBACKENDTYPE_EXTERNAL; |
| 45291 | node->valueBackend.backend.external.value = |
| 45292 | externalValueSource->backend.external.value; |
| 45293 | node->valueBackend.backend.external.callback.notificationRead = |
| 45294 | externalValueSource->backend.external.callback.notificationRead; |
| 45295 | node->valueBackend.backend.external.callback.userWrite = |
| 45296 | externalValueSource->backend.external.callback.userWrite; |
| 45297 | return UA_STATUSCODE_GOOD; |
| 45298 | } |
| 45299 | |
| 45300 | /****************************/ |
| 45301 | /* Set Data Source Callback */ |
| 45302 | /****************************/ |
| 45303 | static UA_StatusCode |
| 45304 | setDataSourceCallback(UA_Server *server, UA_Session *session, |
| 45305 | UA_VariableNode *node, const UA_DataSource *dataSource) { |
| 45306 | if(node->head.nodeClass != UA_NODECLASS_VARIABLE) |
| 45307 | return UA_STATUSCODE_BADNODECLASSINVALID; |
| 45308 | node->valueBackend.backendType = UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK; |
| 45309 | node->valueBackend.backend.dataSource.read = dataSource->read; |
| 45310 | node->valueBackend.backend.dataSource.write = dataSource->write; |
| 45311 | return UA_STATUSCODE_GOOD; |
| 45312 | } |
| 45313 | |
| 45314 | /**********************/ |
| 45315 | /* Set Value Backend */ |
| 45316 | /**********************/ |
| 45317 | |
| 45318 | UA_StatusCode |
| 45319 | UA_Server_setVariableNode_valueBackend(UA_Server *server, const UA_NodeId nodeId, |
| 45320 | const UA_ValueBackend valueBackend){ |
| 45321 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 45322 | lockServer(server); |
| 45323 | switch(valueBackend.backendType){ |
| 45324 | case UA_VALUEBACKENDTYPE_NONE: |
| 45325 | unlockServer(server); |
| 45326 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 45327 | case UA_VALUEBACKENDTYPE_DATA_SOURCE_CALLBACK: |
| 45328 | retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId, |
| 45329 | callback: (UA_EditNodeCallback) setDataSourceCallback, |
| 45330 | data: (UA_DataSource *)(uintptr_t) &valueBackend.backend.dataSource); |
| 45331 | break; |
| 45332 | case UA_VALUEBACKENDTYPE_INTERNAL: |
| 45333 | break; |
| 45334 | case UA_VALUEBACKENDTYPE_EXTERNAL: |
| 45335 | retval = UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId, |
| 45336 | callback: (UA_EditNodeCallback) setExternalValueSource, |
| 45337 | /* cast away const because callback uses const anyway */ |
| 45338 | data: (UA_ValueCallback *)(uintptr_t) &valueBackend); |
| 45339 | break; |
| 45340 | } |
| 45341 | |
| 45342 | |
| 45343 | // UA_StatusCode retval = UA_Server_editNode(server, &server->adminSession, &nodeId, |
| 45344 | // (UA_EditNodeCallback)setValueCallback, |
| 45345 | /* cast away const because callback uses const anyway */ |
| 45346 | // (UA_ValueCallback *)(uintptr_t) &callback); |
| 45347 | |
| 45348 | |
| 45349 | unlockServer(server); |
| 45350 | return retval; |
| 45351 | } |
| 45352 | |
| 45353 | |
| 45354 | /************************************/ |
| 45355 | /* Special Handling of Method Nodes */ |
| 45356 | /************************************/ |
| 45357 | |
| 45358 | #ifdef UA_ENABLE_METHODCALLS |
| 45359 | |
| 45360 | static const UA_NodeId hasproperty = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASPROPERTY}}; |
| 45361 | static const UA_NodeId propertytype = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_PROPERTYTYPE}}; |
| 45362 | |
| 45363 | static UA_StatusCode |
| 45364 | UA_Server_addMethodNodeEx_finish(UA_Server *server, const UA_NodeId nodeId, |
| 45365 | UA_MethodCallback method, |
| 45366 | const size_t inputArgumentsSize, |
| 45367 | const UA_Argument *inputArguments, |
| 45368 | const UA_NodeId inputArgumentsRequestedNewNodeId, |
| 45369 | UA_NodeId *inputArgumentsOutNewNodeId, |
| 45370 | const size_t outputArgumentsSize, |
| 45371 | const UA_Argument *outputArguments, |
| 45372 | const UA_NodeId outputArgumentsRequestedNewNodeId, |
| 45373 | UA_NodeId *outputArgumentsOutNewNodeId) { |
| 45374 | /* Browse to see which argument nodes exist */ |
| 45375 | UA_BrowseDescription bd; |
| 45376 | UA_BrowseDescription_init(p: &bd); |
| 45377 | bd.nodeId = nodeId; |
| 45378 | bd.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY); |
| 45379 | bd.includeSubtypes = false; |
| 45380 | bd.browseDirection = UA_BROWSEDIRECTION_FORWARD; |
| 45381 | bd.nodeClassMask = UA_NODECLASS_VARIABLE; |
| 45382 | bd.resultMask = UA_BROWSERESULTMASK_BROWSENAME; |
| 45383 | |
| 45384 | UA_BrowseResult br; |
| 45385 | UA_BrowseResult_init(p: &br); |
| 45386 | UA_UInt32 maxrefs = 0; |
| 45387 | Operation_Browse(server, session: &server->adminSession, maxrefs: &maxrefs, descr: &bd, result: &br); |
| 45388 | |
| 45389 | UA_StatusCode retval = br.statusCode; |
| 45390 | if(retval != UA_STATUSCODE_GOOD) { |
| 45391 | deleteNode(server, nodeId, true); |
| 45392 | UA_BrowseResult_clear(p: &br); |
| 45393 | return retval; |
| 45394 | } |
| 45395 | |
| 45396 | /* Filter out the argument nodes */ |
| 45397 | UA_NodeId inputArgsId = UA_NODEID_NULL; |
| 45398 | UA_NodeId outputArgsId = UA_NODEID_NULL; |
| 45399 | const UA_QualifiedName inputArgsName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "InputArguments"); |
| 45400 | const UA_QualifiedName outputArgsName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "OutputArguments"); |
| 45401 | for(size_t i = 0; i < br.referencesSize; i++) { |
| 45402 | UA_ReferenceDescription *rd = &br.references[i]; |
| 45403 | if(rd->browseName.namespaceIndex == 0 && |
| 45404 | UA_String_equal(p1: &rd->browseName.name, p2: &inputArgsName.name)) |
| 45405 | inputArgsId = rd->nodeId.nodeId; |
| 45406 | else if(rd->browseName.namespaceIndex == 0 && |
| 45407 | UA_String_equal(p1: &rd->browseName.name, p2: &outputArgsName.name)) |
| 45408 | outputArgsId = rd->nodeId.nodeId; |
| 45409 | } |
| 45410 | |
| 45411 | /* Add the Input Arguments VariableNode */ |
| 45412 | if(inputArgumentsSize > 0 && UA_NodeId_isNull(p: &inputArgsId)) { |
| 45413 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 45414 | char *name = "InputArguments"; |
| 45415 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name); |
| 45416 | attr.dataType = UA_TYPES[UA_TYPES_ARGUMENT].typeId; |
| 45417 | attr.valueRank = UA_VALUERANK_ONE_DIMENSION; |
| 45418 | UA_UInt32 inputArgsSize32 = (UA_UInt32)inputArgumentsSize; |
| 45419 | attr.arrayDimensions = &inputArgsSize32; |
| 45420 | attr.arrayDimensionsSize = 1; |
| 45421 | UA_Variant_setArray(v: &attr.value, array: (void *)(uintptr_t)inputArguments, |
| 45422 | arraySize: inputArgumentsSize, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 45423 | retval = addNode(server, nodeClass: UA_NODECLASS_VARIABLE, requestedNewNodeId: inputArgumentsRequestedNewNodeId, |
| 45424 | parentNodeId: nodeId, referenceTypeId: hasproperty, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name), |
| 45425 | typeDefinition: propertytype, attr: &attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], |
| 45426 | NULL, outNewNodeId: &inputArgsId); |
| 45427 | if(retval != UA_STATUSCODE_GOOD) |
| 45428 | goto error; |
| 45429 | } |
| 45430 | |
| 45431 | /* Add the Output Arguments VariableNode */ |
| 45432 | if(outputArgumentsSize > 0 && UA_NodeId_isNull(p: &outputArgsId)) { |
| 45433 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 45434 | char *name = "OutputArguments"; |
| 45435 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: name); |
| 45436 | attr.dataType = UA_TYPES[UA_TYPES_ARGUMENT].typeId; |
| 45437 | attr.valueRank = UA_VALUERANK_ONE_DIMENSION; |
| 45438 | UA_UInt32 outputArgsSize32 = (UA_UInt32)outputArgumentsSize; |
| 45439 | attr.arrayDimensions = &outputArgsSize32; |
| 45440 | attr.arrayDimensionsSize = 1; |
| 45441 | UA_Variant_setArray(v: &attr.value, array: (void *)(uintptr_t)outputArguments, |
| 45442 | arraySize: outputArgumentsSize, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 45443 | retval = addNode(server, nodeClass: UA_NODECLASS_VARIABLE, requestedNewNodeId: outputArgumentsRequestedNewNodeId, |
| 45444 | parentNodeId: nodeId, referenceTypeId: hasproperty, browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: name), |
| 45445 | typeDefinition: propertytype, attr: &attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], |
| 45446 | NULL, outNewNodeId: &outputArgsId); |
| 45447 | if(retval != UA_STATUSCODE_GOOD) |
| 45448 | goto error; |
| 45449 | } |
| 45450 | |
| 45451 | retval = setMethodNode_callback(server, methodNodeId: nodeId, methodCallback: method); |
| 45452 | if(retval != UA_STATUSCODE_GOOD) |
| 45453 | goto error; |
| 45454 | |
| 45455 | /* Call finish to add the parent reference */ |
| 45456 | retval = addNode_finish(server, session: &server->adminSession, nodeId: &nodeId); |
| 45457 | if(retval != UA_STATUSCODE_GOOD) |
| 45458 | goto error; |
| 45459 | |
| 45460 | if(inputArgumentsOutNewNodeId != NULL) { |
| 45461 | UA_NodeId_copy(src: &inputArgsId, dst: inputArgumentsOutNewNodeId); |
| 45462 | } |
| 45463 | if(outputArgumentsOutNewNodeId != NULL) { |
| 45464 | UA_NodeId_copy(src: &outputArgsId, dst: outputArgumentsOutNewNodeId); |
| 45465 | } |
| 45466 | UA_BrowseResult_clear(p: &br); |
| 45467 | return retval; |
| 45468 | |
| 45469 | error: |
| 45470 | deleteNode(server, nodeId, true); |
| 45471 | deleteNode(server, nodeId: inputArgsId, true); |
| 45472 | deleteNode(server, nodeId: outputArgsId, true); |
| 45473 | UA_BrowseResult_clear(p: &br); |
| 45474 | return retval; |
| 45475 | } |
| 45476 | |
| 45477 | UA_StatusCode |
| 45478 | UA_Server_addMethodNode_finish(UA_Server *server, const UA_NodeId nodeId, |
| 45479 | UA_MethodCallback method, |
| 45480 | size_t inputArgumentsSize, |
| 45481 | const UA_Argument* inputArguments, |
| 45482 | size_t outputArgumentsSize, |
| 45483 | const UA_Argument* outputArguments) { |
| 45484 | lockServer(server); |
| 45485 | UA_StatusCode retval = |
| 45486 | UA_Server_addMethodNodeEx_finish(server, nodeId, method, |
| 45487 | inputArgumentsSize, inputArguments, |
| 45488 | inputArgumentsRequestedNewNodeId: UA_NODEID_NULL, NULL, |
| 45489 | outputArgumentsSize, outputArguments, |
| 45490 | outputArgumentsRequestedNewNodeId: UA_NODEID_NULL, NULL); |
| 45491 | unlockServer(server); |
| 45492 | return retval; |
| 45493 | } |
| 45494 | |
| 45495 | UA_StatusCode |
| 45496 | addMethodNode(UA_Server *server, const UA_NodeId requestedNewNodeId, |
| 45497 | const UA_NodeId parentNodeId, const UA_NodeId referenceTypeId, |
| 45498 | const UA_QualifiedName browseName, |
| 45499 | const UA_MethodAttributes *attr, UA_MethodCallback method, |
| 45500 | size_t inputArgumentsSize, const UA_Argument *inputArguments, |
| 45501 | const UA_NodeId inputArgumentsRequestedNewNodeId, |
| 45502 | UA_NodeId *inputArgumentsOutNewNodeId, |
| 45503 | size_t outputArgumentsSize, const UA_Argument *outputArguments, |
| 45504 | const UA_NodeId outputArgumentsRequestedNewNodeId, |
| 45505 | UA_NodeId *outputArgumentsOutNewNodeId, |
| 45506 | void *nodeContext, UA_NodeId *outNewNodeId) { |
| 45507 | UA_AddNodesItem item; |
| 45508 | UA_AddNodesItem_init(p: &item); |
| 45509 | item.nodeClass = UA_NODECLASS_METHOD; |
| 45510 | item.requestedNewNodeId.nodeId = requestedNewNodeId; |
| 45511 | item.browseName = browseName; |
| 45512 | UA_ExtensionObject_setValueNoDelete(eo: &item.nodeAttributes, p: (void*)(uintptr_t)attr, |
| 45513 | type: &UA_TYPES[UA_TYPES_METHODATTRIBUTES]); |
| 45514 | UA_NodeId newId; |
| 45515 | if(!outNewNodeId) { |
| 45516 | UA_NodeId_init(p: &newId); |
| 45517 | outNewNodeId = &newId; |
| 45518 | } |
| 45519 | UA_StatusCode retval = Operation_addNode_begin(server, session: &server->adminSession, |
| 45520 | nodeContext, item: &item, parentNodeId: &parentNodeId, |
| 45521 | referenceTypeId: &referenceTypeId, outNewNodeId); |
| 45522 | if(retval != UA_STATUSCODE_GOOD) |
| 45523 | return retval; |
| 45524 | |
| 45525 | retval = UA_Server_addMethodNodeEx_finish(server, nodeId: *outNewNodeId, method, |
| 45526 | inputArgumentsSize, inputArguments, |
| 45527 | inputArgumentsRequestedNewNodeId, |
| 45528 | inputArgumentsOutNewNodeId, |
| 45529 | outputArgumentsSize, outputArguments, |
| 45530 | outputArgumentsRequestedNewNodeId, |
| 45531 | outputArgumentsOutNewNodeId); |
| 45532 | if(outNewNodeId == &newId) |
| 45533 | UA_NodeId_clear(p: &newId); |
| 45534 | return retval; |
| 45535 | } |
| 45536 | |
| 45537 | UA_StatusCode |
| 45538 | UA_Server_addMethodNodeEx(UA_Server *server, const UA_NodeId requestedNewNodeId, |
| 45539 | const UA_NodeId parentNodeId, |
| 45540 | const UA_NodeId referenceTypeId, |
| 45541 | const UA_QualifiedName browseName, |
| 45542 | const UA_MethodAttributes attr, UA_MethodCallback method, |
| 45543 | size_t inputArgumentsSize, const UA_Argument *inputArguments, |
| 45544 | const UA_NodeId inputArgumentsRequestedNewNodeId, |
| 45545 | UA_NodeId *inputArgumentsOutNewNodeId, |
| 45546 | size_t outputArgumentsSize, const UA_Argument *outputArguments, |
| 45547 | const UA_NodeId outputArgumentsRequestedNewNodeId, |
| 45548 | UA_NodeId *outputArgumentsOutNewNodeId, |
| 45549 | void *nodeContext, UA_NodeId *outNewNodeId) { |
| 45550 | lockServer(server); |
| 45551 | UA_StatusCode res = addMethodNode(server, requestedNewNodeId, |
| 45552 | parentNodeId, referenceTypeId, |
| 45553 | browseName, attr: &attr, method, |
| 45554 | inputArgumentsSize, inputArguments, |
| 45555 | inputArgumentsRequestedNewNodeId, |
| 45556 | inputArgumentsOutNewNodeId, |
| 45557 | outputArgumentsSize, |
| 45558 | outputArguments, |
| 45559 | outputArgumentsRequestedNewNodeId, |
| 45560 | outputArgumentsOutNewNodeId, |
| 45561 | nodeContext, outNewNodeId); |
| 45562 | unlockServer(server); |
| 45563 | return res; |
| 45564 | } |
| 45565 | |
| 45566 | static UA_StatusCode |
| 45567 | editMethodCallback(UA_Server *server, UA_Session* session, |
| 45568 | UA_Node *node, UA_MethodCallback methodCallback) { |
| 45569 | if(node->head.nodeClass != UA_NODECLASS_METHOD) |
| 45570 | return UA_STATUSCODE_BADNODECLASSINVALID; |
| 45571 | node->methodNode.method = methodCallback; |
| 45572 | return UA_STATUSCODE_GOOD; |
| 45573 | } |
| 45574 | |
| 45575 | UA_StatusCode |
| 45576 | setMethodNode_callback(UA_Server *server, |
| 45577 | const UA_NodeId methodNodeId, |
| 45578 | UA_MethodCallback methodCallback) { |
| 45579 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 45580 | return UA_Server_editNode(server, session: &server->adminSession, nodeId: &methodNodeId, |
| 45581 | callback: (UA_EditNodeCallback)editMethodCallback, |
| 45582 | data: (void*)(uintptr_t)methodCallback); |
| 45583 | } |
| 45584 | |
| 45585 | UA_StatusCode |
| 45586 | UA_Server_setMethodNodeCallback(UA_Server *server, |
| 45587 | const UA_NodeId methodNodeId, |
| 45588 | UA_MethodCallback methodCallback) { |
| 45589 | lockServer(server); |
| 45590 | UA_StatusCode retVal = setMethodNode_callback(server, methodNodeId, methodCallback); |
| 45591 | unlockServer(server); |
| 45592 | return retVal; |
| 45593 | } |
| 45594 | |
| 45595 | UA_StatusCode |
| 45596 | UA_Server_getMethodNodeCallback(UA_Server *server, |
| 45597 | const UA_NodeId methodNodeId, |
| 45598 | UA_MethodCallback *outMethodCallback) { |
| 45599 | lockServer(server); |
| 45600 | const UA_Node *node = UA_NODESTORE_GET(server, nodeId: &methodNodeId); |
| 45601 | if(!node) { |
| 45602 | unlockServer(server); |
| 45603 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 45604 | } |
| 45605 | |
| 45606 | if(node->head.nodeClass != UA_NODECLASS_METHOD) { |
| 45607 | UA_NODESTORE_RELEASE(server, node); |
| 45608 | unlockServer(server); |
| 45609 | return UA_STATUSCODE_BADNODECLASSINVALID; |
| 45610 | } |
| 45611 | |
| 45612 | *outMethodCallback = node->methodNode.method; |
| 45613 | UA_NODESTORE_RELEASE(server, node); |
| 45614 | unlockServer(server); |
| 45615 | return UA_STATUSCODE_GOOD; |
| 45616 | } |
| 45617 | |
| 45618 | #endif |
| 45619 | |
| 45620 | /************************/ |
| 45621 | /* Lifecycle Management */ |
| 45622 | /************************/ |
| 45623 | |
| 45624 | void UA_EXPORT |
| 45625 | UA_Server_setAdminSessionContext(UA_Server *server, |
| 45626 | void *context) { |
| 45627 | server->adminSession.sessionHandle = context; |
| 45628 | } |
| 45629 | |
| 45630 | static UA_StatusCode |
| 45631 | setNodeTypeLifecycleCallback(UA_Server *server, UA_Session *session, |
| 45632 | UA_Node *node, UA_NodeTypeLifecycle *lifecycle) { |
| 45633 | if(node->head.nodeClass == UA_NODECLASS_OBJECTTYPE) { |
| 45634 | node->objectTypeNode.lifecycle = *lifecycle; |
| 45635 | } else if(node->head.nodeClass == UA_NODECLASS_VARIABLETYPE) { |
| 45636 | node->variableTypeNode.lifecycle = *lifecycle; |
| 45637 | } else { |
| 45638 | return UA_STATUSCODE_BADNODECLASSINVALID; |
| 45639 | } |
| 45640 | return UA_STATUSCODE_GOOD; |
| 45641 | } |
| 45642 | |
| 45643 | UA_StatusCode |
| 45644 | setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId, |
| 45645 | UA_NodeTypeLifecycle lifecycle) { |
| 45646 | return UA_Server_editNode(server, session: &server->adminSession, nodeId: &nodeId, |
| 45647 | callback: (UA_EditNodeCallback)setNodeTypeLifecycleCallback, |
| 45648 | data: &lifecycle); |
| 45649 | } |
| 45650 | |
| 45651 | UA_StatusCode |
| 45652 | UA_Server_setNodeTypeLifecycle(UA_Server *server, UA_NodeId nodeId, |
| 45653 | UA_NodeTypeLifecycle lifecycle) { |
| 45654 | lockServer(server); |
| 45655 | UA_StatusCode retval = setNodeTypeLifecycle(server, nodeId, lifecycle); |
| 45656 | unlockServer(server); |
| 45657 | return retval; |
| 45658 | } |
| 45659 | |
| 45660 | /**** amalgamated original file "/src/pubsub/ua_pubsub_networkmessage.c" ****/ |
| 45661 | |
| 45662 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 45663 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 45664 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 45665 | * |
| 45666 | * Copyright (c) 2017 - 2018 Fraunhofer IOSB (Author: Tino Bischoff) |
| 45667 | * Copyright (c) 2019 Fraunhofer IOSB (Author: Andreas Ebner) |
| 45668 | */ |
| 45669 | |
| 45670 | |
| 45671 | |
| 45672 | #ifdef UA_ENABLE_PUBSUB /* conditional compilation */ |
| 45673 | |
| 45674 | const UA_Byte NM_VERSION_MASK = 15; |
| 45675 | const UA_Byte NM_PUBLISHER_ID_ENABLED_MASK = 16; |
| 45676 | const UA_Byte NM_GROUP_HEADER_ENABLED_MASK = 32; |
| 45677 | const UA_Byte NM_PAYLOAD_HEADER_ENABLED_MASK = 64; |
| 45678 | const UA_Byte NM_EXTENDEDFLAGS1_ENABLED_MASK = 128; |
| 45679 | const UA_Byte NM_PUBLISHER_ID_MASK = 7; |
| 45680 | const UA_Byte NM_DATASET_CLASSID_ENABLED_MASK = 8; |
| 45681 | const UA_Byte NM_SECURITY_ENABLED_MASK = 16; |
| 45682 | const UA_Byte NM_TIMESTAMP_ENABLED_MASK = 32; |
| 45683 | const UA_Byte NM_PICOSECONDS_ENABLED_MASK = 64; |
| 45684 | const UA_Byte NM_EXTENDEDFLAGS2_ENABLED_MASK = 128; |
| 45685 | const UA_Byte NM_NETWORK_MSG_TYPE_MASK = 28; |
| 45686 | const UA_Byte NM_CHUNK_MESSAGE_MASK = 1; |
| 45687 | const UA_Byte NM_PROMOTEDFIELDS_ENABLED_MASK = 2; |
| 45688 | const UA_Byte GROUP_HEADER_WRITER_GROUPID_ENABLED = 1; |
| 45689 | const UA_Byte GROUP_HEADER_GROUP_VERSION_ENABLED = 2; |
| 45690 | const UA_Byte GROUP_HEADER_NM_NUMBER_ENABLED = 4; |
| 45691 | const UA_Byte GROUP_HEADER_SEQUENCE_NUMBER_ENABLED = 8; |
| 45692 | const UA_Byte SECURITY_HEADER_NM_SIGNED = 1; |
| 45693 | const UA_Byte SECURITY_HEADER_NM_ENCRYPTED = 2; |
| 45694 | const UA_Byte SECURITY_HEADER_SEC_FOOTER_ENABLED = 4; |
| 45695 | const UA_Byte SECURITY_HEADER_FORCE_KEY_RESET = 8; |
| 45696 | const UA_Byte DS_MESSAGEHEADER_DS_MSG_VALID = 1; |
| 45697 | const UA_Byte DS_MESSAGEHEADER_FIELD_ENCODING_MASK = 6; |
| 45698 | const UA_Byte DS_MESSAGEHEADER_SEQ_NR_ENABLED_MASK = 8; |
| 45699 | const UA_Byte DS_MESSAGEHEADER_STATUS_ENABLED_MASK = 16; |
| 45700 | const UA_Byte DS_MESSAGEHEADER_CONFIGMAJORVERSION_ENABLED_MASK = 32; |
| 45701 | const UA_Byte DS_MESSAGEHEADER_CONFIGMINORVERSION_ENABLED_MASK = 64; |
| 45702 | const UA_Byte DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK = 128; |
| 45703 | const UA_Byte DS_MESSAGEHEADER_DS_MESSAGE_TYPE_MASK = 15; |
| 45704 | const UA_Byte DS_MESSAGEHEADER_TIMESTAMP_ENABLED_MASK = 16; |
| 45705 | const UA_Byte DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK = 32; |
| 45706 | const UA_Byte NM_SHIFT_LEN = 2; |
| 45707 | const UA_Byte DS_MH_SHIFT_LEN = 1; |
| 45708 | |
| 45709 | static UA_Boolean UA_NetworkMessage_ExtendedFlags1Enabled(const UA_NetworkMessage* src); |
| 45710 | static UA_Boolean UA_NetworkMessage_ExtendedFlags2Enabled(const UA_NetworkMessage* src); |
| 45711 | static UA_Boolean UA_DataSetMessageHeader_DataSetFlags2Enabled(const UA_DataSetMessageHeader* src); |
| 45712 | |
| 45713 | UA_StatusCode |
| 45714 | UA_NetworkMessage_updateBufferedMessage(UA_NetworkMessageOffsetBuffer *buffer) { |
| 45715 | UA_StatusCode rv = UA_STATUSCODE_GOOD; |
| 45716 | const UA_Byte *bufEnd = &buffer->buffer.data[buffer->buffer.length]; |
| 45717 | for(size_t i = 0; i < buffer->offsetsSize; ++i) { |
| 45718 | UA_NetworkMessageOffset *nmo = &buffer->offsets[i]; |
| 45719 | UA_Byte *bufPos = &buffer->buffer.data[nmo->offset]; |
| 45720 | switch(nmo->contentType) { |
| 45721 | case UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER: |
| 45722 | case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER: |
| 45723 | rv = UA_UInt16_encodeBinary(src: &nmo->content.sequenceNumber, bufPos: &bufPos, bufEnd); |
| 45724 | nmo->content.sequenceNumber++; |
| 45725 | break; |
| 45726 | case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE: |
| 45727 | rv = UA_DataValue_encodeBinary(src: &nmo->content.value, bufPos: &bufPos, bufEnd); |
| 45728 | break; |
| 45729 | case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE_EXTERNAL: |
| 45730 | rv = UA_DataValue_encodeBinary(src: *nmo->content.externalValue, bufPos: &bufPos, bufEnd); |
| 45731 | break; |
| 45732 | case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT: |
| 45733 | rv = UA_Variant_encodeBinary(src: &nmo->content.value.value, bufPos: &bufPos, bufEnd); |
| 45734 | break; |
| 45735 | case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT_EXTERNAL: |
| 45736 | rv = UA_Variant_encodeBinary(src: &(*nmo->content.externalValue)->value, bufPos: &bufPos, bufEnd); |
| 45737 | break; |
| 45738 | case UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW: |
| 45739 | rv = UA_encodeBinaryInternal(src: nmo->content.value.value.data, |
| 45740 | type: nmo->content.value.value.type, |
| 45741 | bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 45742 | break; |
| 45743 | case UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW_EXTERNAL: |
| 45744 | rv = UA_encodeBinaryInternal(src: (*nmo->content.externalValue)->value.data, |
| 45745 | type: (*nmo->content.externalValue)->value.type, |
| 45746 | bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 45747 | break; |
| 45748 | default: |
| 45749 | break; /* The other fields are assumed to not change between messages. |
| 45750 | * Only used for RT decoding (not encoding). */ |
| 45751 | } |
| 45752 | } |
| 45753 | return rv; |
| 45754 | } |
| 45755 | |
| 45756 | UA_StatusCode |
| 45757 | UA_NetworkMessage_updateBufferedNwMessage(UA_NetworkMessageOffsetBuffer *buffer, |
| 45758 | const UA_ByteString *src, size_t *bufferPosition) { |
| 45759 | /* The offset buffer was not prepared */ |
| 45760 | UA_NetworkMessage *nm = buffer->nm; |
| 45761 | if(!nm) |
| 45762 | return UA_STATUSCODE_BADINTERNALERROR; |
| 45763 | |
| 45764 | /* The source string is too short */ |
| 45765 | if(src->length < buffer->buffer.length + *bufferPosition) |
| 45766 | return UA_STATUSCODE_BADDECODINGERROR; |
| 45767 | |
| 45768 | /* If this remains at UA_UINT32_MAX, then no raw fields are contained */ |
| 45769 | size_t smallestRawOffset = UA_UINT32_MAX; |
| 45770 | |
| 45771 | /* Considering one DSM in RT TODO: Clarify multiple DSM */ |
| 45772 | UA_DataSetMessage* dsm = nm->payload.dataSetPayload.dataSetMessages; |
| 45773 | |
| 45774 | size_t pos = 0; |
| 45775 | size_t payloadCounter = 0; |
| 45776 | UA_DataSetMessageHeader header; |
| 45777 | UA_StatusCode rv = UA_STATUSCODE_GOOD; |
| 45778 | for(size_t i = 0; i < buffer->offsetsSize; ++i) { |
| 45779 | pos = buffer->offsets[i].offset + *bufferPosition; |
| 45780 | switch(buffer->offsets[i].contentType) { |
| 45781 | case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING: |
| 45782 | rv = UA_DataSetMessageHeader_decodeBinary(src, offset: &pos, dst: &header); |
| 45783 | break; |
| 45784 | case UA_PUBSUB_OFFSETTYPE_PUBLISHERID: |
| 45785 | switch(nm->publisherIdType) { |
| 45786 | case UA_PUBLISHERIDTYPE_BYTE: |
| 45787 | rv = UA_Byte_decodeBinary(src, offset: &pos, dst: &nm->publisherId.byte); |
| 45788 | break; |
| 45789 | case UA_PUBLISHERIDTYPE_UINT16: |
| 45790 | rv = UA_UInt16_decodeBinary(src, offset: &pos, dst: &nm->publisherId.uint16); |
| 45791 | break; |
| 45792 | case UA_PUBLISHERIDTYPE_UINT32: |
| 45793 | rv = UA_UInt32_decodeBinary(src, offset: &pos, dst: &nm->publisherId.uint32); |
| 45794 | break; |
| 45795 | case UA_PUBLISHERIDTYPE_UINT64: |
| 45796 | rv = UA_UInt64_decodeBinary(src, offset: &pos, dst: &nm->publisherId.uint64); |
| 45797 | break; |
| 45798 | default: |
| 45799 | /* UA_PUBLISHERIDTYPE_STRING is not supported because of |
| 45800 | * UA_PUBSUB_RT_FIXED_SIZE */ |
| 45801 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 45802 | } |
| 45803 | break; |
| 45804 | case UA_PUBSUB_OFFSETTYPE_WRITERGROUPID: |
| 45805 | rv = UA_UInt16_decodeBinary(src, offset: &pos, dst: &nm->groupHeader.writerGroupId); |
| 45806 | break; |
| 45807 | case UA_PUBSUB_OFFSETTYPE_DATASETWRITERID: |
| 45808 | rv = UA_UInt16_decodeBinary(src, offset: &pos, |
| 45809 | dst: &nm->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[0]); /* TODO */ |
| 45810 | break; |
| 45811 | case UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER: |
| 45812 | rv = UA_UInt16_decodeBinary(src, offset: &pos, dst: &nm->groupHeader.sequenceNumber); |
| 45813 | break; |
| 45814 | case UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER: |
| 45815 | rv = UA_UInt16_decodeBinary(src, offset: &pos, dst: &dsm->header.dataSetMessageSequenceNr); |
| 45816 | break; |
| 45817 | case UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE: |
| 45818 | UA_DataValue_clear(p: &dsm->data.keyFrameData.dataSetFields[payloadCounter]); |
| 45819 | rv = UA_DataValue_decodeBinary(src, offset: &pos, |
| 45820 | dst: &dsm->data.keyFrameData.dataSetFields[payloadCounter]); |
| 45821 | payloadCounter++; |
| 45822 | break; |
| 45823 | case UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT: |
| 45824 | UA_Variant_clear(p: &dsm->data.keyFrameData.dataSetFields[payloadCounter].value); |
| 45825 | rv = UA_Variant_decodeBinary(src, offset: &pos, |
| 45826 | dst: &dsm->data.keyFrameData.dataSetFields[payloadCounter].value); |
| 45827 | dsm->data.keyFrameData.dataSetFields[payloadCounter].hasValue = |
| 45828 | (rv == UA_STATUSCODE_GOOD); |
| 45829 | payloadCounter++; |
| 45830 | break; |
| 45831 | case UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW: |
| 45832 | /* We need only the start address of the raw fields */ |
| 45833 | if(smallestRawOffset > pos){ |
| 45834 | smallestRawOffset = pos; |
| 45835 | dsm->data.keyFrameData.rawFields.data = &src->data[pos]; |
| 45836 | dsm->data.keyFrameData.rawFields.length = buffer->rawMessageLength; |
| 45837 | } |
| 45838 | payloadCounter++; |
| 45839 | break; |
| 45840 | default: |
| 45841 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 45842 | } |
| 45843 | UA_CHECK_STATUS(rv, return rv); |
| 45844 | } |
| 45845 | |
| 45846 | /* Check if the frame is of type "raw" payload. If yes, set the new buffer |
| 45847 | * position to the start position of the raw fields plus the length of the |
| 45848 | * raw fields. */ |
| 45849 | if(smallestRawOffset != UA_UINT32_MAX) { |
| 45850 | *bufferPosition = smallestRawOffset + buffer->rawMessageLength; |
| 45851 | } else { |
| 45852 | *bufferPosition = pos; |
| 45853 | } |
| 45854 | |
| 45855 | return rv; |
| 45856 | } |
| 45857 | |
| 45858 | static UA_StatusCode |
| 45859 | UA_NetworkMessageHeader_encodeBinary(const UA_NetworkMessage *src, UA_Byte **bufPos, |
| 45860 | const UA_Byte *bufEnd) { |
| 45861 | /* UADPVersion + UADP Flags */ |
| 45862 | UA_Byte v = src->version; |
| 45863 | if(src->publisherIdEnabled) |
| 45864 | v |= NM_PUBLISHER_ID_ENABLED_MASK; |
| 45865 | |
| 45866 | if(src->groupHeaderEnabled) |
| 45867 | v |= NM_GROUP_HEADER_ENABLED_MASK; |
| 45868 | |
| 45869 | if(src->payloadHeaderEnabled) |
| 45870 | v |= NM_PAYLOAD_HEADER_ENABLED_MASK; |
| 45871 | |
| 45872 | if(UA_NetworkMessage_ExtendedFlags1Enabled(src)) |
| 45873 | v |= NM_EXTENDEDFLAGS1_ENABLED_MASK; |
| 45874 | |
| 45875 | UA_StatusCode rv = UA_Byte_encodeBinary(src: &v, bufPos, bufEnd); |
| 45876 | UA_CHECK_STATUS(rv, return rv); |
| 45877 | // ExtendedFlags1 |
| 45878 | if(UA_NetworkMessage_ExtendedFlags1Enabled(src)) { |
| 45879 | v = (UA_Byte)src->publisherIdType; |
| 45880 | |
| 45881 | if(src->dataSetClassIdEnabled) |
| 45882 | v |= NM_DATASET_CLASSID_ENABLED_MASK; |
| 45883 | |
| 45884 | if(src->securityEnabled) |
| 45885 | v |= NM_SECURITY_ENABLED_MASK; |
| 45886 | |
| 45887 | if(src->timestampEnabled) |
| 45888 | v |= NM_TIMESTAMP_ENABLED_MASK; |
| 45889 | |
| 45890 | if(src->picosecondsEnabled) |
| 45891 | v |= NM_PICOSECONDS_ENABLED_MASK; |
| 45892 | |
| 45893 | if(UA_NetworkMessage_ExtendedFlags2Enabled(src)) |
| 45894 | v |= NM_EXTENDEDFLAGS2_ENABLED_MASK; |
| 45895 | |
| 45896 | rv = UA_Byte_encodeBinary(src: &v, bufPos, bufEnd); |
| 45897 | UA_CHECK_STATUS(rv, return rv); |
| 45898 | |
| 45899 | // ExtendedFlags2 |
| 45900 | if(UA_NetworkMessage_ExtendedFlags2Enabled(src)) { |
| 45901 | v = (UA_Byte)src->networkMessageType; |
| 45902 | // shift left 2 bit |
| 45903 | v = (UA_Byte) (v << NM_SHIFT_LEN); |
| 45904 | |
| 45905 | if(src->chunkMessage) |
| 45906 | v |= NM_CHUNK_MESSAGE_MASK; |
| 45907 | |
| 45908 | if(src->promotedFieldsEnabled) |
| 45909 | v |= NM_PROMOTEDFIELDS_ENABLED_MASK; |
| 45910 | |
| 45911 | rv = UA_Byte_encodeBinary(src: &v, bufPos, bufEnd); |
| 45912 | UA_CHECK_STATUS(rv, return rv); |
| 45913 | } |
| 45914 | } |
| 45915 | |
| 45916 | // PublisherId |
| 45917 | if(src->publisherIdEnabled) { |
| 45918 | switch (src->publisherIdType) { |
| 45919 | case UA_PUBLISHERIDTYPE_BYTE: |
| 45920 | rv = UA_Byte_encodeBinary(src: &src->publisherId.byte, bufPos, bufEnd); |
| 45921 | break; |
| 45922 | |
| 45923 | case UA_PUBLISHERIDTYPE_UINT16: |
| 45924 | rv = UA_UInt16_encodeBinary(src: &src->publisherId.uint16, bufPos, bufEnd); |
| 45925 | break; |
| 45926 | |
| 45927 | case UA_PUBLISHERIDTYPE_UINT32: |
| 45928 | rv = UA_UInt32_encodeBinary(src: &src->publisherId.uint32, bufPos, bufEnd); |
| 45929 | break; |
| 45930 | |
| 45931 | case UA_PUBLISHERIDTYPE_UINT64: |
| 45932 | rv = UA_UInt64_encodeBinary(src: &src->publisherId.uint64, bufPos, bufEnd); |
| 45933 | break; |
| 45934 | |
| 45935 | case UA_PUBLISHERIDTYPE_STRING: |
| 45936 | rv = UA_String_encodeBinary(src: &src->publisherId.string, bufPos, bufEnd); |
| 45937 | break; |
| 45938 | |
| 45939 | default: |
| 45940 | rv = UA_STATUSCODE_BADINTERNALERROR; |
| 45941 | break; |
| 45942 | } |
| 45943 | UA_CHECK_STATUS(rv, return rv); |
| 45944 | } |
| 45945 | |
| 45946 | // DataSetClassId |
| 45947 | if(src->dataSetClassIdEnabled) { |
| 45948 | rv = UA_Guid_encodeBinary(src: &src->dataSetClassId, bufPos, bufEnd); |
| 45949 | UA_CHECK_STATUS(rv, return rv); |
| 45950 | } |
| 45951 | return UA_STATUSCODE_GOOD; |
| 45952 | } |
| 45953 | |
| 45954 | static UA_StatusCode |
| 45955 | UA_GroupHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos, |
| 45956 | const UA_Byte *bufEnd) { |
| 45957 | UA_Byte v = 0; |
| 45958 | if(src->groupHeader.writerGroupIdEnabled) |
| 45959 | v |= GROUP_HEADER_WRITER_GROUPID_ENABLED; |
| 45960 | |
| 45961 | if(src->groupHeader.groupVersionEnabled) |
| 45962 | v |= GROUP_HEADER_GROUP_VERSION_ENABLED; |
| 45963 | |
| 45964 | if(src->groupHeader.networkMessageNumberEnabled) |
| 45965 | v |= GROUP_HEADER_NM_NUMBER_ENABLED; |
| 45966 | |
| 45967 | if(src->groupHeader.sequenceNumberEnabled) |
| 45968 | v |= GROUP_HEADER_SEQUENCE_NUMBER_ENABLED; |
| 45969 | |
| 45970 | UA_StatusCode rv = UA_Byte_encodeBinary(src: &v, bufPos, bufEnd); |
| 45971 | |
| 45972 | if(src->groupHeader.writerGroupIdEnabled) |
| 45973 | rv |= UA_UInt16_encodeBinary(src: &src->groupHeader.writerGroupId, bufPos, bufEnd); |
| 45974 | |
| 45975 | if(src->groupHeader.groupVersionEnabled) |
| 45976 | rv |= UA_UInt32_encodeBinary(src: &src->groupHeader.groupVersion, bufPos, bufEnd); |
| 45977 | |
| 45978 | if(src->groupHeader.networkMessageNumberEnabled) |
| 45979 | rv |= UA_UInt16_encodeBinary(src: &src->groupHeader.networkMessageNumber, bufPos, bufEnd); |
| 45980 | |
| 45981 | if(src->groupHeader.sequenceNumberEnabled) |
| 45982 | rv |= UA_UInt16_encodeBinary(src: &src->groupHeader.sequenceNumber, bufPos, bufEnd); |
| 45983 | |
| 45984 | return rv; |
| 45985 | } |
| 45986 | |
| 45987 | static UA_StatusCode |
| 45988 | UA_PayloadHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos, |
| 45989 | const UA_Byte *bufEnd) { |
| 45990 | if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET) |
| 45991 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 45992 | |
| 45993 | if(src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds == NULL) |
| 45994 | return UA_STATUSCODE_BADENCODINGERROR; |
| 45995 | |
| 45996 | UA_Byte count = src->payloadHeader.dataSetPayloadHeader.count; |
| 45997 | |
| 45998 | UA_StatusCode rv = UA_Byte_encodeBinary(src: &count, bufPos, bufEnd); |
| 45999 | |
| 46000 | for(UA_Byte i = 0; i < count; i++) { |
| 46001 | UA_UInt16 dswId = src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i]; |
| 46002 | rv |= UA_UInt16_encodeBinary(src: &dswId, bufPos, bufEnd); |
| 46003 | } |
| 46004 | |
| 46005 | return rv; |
| 46006 | } |
| 46007 | |
| 46008 | static UA_StatusCode |
| 46009 | UA_ExtendedNetworkMessageHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos, |
| 46010 | const UA_Byte *bufEnd) { |
| 46011 | UA_StatusCode rv = UA_STATUSCODE_GOOD; |
| 46012 | if(src->timestampEnabled) |
| 46013 | rv |= UA_DateTime_encodeBinary(src: &src->timestamp, bufPos, bufEnd); |
| 46014 | |
| 46015 | if(src->picosecondsEnabled) |
| 46016 | rv |= UA_UInt16_encodeBinary(src: &src->picoseconds, bufPos, bufEnd); |
| 46017 | |
| 46018 | if(src->promotedFieldsEnabled) { |
| 46019 | /* Size (calculate & encode) */ |
| 46020 | UA_UInt16 pfSize = 0; |
| 46021 | for(UA_UInt16 i = 0; i < src->promotedFieldsSize; i++) |
| 46022 | pfSize = (UA_UInt16)(pfSize + UA_Variant_calcSizeBinary(src: &src->promotedFields[i])); |
| 46023 | rv |= UA_UInt16_encodeBinary(src: &pfSize, bufPos, bufEnd); |
| 46024 | |
| 46025 | for(UA_UInt16 i = 0; i < src->promotedFieldsSize; i++) |
| 46026 | rv |= UA_Variant_encodeBinary(src: &src->promotedFields[i], bufPos, bufEnd); |
| 46027 | } |
| 46028 | |
| 46029 | return rv; |
| 46030 | } |
| 46031 | |
| 46032 | static UA_StatusCode |
| 46033 | UA_SecurityHeader_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos, |
| 46034 | const UA_Byte *bufEnd) { |
| 46035 | /* SecurityFlags */ |
| 46036 | UA_Byte v = 0; |
| 46037 | if(src->securityHeader.networkMessageSigned) |
| 46038 | v |= SECURITY_HEADER_NM_SIGNED; |
| 46039 | |
| 46040 | if(src->securityHeader.networkMessageEncrypted) |
| 46041 | v |= SECURITY_HEADER_NM_ENCRYPTED; |
| 46042 | |
| 46043 | if(src->securityHeader.securityFooterEnabled) |
| 46044 | v |= SECURITY_HEADER_SEC_FOOTER_ENABLED; |
| 46045 | |
| 46046 | if(src->securityHeader.forceKeyReset) |
| 46047 | v |= SECURITY_HEADER_FORCE_KEY_RESET; |
| 46048 | |
| 46049 | UA_StatusCode rv = UA_Byte_encodeBinary(src: &v, bufPos, bufEnd); |
| 46050 | |
| 46051 | /* SecurityTokenId */ |
| 46052 | rv |= UA_UInt32_encodeBinary(src: &src->securityHeader.securityTokenId, bufPos, bufEnd); |
| 46053 | |
| 46054 | /* NonceLength */ |
| 46055 | UA_Byte nonceLength = (UA_Byte)src->securityHeader.messageNonceSize; |
| 46056 | rv |= UA_Byte_encodeBinary(src: &nonceLength, bufPos, bufEnd); |
| 46057 | |
| 46058 | /* MessageNonce */ |
| 46059 | for(size_t i = 0; i < src->securityHeader.messageNonceSize; i++) { |
| 46060 | rv |= UA_Byte_encodeBinary(src: &src->securityHeader.messageNonce[i], |
| 46061 | bufPos, bufEnd); |
| 46062 | } |
| 46063 | |
| 46064 | /* SecurityFooterSize */ |
| 46065 | if(src->securityHeader.securityFooterEnabled) { |
| 46066 | rv |= UA_UInt16_encodeBinary(src: &src->securityHeader.securityFooterSize, |
| 46067 | bufPos, bufEnd); |
| 46068 | } |
| 46069 | |
| 46070 | return rv; |
| 46071 | } |
| 46072 | |
| 46073 | UA_StatusCode |
| 46074 | UA_NetworkMessage_encodeHeaders(const UA_NetworkMessage* src, UA_Byte **bufPos, |
| 46075 | const UA_Byte *bufEnd) { |
| 46076 | /* Message Header */ |
| 46077 | UA_StatusCode rv = UA_NetworkMessageHeader_encodeBinary(src, bufPos, bufEnd); |
| 46078 | |
| 46079 | /* Group Header */ |
| 46080 | if(src->groupHeaderEnabled) |
| 46081 | rv |= UA_GroupHeader_encodeBinary(src, bufPos, bufEnd); |
| 46082 | |
| 46083 | /* Payload Header */ |
| 46084 | if(src->payloadHeaderEnabled) |
| 46085 | rv |= UA_PayloadHeader_encodeBinary(src, bufPos, bufEnd); |
| 46086 | |
| 46087 | /* Extended Network Message Header */ |
| 46088 | rv |= UA_ExtendedNetworkMessageHeader_encodeBinary(src, bufPos, bufEnd); |
| 46089 | |
| 46090 | /* SecurityHeader */ |
| 46091 | if(src->securityEnabled) |
| 46092 | rv |= UA_SecurityHeader_encodeBinary(src, bufPos, bufEnd); |
| 46093 | |
| 46094 | return rv; |
| 46095 | } |
| 46096 | |
| 46097 | |
| 46098 | UA_StatusCode |
| 46099 | UA_NetworkMessage_encodePayload(const UA_NetworkMessage* src, UA_Byte **bufPos, |
| 46100 | const UA_Byte *bufEnd) { |
| 46101 | UA_StatusCode rv; |
| 46102 | |
| 46103 | // Payload |
| 46104 | if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET) |
| 46105 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 46106 | |
| 46107 | UA_Byte count = 1; |
| 46108 | |
| 46109 | if(src->payloadHeaderEnabled) { |
| 46110 | count = src->payloadHeader.dataSetPayloadHeader.count; |
| 46111 | if(count > 1) { |
| 46112 | for(UA_Byte i = 0; i < count; i++) { |
| 46113 | /* Calculate the size, if not specified */ |
| 46114 | UA_UInt16 sz = 0; |
| 46115 | if((src->payload.dataSetPayload.sizes != NULL) && |
| 46116 | (src->payload.dataSetPayload.sizes[i] != 0)) { |
| 46117 | sz = src->payload.dataSetPayload.sizes[i]; |
| 46118 | } else { |
| 46119 | UA_DataSetMessage *dsm = &src->payload.dataSetPayload.dataSetMessages[i]; |
| 46120 | sz = (UA_UInt16)UA_DataSetMessage_calcSizeBinary(p: dsm, NULL, currentOffset: 0); |
| 46121 | } |
| 46122 | |
| 46123 | rv = UA_UInt16_encodeBinary(src: &sz, bufPos, bufEnd); |
| 46124 | UA_CHECK_STATUS(rv, return rv); |
| 46125 | } |
| 46126 | } |
| 46127 | } |
| 46128 | |
| 46129 | for(UA_Byte i = 0; i < count; i++) { |
| 46130 | UA_DataSetMessage *dsm = &src->payload.dataSetPayload.dataSetMessages[i]; |
| 46131 | rv = UA_DataSetMessage_encodeBinary(src: dsm, bufPos, bufEnd); |
| 46132 | UA_CHECK_STATUS(rv, return rv); |
| 46133 | } |
| 46134 | |
| 46135 | return UA_STATUSCODE_GOOD; |
| 46136 | } |
| 46137 | |
| 46138 | UA_StatusCode |
| 46139 | UA_NetworkMessage_encodeFooters(const UA_NetworkMessage* src, UA_Byte **bufPos, |
| 46140 | const UA_Byte *bufEnd) { |
| 46141 | UA_StatusCode rv = UA_STATUSCODE_GOOD; |
| 46142 | if(src->securityEnabled && |
| 46143 | src->securityHeader.securityFooterEnabled) { |
| 46144 | for(size_t i = 0; i < src->securityHeader.securityFooterSize; i++) { |
| 46145 | rv |= UA_Byte_encodeBinary(src: &src->securityFooter.data[i], bufPos, bufEnd); |
| 46146 | } |
| 46147 | } |
| 46148 | return rv; |
| 46149 | } |
| 46150 | |
| 46151 | UA_StatusCode |
| 46152 | UA_NetworkMessage_encodeBinary(const UA_NetworkMessage* src, UA_Byte **bufPos, |
| 46153 | const UA_Byte *bufEnd, UA_Byte **dataToEncryptStart) { |
| 46154 | UA_StatusCode rv = UA_NetworkMessage_encodeHeaders(src, bufPos, bufEnd); |
| 46155 | |
| 46156 | if(dataToEncryptStart) |
| 46157 | *dataToEncryptStart = *bufPos; |
| 46158 | |
| 46159 | rv |= UA_NetworkMessage_encodePayload(src, bufPos, bufEnd); |
| 46160 | rv |= UA_NetworkMessage_encodeFooters(src, bufPos, bufEnd); |
| 46161 | return rv; |
| 46162 | } |
| 46163 | |
| 46164 | UA_StatusCode |
| 46165 | UA_NetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) { |
| 46166 | UA_Byte decoded = 0; |
| 46167 | UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, dst: &decoded); |
| 46168 | UA_CHECK_STATUS(rv, return rv); |
| 46169 | |
| 46170 | dst->version = decoded & NM_VERSION_MASK; |
| 46171 | |
| 46172 | if((decoded & NM_PUBLISHER_ID_ENABLED_MASK) != 0) |
| 46173 | dst->publisherIdEnabled = true; |
| 46174 | |
| 46175 | if((decoded & NM_GROUP_HEADER_ENABLED_MASK) != 0) |
| 46176 | dst->groupHeaderEnabled = true; |
| 46177 | |
| 46178 | if((decoded & NM_PAYLOAD_HEADER_ENABLED_MASK) != 0) |
| 46179 | dst->payloadHeaderEnabled = true; |
| 46180 | |
| 46181 | if((decoded & NM_EXTENDEDFLAGS1_ENABLED_MASK) != 0) { |
| 46182 | decoded = 0; |
| 46183 | rv = UA_Byte_decodeBinary(src, offset, dst: &decoded); |
| 46184 | UA_CHECK_STATUS(rv, return rv); |
| 46185 | |
| 46186 | dst->publisherIdType = (UA_PublisherIdType)(decoded & NM_PUBLISHER_ID_MASK); |
| 46187 | if((decoded & NM_DATASET_CLASSID_ENABLED_MASK) != 0) |
| 46188 | dst->dataSetClassIdEnabled = true; |
| 46189 | |
| 46190 | if((decoded & NM_SECURITY_ENABLED_MASK) != 0) |
| 46191 | dst->securityEnabled = true; |
| 46192 | |
| 46193 | if((decoded & NM_TIMESTAMP_ENABLED_MASK) != 0) |
| 46194 | dst->timestampEnabled = true; |
| 46195 | |
| 46196 | if((decoded & NM_PICOSECONDS_ENABLED_MASK) != 0) |
| 46197 | dst->picosecondsEnabled = true; |
| 46198 | |
| 46199 | if((decoded & NM_EXTENDEDFLAGS2_ENABLED_MASK) != 0) { |
| 46200 | decoded = 0; |
| 46201 | rv = UA_Byte_decodeBinary(src, offset, dst: &decoded); |
| 46202 | UA_CHECK_STATUS(rv, return rv); |
| 46203 | |
| 46204 | if((decoded & NM_CHUNK_MESSAGE_MASK) != 0) |
| 46205 | dst->chunkMessage = true; |
| 46206 | |
| 46207 | if((decoded & NM_PROMOTEDFIELDS_ENABLED_MASK) != 0) |
| 46208 | dst->promotedFieldsEnabled = true; |
| 46209 | |
| 46210 | decoded = decoded & NM_NETWORK_MSG_TYPE_MASK; |
| 46211 | decoded = (UA_Byte) (decoded >> NM_SHIFT_LEN); |
| 46212 | dst->networkMessageType = (UA_NetworkMessageType)decoded; |
| 46213 | } |
| 46214 | } |
| 46215 | |
| 46216 | if(dst->publisherIdEnabled) { |
| 46217 | switch (dst->publisherIdType) { |
| 46218 | case UA_PUBLISHERIDTYPE_BYTE: |
| 46219 | rv = UA_Byte_decodeBinary(src, offset, dst: &dst->publisherId.byte); |
| 46220 | break; |
| 46221 | |
| 46222 | case UA_PUBLISHERIDTYPE_UINT16: |
| 46223 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->publisherId.uint16); |
| 46224 | break; |
| 46225 | |
| 46226 | case UA_PUBLISHERIDTYPE_UINT32: |
| 46227 | rv = UA_UInt32_decodeBinary(src, offset, dst: &dst->publisherId.uint32); |
| 46228 | break; |
| 46229 | |
| 46230 | case UA_PUBLISHERIDTYPE_UINT64: |
| 46231 | rv = UA_UInt64_decodeBinary(src, offset, dst: &dst->publisherId.uint64); |
| 46232 | break; |
| 46233 | |
| 46234 | case UA_PUBLISHERIDTYPE_STRING: |
| 46235 | rv = UA_String_decodeBinary(src, offset, dst: &dst->publisherId.string); |
| 46236 | break; |
| 46237 | |
| 46238 | default: |
| 46239 | rv = UA_STATUSCODE_BADINTERNALERROR; |
| 46240 | break; |
| 46241 | } |
| 46242 | UA_CHECK_STATUS(rv, return rv); |
| 46243 | } |
| 46244 | |
| 46245 | if(dst->dataSetClassIdEnabled) { |
| 46246 | rv = UA_Guid_decodeBinary(src, offset, dst: &dst->dataSetClassId); |
| 46247 | UA_CHECK_STATUS(rv, return rv); |
| 46248 | } |
| 46249 | return UA_STATUSCODE_GOOD; |
| 46250 | } |
| 46251 | |
| 46252 | static UA_StatusCode |
| 46253 | UA_GroupHeader_decodeBinary(const UA_ByteString *src, size_t *offset, |
| 46254 | UA_NetworkMessage* dst) { |
| 46255 | UA_Byte decoded = 0; |
| 46256 | UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, dst: &decoded); |
| 46257 | |
| 46258 | if((decoded & GROUP_HEADER_WRITER_GROUPID_ENABLED) != 0) { |
| 46259 | dst->groupHeader.writerGroupIdEnabled = true; |
| 46260 | rv |= UA_UInt16_decodeBinary(src, offset, dst: &dst->groupHeader.writerGroupId); |
| 46261 | } |
| 46262 | |
| 46263 | if((decoded & GROUP_HEADER_GROUP_VERSION_ENABLED) != 0) { |
| 46264 | dst->groupHeader.groupVersionEnabled = true; |
| 46265 | rv |= UA_UInt32_decodeBinary(src, offset, dst: &dst->groupHeader.groupVersion); |
| 46266 | } |
| 46267 | |
| 46268 | if((decoded & GROUP_HEADER_NM_NUMBER_ENABLED) != 0) { |
| 46269 | dst->groupHeader.networkMessageNumberEnabled = true; |
| 46270 | rv |= UA_UInt16_decodeBinary(src, offset, dst: &dst->groupHeader.networkMessageNumber); |
| 46271 | } |
| 46272 | |
| 46273 | if((decoded & GROUP_HEADER_SEQUENCE_NUMBER_ENABLED) != 0) { |
| 46274 | dst->groupHeader.sequenceNumberEnabled = true; |
| 46275 | rv |= UA_UInt16_decodeBinary(src, offset, dst: &dst->groupHeader.sequenceNumber); |
| 46276 | } |
| 46277 | |
| 46278 | return rv; |
| 46279 | } |
| 46280 | |
| 46281 | static UA_StatusCode |
| 46282 | UA_PayloadHeader_decodeBinary(const UA_ByteString *src, size_t *offset, |
| 46283 | UA_NetworkMessage* dst) { |
| 46284 | |
| 46285 | if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET) |
| 46286 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 46287 | |
| 46288 | UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, dst: &dst->payloadHeader.dataSetPayloadHeader.count); |
| 46289 | UA_CHECK_STATUS(rv, return rv); |
| 46290 | |
| 46291 | dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds = |
| 46292 | (UA_UInt16 *)UA_Array_new(size: dst->payloadHeader.dataSetPayloadHeader.count, |
| 46293 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 46294 | for(UA_Byte i = 0; i < dst->payloadHeader.dataSetPayloadHeader.count; i++) { |
| 46295 | rv = UA_UInt16_decodeBinary(src, offset, |
| 46296 | dst: &dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i]); |
| 46297 | UA_CHECK_STATUS(rv, return rv); |
| 46298 | } |
| 46299 | return UA_STATUSCODE_GOOD; |
| 46300 | } |
| 46301 | |
| 46302 | static UA_StatusCode |
| 46303 | UA_ExtendedNetworkMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, |
| 46304 | UA_NetworkMessage* dst) { |
| 46305 | UA_StatusCode rv; |
| 46306 | |
| 46307 | // Timestamp |
| 46308 | if(dst->timestampEnabled) { |
| 46309 | rv = UA_DateTime_decodeBinary(src, offset, dst: &dst->timestamp); |
| 46310 | UA_CHECK_STATUS(rv, goto error); |
| 46311 | } |
| 46312 | |
| 46313 | // Picoseconds |
| 46314 | if(dst->picosecondsEnabled) { |
| 46315 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->picoseconds); |
| 46316 | UA_CHECK_STATUS(rv, goto error); |
| 46317 | } |
| 46318 | |
| 46319 | // PromotedFields |
| 46320 | if(dst->promotedFieldsEnabled) { |
| 46321 | // Size |
| 46322 | UA_UInt16 promotedFieldsSize = 0; |
| 46323 | rv = UA_UInt16_decodeBinary(src, offset, dst: &promotedFieldsSize); |
| 46324 | UA_CHECK_STATUS(rv, goto error); |
| 46325 | |
| 46326 | // promotedFieldsSize: here size in Byte, not the number of objects! |
| 46327 | if(promotedFieldsSize > 0) { |
| 46328 | // store offset, later compared with promotedFieldsSize |
| 46329 | size_t offsetEnd = (*offset) + promotedFieldsSize; |
| 46330 | |
| 46331 | unsigned int counter = 0; |
| 46332 | do { |
| 46333 | if(counter == 0) { |
| 46334 | dst->promotedFields = (UA_Variant*)UA_malloc(size: UA_TYPES[UA_TYPES_VARIANT].memSize); |
| 46335 | UA_CHECK_MEM(dst->promotedFields, |
| 46336 | return UA_STATUSCODE_BADOUTOFMEMORY); |
| 46337 | // set promotedFieldsSize to the number of objects |
| 46338 | dst->promotedFieldsSize = (UA_UInt16) (counter + 1); |
| 46339 | } else { |
| 46340 | dst->promotedFields = (UA_Variant*) |
| 46341 | UA_realloc(ptr: dst->promotedFields, |
| 46342 | size: (size_t) UA_TYPES[UA_TYPES_VARIANT].memSize * (counter + 1)); |
| 46343 | UA_CHECK_MEM(dst->promotedFields, |
| 46344 | return UA_STATUSCODE_BADOUTOFMEMORY); |
| 46345 | // set promotedFieldsSize to the number of objects |
| 46346 | dst->promotedFieldsSize = (UA_UInt16) (counter + 1); |
| 46347 | } |
| 46348 | |
| 46349 | UA_Variant_init(p: &dst->promotedFields[counter]); |
| 46350 | rv = UA_Variant_decodeBinary(src, offset, dst: &dst->promotedFields[counter]); |
| 46351 | UA_CHECK_STATUS(rv, goto error); |
| 46352 | |
| 46353 | counter++; |
| 46354 | } while ((*offset) < offsetEnd); |
| 46355 | } |
| 46356 | } |
| 46357 | return UA_STATUSCODE_GOOD; |
| 46358 | |
| 46359 | error: |
| 46360 | if(dst->promotedFields) { |
| 46361 | UA_free(ptr: dst->promotedFields); |
| 46362 | dst->promotedFields = NULL; |
| 46363 | } |
| 46364 | return rv; |
| 46365 | } |
| 46366 | |
| 46367 | static UA_StatusCode |
| 46368 | UA_SecurityHeader_decodeBinary(const UA_ByteString *src, size_t *offset, |
| 46369 | UA_NetworkMessage* dst) { |
| 46370 | UA_Byte decoded = 0; |
| 46371 | // SecurityFlags |
| 46372 | decoded = 0; |
| 46373 | UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, dst: &decoded); |
| 46374 | UA_CHECK_STATUS(rv, return rv); |
| 46375 | |
| 46376 | if((decoded & SECURITY_HEADER_NM_SIGNED) != 0) |
| 46377 | dst->securityHeader.networkMessageSigned = true; |
| 46378 | |
| 46379 | if((decoded & SECURITY_HEADER_NM_ENCRYPTED) != 0) |
| 46380 | dst->securityHeader.networkMessageEncrypted = true; |
| 46381 | |
| 46382 | if((decoded & SECURITY_HEADER_SEC_FOOTER_ENABLED) != 0) |
| 46383 | dst->securityHeader.securityFooterEnabled = true; |
| 46384 | |
| 46385 | if((decoded & SECURITY_HEADER_FORCE_KEY_RESET) != 0) |
| 46386 | dst->securityHeader.forceKeyReset = true; |
| 46387 | |
| 46388 | // SecurityTokenId |
| 46389 | rv = UA_UInt32_decodeBinary(src, offset, dst: &dst->securityHeader.securityTokenId); |
| 46390 | UA_CHECK_STATUS(rv, return rv); |
| 46391 | |
| 46392 | // MessageNonce |
| 46393 | UA_Byte nonceLength; |
| 46394 | rv = UA_Byte_decodeBinary(src, offset, dst: &nonceLength); |
| 46395 | UA_CHECK_STATUS(rv, return rv); |
| 46396 | if(nonceLength > UA_NETWORKMESSAGE_MAX_NONCE_LENGTH) |
| 46397 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 46398 | if(nonceLength > 0) { |
| 46399 | dst->securityHeader.messageNonceSize = nonceLength; |
| 46400 | for(UA_Byte i = 0; i < nonceLength; i++) { |
| 46401 | rv = UA_Byte_decodeBinary(src, offset, |
| 46402 | dst: &dst->securityHeader.messageNonce[i]); |
| 46403 | UA_CHECK_STATUS(rv, return rv); |
| 46404 | } |
| 46405 | } |
| 46406 | |
| 46407 | // SecurityFooterSize |
| 46408 | if(dst->securityHeader.securityFooterEnabled) { |
| 46409 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->securityHeader.securityFooterSize); |
| 46410 | UA_CHECK_STATUS(rv, return rv); |
| 46411 | } |
| 46412 | return UA_STATUSCODE_GOOD; |
| 46413 | } |
| 46414 | |
| 46415 | UA_StatusCode |
| 46416 | UA_NetworkMessage_decodeHeaders(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst) { |
| 46417 | |
| 46418 | UA_StatusCode rv = UA_NetworkMessageHeader_decodeBinary(src, offset, dst); |
| 46419 | UA_CHECK_STATUS(rv, return rv); |
| 46420 | |
| 46421 | if(dst->groupHeaderEnabled) { |
| 46422 | rv = UA_GroupHeader_decodeBinary(src, offset, dst); |
| 46423 | UA_CHECK_STATUS(rv, return rv); |
| 46424 | } |
| 46425 | |
| 46426 | if(dst->payloadHeaderEnabled) { |
| 46427 | rv = UA_PayloadHeader_decodeBinary(src, offset, dst); |
| 46428 | UA_CHECK_STATUS(rv, return rv); |
| 46429 | } |
| 46430 | |
| 46431 | rv = UA_ExtendedNetworkMessageHeader_decodeBinary(src, offset, dst); |
| 46432 | UA_CHECK_STATUS(rv, return rv); |
| 46433 | |
| 46434 | if(dst->securityEnabled) { |
| 46435 | rv = UA_SecurityHeader_decodeBinary(src, offset, dst); |
| 46436 | UA_CHECK_STATUS(rv, return rv); |
| 46437 | } |
| 46438 | |
| 46439 | return UA_STATUSCODE_GOOD; |
| 46440 | } |
| 46441 | |
| 46442 | UA_StatusCode |
| 46443 | UA_NetworkMessage_decodePayload(const UA_ByteString *src, size_t *offset, UA_NetworkMessage *dst, const UA_DataTypeArray *customTypes, UA_DataSetMetaDataType *dsm) { |
| 46444 | |
| 46445 | // Payload |
| 46446 | if(dst->networkMessageType != UA_NETWORKMESSAGE_DATASET) |
| 46447 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 46448 | |
| 46449 | UA_StatusCode rv; |
| 46450 | |
| 46451 | UA_Byte count = 1; |
| 46452 | if(dst->payloadHeaderEnabled) { |
| 46453 | count = dst->payloadHeader.dataSetPayloadHeader.count; |
| 46454 | if(count > 1) { |
| 46455 | dst->payload.dataSetPayload.sizes = (UA_UInt16 *)UA_Array_new(size: count, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 46456 | for(UA_Byte i = 0; i < count; i++) { |
| 46457 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->payload.dataSetPayload.sizes[i]); |
| 46458 | UA_CHECK_STATUS(rv, return rv); |
| 46459 | } |
| 46460 | } |
| 46461 | } |
| 46462 | |
| 46463 | dst->payload.dataSetPayload.dataSetMessages = (UA_DataSetMessage*) |
| 46464 | UA_calloc(nmemb: count, size: sizeof(UA_DataSetMessage)); |
| 46465 | UA_CHECK_MEM(dst->payload.dataSetPayload.dataSetMessages, |
| 46466 | return UA_STATUSCODE_BADOUTOFMEMORY); |
| 46467 | |
| 46468 | if(count == 1) |
| 46469 | rv = UA_DataSetMessage_decodeBinary(src, offset, |
| 46470 | dst: &dst->payload.dataSetPayload.dataSetMessages[0], |
| 46471 | dsmSize: 0, customTypes, dsm); |
| 46472 | else { |
| 46473 | for(UA_Byte i = 0; i < count; i++) { |
| 46474 | rv = UA_DataSetMessage_decodeBinary(src, offset, |
| 46475 | dst: &dst->payload.dataSetPayload.dataSetMessages[i], |
| 46476 | dsmSize: dst->payload.dataSetPayload.sizes[i], customTypes, |
| 46477 | dsm); |
| 46478 | } |
| 46479 | } |
| 46480 | UA_CHECK_STATUS(rv, return rv); |
| 46481 | |
| 46482 | return UA_STATUSCODE_GOOD; |
| 46483 | |
| 46484 | /** |
| 46485 | * TODO: check if making the cleanup to free its own allocated memory is better, |
| 46486 | * currently the free happens in a parent context |
| 46487 | */ |
| 46488 | } |
| 46489 | |
| 46490 | UA_StatusCode |
| 46491 | UA_NetworkMessage_decodeFooters(const UA_ByteString *src, size_t *offset, |
| 46492 | UA_NetworkMessage *dst) { |
| 46493 | if(!dst->securityEnabled) |
| 46494 | return UA_STATUSCODE_GOOD; |
| 46495 | |
| 46496 | // SecurityFooter |
| 46497 | UA_StatusCode rv = UA_STATUSCODE_GOOD; |
| 46498 | if(dst->securityHeader.securityFooterEnabled && |
| 46499 | dst->securityHeader.securityFooterSize > 0) { |
| 46500 | rv = UA_ByteString_allocBuffer(bs: &dst->securityFooter, |
| 46501 | length: dst->securityHeader.securityFooterSize); |
| 46502 | UA_CHECK_STATUS(rv, return rv); |
| 46503 | |
| 46504 | for(UA_UInt16 i = 0; i < dst->securityHeader.securityFooterSize; i++) { |
| 46505 | rv |= UA_Byte_decodeBinary(src, offset, dst: &dst->securityFooter.data[i]); |
| 46506 | } |
| 46507 | } |
| 46508 | return rv; |
| 46509 | } |
| 46510 | |
| 46511 | UA_StatusCode |
| 46512 | UA_NetworkMessage_decodeBinary(const UA_ByteString *src, size_t *offset, |
| 46513 | UA_NetworkMessage* dst, const UA_DataTypeArray *customTypes) { |
| 46514 | /* headers only need to be decoded when not in encryption mode |
| 46515 | * because headers are already decoded when encryption mode is enabled |
| 46516 | * to check for security parameters and decrypt/verify |
| 46517 | * |
| 46518 | * TODO: check if there is a workaround to use this function |
| 46519 | * also when encryption is enabled |
| 46520 | */ |
| 46521 | // #ifndef UA_ENABLE_PUBSUB_ENCRYPTION |
| 46522 | // if(*offset == 0) { |
| 46523 | // rv = UA_NetworkMessage_decodeHeaders(src, offset, dst); |
| 46524 | // UA_CHECK_STATUS(rv, return rv); |
| 46525 | // } |
| 46526 | // #endif |
| 46527 | |
| 46528 | UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(src, offset, dst); |
| 46529 | UA_CHECK_STATUS(rv, return rv); |
| 46530 | |
| 46531 | rv = UA_NetworkMessage_decodePayload(src, offset, dst, customTypes, NULL); |
| 46532 | UA_CHECK_STATUS(rv, return rv); |
| 46533 | |
| 46534 | rv = UA_NetworkMessage_decodeFooters(src, offset, dst); |
| 46535 | UA_CHECK_STATUS(rv, return rv); |
| 46536 | |
| 46537 | return UA_STATUSCODE_GOOD; |
| 46538 | } |
| 46539 | |
| 46540 | static UA_Boolean |
| 46541 | increaseOffsetArray(UA_NetworkMessageOffsetBuffer *offsetBuffer) { |
| 46542 | UA_NetworkMessageOffset *tmpOffsets = (UA_NetworkMessageOffset *) |
| 46543 | UA_realloc(ptr: offsetBuffer->offsets, size: sizeof(UA_NetworkMessageOffset) * (offsetBuffer->offsetsSize + (size_t)1)); |
| 46544 | UA_CHECK_MEM(tmpOffsets, return false); |
| 46545 | memset(s: &tmpOffsets[offsetBuffer->offsetsSize], c: 0, n: sizeof(UA_NetworkMessageOffset)); |
| 46546 | offsetBuffer->offsets = tmpOffsets; |
| 46547 | offsetBuffer->offsetsSize++; |
| 46548 | return true; |
| 46549 | } |
| 46550 | |
| 46551 | size_t |
| 46552 | UA_NetworkMessage_calcSizeBinary(UA_NetworkMessage *p, |
| 46553 | UA_NetworkMessageOffsetBuffer *offsetBuffer) { |
| 46554 | size_t size = 1; /* byte */ |
| 46555 | if(UA_NetworkMessage_ExtendedFlags1Enabled(src: p)) { |
| 46556 | size += 1; /* byte */ |
| 46557 | if(UA_NetworkMessage_ExtendedFlags2Enabled(src: p)) |
| 46558 | size += 1; /* byte */ |
| 46559 | } |
| 46560 | |
| 46561 | if(p->publisherIdEnabled) { |
| 46562 | if(offsetBuffer) { |
| 46563 | size_t pos = offsetBuffer->offsetsSize; |
| 46564 | if(!increaseOffsetArray(offsetBuffer)) |
| 46565 | return 0; |
| 46566 | |
| 46567 | offsetBuffer->offsets[pos].offset = size; |
| 46568 | offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_PUBLISHERID; |
| 46569 | } |
| 46570 | |
| 46571 | switch(p->publisherIdType) { |
| 46572 | case UA_PUBLISHERIDTYPE_BYTE: |
| 46573 | size += 1; /* byte */ |
| 46574 | break; |
| 46575 | case UA_PUBLISHERIDTYPE_UINT16: |
| 46576 | size += 2; /* uint16 */ |
| 46577 | break; |
| 46578 | case UA_PUBLISHERIDTYPE_UINT32: |
| 46579 | size += 4; /* uint32 */ |
| 46580 | break; |
| 46581 | case UA_PUBLISHERIDTYPE_UINT64: |
| 46582 | size += 8; /* uint64 */ |
| 46583 | break; |
| 46584 | case UA_PUBLISHERIDTYPE_STRING: |
| 46585 | size += UA_String_calcSizeBinary(src: &p->publisherId.string); |
| 46586 | break; |
| 46587 | } |
| 46588 | } |
| 46589 | |
| 46590 | if(p->dataSetClassIdEnabled) |
| 46591 | size += 16; /* guid */ |
| 46592 | |
| 46593 | // Group Header |
| 46594 | if(p->groupHeaderEnabled) { |
| 46595 | size += 1; /* byte */ |
| 46596 | |
| 46597 | if(p->groupHeader.writerGroupIdEnabled) { |
| 46598 | if(offsetBuffer) { |
| 46599 | size_t pos = offsetBuffer->offsetsSize; |
| 46600 | if(!increaseOffsetArray(offsetBuffer)) |
| 46601 | return 0; |
| 46602 | |
| 46603 | offsetBuffer->offsets[pos].offset = size; |
| 46604 | offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_WRITERGROUPID; |
| 46605 | } |
| 46606 | size += 2; /* UA_UInt16_calcSizeBinary(&p->groupHeader.writerGroupId) */ |
| 46607 | } |
| 46608 | |
| 46609 | if(p->groupHeader.groupVersionEnabled) |
| 46610 | size += 4; /* UA_UInt32_calcSizeBinary(&p->groupHeader.groupVersion) */ |
| 46611 | |
| 46612 | if(p->groupHeader.networkMessageNumberEnabled) { |
| 46613 | size += 2; /* UA_UInt16_calcSizeBinary(&p->groupHeader.networkMessageNumber) */ |
| 46614 | } |
| 46615 | |
| 46616 | if(p->groupHeader.sequenceNumberEnabled){ |
| 46617 | if(offsetBuffer){ |
| 46618 | size_t pos = offsetBuffer->offsetsSize; |
| 46619 | if(!increaseOffsetArray(offsetBuffer)) |
| 46620 | return 0; |
| 46621 | offsetBuffer->offsets[pos].offset = size; |
| 46622 | offsetBuffer->offsets[pos].content.sequenceNumber = |
| 46623 | p->groupHeader.sequenceNumber; |
| 46624 | offsetBuffer->offsets[pos].contentType = |
| 46625 | UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_SEQUENCENUMBER; |
| 46626 | } |
| 46627 | size += 2; /* UA_UInt16_calcSizeBinary(&p->groupHeader.sequenceNumber) */ |
| 46628 | } |
| 46629 | } |
| 46630 | |
| 46631 | // Payload Header |
| 46632 | if(p->payloadHeaderEnabled) { |
| 46633 | if(p->networkMessageType != UA_NETWORKMESSAGE_DATASET) |
| 46634 | return 0; /* not implemented */ |
| 46635 | if(!p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds) |
| 46636 | return 0; /* no dataSetWriterIds given! */ |
| 46637 | size += 1; /* p->payloadHeader.dataSetPayloadHeader.count */ |
| 46638 | if(offsetBuffer) { |
| 46639 | size_t pos = offsetBuffer->offsetsSize; |
| 46640 | if(!increaseOffsetArray(offsetBuffer)) |
| 46641 | return 0; |
| 46642 | offsetBuffer->offsets[pos].offset = size; |
| 46643 | offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_DATASETWRITERID; |
| 46644 | } |
| 46645 | size += (size_t)(2LU * p->payloadHeader.dataSetPayloadHeader.count); /* uint16 */ |
| 46646 | } |
| 46647 | |
| 46648 | if(p->timestampEnabled) { |
| 46649 | if(offsetBuffer){ |
| 46650 | size_t pos = offsetBuffer->offsetsSize; |
| 46651 | if(!increaseOffsetArray(offsetBuffer)) |
| 46652 | return 0; |
| 46653 | offsetBuffer->offsets[pos].offset = size; |
| 46654 | offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_TIMESTAMP; |
| 46655 | } |
| 46656 | size += 8; /* UA_DateTime_calcSizeBinary(&p->timestamp) */ |
| 46657 | } |
| 46658 | |
| 46659 | if(p->picosecondsEnabled){ |
| 46660 | if(offsetBuffer) { |
| 46661 | size_t pos = offsetBuffer->offsetsSize; |
| 46662 | if(!increaseOffsetArray(offsetBuffer)) |
| 46663 | return 0; |
| 46664 | offsetBuffer->offsets[pos].offset = size; |
| 46665 | offsetBuffer->offsets[pos].contentType = UA_PUBSUB_OFFSETTYPE_TIMESTAMP_PICOSECONDS; |
| 46666 | } |
| 46667 | size += 2; /* UA_UInt16_calcSizeBinary(&p->picoseconds) */ |
| 46668 | } |
| 46669 | |
| 46670 | if(p->promotedFieldsEnabled) { |
| 46671 | size += 2; /* UA_UInt16_calcSizeBinary(&p->promotedFieldsSize) */ |
| 46672 | for(UA_UInt16 i = 0; i < p->promotedFieldsSize; i++) |
| 46673 | size += UA_Variant_calcSizeBinary(src: &p->promotedFields[i]); |
| 46674 | } |
| 46675 | |
| 46676 | if(p->securityEnabled) { |
| 46677 | size += 1; /* UA_Byte_calcSizeBinary(&byte) */ |
| 46678 | size += 4; /* UA_UInt32_calcSizeBinary(&p->securityHeader.securityTokenId) */ |
| 46679 | size += 1; /* UA_Byte_calcSizeBinary(&p->securityHeader.nonceLength) */ |
| 46680 | size += p->securityHeader.messageNonceSize; |
| 46681 | if(p->securityHeader.securityFooterEnabled) |
| 46682 | size += 2; /* UA_UInt16_calcSizeBinary(&p->securityHeader.securityFooterSize) */ |
| 46683 | } |
| 46684 | |
| 46685 | /* Encode the payload */ |
| 46686 | if(p->networkMessageType != UA_NETWORKMESSAGE_DATASET) |
| 46687 | return 0; /* not implemented */ |
| 46688 | UA_Byte count = 1; |
| 46689 | if(p->payloadHeaderEnabled) { |
| 46690 | count = p->payloadHeader.dataSetPayloadHeader.count; |
| 46691 | if(count > 1) |
| 46692 | size += (size_t)(2LU * count); /* uint16 */ |
| 46693 | } |
| 46694 | for(size_t i = 0; i < count; i++) { |
| 46695 | UA_DataSetMessage *dsm = &p->payload.dataSetPayload.dataSetMessages[i]; |
| 46696 | size = UA_DataSetMessage_calcSizeBinary(p: dsm, offsetBuffer, currentOffset: size); |
| 46697 | } |
| 46698 | |
| 46699 | if(p->securityEnabled && p->securityHeader.securityFooterEnabled) |
| 46700 | size += p->securityHeader.securityFooterSize; |
| 46701 | |
| 46702 | return size; |
| 46703 | } |
| 46704 | |
| 46705 | void |
| 46706 | UA_NetworkMessage_clear(UA_NetworkMessage* p) { |
| 46707 | if(p->promotedFieldsEnabled) { |
| 46708 | UA_Array_delete(p: p->promotedFields, size: p->promotedFieldsSize, |
| 46709 | type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 46710 | } |
| 46711 | |
| 46712 | if(p->networkMessageType == UA_NETWORKMESSAGE_DATASET) { |
| 46713 | if(p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds && |
| 46714 | p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds != UA_EMPTY_ARRAY_SENTINEL) |
| 46715 | UA_free(ptr: p->payloadHeader.dataSetPayloadHeader.dataSetWriterIds); |
| 46716 | |
| 46717 | if(p->payload.dataSetPayload.sizes) |
| 46718 | UA_free(ptr: p->payload.dataSetPayload.sizes); |
| 46719 | |
| 46720 | if(p->payload.dataSetPayload.dataSetMessages) { |
| 46721 | UA_Byte count = 1; |
| 46722 | if(p->payloadHeaderEnabled) |
| 46723 | count = p->payloadHeader.dataSetPayloadHeader.count; |
| 46724 | for(size_t i = 0; i < count; i++) |
| 46725 | UA_DataSetMessage_clear(p: &p->payload.dataSetPayload.dataSetMessages[i]); |
| 46726 | UA_free(ptr: p->payload.dataSetPayload.dataSetMessages); |
| 46727 | } |
| 46728 | } |
| 46729 | |
| 46730 | UA_ByteString_clear(p: &p->securityFooter); |
| 46731 | UA_String_clear(p: &p->messageId); |
| 46732 | |
| 46733 | if(p->publisherIdEnabled && |
| 46734 | p->publisherIdType == UA_PUBLISHERIDTYPE_STRING) |
| 46735 | UA_String_clear(p: &p->publisherId.string); |
| 46736 | |
| 46737 | memset(s: p, c: 0, n: sizeof(UA_NetworkMessage)); |
| 46738 | } |
| 46739 | |
| 46740 | UA_Boolean |
| 46741 | UA_NetworkMessage_ExtendedFlags1Enabled(const UA_NetworkMessage* src) { |
| 46742 | if(src->publisherIdType != UA_PUBLISHERIDTYPE_BYTE || |
| 46743 | src->dataSetClassIdEnabled || src->securityEnabled || |
| 46744 | src->timestampEnabled || src->picosecondsEnabled || |
| 46745 | UA_NetworkMessage_ExtendedFlags2Enabled(src)) |
| 46746 | return true; |
| 46747 | return false; |
| 46748 | } |
| 46749 | |
| 46750 | UA_Boolean |
| 46751 | UA_NetworkMessage_ExtendedFlags2Enabled(const UA_NetworkMessage* src) { |
| 46752 | if(src->chunkMessage || src->promotedFieldsEnabled || |
| 46753 | src->networkMessageType != UA_NETWORKMESSAGE_DATASET) |
| 46754 | return true; |
| 46755 | return false; |
| 46756 | } |
| 46757 | |
| 46758 | UA_Boolean |
| 46759 | UA_DataSetMessageHeader_DataSetFlags2Enabled(const UA_DataSetMessageHeader* src) { |
| 46760 | if(src->dataSetMessageType != UA_DATASETMESSAGE_DATAKEYFRAME || |
| 46761 | src->timestampEnabled || src->picoSecondsIncluded) |
| 46762 | return true; |
| 46763 | return false; |
| 46764 | } |
| 46765 | |
| 46766 | UA_StatusCode |
| 46767 | UA_DataSetMessageHeader_encodeBinary(const UA_DataSetMessageHeader* src, UA_Byte **bufPos, |
| 46768 | const UA_Byte *bufEnd) { |
| 46769 | UA_Byte v; |
| 46770 | // DataSetFlags1 |
| 46771 | v = (UA_Byte)src->fieldEncoding; |
| 46772 | // shift left 1 bit |
| 46773 | v = (UA_Byte)(v << DS_MH_SHIFT_LEN); |
| 46774 | |
| 46775 | if(src->dataSetMessageValid) |
| 46776 | v |= DS_MESSAGEHEADER_DS_MSG_VALID; |
| 46777 | |
| 46778 | if(src->dataSetMessageSequenceNrEnabled) |
| 46779 | v |= DS_MESSAGEHEADER_SEQ_NR_ENABLED_MASK; |
| 46780 | |
| 46781 | if(src->statusEnabled) |
| 46782 | v |= DS_MESSAGEHEADER_STATUS_ENABLED_MASK; |
| 46783 | |
| 46784 | if(src->configVersionMajorVersionEnabled) |
| 46785 | v |= DS_MESSAGEHEADER_CONFIGMAJORVERSION_ENABLED_MASK; |
| 46786 | |
| 46787 | if(src->configVersionMinorVersionEnabled) |
| 46788 | v |= DS_MESSAGEHEADER_CONFIGMINORVERSION_ENABLED_MASK; |
| 46789 | |
| 46790 | if(UA_DataSetMessageHeader_DataSetFlags2Enabled(src)) |
| 46791 | v |= DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK; |
| 46792 | |
| 46793 | UA_StatusCode rv = UA_Byte_encodeBinary(src: &v, bufPos, bufEnd); |
| 46794 | UA_CHECK_STATUS(rv, return rv); |
| 46795 | |
| 46796 | // DataSetFlags2 |
| 46797 | if(UA_DataSetMessageHeader_DataSetFlags2Enabled(src)) { |
| 46798 | v = (UA_Byte)src->dataSetMessageType; |
| 46799 | |
| 46800 | if(src->timestampEnabled) |
| 46801 | v |= DS_MESSAGEHEADER_TIMESTAMP_ENABLED_MASK; |
| 46802 | |
| 46803 | if(src->picoSecondsIncluded) |
| 46804 | v |= DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK; |
| 46805 | |
| 46806 | rv = UA_Byte_encodeBinary(src: &v, bufPos, bufEnd); |
| 46807 | UA_CHECK_STATUS(rv, return rv); |
| 46808 | } |
| 46809 | |
| 46810 | // DataSetMessageSequenceNr |
| 46811 | if(src->dataSetMessageSequenceNrEnabled) { |
| 46812 | rv = UA_UInt16_encodeBinary(src: &src->dataSetMessageSequenceNr, bufPos, bufEnd); |
| 46813 | UA_CHECK_STATUS(rv, return rv); |
| 46814 | } |
| 46815 | |
| 46816 | // Timestamp |
| 46817 | if(src->timestampEnabled) { |
| 46818 | rv = UA_DateTime_encodeBinary(src: &src->timestamp, bufPos, bufEnd); /* UtcTime */ |
| 46819 | UA_CHECK_STATUS(rv, return rv); |
| 46820 | } |
| 46821 | |
| 46822 | // PicoSeconds |
| 46823 | if(src->picoSecondsIncluded) { |
| 46824 | rv = UA_UInt16_encodeBinary(src: &src->picoSeconds, bufPos, bufEnd); |
| 46825 | UA_CHECK_STATUS(rv, return rv); |
| 46826 | } |
| 46827 | |
| 46828 | // Status |
| 46829 | if(src->statusEnabled) { |
| 46830 | rv = UA_UInt16_encodeBinary(src: &src->status, bufPos, bufEnd); |
| 46831 | UA_CHECK_STATUS(rv, return rv); |
| 46832 | } |
| 46833 | |
| 46834 | // ConfigVersionMajorVersion |
| 46835 | if(src->configVersionMajorVersionEnabled) { |
| 46836 | rv = UA_UInt32_encodeBinary(src: &src->configVersionMajorVersion, bufPos, bufEnd); |
| 46837 | UA_CHECK_STATUS(rv, return rv); |
| 46838 | } |
| 46839 | |
| 46840 | // ConfigVersionMinorVersion |
| 46841 | if(src->configVersionMinorVersionEnabled) { |
| 46842 | rv = UA_UInt32_encodeBinary(src: &src->configVersionMinorVersion, bufPos, bufEnd); |
| 46843 | UA_CHECK_STATUS(rv, return rv); |
| 46844 | } |
| 46845 | |
| 46846 | return UA_STATUSCODE_GOOD; |
| 46847 | } |
| 46848 | |
| 46849 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 46850 | |
| 46851 | UA_StatusCode |
| 46852 | UA_NetworkMessage_signEncrypt(UA_NetworkMessage *nm, UA_MessageSecurityMode securityMode, |
| 46853 | UA_PubSubSecurityPolicy *policy, void *policyContext, |
| 46854 | UA_Byte *messageStart, UA_Byte *encryptStart, |
| 46855 | UA_Byte *sigStart) { |
| 46856 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 46857 | |
| 46858 | /* Encrypt the payload */ |
| 46859 | if(securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 46860 | /* Set the temporary MessageNonce in the SecurityPolicy */ |
| 46861 | const UA_ByteString nonce = { |
| 46862 | (size_t)nm->securityHeader.messageNonceSize, |
| 46863 | nm->securityHeader.messageNonce |
| 46864 | }; |
| 46865 | res = policy->setMessageNonce(policyContext, &nonce); |
| 46866 | UA_CHECK_STATUS(res, return res); |
| 46867 | |
| 46868 | /* The encryption is done in-place, no need to encode again */ |
| 46869 | UA_ByteString encryptBuf; |
| 46870 | encryptBuf.data = encryptStart; |
| 46871 | encryptBuf.length = (uintptr_t)sigStart - (uintptr_t)encryptStart; |
| 46872 | res = policy->symmetricModule.cryptoModule.encryptionAlgorithm. |
| 46873 | encrypt(policyContext, &encryptBuf); |
| 46874 | UA_CHECK_STATUS(res, return res); |
| 46875 | } |
| 46876 | |
| 46877 | /* Sign the entire message */ |
| 46878 | if(securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 46879 | securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 46880 | UA_ByteString sigBuf; |
| 46881 | sigBuf.length = (uintptr_t)sigStart - (uintptr_t)messageStart; |
| 46882 | sigBuf.data = messageStart; |
| 46883 | size_t sigSize = policy->symmetricModule.cryptoModule. |
| 46884 | signatureAlgorithm.getLocalSignatureSize(policyContext); |
| 46885 | UA_ByteString sig = {sigSize, sigStart}; |
| 46886 | res = policy->symmetricModule.cryptoModule. |
| 46887 | signatureAlgorithm.sign(policyContext, &sigBuf, &sig); |
| 46888 | } |
| 46889 | |
| 46890 | return res; |
| 46891 | } |
| 46892 | #endif |
| 46893 | |
| 46894 | UA_StatusCode |
| 46895 | UA_DataSetMessageHeader_decodeBinary(const UA_ByteString *src, size_t *offset, |
| 46896 | UA_DataSetMessageHeader* dst) { |
| 46897 | memset(s: dst, c: 0, n: sizeof(UA_DataSetMessageHeader)); |
| 46898 | UA_Byte v = 0; |
| 46899 | UA_StatusCode rv = UA_Byte_decodeBinary(src, offset, dst: &v); |
| 46900 | UA_CHECK_STATUS(rv, return rv); |
| 46901 | |
| 46902 | UA_Byte v2 = v & DS_MESSAGEHEADER_FIELD_ENCODING_MASK; |
| 46903 | v2 = (UA_Byte)(v2 >> DS_MH_SHIFT_LEN); |
| 46904 | dst->fieldEncoding = (UA_FieldEncoding)v2; |
| 46905 | |
| 46906 | if((v & DS_MESSAGEHEADER_DS_MSG_VALID) != 0) |
| 46907 | dst->dataSetMessageValid = true; |
| 46908 | |
| 46909 | if((v & DS_MESSAGEHEADER_SEQ_NR_ENABLED_MASK) != 0) |
| 46910 | dst->dataSetMessageSequenceNrEnabled = true; |
| 46911 | |
| 46912 | if((v & DS_MESSAGEHEADER_STATUS_ENABLED_MASK) != 0) |
| 46913 | dst->statusEnabled = true; |
| 46914 | |
| 46915 | if((v & DS_MESSAGEHEADER_CONFIGMAJORVERSION_ENABLED_MASK) != 0) |
| 46916 | dst->configVersionMajorVersionEnabled = true; |
| 46917 | |
| 46918 | if((v & DS_MESSAGEHEADER_CONFIGMINORVERSION_ENABLED_MASK) != 0) |
| 46919 | dst->configVersionMinorVersionEnabled = true; |
| 46920 | |
| 46921 | if((v & DS_MESSAGEHEADER_FLAGS2_ENABLED_MASK) != 0) { |
| 46922 | v = 0; |
| 46923 | rv = UA_Byte_decodeBinary(src, offset, dst: &v); |
| 46924 | UA_CHECK_STATUS(rv, return rv); |
| 46925 | |
| 46926 | dst->dataSetMessageType = (UA_DataSetMessageType)(v & DS_MESSAGEHEADER_DS_MESSAGE_TYPE_MASK); |
| 46927 | |
| 46928 | if((v & DS_MESSAGEHEADER_TIMESTAMP_ENABLED_MASK) != 0) |
| 46929 | dst->timestampEnabled = true; |
| 46930 | |
| 46931 | if((v & DS_MESSAGEHEADER_PICOSECONDS_INCLUDED_MASK) != 0) |
| 46932 | dst->picoSecondsIncluded = true; |
| 46933 | } else { |
| 46934 | dst->dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME; |
| 46935 | dst->picoSecondsIncluded = false; |
| 46936 | } |
| 46937 | |
| 46938 | if(dst->dataSetMessageSequenceNrEnabled) { |
| 46939 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->dataSetMessageSequenceNr); |
| 46940 | UA_CHECK_STATUS(rv, return rv); |
| 46941 | } else { |
| 46942 | dst->dataSetMessageSequenceNr = 0; |
| 46943 | } |
| 46944 | |
| 46945 | if(dst->timestampEnabled) { |
| 46946 | rv = UA_DateTime_decodeBinary(src, offset, dst: &dst->timestamp); /* UtcTime */ |
| 46947 | UA_CHECK_STATUS(rv, return rv); |
| 46948 | } else { |
| 46949 | dst->timestamp = 0; |
| 46950 | } |
| 46951 | |
| 46952 | if(dst->picoSecondsIncluded) { |
| 46953 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->picoSeconds); |
| 46954 | UA_CHECK_STATUS(rv, return rv); |
| 46955 | } else { |
| 46956 | dst->picoSeconds = 0; |
| 46957 | } |
| 46958 | |
| 46959 | if(dst->statusEnabled) { |
| 46960 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->status); |
| 46961 | UA_CHECK_STATUS(rv, return rv); |
| 46962 | } else { |
| 46963 | dst->status = 0; |
| 46964 | } |
| 46965 | |
| 46966 | if(dst->configVersionMajorVersionEnabled) { |
| 46967 | rv = UA_UInt32_decodeBinary(src, offset, dst: &dst->configVersionMajorVersion); |
| 46968 | UA_CHECK_STATUS(rv, return rv); |
| 46969 | } else { |
| 46970 | dst->configVersionMajorVersion = 0; |
| 46971 | } |
| 46972 | |
| 46973 | if(dst->configVersionMinorVersionEnabled) { |
| 46974 | rv = UA_UInt32_decodeBinary(src, offset, dst: &dst->configVersionMinorVersion); |
| 46975 | UA_CHECK_STATUS(rv, return rv); |
| 46976 | } else { |
| 46977 | dst->configVersionMinorVersion = 0; |
| 46978 | } |
| 46979 | |
| 46980 | return UA_STATUSCODE_GOOD; |
| 46981 | } |
| 46982 | |
| 46983 | UA_StatusCode |
| 46984 | UA_DataSetMessage_encodeBinary(const UA_DataSetMessage* src, UA_Byte **bufPos, |
| 46985 | const UA_Byte *bufEnd) { |
| 46986 | UA_StatusCode rv = UA_DataSetMessageHeader_encodeBinary(src: &src->header, bufPos, bufEnd); |
| 46987 | UA_CHECK_STATUS(rv, return rv); |
| 46988 | |
| 46989 | if(src->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) { |
| 46990 | /* Heartbeat: "DataSetMessage is a key frame that only contains header |
| 46991 | * information" */ |
| 46992 | if(src->data.keyFrameData.fieldCount == 0) |
| 46993 | return rv; |
| 46994 | |
| 46995 | if(src->header.fieldEncoding != UA_FIELDENCODING_RAWDATA) { |
| 46996 | rv = UA_UInt16_encodeBinary(src: &src->data.keyFrameData.fieldCount, |
| 46997 | bufPos, bufEnd); |
| 46998 | UA_CHECK_STATUS(rv, return rv); |
| 46999 | } |
| 47000 | |
| 47001 | for(UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) { |
| 47002 | const UA_DataValue *v = &src->data.keyFrameData.dataSetFields[i]; |
| 47003 | |
| 47004 | if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) { |
| 47005 | rv = UA_Variant_encodeBinary(src: &v->value, bufPos, bufEnd); |
| 47006 | } else if(src->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) { |
| 47007 | UA_FieldMetaData *fmd = |
| 47008 | &src->data.keyFrameData.dataSetMetaDataType->fields[i]; |
| 47009 | if(fmd->maxStringLength != 0 && |
| 47010 | (v->value.type->typeKind == UA_DATATYPEKIND_STRING || |
| 47011 | v->value.type->typeKind == UA_DATATYPEKIND_BYTESTRING)){ |
| 47012 | rv = UA_encodeBinaryInternal(src: v->value.data, type: v->value.type, |
| 47013 | bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 47014 | size_t lengthDifference = fmd->maxStringLength - |
| 47015 | ((UA_String *)v->value.data)->length; |
| 47016 | memset(s: *bufPos, c: 0, n: lengthDifference); |
| 47017 | *bufPos += lengthDifference; |
| 47018 | } else { |
| 47019 | /* padding not yet supported for strings as part of structures */ |
| 47020 | rv = UA_encodeBinaryInternal(src: v->value.data, type: v->value.type, |
| 47021 | bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 47022 | } |
| 47023 | } else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) { |
| 47024 | rv = UA_DataValue_encodeBinary(src: v, bufPos, bufEnd); |
| 47025 | } |
| 47026 | |
| 47027 | UA_CHECK_STATUS(rv, return rv); |
| 47028 | } |
| 47029 | } else if(src->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) { |
| 47030 | // Encode Delta Frame |
| 47031 | // Here the FieldCount is always present |
| 47032 | rv = UA_UInt16_encodeBinary(src: &src->data.deltaFrameData.fieldCount, bufPos, bufEnd); |
| 47033 | UA_CHECK_STATUS(rv, return rv); |
| 47034 | |
| 47035 | if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) { |
| 47036 | for(UA_UInt16 i = 0; i < src->data.deltaFrameData.fieldCount; i++) { |
| 47037 | rv = UA_UInt16_encodeBinary(src: &src->data.deltaFrameData.deltaFrameFields[i].fieldIndex, bufPos, bufEnd); |
| 47038 | UA_CHECK_STATUS(rv, return rv); |
| 47039 | |
| 47040 | rv = UA_Variant_encodeBinary(src: &src->data.deltaFrameData.deltaFrameFields[i].fieldValue.value, bufPos, bufEnd); |
| 47041 | UA_CHECK_STATUS(rv, return rv); |
| 47042 | } |
| 47043 | } else if(src->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) { |
| 47044 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 47045 | } else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) { |
| 47046 | for(UA_UInt16 i = 0; i < src->data.deltaFrameData.fieldCount; i++) { |
| 47047 | rv = UA_UInt16_encodeBinary(src: &src->data.deltaFrameData.deltaFrameFields[i].fieldIndex, bufPos, bufEnd); |
| 47048 | UA_CHECK_STATUS(rv, return rv); |
| 47049 | |
| 47050 | rv = UA_DataValue_encodeBinary(src: &src->data.deltaFrameData.deltaFrameFields[i].fieldValue, bufPos, bufEnd); |
| 47051 | UA_CHECK_STATUS(rv, return rv); |
| 47052 | } |
| 47053 | } |
| 47054 | } else if(src->header.dataSetMessageType != UA_DATASETMESSAGE_KEEPALIVE) { |
| 47055 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 47056 | } |
| 47057 | |
| 47058 | /* if the configuredSize is set -> padd the message with 0. */ |
| 47059 | if(src->configuredSize > 0 && src->header.dataSetMessageValid) { |
| 47060 | size_t padding = (size_t)(bufEnd - *bufPos); |
| 47061 | /* Set the bytes to 0*/ |
| 47062 | memset(s: *bufPos, c: 0, n: padding); |
| 47063 | /* move the bufpos accordingly*/ |
| 47064 | *bufPos += padding; |
| 47065 | } |
| 47066 | /* Keep-Alive Message contains no Payload Data */ |
| 47067 | return UA_STATUSCODE_GOOD; |
| 47068 | } |
| 47069 | |
| 47070 | UA_StatusCode |
| 47071 | UA_DataSetMessage_decodeBinary(const UA_ByteString *src, size_t *offset, UA_DataSetMessage* dst, UA_UInt16 dsmSize, const UA_DataTypeArray *customTypes, UA_DataSetMetaDataType *dsm) { |
| 47072 | size_t initialOffset = *offset; |
| 47073 | memset(s: dst, c: 0, n: sizeof(UA_DataSetMessage)); |
| 47074 | UA_StatusCode rv = UA_DataSetMessageHeader_decodeBinary(src, offset, dst: &dst->header); |
| 47075 | UA_CHECK_STATUS(rv, return rv); |
| 47076 | |
| 47077 | if(dst->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) { |
| 47078 | if(*offset == src->length) { |
| 47079 | /* Messages ends after the header --> Heartbeat */ |
| 47080 | return rv; |
| 47081 | } |
| 47082 | |
| 47083 | switch(dst->header.fieldEncoding) { |
| 47084 | case UA_FIELDENCODING_VARIANT: |
| 47085 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->data.keyFrameData.fieldCount); |
| 47086 | UA_CHECK_STATUS(rv, return rv); |
| 47087 | dst->data.keyFrameData.dataSetFields = |
| 47088 | (UA_DataValue *)UA_Array_new(size: dst->data.keyFrameData.fieldCount, type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 47089 | for(UA_UInt16 i = 0; i < dst->data.keyFrameData.fieldCount; i++) { |
| 47090 | UA_DataValue_init(p: &dst->data.keyFrameData.dataSetFields[i]); |
| 47091 | rv = UA_decodeBinaryInternal(src, offset, dst: &dst->data.keyFrameData.dataSetFields[i].value, type: &UA_TYPES[UA_TYPES_VARIANT], customTypes); |
| 47092 | UA_CHECK_STATUS(rv, return rv); |
| 47093 | |
| 47094 | dst->data.keyFrameData.dataSetFields[i].hasValue = true; |
| 47095 | } |
| 47096 | break; |
| 47097 | case UA_FIELDENCODING_DATAVALUE: |
| 47098 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->data.keyFrameData.fieldCount); |
| 47099 | UA_CHECK_STATUS(rv, return rv); |
| 47100 | dst->data.keyFrameData.dataSetFields = |
| 47101 | (UA_DataValue *)UA_Array_new(size: dst->data.keyFrameData.fieldCount, type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 47102 | for(UA_UInt16 i = 0; i < dst->data.keyFrameData.fieldCount; i++) { |
| 47103 | rv = UA_decodeBinaryInternal(src, offset, |
| 47104 | dst: &dst->data.keyFrameData.dataSetFields[i], |
| 47105 | type: &UA_TYPES[UA_TYPES_DATAVALUE], customTypes); |
| 47106 | UA_CHECK_STATUS(rv, return rv); |
| 47107 | } |
| 47108 | break; |
| 47109 | case UA_FIELDENCODING_RAWDATA: |
| 47110 | dst->data.keyFrameData.rawFields.data = &src->data[*offset]; |
| 47111 | dst->data.keyFrameData.rawFields.length = dsmSize; |
| 47112 | if(dsmSize == 0){ |
| 47113 | if(dsm != NULL) { |
| 47114 | size_t tmpOffset = 0; |
| 47115 | // calculate the length of the DSM-Payload for a single DSM |
| 47116 | dst->data.keyFrameData.fieldCount = (UA_UInt16)dsm->fieldsSize; |
| 47117 | for(size_t i = 0; i < dsm->fieldsSize; i++) { |
| 47118 | /* TODO The datatype reference should be part of the internal |
| 47119 | * pubsub configuration to avoid the time-expensive lookup */ |
| 47120 | const UA_DataType *type = |
| 47121 | UA_findDataTypeWithCustom(typeId: &dsm->fields[i].dataType, |
| 47122 | customTypes); |
| 47123 | dst->data.keyFrameData.rawFields.length += type->memSize; |
| 47124 | UA_STACKARRAY(UA_Byte, value, type->memSize); |
| 47125 | rv = UA_decodeBinaryInternal(src: &dst->data.keyFrameData.rawFields, |
| 47126 | offset: &tmpOffset, dst: value, type, NULL); |
| 47127 | UA_CHECK_STATUS(rv, return rv); |
| 47128 | if(dsm->fields[i].maxStringLength != 0) { |
| 47129 | if(type->typeKind == UA_DATATYPEKIND_STRING || |
| 47130 | type->typeKind == UA_DATATYPEKIND_BYTESTRING) { |
| 47131 | UA_ByteString *bs = (UA_ByteString *) value; |
| 47132 | //check if length < maxStringLength, The types ByteString and String are equal in their base definition |
| 47133 | size_t lengthDifference = dsm->fields[i].maxStringLength - bs->length; |
| 47134 | tmpOffset += lengthDifference; |
| 47135 | dst->data.keyFrameData.rawFields.length += lengthDifference; |
| 47136 | } |
| 47137 | } |
| 47138 | } |
| 47139 | *offset += tmpOffset; |
| 47140 | } else { |
| 47141 | //TODO calculate the length of the DSM-Payload for a single DSM |
| 47142 | //Problem: Size is not set and MetaData information are needed. |
| 47143 | //Increase offset to avoid endless chunk loop. Needs to be fixed when |
| 47144 | //pubsub security footer and signatur is enabled. |
| 47145 | *offset += 1500; |
| 47146 | } |
| 47147 | } else { |
| 47148 | *offset += (dsmSize - (*offset - initialOffset)); |
| 47149 | } |
| 47150 | break; |
| 47151 | default: |
| 47152 | return UA_STATUSCODE_BADINTERNALERROR; |
| 47153 | } |
| 47154 | } else if(dst->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) { |
| 47155 | switch(dst->header.fieldEncoding) { |
| 47156 | case UA_FIELDENCODING_VARIANT: { |
| 47157 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->data.deltaFrameData.fieldCount); |
| 47158 | UA_CHECK_STATUS(rv, return rv); |
| 47159 | size_t memsize = sizeof(UA_DataSetMessage_DeltaFrameField) * dst->data.deltaFrameData.fieldCount; |
| 47160 | dst->data.deltaFrameData.deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)UA_malloc(size: memsize); |
| 47161 | for(UA_UInt16 i = 0; i < dst->data.deltaFrameData.fieldCount; i++) { |
| 47162 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->data.deltaFrameData.deltaFrameFields[i].fieldIndex); |
| 47163 | UA_CHECK_STATUS(rv, return rv); |
| 47164 | |
| 47165 | UA_DataValue_init(p: &dst->data.deltaFrameData.deltaFrameFields[i].fieldValue); |
| 47166 | rv = UA_decodeBinaryInternal(src, offset, dst: &dst->data.deltaFrameData.deltaFrameFields[i].fieldValue.value, type: &UA_TYPES[UA_TYPES_VARIANT], customTypes); |
| 47167 | UA_CHECK_STATUS(rv, return rv); |
| 47168 | |
| 47169 | dst->data.deltaFrameData.deltaFrameFields[i].fieldValue.hasValue = true; |
| 47170 | } |
| 47171 | break; |
| 47172 | } |
| 47173 | case UA_FIELDENCODING_DATAVALUE: { |
| 47174 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->data.deltaFrameData.fieldCount); |
| 47175 | UA_CHECK_STATUS(rv, return rv); |
| 47176 | size_t memsize = sizeof(UA_DataSetMessage_DeltaFrameField) * dst->data.deltaFrameData.fieldCount; |
| 47177 | dst->data.deltaFrameData.deltaFrameFields = (UA_DataSetMessage_DeltaFrameField*)UA_malloc(size: memsize); |
| 47178 | for(UA_UInt16 i = 0; i < dst->data.deltaFrameData.fieldCount; i++) { |
| 47179 | rv = UA_UInt16_decodeBinary(src, offset, dst: &dst->data.deltaFrameData.deltaFrameFields[i].fieldIndex); |
| 47180 | UA_CHECK_STATUS(rv, return rv); |
| 47181 | |
| 47182 | rv = UA_decodeBinaryInternal(src, offset, |
| 47183 | dst: &dst->data.deltaFrameData.deltaFrameFields[i].fieldValue, |
| 47184 | type: &UA_TYPES[UA_TYPES_DATAVALUE], customTypes); |
| 47185 | |
| 47186 | UA_CHECK_STATUS(rv, return rv); |
| 47187 | } |
| 47188 | break; |
| 47189 | } |
| 47190 | case UA_FIELDENCODING_RAWDATA: { |
| 47191 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 47192 | } |
| 47193 | default: |
| 47194 | return UA_STATUSCODE_BADINTERNALERROR; |
| 47195 | } |
| 47196 | } else if(dst->header.dataSetMessageType != UA_DATASETMESSAGE_KEEPALIVE) { |
| 47197 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 47198 | } |
| 47199 | |
| 47200 | /* Keep-Alive Message contains no Payload Data */ |
| 47201 | return UA_STATUSCODE_GOOD; |
| 47202 | } |
| 47203 | |
| 47204 | size_t |
| 47205 | UA_DataSetMessage_calcSizeBinary(UA_DataSetMessage* p, |
| 47206 | UA_NetworkMessageOffsetBuffer *offsetBuffer, |
| 47207 | size_t currentOffset) { |
| 47208 | size_t size = currentOffset; |
| 47209 | |
| 47210 | if(offsetBuffer) { |
| 47211 | size_t pos = offsetBuffer->offsetsSize; |
| 47212 | if(!increaseOffsetArray(offsetBuffer)) |
| 47213 | return 0; |
| 47214 | offsetBuffer->offsets[pos].offset = size; |
| 47215 | UA_DataValue_init(p: &offsetBuffer->offsets[pos].content.value); |
| 47216 | UA_Variant_setScalar(v: &offsetBuffer->offsets[pos].content.value.value, |
| 47217 | p: &p->header.fieldEncoding, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 47218 | offsetBuffer->offsets[pos].contentType = |
| 47219 | UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING; |
| 47220 | } |
| 47221 | |
| 47222 | size += 1; /* byte: DataSetMessage Type + Flags */ |
| 47223 | if(UA_DataSetMessageHeader_DataSetFlags2Enabled(src: &p->header)) |
| 47224 | size += 1; /* byte */ |
| 47225 | |
| 47226 | if(p->header.dataSetMessageSequenceNrEnabled) { |
| 47227 | if(offsetBuffer) { |
| 47228 | size_t pos = offsetBuffer->offsetsSize; |
| 47229 | if(!increaseOffsetArray(offsetBuffer)) |
| 47230 | return 0; |
| 47231 | offsetBuffer->offsets[pos].offset = size; |
| 47232 | offsetBuffer->offsets[pos].content.sequenceNumber = |
| 47233 | p->header.dataSetMessageSequenceNr; |
| 47234 | offsetBuffer->offsets[pos].contentType = |
| 47235 | UA_PUBSUB_OFFSETTYPE_DATASETMESSAGE_SEQUENCENUMBER; |
| 47236 | } |
| 47237 | size += 2; /* UA_UInt16_calcSizeBinary(&p->header.dataSetMessageSequenceNr) */ |
| 47238 | } |
| 47239 | |
| 47240 | if(p->header.timestampEnabled) |
| 47241 | size += 8; /* UA_DateTime_calcSizeBinary(&p->header.timestamp) */ |
| 47242 | |
| 47243 | if(p->header.picoSecondsIncluded) |
| 47244 | size += 2; /* UA_UInt16_calcSizeBinary(&p->header.picoSeconds) */ |
| 47245 | |
| 47246 | if(p->header.statusEnabled) |
| 47247 | size += 2; /* UA_UInt16_calcSizeBinary(&p->header.status) */ |
| 47248 | |
| 47249 | if(p->header.configVersionMajorVersionEnabled) |
| 47250 | size += 4; /* UA_UInt32_calcSizeBinary(&p->header.configVersionMajorVersion) */ |
| 47251 | |
| 47252 | if(p->header.configVersionMinorVersionEnabled) |
| 47253 | size += 4; /* UA_UInt32_calcSizeBinary(&p->header.configVersionMinorVersion) */ |
| 47254 | |
| 47255 | /* Keyframe with no fields is a heartbeat */ |
| 47256 | if(p->header.dataSetMessageType == UA_DATASETMESSAGE_KEEPALIVE || |
| 47257 | (p->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME && |
| 47258 | p->data.keyFrameData.fieldCount == 0)) |
| 47259 | return size; |
| 47260 | |
| 47261 | if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) { |
| 47262 | if(p->header.fieldEncoding != UA_FIELDENCODING_RAWDATA) |
| 47263 | size += 2; /* p->data.keyFrameData.fieldCount */ |
| 47264 | |
| 47265 | for(UA_UInt16 i = 0; i < p->data.keyFrameData.fieldCount; i++){ |
| 47266 | UA_NetworkMessageOffset *nmo = NULL; |
| 47267 | const UA_DataValue *v = &p->data.keyFrameData.dataSetFields[i]; |
| 47268 | if(offsetBuffer) { |
| 47269 | size_t pos = offsetBuffer->offsetsSize; |
| 47270 | if(!increaseOffsetArray(offsetBuffer)) |
| 47271 | return 0; |
| 47272 | nmo = &offsetBuffer->offsets[pos]; |
| 47273 | nmo->offset = size; |
| 47274 | } |
| 47275 | |
| 47276 | if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) { |
| 47277 | if(offsetBuffer) |
| 47278 | nmo->contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT; |
| 47279 | size += UA_calcSizeBinary(p: &v->value, type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 47280 | } else if(p->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) { |
| 47281 | if(p->data.keyFrameData.dataSetFields != NULL) { |
| 47282 | if(offsetBuffer) { |
| 47283 | if(!v->value.type->pointerFree) |
| 47284 | return 0; /* only integer types for now */ |
| 47285 | /* Count the memory size of the specific field */ |
| 47286 | offsetBuffer->rawMessageLength += v->value.type->memSize; |
| 47287 | nmo->contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW; |
| 47288 | } |
| 47289 | size += UA_calcSizeBinary(p: v->value.data, type: v->value.type); |
| 47290 | |
| 47291 | /* Handle zero-padding for strings with max-string-length. |
| 47292 | * Currently not supported for strings that are a part of larger |
| 47293 | * structures. */ |
| 47294 | UA_FieldMetaData *fmd = |
| 47295 | &p->data.keyFrameData.dataSetMetaDataType->fields[i]; |
| 47296 | if(fmd->maxStringLength != 0 && |
| 47297 | (v->value.type->typeKind == UA_DATATYPEKIND_STRING || |
| 47298 | v->value.type->typeKind == UA_DATATYPEKIND_BYTESTRING)) { |
| 47299 | /* Check if length < maxStringLength, The types ByteString |
| 47300 | * and String are equal in their base definition */ |
| 47301 | size_t lengthDifference = fmd->maxStringLength - |
| 47302 | ((UA_String *)v->value.data)->length; |
| 47303 | size += lengthDifference; |
| 47304 | } |
| 47305 | } else { |
| 47306 | /* get length calculated in UA_DataSetMessage_decodeBinary */ |
| 47307 | if(offsetBuffer) { |
| 47308 | offsetBuffer->rawMessageLength = p->data.keyFrameData.rawFields.length; |
| 47309 | nmo->contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW; |
| 47310 | } |
| 47311 | size += p->data.keyFrameData.rawFields.length; |
| 47312 | /* no iteration needed */ |
| 47313 | break; |
| 47314 | } |
| 47315 | } else if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) { |
| 47316 | if(offsetBuffer) |
| 47317 | nmo->contentType = UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE; |
| 47318 | size += UA_calcSizeBinary(p: v, type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 47319 | } |
| 47320 | } |
| 47321 | } else if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) { |
| 47322 | if(offsetBuffer) |
| 47323 | return 0; /* Not supported for RT */ |
| 47324 | |
| 47325 | if(p->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) |
| 47326 | return 0; /* not supported */ |
| 47327 | |
| 47328 | size += 2; /* p->data.deltaFrameData.fieldCount */ |
| 47329 | size += (size_t)(2LU * p->data.deltaFrameData.fieldCount); /* fieldIndex per field */ |
| 47330 | |
| 47331 | for(UA_UInt16 i = 0; i < p->data.deltaFrameData.fieldCount; i++) { |
| 47332 | const UA_DataValue *v = &p->data.deltaFrameData.deltaFrameFields[i].fieldValue; |
| 47333 | if(p->header.fieldEncoding == UA_FIELDENCODING_VARIANT) |
| 47334 | size += UA_calcSizeBinary(p: &v->value, type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 47335 | else if(p->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) |
| 47336 | size += UA_calcSizeBinary(p: v, type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 47337 | } |
| 47338 | } else { |
| 47339 | return 0; |
| 47340 | } |
| 47341 | |
| 47342 | if(p->configuredSize > 0) { |
| 47343 | /* If the message is larger than the configuredSize, it shall be set to not valid */ |
| 47344 | if(p->configuredSize < size) |
| 47345 | p->header.dataSetMessageValid = UA_FALSE; |
| 47346 | |
| 47347 | size = p->configuredSize; |
| 47348 | } |
| 47349 | |
| 47350 | /* KeepAlive-Message contains no Payload Data */ |
| 47351 | return size; |
| 47352 | } |
| 47353 | |
| 47354 | void |
| 47355 | UA_DataSetMessage_clear(UA_DataSetMessage* p) { |
| 47356 | if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) { |
| 47357 | if(p->data.keyFrameData.dataSetFields) { |
| 47358 | UA_Array_delete(p: p->data.keyFrameData.dataSetFields, |
| 47359 | size: p->data.keyFrameData.fieldCount, |
| 47360 | type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 47361 | } |
| 47362 | |
| 47363 | /* Json keys */ |
| 47364 | if(p->data.keyFrameData.fieldNames){ |
| 47365 | UA_Array_delete(p: p->data.keyFrameData.fieldNames, |
| 47366 | size: p->data.keyFrameData.fieldCount, |
| 47367 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 47368 | } |
| 47369 | } else if(p->header.dataSetMessageType == UA_DATASETMESSAGE_DATADELTAFRAME) { |
| 47370 | if(p->data.deltaFrameData.deltaFrameFields) { |
| 47371 | for(UA_UInt16 i = 0; i < p->data.deltaFrameData.fieldCount; i++) { |
| 47372 | UA_DataSetMessage_DeltaFrameField *f = |
| 47373 | &p->data.deltaFrameData.deltaFrameFields[i]; |
| 47374 | UA_DataValue_clear(p: &f->fieldValue); |
| 47375 | } |
| 47376 | UA_free(ptr: p->data.deltaFrameData.deltaFrameFields); |
| 47377 | } |
| 47378 | } |
| 47379 | |
| 47380 | memset(s: p, c: 0, n: sizeof(UA_DataSetMessage)); |
| 47381 | } |
| 47382 | |
| 47383 | void |
| 47384 | UA_NetworkMessageOffsetBuffer_clear(UA_NetworkMessageOffsetBuffer *nmob) { |
| 47385 | UA_ByteString_clear(p: &nmob->buffer); |
| 47386 | |
| 47387 | if(nmob->nm) { |
| 47388 | UA_NetworkMessage_clear(p: nmob->nm); |
| 47389 | UA_free(ptr: nmob->nm); |
| 47390 | } |
| 47391 | |
| 47392 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 47393 | UA_ByteString_clear(&nmob->encryptBuffer); |
| 47394 | #endif |
| 47395 | |
| 47396 | if(nmob->offsetsSize == 0) |
| 47397 | return; |
| 47398 | |
| 47399 | for(size_t i = 0; i < nmob->offsetsSize; i++) { |
| 47400 | UA_NetworkMessageOffset *offset = &nmob->offsets[i]; |
| 47401 | if(offset->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT || |
| 47402 | offset->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE || |
| 47403 | offset->contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW) { |
| 47404 | UA_DataValue_clear(p: &offset->content.value); |
| 47405 | continue; |
| 47406 | } |
| 47407 | |
| 47408 | if(offset->contentType == UA_PUBSUB_OFFSETTYPE_NETWORKMESSAGE_FIELDENCDODING) { |
| 47409 | offset->content.value.value.data = NULL; |
| 47410 | UA_DataValue_clear(p: &offset->content.value); |
| 47411 | } |
| 47412 | } |
| 47413 | |
| 47414 | UA_free(ptr: nmob->offsets); |
| 47415 | |
| 47416 | memset(s: nmob, c: 0, n: sizeof(UA_NetworkMessageOffsetBuffer)); |
| 47417 | } |
| 47418 | |
| 47419 | #endif /* UA_ENABLE_PUBSUB */ |
| 47420 | |
| 47421 | /**** amalgamated original file "/src/pubsub/ua_pubsub_eventloop.c" ****/ |
| 47422 | |
| 47423 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 47424 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 47425 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 47426 | * |
| 47427 | * Copyright (c) 2023 Fraunhofer IOSB (Author: Julius Pfrommer) |
| 47428 | */ |
| 47429 | |
| 47430 | |
| 47431 | #ifdef UA_ENABLE_PUBSUB /* conditional compilation */ |
| 47432 | |
| 47433 | /********************/ |
| 47434 | /* PubSubConnection */ |
| 47435 | /********************/ |
| 47436 | |
| 47437 | static UA_StatusCode |
| 47438 | UA_PubSubConnection_connectUDP(UA_Server *server, UA_PubSubConnection *c, |
| 47439 | UA_Boolean validate); |
| 47440 | |
| 47441 | static UA_StatusCode |
| 47442 | UA_PubSubConnection_connectETH(UA_Server *server, UA_PubSubConnection *c, |
| 47443 | UA_Boolean validate); |
| 47444 | |
| 47445 | static UA_StatusCode |
| 47446 | UA_ReaderGroup_connectMQTT(UA_Server *server, UA_ReaderGroup *rg, |
| 47447 | UA_Boolean validate); |
| 47448 | |
| 47449 | static UA_StatusCode |
| 47450 | UA_WriterGroup_connectMQTT(UA_Server *server, UA_WriterGroup *wg, |
| 47451 | UA_Boolean validate); |
| 47452 | |
| 47453 | static UA_StatusCode |
| 47454 | UA_WriterGroup_connectUDPUnicast(UA_Server *server, UA_WriterGroup *wg, |
| 47455 | UA_Boolean validate); |
| 47456 | |
| 47457 | #define UA_PUBSUB_PROFILES_SIZE 4 |
| 47458 | |
| 47459 | typedef struct { |
| 47460 | UA_String profileURI; |
| 47461 | UA_String protocol; |
| 47462 | UA_Boolean json; |
| 47463 | UA_StatusCode (*connect)(UA_Server *server, UA_PubSubConnection *c, |
| 47464 | UA_Boolean validate); |
| 47465 | UA_StatusCode (*connectWriterGroup)(UA_Server *server, UA_WriterGroup *wg, |
| 47466 | UA_Boolean validate); |
| 47467 | UA_StatusCode (*connectReaderGroup)(UA_Server *server, UA_ReaderGroup *rg, |
| 47468 | UA_Boolean validate); |
| 47469 | } ProfileMapping; |
| 47470 | |
| 47471 | static ProfileMapping transportProfiles[UA_PUBSUB_PROFILES_SIZE] = { |
| 47472 | {UA_STRING_STATIC("http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"), |
| 47473 | UA_STRING_STATIC("udp"), false, UA_PubSubConnection_connectUDP, |
| 47474 | UA_WriterGroup_connectUDPUnicast, NULL}, |
| 47475 | {UA_STRING_STATIC("http://opcfoundation.org/UA-Profile/Transport/pubsub-mqtt-uadp"), |
| 47476 | UA_STRING_STATIC("mqtt"), false, NULL, |
| 47477 | UA_WriterGroup_connectMQTT, UA_ReaderGroup_connectMQTT}, |
| 47478 | {UA_STRING_STATIC("http://opcfoundation.org/UA-Profile/Transport/pubsub-mqtt-json"), |
| 47479 | UA_STRING_STATIC("mqtt"), true, NULL, |
| 47480 | UA_WriterGroup_connectMQTT, UA_ReaderGroup_connectMQTT}, |
| 47481 | {UA_STRING_STATIC("http://opcfoundation.org/UA-Profile/Transport/pubsub-eth-uadp"), |
| 47482 | UA_STRING_STATIC("eth"), false, UA_PubSubConnection_connectETH, NULL, NULL} |
| 47483 | }; |
| 47484 | |
| 47485 | static ProfileMapping * |
| 47486 | getProfile(UA_String profileUri) { |
| 47487 | for(size_t profile = 0; profile < UA_PUBSUB_PROFILES_SIZE; profile++) { |
| 47488 | if(UA_String_equal(p1: &profileUri, p2: &transportProfiles[profile].profileURI)) |
| 47489 | return &transportProfiles[profile]; |
| 47490 | } |
| 47491 | return NULL; |
| 47492 | } |
| 47493 | |
| 47494 | static UA_ConnectionManager * |
| 47495 | getCM(UA_EventLoop *el, UA_String protocol) { |
| 47496 | for(UA_EventSource *es = el->eventSources; es != NULL; es = es->next) { |
| 47497 | if(es->eventSourceType != UA_EVENTSOURCETYPE_CONNECTIONMANAGER) |
| 47498 | continue; |
| 47499 | UA_ConnectionManager *cm = (UA_ConnectionManager*)es; |
| 47500 | if(UA_String_equal(p1: &protocol, p2: &cm->protocol)) |
| 47501 | return cm; |
| 47502 | } |
| 47503 | return NULL; |
| 47504 | } |
| 47505 | |
| 47506 | static void |
| 47507 | UA_PubSubConnection_removeConnection(UA_PubSubConnection *c, |
| 47508 | uintptr_t connectionId) { |
| 47509 | if(c->sendChannel == connectionId) { |
| 47510 | c->sendChannel = 0; |
| 47511 | return; |
| 47512 | } |
| 47513 | for(size_t i = 0; i < UA_PUBSUB_MAXCHANNELS; i++) { |
| 47514 | if(c->recvChannels[i] != connectionId) |
| 47515 | continue; |
| 47516 | c->recvChannels[i] = 0; |
| 47517 | c->recvChannelsSize--; |
| 47518 | return; |
| 47519 | } |
| 47520 | } |
| 47521 | |
| 47522 | static UA_StatusCode |
| 47523 | UA_PubSubConnection_addSendConnection(UA_PubSubConnection *c, |
| 47524 | uintptr_t connectionId) { |
| 47525 | if(c->sendChannel != 0 && c->sendChannel != connectionId) |
| 47526 | return UA_STATUSCODE_BADINTERNALERROR; |
| 47527 | c->sendChannel = connectionId; |
| 47528 | return UA_STATUSCODE_GOOD; |
| 47529 | } |
| 47530 | |
| 47531 | static UA_StatusCode |
| 47532 | UA_PubSubConnection_addRecvConnection(UA_PubSubConnection *c, |
| 47533 | uintptr_t connectionId) { |
| 47534 | for(size_t i = 0; i < UA_PUBSUB_MAXCHANNELS; i++) { |
| 47535 | if(c->recvChannels[i] == connectionId) |
| 47536 | return UA_STATUSCODE_GOOD; |
| 47537 | } |
| 47538 | if(c->recvChannelsSize >= UA_PUBSUB_MAXCHANNELS) |
| 47539 | return UA_STATUSCODE_BADINTERNALERROR; |
| 47540 | for(size_t i = 0; i < UA_PUBSUB_MAXCHANNELS; i++) { |
| 47541 | if(c->recvChannels[i] != 0) |
| 47542 | continue; |
| 47543 | c->recvChannels[i] = connectionId; |
| 47544 | c->recvChannelsSize++; |
| 47545 | break; |
| 47546 | } |
| 47547 | return UA_STATUSCODE_GOOD; |
| 47548 | } |
| 47549 | |
| 47550 | void |
| 47551 | UA_PubSubConnection_disconnect(UA_PubSubConnection *c) { |
| 47552 | if(!c->cm) |
| 47553 | return; |
| 47554 | if(c->sendChannel != 0) |
| 47555 | c->cm->closeConnection(c->cm, c->sendChannel); |
| 47556 | for(size_t i = 0; i < UA_PUBSUB_MAXCHANNELS; i++) { |
| 47557 | if(c->recvChannels[i] != 0) |
| 47558 | c->cm->closeConnection(c->cm, c->recvChannels[i]); |
| 47559 | } |
| 47560 | } |
| 47561 | |
| 47562 | static void |
| 47563 | PubSubChannelCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 47564 | void *application, void **connectionContext, |
| 47565 | UA_ConnectionState state, const UA_KeyValueMap *params, |
| 47566 | UA_ByteString msg, UA_Boolean recv) { |
| 47567 | if(!connectionContext) |
| 47568 | return; |
| 47569 | |
| 47570 | /* Get the context pointers */ |
| 47571 | UA_Server *server = (UA_Server*)application; |
| 47572 | UA_PubSubConnection *psc = (UA_PubSubConnection*)*connectionContext; |
| 47573 | |
| 47574 | lockServer(server); |
| 47575 | |
| 47576 | /* The connection is closing in the EventLoop. This is the last callback |
| 47577 | * from that connection. Clean up the SecureChannel in the client. */ |
| 47578 | if(state == UA_CONNECTIONSTATE_CLOSING) { |
| 47579 | /* Reset the connection identifiers */ |
| 47580 | UA_PubSubConnection_removeConnection(c: psc, connectionId); |
| 47581 | |
| 47582 | /* PSC marked for deletion and the last EventLoop connection has closed */ |
| 47583 | if(psc->deleteFlag && psc->recvChannelsSize == 0 && psc->sendChannel == 0) { |
| 47584 | UA_PubSubConnection_delete(server, c: psc); |
| 47585 | unlockServer(server); |
| 47586 | return; |
| 47587 | } |
| 47588 | |
| 47589 | /* Reconnect automatically if the connection was operational. This sets |
| 47590 | * the connection state if connecting fails. Attention! If there are |
| 47591 | * several send or recv channels, then the connection is only reopened if |
| 47592 | * all of them close - which is usually the case. */ |
| 47593 | if(psc->state == UA_PUBSUBSTATE_OPERATIONAL) |
| 47594 | UA_PubSubConnection_connect(server, c: psc, false); |
| 47595 | |
| 47596 | unlockServer(server); |
| 47597 | return; |
| 47598 | } |
| 47599 | |
| 47600 | /* Store the connectionId (if a new connection) */ |
| 47601 | UA_StatusCode res = (recv) ? |
| 47602 | UA_PubSubConnection_addRecvConnection(c: psc, connectionId) : |
| 47603 | UA_PubSubConnection_addSendConnection(c: psc, connectionId); |
| 47604 | if(res != UA_STATUSCODE_GOOD) { |
| 47605 | UA_LOG_WARNING_CONNECTION(server->config.logging, psc, |
| 47606 | "No more space for an additional EventLoop connection"); |
| 47607 | if(psc->cm) |
| 47608 | psc->cm->closeConnection(psc->cm, connectionId); |
| 47609 | unlockServer(server); |
| 47610 | return; |
| 47611 | } |
| 47612 | |
| 47613 | /* No message received */ |
| 47614 | if(!recv || msg.length == 0) { |
| 47615 | unlockServer(server); |
| 47616 | return; |
| 47617 | } |
| 47618 | |
| 47619 | /* Connection open, set to operational if not already done */ |
| 47620 | if(psc->state != UA_PUBSUBSTATE_OPERATIONAL) |
| 47621 | UA_PubSubConnection_setPubSubState(server, connection: psc, state: UA_PUBSUBSTATE_OPERATIONAL, |
| 47622 | UA_STATUSCODE_GOOD); |
| 47623 | |
| 47624 | UA_NetworkMessage nm; |
| 47625 | memset(s: &nm, c: 0, n: sizeof(UA_NetworkMessage)); |
| 47626 | |
| 47627 | UA_Boolean nonRT = false; |
| 47628 | UA_Boolean processed = false; |
| 47629 | |
| 47630 | /* Process buffer ReaderGroups */ |
| 47631 | UA_ReaderGroup *rg; |
| 47632 | LIST_FOREACH(rg, &psc->readerGroups, listEntry) { |
| 47633 | if(rg->state != UA_PUBSUBSTATE_OPERATIONAL && |
| 47634 | rg->state != UA_PUBSUBSTATE_PREOPERATIONAL) |
| 47635 | continue; |
| 47636 | if(rg->config.rtLevel & UA_PUBSUB_RT_FIXED_SIZE) { |
| 47637 | processed |= UA_ReaderGroup_decodeAndProcessRT(server, readerGroup: rg, buf: &msg); |
| 47638 | continue; |
| 47639 | } |
| 47640 | |
| 47641 | if(!nonRT) { |
| 47642 | nonRT = true; |
| 47643 | /* Decode once for all nonRT ReaderGroups */ |
| 47644 | if(rg->config.encodingMimeType == UA_PUBSUB_ENCODING_UADP) { |
| 47645 | size_t currentPosition = 0; |
| 47646 | res = decodeNetworkMessage(server, buffer: &msg, pos: ¤tPosition, nm: &nm, connection: psc); |
| 47647 | } else { /* if(writerGroup->config.encodingMimeType == UA_PUBSUB_ENCODING_JSON) */ |
| 47648 | #ifdef UA_ENABLE_JSON_ENCODING |
| 47649 | res = UA_NetworkMessage_decodeJson(dst: &nm, src: &msg); |
| 47650 | #else |
| 47651 | res = UA_STATUSCODE_BADNOTSUPPORTED; |
| 47652 | #endif |
| 47653 | } |
| 47654 | if(res != UA_STATUSCODE_GOOD) { |
| 47655 | UA_LOG_WARNING_CONNECTION(server->config.logging, psc, |
| 47656 | "Verify, decrypt and decode network message failed"); |
| 47657 | nonRT = false; |
| 47658 | } |
| 47659 | } |
| 47660 | } |
| 47661 | |
| 47662 | /* Process the received message for the non-RT ReaderGroups */ |
| 47663 | if(nonRT) { |
| 47664 | LIST_FOREACH(rg, &psc->readerGroups, listEntry) { |
| 47665 | if(rg->state != UA_PUBSUBSTATE_OPERATIONAL && |
| 47666 | rg->state != UA_PUBSUBSTATE_PREOPERATIONAL) |
| 47667 | continue; |
| 47668 | if(rg->config.rtLevel & UA_PUBSUB_RT_FIXED_SIZE) |
| 47669 | continue; |
| 47670 | processed |= UA_ReaderGroup_process(server, readerGroup: rg, nm: &nm); |
| 47671 | } |
| 47672 | UA_NetworkMessage_clear(p: &nm); |
| 47673 | } |
| 47674 | |
| 47675 | if(!processed) { |
| 47676 | UA_DateTime nowM = UA_DateTime_nowMonotonic(); |
| 47677 | if(psc->silenceErrorUntil < nowM) { |
| 47678 | UA_LOG_WARNING_CONNECTION(server->config.logging, psc, |
| 47679 | "Message received that could not be processed. " |
| 47680 | "Check PublisherID, WriterGroupID and DatasetWriterID. " |
| 47681 | "(This error is now silenced for 10s.)"); |
| 47682 | psc->silenceErrorUntil = nowM + (UA_DateTime)(10.0 * UA_DATETIME_SEC); |
| 47683 | } |
| 47684 | } |
| 47685 | |
| 47686 | unlockServer(server); |
| 47687 | } |
| 47688 | |
| 47689 | static void |
| 47690 | PubSubRecvChannelCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 47691 | void *application, void **connectionContext, |
| 47692 | UA_ConnectionState state, const UA_KeyValueMap *params, |
| 47693 | UA_ByteString msg) { |
| 47694 | PubSubChannelCallback(cm, connectionId, application, connectionContext, |
| 47695 | state, params, msg, true); |
| 47696 | } |
| 47697 | |
| 47698 | static void |
| 47699 | PubSubSendChannelCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 47700 | void *application, void **connectionContext, |
| 47701 | UA_ConnectionState state, const UA_KeyValueMap *params, |
| 47702 | UA_ByteString msg) { |
| 47703 | PubSubChannelCallback(cm, connectionId, application, connectionContext, |
| 47704 | state, params, msg, false); |
| 47705 | } |
| 47706 | |
| 47707 | static UA_StatusCode |
| 47708 | UA_PubSubConnection_connectUDP(UA_Server *server, UA_PubSubConnection *c, |
| 47709 | UA_Boolean validate) { |
| 47710 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 47711 | |
| 47712 | UA_NetworkAddressUrlDataType *addressUrl = (UA_NetworkAddressUrlDataType*) |
| 47713 | c->config.address.data; |
| 47714 | |
| 47715 | /* Extract hostname and port */ |
| 47716 | UA_String address; |
| 47717 | UA_UInt16 port; |
| 47718 | UA_StatusCode res = UA_parseEndpointUrl(endpointUrl: &addressUrl->url, outHostname: &address, outPort: &port, NULL); |
| 47719 | if(res != UA_STATUSCODE_GOOD) { |
| 47720 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 47721 | "Could not parse the UDP network URL"); |
| 47722 | return res; |
| 47723 | } |
| 47724 | |
| 47725 | /* Detect a wildcard address for unicast receiving. The individual |
| 47726 | * DataSetWriters then contain additional target hostnames for sending. |
| 47727 | * |
| 47728 | * "localhost" and the empty hostname are used as a special "receive all" |
| 47729 | * wildcard for PubSub UDP. All other addresses (also the 127.0.0/8 and ::1 |
| 47730 | * range) are handled differently. For them we only receive messages that |
| 47731 | * originate from these addresses. |
| 47732 | * |
| 47733 | * The EventLoop backend detects whether an address is multicast capable and |
| 47734 | * registers it for the multicast group in the background. */ |
| 47735 | UA_String localhostAddr = UA_STRING_STATIC("localhost"); |
| 47736 | UA_Boolean receive_all = |
| 47737 | (address.length == 0) || UA_String_equal(p1: &localhostAddr, p2: &address); |
| 47738 | |
| 47739 | /* Set up the connection parameters */ |
| 47740 | UA_Boolean listen = true; |
| 47741 | UA_Boolean reuse = true; |
| 47742 | UA_Boolean loopback = true; |
| 47743 | UA_KeyValuePair kvp[7]; |
| 47744 | UA_KeyValueMap kvm = {5, kvp}; |
| 47745 | kvp[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "port"); |
| 47746 | UA_Variant_setScalar(v: &kvp[0].value, p: &port, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 47747 | kvp[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "listen"); |
| 47748 | UA_Variant_setScalar(v: &kvp[1].value, p: &listen, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 47749 | kvp[2].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "validate"); |
| 47750 | UA_Variant_setScalar(v: &kvp[2].value, p: &validate, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 47751 | kvp[3].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "reuse"); |
| 47752 | UA_Variant_setScalar(v: &kvp[3].value, p: &reuse, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 47753 | kvp[4].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "loopback"); |
| 47754 | UA_Variant_setScalar(v: &kvp[4].value, p: &loopback, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 47755 | if(!receive_all) { |
| 47756 | /* The "receive all" wildcard is different in the eventloop UDP layer. |
| 47757 | * Omit the address entirely to receive all.*/ |
| 47758 | kvp[5].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "address"); |
| 47759 | UA_Variant_setScalar(v: &kvp[5].value, p: &address, type: &UA_TYPES[UA_TYPES_STRING]); |
| 47760 | kvm.mapSize++; |
| 47761 | } |
| 47762 | if(!UA_String_isEmpty(s: &addressUrl->networkInterface)) { |
| 47763 | kvp[kvm.mapSize].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "interface"); |
| 47764 | UA_Variant_setScalar(v: &kvp[kvm.mapSize].value, p: &addressUrl->networkInterface, |
| 47765 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 47766 | kvm.mapSize++; |
| 47767 | } |
| 47768 | |
| 47769 | /* Open a recv connection */ |
| 47770 | if(c->recvChannelsSize == 0) { |
| 47771 | /* Validate only if no ReaderGroup configured */ |
| 47772 | validate = (c->readerGroupsSize == 0); |
| 47773 | if(validate) { |
| 47774 | UA_LOG_INFO_CONNECTION(server->config.logging, c, |
| 47775 | "No ReaderGroups configured. " |
| 47776 | "Only validate the connection parameters " |
| 47777 | "instead of opening a receiving channel."); |
| 47778 | } |
| 47779 | |
| 47780 | res = c->cm->openConnection(c->cm, &kvm, server, c, PubSubRecvChannelCallback); |
| 47781 | if(res != UA_STATUSCODE_GOOD) { |
| 47782 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 47783 | "Could not open an UDP channel for receiving"); |
| 47784 | return res; |
| 47785 | } |
| 47786 | } |
| 47787 | |
| 47788 | /* Receive all -- sending is handled in the DataSetWriter */ |
| 47789 | if(receive_all) { |
| 47790 | UA_LOG_INFO_CONNECTION(server->config.logging, c, |
| 47791 | "Localhost address - don't open UDP send connection"); |
| 47792 | return UA_STATUSCODE_GOOD; |
| 47793 | } |
| 47794 | |
| 47795 | /* Open a send connection */ |
| 47796 | if(c->sendChannel == 0) { |
| 47797 | /* Validate only if no WriterGroup configured */ |
| 47798 | validate = (c->writerGroupsSize == 0); |
| 47799 | if(validate) { |
| 47800 | UA_LOG_INFO_CONNECTION(server->config.logging, c, |
| 47801 | "No WriterGroups configured. " |
| 47802 | "Only validate the connection parameters " |
| 47803 | "instead of opening a channel for sending."); |
| 47804 | } |
| 47805 | |
| 47806 | listen = false; |
| 47807 | res = c->cm->openConnection(c->cm, &kvm, server, c, PubSubSendChannelCallback); |
| 47808 | if(res != UA_STATUSCODE_GOOD) { |
| 47809 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 47810 | "Could not open an UDP recv channel"); |
| 47811 | return res; |
| 47812 | } |
| 47813 | } |
| 47814 | |
| 47815 | return UA_STATUSCODE_GOOD; |
| 47816 | } |
| 47817 | |
| 47818 | static UA_StatusCode |
| 47819 | UA_PubSubConnection_connectETH(UA_Server *server, UA_PubSubConnection *c, |
| 47820 | UA_Boolean validate) { |
| 47821 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 47822 | |
| 47823 | UA_NetworkAddressUrlDataType *addressUrl = (UA_NetworkAddressUrlDataType*) |
| 47824 | c->config.address.data; |
| 47825 | |
| 47826 | /* Extract hostname and port */ |
| 47827 | UA_String address; |
| 47828 | UA_String vidPCP = UA_STRING_NULL; |
| 47829 | UA_StatusCode res = UA_parseEndpointUrl(endpointUrl: &addressUrl->url, outHostname: &address, NULL, outPath: &vidPCP); |
| 47830 | if(res != UA_STATUSCODE_GOOD) { |
| 47831 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 47832 | "Could not parse the ETH network URL"); |
| 47833 | return res; |
| 47834 | } |
| 47835 | |
| 47836 | /* Set up the connection parameters. |
| 47837 | * TDOD: Complete the considered parameters. VID, PCP, etc. */ |
| 47838 | UA_Boolean listen = true; |
| 47839 | UA_KeyValuePair kvp[4]; |
| 47840 | UA_KeyValueMap kvm = {4, kvp}; |
| 47841 | kvp[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "address"); |
| 47842 | UA_Variant_setScalar(v: &kvp[0].value, p: &address, type: &UA_TYPES[UA_TYPES_STRING]); |
| 47843 | kvp[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "listen"); |
| 47844 | UA_Variant_setScalar(v: &kvp[1].value, p: &listen, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 47845 | kvp[2].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "interface"); |
| 47846 | UA_Variant_setScalar(v: &kvp[2].value, p: &addressUrl->networkInterface, |
| 47847 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 47848 | kvp[3].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "validate"); |
| 47849 | UA_Variant_setScalar(v: &kvp[3].value, p: &validate, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 47850 | |
| 47851 | /* Open recv channels */ |
| 47852 | if(c->recvChannelsSize == 0) { |
| 47853 | res = c->cm->openConnection(c->cm, &kvm, server, c, PubSubRecvChannelCallback); |
| 47854 | if(res != UA_STATUSCODE_GOOD) { |
| 47855 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 47856 | "Could not open an ETH recv channel"); |
| 47857 | return res; |
| 47858 | } |
| 47859 | } |
| 47860 | |
| 47861 | /* Open send channels */ |
| 47862 | if(c->sendChannel == 0) { |
| 47863 | listen = false; |
| 47864 | res = c->cm->openConnection(c->cm, &kvm, server, c, PubSubSendChannelCallback); |
| 47865 | if(res != UA_STATUSCODE_GOOD) { |
| 47866 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 47867 | "Could not open an ETH channel for sending"); |
| 47868 | } |
| 47869 | } |
| 47870 | |
| 47871 | return res; |
| 47872 | } |
| 47873 | |
| 47874 | static UA_Boolean |
| 47875 | UA_PubSubConnection_isConnected(UA_PubSubConnection *c) { |
| 47876 | if(c->sendChannel == 0 && c->writerGroupsSize > 0) |
| 47877 | return false; |
| 47878 | if(c->recvChannelsSize == 0 && c->readerGroupsSize > 0) |
| 47879 | return false; |
| 47880 | return true; |
| 47881 | } |
| 47882 | |
| 47883 | UA_StatusCode |
| 47884 | UA_PubSubConnection_connect(UA_Server *server, UA_PubSubConnection *c, |
| 47885 | UA_Boolean validate) { |
| 47886 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 47887 | |
| 47888 | /* Already connected -> success */ |
| 47889 | if(UA_PubSubConnection_isConnected(c) && !validate) |
| 47890 | return UA_STATUSCODE_GOOD; |
| 47891 | |
| 47892 | UA_EventLoop *el = UA_PubSubConnection_getEL(server, c); |
| 47893 | if(!el) { |
| 47894 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, "No EventLoop configured"); |
| 47895 | UA_PubSubConnection_setPubSubState(server, connection: c, state: UA_PUBSUBSTATE_ERROR, |
| 47896 | UA_STATUSCODE_BADINTERNALERROR); |
| 47897 | return UA_STATUSCODE_BADINTERNALERROR;; |
| 47898 | } |
| 47899 | |
| 47900 | /* Look up the connection manager for the connection */ |
| 47901 | ProfileMapping *profile = getProfile(profileUri: c->config.transportProfileUri); |
| 47902 | UA_ConnectionManager *cm = NULL; |
| 47903 | if(profile) |
| 47904 | cm = getCM(el, protocol: profile->protocol); |
| 47905 | if(!cm || (c->cm && cm != c->cm)) { |
| 47906 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 47907 | "The requested protocol is not supported"); |
| 47908 | UA_PubSubConnection_setPubSubState(server, connection: c, state: UA_PUBSUBSTATE_ERROR, |
| 47909 | UA_STATUSCODE_BADINTERNALERROR); |
| 47910 | return UA_STATUSCODE_BADINTERNALERROR; |
| 47911 | } |
| 47912 | |
| 47913 | c->cm = cm; |
| 47914 | c->json = profile->json; |
| 47915 | |
| 47916 | /* Check the configuration address type */ |
| 47917 | if(!UA_Variant_hasScalarType(v: &c->config.address, |
| 47918 | type: &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE])) { |
| 47919 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, "No NetworkAddressUrlDataType " |
| 47920 | "for the address configuration"); |
| 47921 | return UA_STATUSCODE_BADINTERNALERROR; |
| 47922 | } |
| 47923 | |
| 47924 | /* Connect */ |
| 47925 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 47926 | if(profile->connect) |
| 47927 | res = profile->connect(server, c, validate); |
| 47928 | if(res != UA_STATUSCODE_GOOD && !validate) |
| 47929 | UA_PubSubConnection_setPubSubState(server, connection: c, state: UA_PUBSUBSTATE_ERROR, cause: res); |
| 47930 | return res; |
| 47931 | } |
| 47932 | |
| 47933 | /***************/ |
| 47934 | /* WriterGroup */ |
| 47935 | /***************/ |
| 47936 | |
| 47937 | static void |
| 47938 | WriterGroupChannelCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 47939 | void *application, void **connectionContext, |
| 47940 | UA_ConnectionState state, const UA_KeyValueMap *params, |
| 47941 | UA_ByteString msg) { |
| 47942 | if(!connectionContext) |
| 47943 | return; |
| 47944 | |
| 47945 | /* Get the context pointers */ |
| 47946 | UA_Server *server = (UA_Server*)application; |
| 47947 | UA_WriterGroup *wg = (UA_WriterGroup*)*connectionContext; |
| 47948 | |
| 47949 | lockServer(server); |
| 47950 | |
| 47951 | /* The connection is closing in the EventLoop. This is the last callback |
| 47952 | * from that connection. Clean up the SecureChannel in the client. */ |
| 47953 | if(state == UA_CONNECTIONSTATE_CLOSING) { |
| 47954 | if(wg->sendChannel == connectionId) { |
| 47955 | /* Reset the connection channel */ |
| 47956 | wg->sendChannel = 0; |
| 47957 | |
| 47958 | /* PSC marked for deletion and the last EventLoop connection has closed */ |
| 47959 | if(wg->deleteFlag) { |
| 47960 | UA_WriterGroup_remove(server, wg); |
| 47961 | unlockServer(server); |
| 47962 | return; |
| 47963 | } |
| 47964 | } |
| 47965 | |
| 47966 | /* Reconnect automatically if the connection was operational. This sets |
| 47967 | * the connection state if connecting fails. Attention! If there are |
| 47968 | * several send or recv channels, then the connection is only reopened if |
| 47969 | * all of them close - which is usually the case. */ |
| 47970 | if(wg->state == UA_PUBSUBSTATE_OPERATIONAL) |
| 47971 | UA_WriterGroup_connect(server, wg, false); |
| 47972 | |
| 47973 | unlockServer(server); |
| 47974 | return; |
| 47975 | } |
| 47976 | |
| 47977 | /* Store the connectionId (if a new connection) */ |
| 47978 | if(wg->sendChannel && wg->sendChannel != connectionId) { |
| 47979 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 47980 | "WriterGroup is already bound to a different channel"); |
| 47981 | unlockServer(server); |
| 47982 | return; |
| 47983 | } |
| 47984 | wg->sendChannel = connectionId; |
| 47985 | |
| 47986 | /* Connection open, set to operational if not already done */ |
| 47987 | if(wg->state != UA_PUBSUBSTATE_OPERATIONAL) |
| 47988 | UA_WriterGroup_setPubSubState(server, writerGroup: wg, state: UA_PUBSUBSTATE_OPERATIONAL, |
| 47989 | UA_STATUSCODE_GOOD); |
| 47990 | |
| 47991 | /* Send-channels don't receive messages */ |
| 47992 | unlockServer(server); |
| 47993 | } |
| 47994 | |
| 47995 | static UA_StatusCode |
| 47996 | UA_WriterGroup_connectUDPUnicast(UA_Server *server, UA_WriterGroup *wg, |
| 47997 | UA_Boolean validate) { |
| 47998 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 47999 | |
| 48000 | /* Already connected? */ |
| 48001 | if(wg->sendChannel != 0 && !validate) |
| 48002 | return UA_STATUSCODE_GOOD; |
| 48003 | |
| 48004 | /* Check if address is available in TransportSettings */ |
| 48005 | if(((wg->config.transportSettings.encoding == UA_EXTENSIONOBJECT_DECODED || |
| 48006 | wg->config.transportSettings.encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) && |
| 48007 | wg->config.transportSettings.content.decoded.type == |
| 48008 | &UA_TYPES[UA_TYPES_DATAGRAMWRITERGROUPTRANSPORTDATATYPE])) |
| 48009 | return UA_STATUSCODE_GOOD; |
| 48010 | |
| 48011 | /* Unpack the TransportSettings */ |
| 48012 | if((wg->config.transportSettings.encoding != UA_EXTENSIONOBJECT_DECODED && |
| 48013 | wg->config.transportSettings.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) || |
| 48014 | wg->config.transportSettings.content.decoded.type != |
| 48015 | &UA_TYPES[UA_TYPES_DATAGRAMWRITERGROUPTRANSPORT2DATATYPE]) { |
| 48016 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 48017 | "Invalid TransportSettings for a UDP Connection"); |
| 48018 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48019 | } |
| 48020 | UA_DatagramWriterGroupTransport2DataType *ts = |
| 48021 | (UA_DatagramWriterGroupTransport2DataType*) |
| 48022 | wg->config.transportSettings.content.decoded.data; |
| 48023 | |
| 48024 | /* Unpack the address */ |
| 48025 | if((ts->address.encoding != UA_EXTENSIONOBJECT_DECODED && |
| 48026 | ts->address.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) || |
| 48027 | ts->address.content.decoded.type != &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]) { |
| 48028 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 48029 | "Invalid TransportSettings Address for a UDP Connection"); |
| 48030 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48031 | } |
| 48032 | UA_NetworkAddressUrlDataType *addressUrl = (UA_NetworkAddressUrlDataType *) |
| 48033 | ts->address.content.decoded.data; |
| 48034 | |
| 48035 | /* Extract hostname and port */ |
| 48036 | UA_String address; |
| 48037 | UA_UInt16 port; |
| 48038 | UA_StatusCode res = UA_parseEndpointUrl(endpointUrl: &addressUrl->url, outHostname: &address, outPort: &port, NULL); |
| 48039 | if(res != UA_STATUSCODE_GOOD) { |
| 48040 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 48041 | "Could not parse the UDP network URL"); |
| 48042 | return res; |
| 48043 | } |
| 48044 | |
| 48045 | /* Set up the connection parameters */ |
| 48046 | UA_Boolean listen = false; |
| 48047 | UA_KeyValuePair kvp[5]; |
| 48048 | UA_KeyValueMap kvm = {4, kvp}; |
| 48049 | kvp[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "address"); |
| 48050 | UA_Variant_setScalar(v: &kvp[0].value, p: &address, type: &UA_TYPES[UA_TYPES_STRING]); |
| 48051 | kvp[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "port"); |
| 48052 | UA_Variant_setScalar(v: &kvp[1].value, p: &port, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 48053 | kvp[2].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "listen"); |
| 48054 | UA_Variant_setScalar(v: &kvp[2].value, p: &listen, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 48055 | kvp[3].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "validate"); |
| 48056 | UA_Variant_setScalar(v: &kvp[3].value, p: &validate, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 48057 | if(!UA_String_isEmpty(s: &addressUrl->networkInterface)) { |
| 48058 | kvp[4].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "interface"); |
| 48059 | UA_Variant_setScalar(v: &kvp[4].value, p: &addressUrl->networkInterface, |
| 48060 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 48061 | kvm.mapSize++; |
| 48062 | } |
| 48063 | |
| 48064 | /* Connect */ |
| 48065 | UA_ConnectionManager *cm = wg->linkedConnection->cm; |
| 48066 | res = cm->openConnection(cm, &kvm, server, wg, WriterGroupChannelCallback); |
| 48067 | if(res != UA_STATUSCODE_GOOD) { |
| 48068 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 48069 | "Could not open a UDP send channel"); |
| 48070 | } |
| 48071 | return res; |
| 48072 | } |
| 48073 | |
| 48074 | static UA_StatusCode |
| 48075 | UA_WriterGroup_connectMQTT(UA_Server *server, UA_WriterGroup *wg, |
| 48076 | UA_Boolean validate) { |
| 48077 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 48078 | |
| 48079 | UA_PubSubConnection *c = wg->linkedConnection; |
| 48080 | UA_NetworkAddressUrlDataType *addressUrl = (UA_NetworkAddressUrlDataType*) |
| 48081 | c->config.address.data; |
| 48082 | |
| 48083 | /* Get the TransportSettings */ |
| 48084 | UA_ExtensionObject *ts = &wg->config.transportSettings; |
| 48085 | if((ts->encoding != UA_EXTENSIONOBJECT_DECODED && |
| 48086 | ts->encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) || |
| 48087 | ts->content.decoded.type != |
| 48088 | &UA_TYPES[UA_TYPES_BROKERWRITERGROUPTRANSPORTDATATYPE]) { |
| 48089 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 48090 | "Wrong TransportSettings type for MQTT"); |
| 48091 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48092 | } |
| 48093 | UA_BrokerWriterGroupTransportDataType *transportSettings = |
| 48094 | (UA_BrokerWriterGroupTransportDataType*)ts->content.decoded.data; |
| 48095 | |
| 48096 | /* Extract hostname and port */ |
| 48097 | UA_String address; |
| 48098 | UA_UInt16 port = 1883; /* Default */ |
| 48099 | UA_StatusCode res = UA_parseEndpointUrl(endpointUrl: &addressUrl->url, outHostname: &address, outPort: &port, NULL); |
| 48100 | if(res != UA_STATUSCODE_GOOD) { |
| 48101 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 48102 | "Could not parse the MQTT network URL"); |
| 48103 | return res; |
| 48104 | } |
| 48105 | |
| 48106 | /* Set up the connection parameters. |
| 48107 | * TODO: Complete the MQTT parameters. */ |
| 48108 | UA_Boolean listen = false; |
| 48109 | UA_KeyValuePair kvp[5]; |
| 48110 | UA_KeyValueMap kvm = {5, kvp}; |
| 48111 | kvp[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "address"); |
| 48112 | UA_Variant_setScalar(v: &kvp[0].value, p: &address, type: &UA_TYPES[UA_TYPES_STRING]); |
| 48113 | kvp[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "subscribe"); |
| 48114 | UA_Variant_setScalar(v: &kvp[1].value, p: &listen, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 48115 | kvp[2].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "port"); |
| 48116 | UA_Variant_setScalar(v: &kvp[2].value, p: &port, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 48117 | kvp[3].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "topic"); |
| 48118 | UA_Variant_setScalar(v: &kvp[3].value, p: &transportSettings->queueName, |
| 48119 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 48120 | kvp[4].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "validate"); |
| 48121 | UA_Variant_setScalar(v: &kvp[4].value, p: &validate, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 48122 | |
| 48123 | /* Connect */ |
| 48124 | res = c->cm->openConnection(c->cm, &kvm, server, wg, WriterGroupChannelCallback); |
| 48125 | if(res != UA_STATUSCODE_GOOD) { |
| 48126 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 48127 | "Could not open the MQTT connection"); |
| 48128 | } |
| 48129 | return res; |
| 48130 | } |
| 48131 | |
| 48132 | void |
| 48133 | UA_WriterGroup_disconnect(UA_WriterGroup *wg) { |
| 48134 | if(wg->sendChannel == 0) |
| 48135 | return; |
| 48136 | UA_PubSubConnection *c = wg->linkedConnection; |
| 48137 | if(!c || !c->cm) |
| 48138 | return; |
| 48139 | c->cm->closeConnection(c->cm, wg->sendChannel); |
| 48140 | } |
| 48141 | |
| 48142 | UA_StatusCode |
| 48143 | UA_WriterGroup_connect(UA_Server *server, UA_WriterGroup *wg, UA_Boolean validate) { |
| 48144 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 48145 | |
| 48146 | /* Already connected */ |
| 48147 | if(wg->sendChannel != 0 && !validate) |
| 48148 | return UA_STATUSCODE_GOOD; |
| 48149 | |
| 48150 | /* Is this a WriterGroup with custom TransportSettings beyond the |
| 48151 | * PubSubConnection? */ |
| 48152 | if(wg->config.transportSettings.encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) |
| 48153 | return UA_STATUSCODE_GOOD; |
| 48154 | |
| 48155 | UA_EventLoop *el = UA_PubSubConnection_getEL(server, c: wg->linkedConnection); |
| 48156 | if(!el) { |
| 48157 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, "No EventLoop configured"); |
| 48158 | UA_WriterGroup_setPubSubState(server, writerGroup: wg, state: UA_PUBSUBSTATE_ERROR, |
| 48159 | UA_STATUSCODE_BADINTERNALERROR); |
| 48160 | return UA_STATUSCODE_BADINTERNALERROR;; |
| 48161 | } |
| 48162 | |
| 48163 | UA_PubSubConnection *c = wg->linkedConnection; |
| 48164 | if(!c) |
| 48165 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48166 | |
| 48167 | /* Look up the connection manager for the connection */ |
| 48168 | ProfileMapping *profile = getProfile(profileUri: c->config.transportProfileUri); |
| 48169 | UA_ConnectionManager *cm = NULL; |
| 48170 | if(profile) |
| 48171 | cm = getCM(el, protocol: profile->protocol); |
| 48172 | if(!cm || (c->cm && cm != c->cm)) { |
| 48173 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 48174 | "The requested protocol is not supported"); |
| 48175 | UA_PubSubConnection_setPubSubState(server, connection: c, state: UA_PUBSUBSTATE_ERROR, |
| 48176 | UA_STATUSCODE_BADINTERNALERROR); |
| 48177 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48178 | } |
| 48179 | |
| 48180 | c->cm = cm; |
| 48181 | c->json = profile->json; |
| 48182 | |
| 48183 | /* Connect */ |
| 48184 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 48185 | if(profile->connectWriterGroup) |
| 48186 | res = profile->connectWriterGroup(server, wg, validate); |
| 48187 | if(res != UA_STATUSCODE_GOOD && !validate) { |
| 48188 | UA_WriterGroup_setPubSubState(server, writerGroup: wg, state: UA_PUBSUBSTATE_ERROR, cause: res); |
| 48189 | return res; |
| 48190 | } |
| 48191 | |
| 48192 | /* Set to preoperational. Set the state "manually" to avoid recursion. Also |
| 48193 | * this is the only place to set pre-operational for PubSubConnections. The |
| 48194 | * state will be set to operational in the network callback when the |
| 48195 | * connection has fully opened. */ |
| 48196 | if(wg->state != UA_PUBSUBSTATE_OPERATIONAL && !validate) |
| 48197 | wg->state = UA_PUBSUBSTATE_PREOPERATIONAL; |
| 48198 | |
| 48199 | return UA_STATUSCODE_GOOD; |
| 48200 | } |
| 48201 | |
| 48202 | /***************/ |
| 48203 | /* ReaderGroup */ |
| 48204 | /***************/ |
| 48205 | |
| 48206 | static void |
| 48207 | UA_ReaderGroup_removeConnection(UA_ReaderGroup *rg, |
| 48208 | uintptr_t connectionId) { |
| 48209 | for(size_t i = 0; i < UA_PUBSUB_MAXCHANNELS; i++) { |
| 48210 | if(rg->recvChannels[i] != connectionId) |
| 48211 | continue; |
| 48212 | rg->recvChannels[i] = 0; |
| 48213 | rg->recvChannelsSize--; |
| 48214 | return; |
| 48215 | } |
| 48216 | } |
| 48217 | |
| 48218 | static UA_StatusCode |
| 48219 | UA_ReaderGroup_addRecvConnection(UA_ReaderGroup*c, |
| 48220 | uintptr_t connectionId) { |
| 48221 | for(size_t i = 0; i < UA_PUBSUB_MAXCHANNELS; i++) { |
| 48222 | if(c->recvChannels[i] == connectionId) |
| 48223 | return UA_STATUSCODE_GOOD; |
| 48224 | } |
| 48225 | if(c->recvChannelsSize >= UA_PUBSUB_MAXCHANNELS) |
| 48226 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48227 | for(size_t i = 0; i < UA_PUBSUB_MAXCHANNELS; i++) { |
| 48228 | if(c->recvChannels[i] != 0) |
| 48229 | continue; |
| 48230 | c->recvChannels[i] = connectionId; |
| 48231 | c->recvChannelsSize++; |
| 48232 | break; |
| 48233 | } |
| 48234 | return UA_STATUSCODE_GOOD; |
| 48235 | } |
| 48236 | |
| 48237 | static void |
| 48238 | ReaderGroupChannelCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 48239 | void *application, void **connectionContext, |
| 48240 | UA_ConnectionState state, const UA_KeyValueMap *params, |
| 48241 | UA_ByteString msg) { |
| 48242 | if(!connectionContext) |
| 48243 | return; |
| 48244 | |
| 48245 | /* Get the context pointers */ |
| 48246 | UA_Server *server = (UA_Server*)application; |
| 48247 | UA_ReaderGroup *rg = (UA_ReaderGroup*)*connectionContext; |
| 48248 | |
| 48249 | lockServer(server); |
| 48250 | |
| 48251 | /* The connection is closing in the EventLoop. This is the last callback |
| 48252 | * from that connection. Clean up the SecureChannel in the client. */ |
| 48253 | if(state == UA_CONNECTIONSTATE_CLOSING) { |
| 48254 | /* Reset the connection identifiers */ |
| 48255 | UA_ReaderGroup_removeConnection(rg, connectionId); |
| 48256 | |
| 48257 | /* PSC marked for deletion and the last EventLoop connection has closed */ |
| 48258 | if(rg->deleteFlag && rg->recvChannelsSize == 0) { |
| 48259 | UA_ReaderGroup_remove(server, rg); |
| 48260 | unlockServer(server); |
| 48261 | return; |
| 48262 | } |
| 48263 | |
| 48264 | /* Reconnect if still operational */ |
| 48265 | UA_ReaderGroup_setPubSubState(server, readerGroup: rg, state: rg->state, UA_STATUSCODE_GOOD); |
| 48266 | unlockServer(server); |
| 48267 | return; |
| 48268 | } |
| 48269 | |
| 48270 | /* Store the connectionId (if a new connection) */ |
| 48271 | UA_StatusCode res = UA_ReaderGroup_addRecvConnection(c: rg, connectionId); |
| 48272 | if(res != UA_STATUSCODE_GOOD) { |
| 48273 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, |
| 48274 | "No more space for an additional EventLoop connection"); |
| 48275 | UA_PubSubConnection *c = rg->linkedConnection; |
| 48276 | if(c && c->cm) |
| 48277 | c->cm->closeConnection(c->cm, connectionId); |
| 48278 | unlockServer(server); |
| 48279 | return; |
| 48280 | } |
| 48281 | |
| 48282 | /* No message received */ |
| 48283 | if(msg.length == 0) { |
| 48284 | unlockServer(server); |
| 48285 | return; |
| 48286 | } |
| 48287 | |
| 48288 | /* Received the first message - set to operational */ |
| 48289 | if(rg->state == UA_PUBSUBSTATE_PREOPERATIONAL) { |
| 48290 | rg->state = UA_PUBSUBSTATE_OPERATIONAL; |
| 48291 | UA_ServerConfig *config = &server->config; |
| 48292 | if(config->pubSubConfig.stateChangeCallback != 0) { |
| 48293 | config->pubSubConfig.stateChangeCallback(server, &rg->identifier, |
| 48294 | rg->state, UA_STATUSCODE_GOOD); |
| 48295 | } |
| 48296 | } |
| 48297 | |
| 48298 | if(rg->state != UA_PUBSUBSTATE_OPERATIONAL) { |
| 48299 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, |
| 48300 | "Received a messaage for a non-operational ReaderGroup"); |
| 48301 | unlockServer(server); |
| 48302 | return; |
| 48303 | } |
| 48304 | |
| 48305 | /* ReaderGroup with realtime processing */ |
| 48306 | if(rg->config.rtLevel & UA_PUBSUB_RT_FIXED_SIZE) { |
| 48307 | UA_ReaderGroup_decodeAndProcessRT(server, readerGroup: rg, buf: &msg); |
| 48308 | unlockServer(server); |
| 48309 | return; |
| 48310 | } |
| 48311 | |
| 48312 | /* Decode message */ |
| 48313 | UA_NetworkMessage nm; |
| 48314 | memset(s: &nm, c: 0, n: sizeof(UA_NetworkMessage)); |
| 48315 | if(rg->config.encodingMimeType == UA_PUBSUB_ENCODING_UADP) { |
| 48316 | size_t currentPosition = 0; |
| 48317 | res = decodeNetworkMessage(server, buffer: &msg, pos: ¤tPosition, |
| 48318 | nm: &nm, connection: rg->linkedConnection); |
| 48319 | } else { /* if(writerGroup->config.encodingMimeType == UA_PUBSUB_ENCODING_JSON) */ |
| 48320 | #ifdef UA_ENABLE_JSON_ENCODING |
| 48321 | res = UA_NetworkMessage_decodeJson(dst: &nm, src: &msg); |
| 48322 | #else |
| 48323 | res = UA_STATUSCODE_BADNOTSUPPORTED; |
| 48324 | #endif |
| 48325 | } |
| 48326 | if(res != UA_STATUSCODE_GOOD) { |
| 48327 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, |
| 48328 | "Verify, decrypt and decode network message failed"); |
| 48329 | unlockServer(server); |
| 48330 | return; |
| 48331 | } |
| 48332 | |
| 48333 | /* Process the decoded message */ |
| 48334 | UA_ReaderGroup_process(server, readerGroup: rg, nm: &nm); |
| 48335 | UA_NetworkMessage_clear(p: &nm); |
| 48336 | unlockServer(server); |
| 48337 | } |
| 48338 | |
| 48339 | static UA_StatusCode |
| 48340 | UA_ReaderGroup_connectMQTT(UA_Server *server, UA_ReaderGroup *rg, |
| 48341 | UA_Boolean validate) { |
| 48342 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 48343 | |
| 48344 | UA_PubSubConnection *c = rg->linkedConnection; |
| 48345 | UA_NetworkAddressUrlDataType *addressUrl = (UA_NetworkAddressUrlDataType*) |
| 48346 | c->config.address.data; |
| 48347 | |
| 48348 | /* Get the TransportSettings */ |
| 48349 | UA_ExtensionObject *ts = &rg->config.transportSettings; |
| 48350 | if((ts->encoding != UA_EXTENSIONOBJECT_DECODED && |
| 48351 | ts->encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) || |
| 48352 | ts->content.decoded.type != |
| 48353 | &UA_TYPES[UA_TYPES_BROKERDATASETREADERTRANSPORTDATATYPE]) { |
| 48354 | UA_LOG_ERROR_READERGROUP(server->config.logging, rg, |
| 48355 | "Wrong TransportSettings type for MQTT"); |
| 48356 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48357 | } |
| 48358 | UA_BrokerDataSetReaderTransportDataType *transportSettings = |
| 48359 | (UA_BrokerDataSetReaderTransportDataType*)ts->content.decoded.data; |
| 48360 | |
| 48361 | /* Extract hostname and port */ |
| 48362 | UA_String address; |
| 48363 | UA_UInt16 port = 1883; /* Default */ |
| 48364 | UA_StatusCode res = UA_parseEndpointUrl(endpointUrl: &addressUrl->url, outHostname: &address, outPort: &port, NULL); |
| 48365 | if(res != UA_STATUSCODE_GOOD) { |
| 48366 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 48367 | "Could not parse the MQTT network URL"); |
| 48368 | return res; |
| 48369 | } |
| 48370 | |
| 48371 | /* Set up the connection parameters. |
| 48372 | * TODO: Complete the MQTT parameters. */ |
| 48373 | UA_Boolean listen = true; |
| 48374 | UA_KeyValuePair kvp[5]; |
| 48375 | UA_KeyValueMap kvm = {5, kvp}; |
| 48376 | kvp[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "address"); |
| 48377 | UA_Variant_setScalar(v: &kvp[0].value, p: &address, type: &UA_TYPES[UA_TYPES_STRING]); |
| 48378 | kvp[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "subscribe"); |
| 48379 | UA_Variant_setScalar(v: &kvp[1].value, p: &listen, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 48380 | kvp[2].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "port"); |
| 48381 | UA_Variant_setScalar(v: &kvp[2].value, p: &port, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 48382 | kvp[3].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "topic"); |
| 48383 | UA_Variant_setScalar(v: &kvp[3].value, p: &transportSettings->queueName, |
| 48384 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 48385 | kvp[4].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "validate"); |
| 48386 | UA_Variant_setScalar(v: &kvp[4].value, p: &validate, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 48387 | |
| 48388 | /* Connect */ |
| 48389 | res = c->cm->openConnection(c->cm, &kvm, server, rg, ReaderGroupChannelCallback); |
| 48390 | if(res != UA_STATUSCODE_GOOD) { |
| 48391 | UA_LOG_ERROR_READERGROUP(server->config.logging, rg, |
| 48392 | "Could not open the MQTT connection"); |
| 48393 | } |
| 48394 | return res; |
| 48395 | } |
| 48396 | |
| 48397 | void |
| 48398 | UA_ReaderGroup_disconnect(UA_ReaderGroup *rg) { |
| 48399 | UA_PubSubConnection *c = rg->linkedConnection; |
| 48400 | if(!c) |
| 48401 | return; |
| 48402 | for(size_t i = 0; i < UA_PUBSUB_MAXCHANNELS; i++) { |
| 48403 | if(rg->recvChannels[i] != 0) |
| 48404 | c->cm->closeConnection(c->cm, rg->recvChannels[i]); |
| 48405 | } |
| 48406 | } |
| 48407 | |
| 48408 | UA_StatusCode |
| 48409 | UA_ReaderGroup_connect(UA_Server *server, UA_ReaderGroup *rg, UA_Boolean validate) { |
| 48410 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 48411 | |
| 48412 | /* Already connected */ |
| 48413 | if(rg->recvChannelsSize != 0 && !validate) |
| 48414 | return UA_STATUSCODE_GOOD; |
| 48415 | |
| 48416 | /* Is this a ReaderGroup with custom TransportSettings beyond the |
| 48417 | * PubSubConnection? */ |
| 48418 | if(rg->config.transportSettings.encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) |
| 48419 | return UA_STATUSCODE_GOOD; |
| 48420 | |
| 48421 | UA_EventLoop *el = UA_PubSubConnection_getEL(server, c: rg->linkedConnection); |
| 48422 | if(!el) { |
| 48423 | UA_LOG_ERROR_READERGROUP(server->config.logging, rg, "No EventLoop configured"); |
| 48424 | UA_ReaderGroup_setPubSubState(server, readerGroup: rg, state: UA_PUBSUBSTATE_ERROR, |
| 48425 | UA_STATUSCODE_BADINTERNALERROR); |
| 48426 | return UA_STATUSCODE_BADINTERNALERROR;; |
| 48427 | } |
| 48428 | |
| 48429 | UA_PubSubConnection *c = rg->linkedConnection; |
| 48430 | if(!c) |
| 48431 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48432 | |
| 48433 | /* Look up the connection manager for the connection */ |
| 48434 | ProfileMapping *profile = getProfile(profileUri: c->config.transportProfileUri); |
| 48435 | UA_ConnectionManager *cm = NULL; |
| 48436 | if(profile) |
| 48437 | cm = getCM(el, protocol: profile->protocol); |
| 48438 | if(!cm || (c->cm && cm != c->cm)) { |
| 48439 | UA_LOG_ERROR_CONNECTION(server->config.logging, c, |
| 48440 | "The requested protocol is not supported"); |
| 48441 | UA_PubSubConnection_setPubSubState(server, connection: c, state: UA_PUBSUBSTATE_ERROR, |
| 48442 | UA_STATUSCODE_BADINTERNALERROR); |
| 48443 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48444 | } |
| 48445 | |
| 48446 | c->cm = cm; |
| 48447 | c->json = profile->json; |
| 48448 | |
| 48449 | /* Connect */ |
| 48450 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 48451 | if(profile->connectReaderGroup) |
| 48452 | res = profile->connectReaderGroup(server, rg, validate); |
| 48453 | if(res != UA_STATUSCODE_GOOD && !validate) { |
| 48454 | UA_ReaderGroup_setPubSubState(server, readerGroup: rg, state: UA_PUBSUBSTATE_ERROR, cause: res); |
| 48455 | return res; |
| 48456 | } |
| 48457 | |
| 48458 | return UA_STATUSCODE_GOOD; |
| 48459 | } |
| 48460 | |
| 48461 | #endif /* UA_ENABLE_PUBSUB */ |
| 48462 | |
| 48463 | /**** amalgamated original file "/src/pubsub/ua_pubsub_connection.c" ****/ |
| 48464 | |
| 48465 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 48466 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 48467 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 48468 | * |
| 48469 | * Copyright (c) 2017-2022 Fraunhofer IOSB (Author: Andreas Ebner) |
| 48470 | * Copyright (c) 2019, 2022 Fraunhofer IOSB (Author: Julius Pfrommer) |
| 48471 | * Copyright (c) 2019 Kalycito Infotech Private Limited |
| 48472 | * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes) |
| 48473 | * Copyright (c) 2022 Siemens AG (Author: Thomas Fischer) |
| 48474 | * Copyright (c) 2022 Fraunhofer IOSB (Author: Noel Graf) |
| 48475 | */ |
| 48476 | |
| 48477 | |
| 48478 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 48479 | #endif |
| 48480 | |
| 48481 | #ifdef UA_ENABLE_PUBSUB /* conditional compilation */ |
| 48482 | |
| 48483 | UA_StatusCode |
| 48484 | decodeNetworkMessage(UA_Server *server, UA_ByteString *buffer, size_t *pos, |
| 48485 | UA_NetworkMessage *nm, UA_PubSubConnection *connection) { |
| 48486 | #ifdef UA_DEBUG_DUMP_PKGS |
| 48487 | UA_dump_hex_pkg(buffer->data, buffer->length); |
| 48488 | #endif |
| 48489 | |
| 48490 | UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(src: buffer, offset: pos, dst: nm); |
| 48491 | if(rv != UA_STATUSCODE_GOOD) { |
| 48492 | UA_LOG_WARNING_CONNECTION(server->config.logging, connection, |
| 48493 | "PubSub receive. decoding headers failed"); |
| 48494 | UA_NetworkMessage_clear(p: nm); |
| 48495 | return rv; |
| 48496 | } |
| 48497 | |
| 48498 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 48499 | UA_Boolean processed = false; |
| 48500 | UA_ReaderGroup *readerGroup; |
| 48501 | UA_DataSetReader *reader; |
| 48502 | |
| 48503 | /* Choose a correct readergroup for decrypt/verify this message |
| 48504 | * (there could be multiple) */ |
| 48505 | LIST_FOREACH(readerGroup, &connection->readerGroups, listEntry) { |
| 48506 | LIST_FOREACH(reader, &readerGroup->readers, listEntry) { |
| 48507 | UA_StatusCode retval = |
| 48508 | UA_DataSetReader_checkIdentifier(server, nm, reader, readerGroup->config); |
| 48509 | if(retval != UA_STATUSCODE_GOOD) |
| 48510 | continue; |
| 48511 | processed = true; |
| 48512 | rv = verifyAndDecryptNetworkMessage(server->config.logging, buffer, pos, |
| 48513 | nm, readerGroup); |
| 48514 | if(rv != UA_STATUSCODE_GOOD) { |
| 48515 | UA_LOG_WARNING_CONNECTION(server->config.logging, connection, |
| 48516 | "Subscribe failed, verify and decrypt " |
| 48517 | "network message failed."); |
| 48518 | UA_NetworkMessage_clear(nm); |
| 48519 | return rv; |
| 48520 | } |
| 48521 | |
| 48522 | /* break out of all loops when first verify & decrypt was successful */ |
| 48523 | goto loops_exit; |
| 48524 | } |
| 48525 | } |
| 48526 | |
| 48527 | loops_exit: |
| 48528 | if(!processed) { |
| 48529 | UA_DateTime nowM = UA_DateTime_nowMonotonic(); |
| 48530 | if(connection->silenceErrorUntil < nowM) { |
| 48531 | UA_LOG_INFO_CONNECTION(server->config.logging, connection, |
| 48532 | "Dataset reader not found. Check PublisherId, " |
| 48533 | "WriterGroupId and DatasetWriterId. " |
| 48534 | "(This error is now silenced for 10s.)"); |
| 48535 | connection->silenceErrorUntil = nowM + (UA_DateTime)(10.0 * UA_DATETIME_SEC); |
| 48536 | } |
| 48537 | /* Possible multicast scenario: there are multiple connections (with one |
| 48538 | * or more ReaderGroups) within a multicast group every connection |
| 48539 | * receives all network messages, even if some of them are not meant for |
| 48540 | * the connection currently processed -> therefore it is ok if the |
| 48541 | * connection does not have a DataSetReader for every received network |
| 48542 | * message. We must not return an error here, but continue with the |
| 48543 | * buffer decoding and see if we have a matching DataSetReader for the |
| 48544 | * next network message. */ |
| 48545 | } |
| 48546 | #endif |
| 48547 | |
| 48548 | rv = UA_NetworkMessage_decodePayload(src: buffer, offset: pos, dst: nm, customTypes: server->config.customDataTypes, NULL); |
| 48549 | if(rv != UA_STATUSCODE_GOOD) { |
| 48550 | UA_NetworkMessage_clear(p: nm); |
| 48551 | return rv; |
| 48552 | } |
| 48553 | |
| 48554 | rv = UA_NetworkMessage_decodeFooters(src: buffer, offset: pos, dst: nm); |
| 48555 | if(rv != UA_STATUSCODE_GOOD) { |
| 48556 | UA_NetworkMessage_clear(p: nm); |
| 48557 | return rv; |
| 48558 | } |
| 48559 | |
| 48560 | return UA_STATUSCODE_GOOD; |
| 48561 | } |
| 48562 | |
| 48563 | UA_StatusCode |
| 48564 | UA_PubSubConnectionConfig_copy(const UA_PubSubConnectionConfig *src, |
| 48565 | UA_PubSubConnectionConfig *dst) { |
| 48566 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 48567 | memcpy(dest: dst, src: src, n: sizeof(UA_PubSubConnectionConfig)); |
| 48568 | if(src->publisherIdType == UA_PUBLISHERIDTYPE_STRING) { |
| 48569 | res |= UA_String_copy(src: &src->publisherId.string, dst: &dst->publisherId.string); |
| 48570 | } |
| 48571 | res |= UA_String_copy(src: &src->name, dst: &dst->name); |
| 48572 | res |= UA_Variant_copy(src: &src->address, dst: &dst->address); |
| 48573 | res |= UA_String_copy(src: &src->transportProfileUri, dst: &dst->transportProfileUri); |
| 48574 | res |= UA_Variant_copy(src: &src->connectionTransportSettings, |
| 48575 | dst: &dst->connectionTransportSettings); |
| 48576 | res |= UA_KeyValueMap_copy(src: &src->connectionProperties, |
| 48577 | dst: &dst->connectionProperties); |
| 48578 | if(res != UA_STATUSCODE_GOOD) |
| 48579 | UA_PubSubConnectionConfig_clear(connectionConfig: dst); |
| 48580 | return res; |
| 48581 | } |
| 48582 | |
| 48583 | UA_StatusCode |
| 48584 | UA_Server_getPubSubConnectionConfig(UA_Server *server, const UA_NodeId connection, |
| 48585 | UA_PubSubConnectionConfig *config) { |
| 48586 | if(!config) |
| 48587 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 48588 | lockServer(server); |
| 48589 | UA_PubSubConnection *currentPubSubConnection = |
| 48590 | UA_PubSubConnection_findConnectionbyId(server, connectionIdentifier: connection); |
| 48591 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 48592 | if(currentPubSubConnection) |
| 48593 | res = UA_PubSubConnectionConfig_copy(src: ¤tPubSubConnection->config, dst: config); |
| 48594 | unlockServer(server); |
| 48595 | return res; |
| 48596 | } |
| 48597 | |
| 48598 | UA_PubSubConnection * |
| 48599 | UA_PubSubConnection_findConnectionbyId(UA_Server *server, UA_NodeId connectionIdentifier) { |
| 48600 | UA_PubSubConnection *pubSubConnection; |
| 48601 | TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){ |
| 48602 | if(UA_NodeId_equal(p1: &connectionIdentifier, p2: &pubSubConnection->identifier)) |
| 48603 | break; |
| 48604 | } |
| 48605 | return pubSubConnection; |
| 48606 | } |
| 48607 | |
| 48608 | void |
| 48609 | UA_PubSubConnectionConfig_clear(UA_PubSubConnectionConfig *connectionConfig) { |
| 48610 | if(connectionConfig->publisherIdType == UA_PUBLISHERIDTYPE_STRING) |
| 48611 | UA_String_clear(p: &connectionConfig->publisherId.string); |
| 48612 | UA_String_clear(p: &connectionConfig->name); |
| 48613 | UA_String_clear(p: &connectionConfig->transportProfileUri); |
| 48614 | UA_Variant_clear(p: &connectionConfig->connectionTransportSettings); |
| 48615 | UA_Variant_clear(p: &connectionConfig->address); |
| 48616 | UA_KeyValueMap_clear(map: &connectionConfig->connectionProperties); |
| 48617 | } |
| 48618 | |
| 48619 | UA_StatusCode |
| 48620 | UA_PubSubConnection_create(UA_Server *server, const UA_PubSubConnectionConfig *cc, |
| 48621 | UA_NodeId *cId) { |
| 48622 | /* Validate preconditions */ |
| 48623 | UA_CHECK_MEM(server, return UA_STATUSCODE_BADINTERNALERROR); |
| 48624 | UA_CHECK_ERROR(cc != NULL, return UA_STATUSCODE_BADINTERNALERROR, |
| 48625 | server->config.logging, UA_LOGCATEGORY_SERVER, |
| 48626 | "PubSub Connection creation failed. Missing connection configuration."); |
| 48627 | |
| 48628 | /* Allocate */ |
| 48629 | UA_PubSubConnection *c = (UA_PubSubConnection *) |
| 48630 | UA_calloc(nmemb: 1, size: sizeof(UA_PubSubConnection)); |
| 48631 | if(!c) { |
| 48632 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 48633 | msg: "PubSub Connection creation failed. Out of Memory."); |
| 48634 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 48635 | } |
| 48636 | c->componentType = UA_PUBSUB_COMPONENT_CONNECTION; |
| 48637 | |
| 48638 | /* Copy the connection config */ |
| 48639 | UA_StatusCode ret = UA_PubSubConnectionConfig_copy(src: cc, dst: &c->config); |
| 48640 | UA_CHECK_STATUS(ret, UA_free(c); return ret); |
| 48641 | |
| 48642 | /* Assign the connection identifier */ |
| 48643 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 48644 | /* Internally create a unique id */ |
| 48645 | addPubSubConnectionRepresentation(server, connection: c); |
| 48646 | #else |
| 48647 | /* Create a unique NodeId that does not correspond to a Node */ |
| 48648 | UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, |
| 48649 | &c->identifier); |
| 48650 | #endif |
| 48651 | |
| 48652 | /* Register */ |
| 48653 | UA_PubSubManager *pubSubManager = &server->pubSubManager; |
| 48654 | TAILQ_INSERT_HEAD(&pubSubManager->connections, c, listEntry); |
| 48655 | pubSubManager->connectionsSize++; |
| 48656 | |
| 48657 | /* Validate-connect to check the parameters */ |
| 48658 | ret = UA_PubSubConnection_connect(server, c, true); |
| 48659 | if(ret != UA_STATUSCODE_GOOD) |
| 48660 | goto cleanup; |
| 48661 | |
| 48662 | /* Make the connection operational */ |
| 48663 | ret = UA_PubSubConnection_setPubSubState(server, connection: c, state: UA_PUBSUBSTATE_OPERATIONAL, |
| 48664 | UA_STATUSCODE_GOOD); |
| 48665 | if(ret != UA_STATUSCODE_GOOD) |
| 48666 | goto cleanup; |
| 48667 | |
| 48668 | /* Copy the created NodeId to the output. Cannot fail as we create a |
| 48669 | * numerical NodeId. */ |
| 48670 | if(cId) |
| 48671 | UA_NodeId_copy(src: &c->identifier, dst: cId); |
| 48672 | |
| 48673 | cleanup: |
| 48674 | if(ret != UA_STATUSCODE_GOOD) |
| 48675 | UA_PubSubConnection_delete(server, c); |
| 48676 | return ret; |
| 48677 | } |
| 48678 | |
| 48679 | UA_StatusCode |
| 48680 | UA_Server_addPubSubConnection(UA_Server *server, const UA_PubSubConnectionConfig *cc, |
| 48681 | UA_NodeId *cId) { |
| 48682 | lockServer(server); |
| 48683 | UA_StatusCode res = UA_PubSubConnection_create(server, cc, cId); |
| 48684 | unlockServer(server); |
| 48685 | return res; |
| 48686 | } |
| 48687 | |
| 48688 | static void |
| 48689 | delayedPubSubConnection_delete(void *application, void *context) { |
| 48690 | UA_Server *server = (UA_Server*)application; |
| 48691 | UA_PubSubConnection *c = (UA_PubSubConnection*)context; |
| 48692 | lockServer(server); |
| 48693 | UA_PubSubConnection_delete(server, c); |
| 48694 | unlockServer(server); |
| 48695 | } |
| 48696 | |
| 48697 | /* Clean up the PubSubConnection. If no EventLoop connection is attached we can |
| 48698 | * immediately free. Otherwise we close the EventLoop connections and free in |
| 48699 | * the connection callback. */ |
| 48700 | void |
| 48701 | UA_PubSubConnection_delete(UA_Server *server, UA_PubSubConnection *c) { |
| 48702 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 48703 | |
| 48704 | /* Disable (and disconnect) and set the deleteFlag. This prevents a |
| 48705 | * reconnect and triggers the deletion when the last open socket is |
| 48706 | * closed. */ |
| 48707 | c->deleteFlag = true; |
| 48708 | UA_PubSubConnection_setPubSubState(server, connection: c, state: UA_PUBSUBSTATE_DISABLED, UA_STATUSCODE_GOOD); |
| 48709 | |
| 48710 | /* Stop and unfreeze all ReaderGroupds and WriterGroups attached to the |
| 48711 | * Connection. Do this before removing them because we need to unfreeze all |
| 48712 | * to remove the Connection.*/ |
| 48713 | UA_ReaderGroup *readerGroup, *tmpReaderGroup; |
| 48714 | LIST_FOREACH(readerGroup, &c->readerGroups, listEntry) { |
| 48715 | UA_ReaderGroup_setPubSubState(server, readerGroup, state: UA_PUBSUBSTATE_DISABLED, |
| 48716 | UA_STATUSCODE_BADSHUTDOWN); |
| 48717 | UA_ReaderGroup_unfreezeConfiguration(server, rg: readerGroup); |
| 48718 | } |
| 48719 | |
| 48720 | UA_WriterGroup *writerGroup, *tmpWriterGroup; |
| 48721 | LIST_FOREACH(writerGroup, &c->writerGroups, listEntry) { |
| 48722 | UA_WriterGroup_setPubSubState(server, writerGroup, state: UA_PUBSUBSTATE_DISABLED, |
| 48723 | UA_STATUSCODE_BADSHUTDOWN); |
| 48724 | UA_WriterGroup_unfreezeConfiguration(server, wg: writerGroup); |
| 48725 | } |
| 48726 | |
| 48727 | /* Remove all ReaderGorups and WriterGroups */ |
| 48728 | LIST_FOREACH_SAFE(readerGroup, &c->readerGroups, listEntry, tmpReaderGroup) { |
| 48729 | UA_ReaderGroup_remove(server, rg: readerGroup); |
| 48730 | } |
| 48731 | |
| 48732 | LIST_FOREACH_SAFE(writerGroup, &c->writerGroups, listEntry, tmpWriterGroup) { |
| 48733 | UA_WriterGroup_remove(server, wg: writerGroup); |
| 48734 | } |
| 48735 | |
| 48736 | /* Not all sockets are closed. This method will be called again */ |
| 48737 | if(c->sendChannel != 0 || c->recvChannelsSize > 0) |
| 48738 | return; |
| 48739 | |
| 48740 | /* The WriterGroups / ReaderGroups are not deleted. Try again in the next |
| 48741 | * iteration of the event loop.*/ |
| 48742 | if(!LIST_EMPTY(&c->writerGroups) || !LIST_EMPTY(&c->readerGroups)) { |
| 48743 | UA_EventLoop *el = UA_PubSubConnection_getEL(server, c); |
| 48744 | c->dc.callback = delayedPubSubConnection_delete; |
| 48745 | c->dc.application = server; |
| 48746 | c->dc.context = c; |
| 48747 | el->addDelayedCallback(el, &c->dc); |
| 48748 | return; |
| 48749 | } |
| 48750 | |
| 48751 | /* Remove from the information model */ |
| 48752 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 48753 | deleteNode(server, nodeId: c->identifier, true); |
| 48754 | #endif |
| 48755 | |
| 48756 | /* Unlink from the server */ |
| 48757 | TAILQ_REMOVE(&server->pubSubManager.connections, c, listEntry); |
| 48758 | server->pubSubManager.connectionsSize--; |
| 48759 | |
| 48760 | UA_PubSubConnectionConfig_clear(connectionConfig: &c->config); |
| 48761 | UA_NodeId_clear(p: &c->identifier); |
| 48762 | UA_free(ptr: c); |
| 48763 | } |
| 48764 | |
| 48765 | UA_StatusCode |
| 48766 | UA_Server_removePubSubConnection(UA_Server *server, const UA_NodeId connection) { |
| 48767 | lockServer(server); |
| 48768 | UA_PubSubConnection *psc = |
| 48769 | UA_PubSubConnection_findConnectionbyId(server, connectionIdentifier: connection); |
| 48770 | if(!psc) { |
| 48771 | unlockServer(server); |
| 48772 | return UA_STATUSCODE_BADNOTFOUND; |
| 48773 | } |
| 48774 | UA_PubSubConnection_delete(server, c: psc); |
| 48775 | unlockServer(server); |
| 48776 | return UA_STATUSCODE_GOOD; |
| 48777 | } |
| 48778 | |
| 48779 | UA_StatusCode |
| 48780 | UA_PubSubConnection_setPubSubState(UA_Server *server, UA_PubSubConnection *c, |
| 48781 | UA_PubSubState state, UA_StatusCode cause) { |
| 48782 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 48783 | |
| 48784 | if(c->deleteFlag && state != UA_PUBSUBSTATE_DISABLED) { |
| 48785 | UA_LOG_WARNING_CONNECTION(server->config.logging, c, |
| 48786 | "The connection is being deleted. Can only be disabled."); |
| 48787 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48788 | } |
| 48789 | |
| 48790 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 48791 | UA_PubSubState oldState = c->state; |
| 48792 | UA_WriterGroup *writerGroup; |
| 48793 | UA_ReaderGroup *readerGroup; |
| 48794 | |
| 48795 | switch(state) { |
| 48796 | case UA_PUBSUBSTATE_ERROR: |
| 48797 | case UA_PUBSUBSTATE_PAUSED: |
| 48798 | case UA_PUBSUBSTATE_DISABLED: |
| 48799 | if(state == oldState) |
| 48800 | break; |
| 48801 | |
| 48802 | /* Close the EventLoop connection */ |
| 48803 | c->state = state; |
| 48804 | UA_PubSubConnection_disconnect(c); |
| 48805 | |
| 48806 | /* Disable Reader and WriterGroups */ |
| 48807 | LIST_FOREACH(readerGroup, &c->readerGroups, listEntry) { |
| 48808 | UA_ReaderGroup_setPubSubState(server, readerGroup, state, |
| 48809 | UA_STATUSCODE_BADRESOURCEUNAVAILABLE); |
| 48810 | } |
| 48811 | LIST_FOREACH(writerGroup, &c->writerGroups, listEntry) { |
| 48812 | UA_WriterGroup_setPubSubState(server, writerGroup, state, |
| 48813 | UA_STATUSCODE_BADRESOURCEUNAVAILABLE); |
| 48814 | } |
| 48815 | break; |
| 48816 | |
| 48817 | case UA_PUBSUBSTATE_PREOPERATIONAL: |
| 48818 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 48819 | /* Called also if the connection is already operational. We might to |
| 48820 | * open an additional recv connection, etc. Sets the new state |
| 48821 | * internally. */ |
| 48822 | if(oldState != UA_PUBSUBSTATE_OPERATIONAL) |
| 48823 | c->state = UA_PUBSUBSTATE_PREOPERATIONAL; |
| 48824 | ret = UA_PubSubConnection_connect(server, c, false); |
| 48825 | if(ret != UA_STATUSCODE_GOOD) |
| 48826 | UA_PubSubConnection_setPubSubState(server, c, |
| 48827 | state: UA_PUBSUBSTATE_ERROR, cause: ret); |
| 48828 | break; |
| 48829 | default: |
| 48830 | UA_LOG_WARNING_CONNECTION(server->config.logging, c, |
| 48831 | "Received unknown PubSub state!"); |
| 48832 | return UA_STATUSCODE_BADINTERNALERROR; |
| 48833 | } |
| 48834 | |
| 48835 | /* Inform application about state change */ |
| 48836 | if(c->state != oldState) { |
| 48837 | UA_ServerConfig *config = &server->config; |
| 48838 | if(config->pubSubConfig.stateChangeCallback) |
| 48839 | config->pubSubConfig.stateChangeCallback(server, &c->identifier, state, cause); |
| 48840 | } |
| 48841 | return ret; |
| 48842 | } |
| 48843 | |
| 48844 | UA_EventLoop * |
| 48845 | UA_PubSubConnection_getEL(UA_Server *server, UA_PubSubConnection *c) { |
| 48846 | if(c->config.eventLoop) |
| 48847 | return c->config.eventLoop; |
| 48848 | return server->config.eventLoop; |
| 48849 | } |
| 48850 | |
| 48851 | #endif /* UA_ENABLE_PUBSUB */ |
| 48852 | |
| 48853 | /**** amalgamated original file "/src/pubsub/ua_pubsub_dataset.c" ****/ |
| 48854 | |
| 48855 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 48856 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 48857 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 48858 | * |
| 48859 | * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner) |
| 48860 | * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer) |
| 48861 | * Copyright (c) 2019-2021 Kalycito Infotech Private Limited |
| 48862 | * Copyright (c) 2020 Yannick Wallerer, Siemens AG |
| 48863 | * Copyright (c) 2020 Thomas Fischer, Siemens AG |
| 48864 | * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes) |
| 48865 | */ |
| 48866 | |
| 48867 | |
| 48868 | #ifdef UA_ENABLE_PUBSUB /* conditional compilation */ |
| 48869 | |
| 48870 | static void |
| 48871 | UA_DataSetField_clear(UA_DataSetField *field) { |
| 48872 | UA_DataSetFieldConfig_clear(dataSetFieldConfig: &field->config); |
| 48873 | UA_NodeId_clear(p: &field->identifier); |
| 48874 | UA_NodeId_clear(p: &field->publishedDataSet); |
| 48875 | UA_FieldMetaData_clear(p: &field->fieldMetaData); |
| 48876 | } |
| 48877 | |
| 48878 | UA_StatusCode |
| 48879 | UA_PublishedDataSetConfig_copy(const UA_PublishedDataSetConfig *src, |
| 48880 | UA_PublishedDataSetConfig *dst) { |
| 48881 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 48882 | memcpy(dest: dst, src: src, n: sizeof(UA_PublishedDataSetConfig)); |
| 48883 | res |= UA_String_copy(src: &src->name, dst: &dst->name); |
| 48884 | switch(src->publishedDataSetType) { |
| 48885 | case UA_PUBSUB_DATASET_PUBLISHEDITEMS: |
| 48886 | //no additional items |
| 48887 | break; |
| 48888 | |
| 48889 | case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE: |
| 48890 | if(src->config.itemsTemplate.variablesToAddSize > 0) { |
| 48891 | dst->config.itemsTemplate.variablesToAdd = (UA_PublishedVariableDataType *) |
| 48892 | UA_calloc(nmemb: src->config.itemsTemplate.variablesToAddSize, |
| 48893 | size: sizeof(UA_PublishedVariableDataType)); |
| 48894 | if(!dst->config.itemsTemplate.variablesToAdd) { |
| 48895 | res = UA_STATUSCODE_BADOUTOFMEMORY; |
| 48896 | break; |
| 48897 | } |
| 48898 | dst->config.itemsTemplate.variablesToAddSize = |
| 48899 | src->config.itemsTemplate.variablesToAddSize; |
| 48900 | } |
| 48901 | |
| 48902 | for(size_t i = 0; i < src->config.itemsTemplate.variablesToAddSize; i++) { |
| 48903 | res |= UA_PublishedVariableDataType_copy(src: &src->config.itemsTemplate.variablesToAdd[i], |
| 48904 | dst: &dst->config.itemsTemplate.variablesToAdd[i]); |
| 48905 | } |
| 48906 | res |= UA_DataSetMetaDataType_copy(src: &src->config.itemsTemplate.metaData, |
| 48907 | dst: &dst->config.itemsTemplate.metaData); |
| 48908 | break; |
| 48909 | |
| 48910 | default: |
| 48911 | res = UA_STATUSCODE_BADINVALIDARGUMENT; |
| 48912 | break; |
| 48913 | } |
| 48914 | |
| 48915 | if(res != UA_STATUSCODE_GOOD) |
| 48916 | UA_PublishedDataSetConfig_clear(pdsConfig: dst); |
| 48917 | return res; |
| 48918 | } |
| 48919 | |
| 48920 | UA_StatusCode |
| 48921 | getPublishedDataSetConfig(UA_Server *server, const UA_NodeId pds, |
| 48922 | UA_PublishedDataSetConfig *config) { |
| 48923 | if(!config) |
| 48924 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 48925 | UA_PublishedDataSet *currentPDS = UA_PublishedDataSet_findPDSbyId(server, identifier: pds); |
| 48926 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 48927 | if(currentPDS) |
| 48928 | res = UA_PublishedDataSetConfig_copy(src: ¤tPDS->config, dst: config); |
| 48929 | return res; |
| 48930 | } |
| 48931 | |
| 48932 | UA_StatusCode |
| 48933 | UA_Server_getPublishedDataSetConfig(UA_Server *server, const UA_NodeId pds, |
| 48934 | UA_PublishedDataSetConfig *config) { |
| 48935 | lockServer(server); |
| 48936 | UA_StatusCode res = getPublishedDataSetConfig(server, pds, config); |
| 48937 | unlockServer(server); |
| 48938 | return res; |
| 48939 | } |
| 48940 | |
| 48941 | UA_StatusCode |
| 48942 | UA_Server_getPublishedDataSetMetaData(UA_Server *server, const UA_NodeId pds, |
| 48943 | UA_DataSetMetaDataType *metaData) { |
| 48944 | if(!metaData) |
| 48945 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 48946 | lockServer(server); |
| 48947 | UA_PublishedDataSet *currentPDS = UA_PublishedDataSet_findPDSbyId(server, identifier: pds); |
| 48948 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 48949 | if(currentPDS) |
| 48950 | res = UA_DataSetMetaDataType_copy(src: ¤tPDS->dataSetMetaData, dst: metaData); |
| 48951 | unlockServer(server); |
| 48952 | return res; |
| 48953 | } |
| 48954 | |
| 48955 | UA_PublishedDataSet * |
| 48956 | UA_PublishedDataSet_findPDSbyId(UA_Server *server, UA_NodeId identifier) { |
| 48957 | UA_PublishedDataSet *tmpPDS = NULL; |
| 48958 | TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry) { |
| 48959 | if(UA_NodeId_equal(p1: &tmpPDS->identifier, p2: &identifier)) |
| 48960 | break; |
| 48961 | } |
| 48962 | return tmpPDS; |
| 48963 | } |
| 48964 | |
| 48965 | UA_PublishedDataSet * |
| 48966 | UA_PublishedDataSet_findPDSbyName(UA_Server *server, UA_String name) { |
| 48967 | UA_PublishedDataSet *tmpPDS = NULL; |
| 48968 | TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry) { |
| 48969 | if(UA_String_equal(p1: &name, p2: &tmpPDS->config.name)) |
| 48970 | break; |
| 48971 | } |
| 48972 | |
| 48973 | return tmpPDS; |
| 48974 | } |
| 48975 | |
| 48976 | void |
| 48977 | UA_PublishedDataSetConfig_clear(UA_PublishedDataSetConfig *pdsConfig) { |
| 48978 | //delete pds config |
| 48979 | UA_String_clear(p: &pdsConfig->name); |
| 48980 | switch (pdsConfig->publishedDataSetType){ |
| 48981 | case UA_PUBSUB_DATASET_PUBLISHEDITEMS: |
| 48982 | //no additional items |
| 48983 | break; |
| 48984 | case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE: |
| 48985 | if(pdsConfig->config.itemsTemplate.variablesToAddSize > 0){ |
| 48986 | for(size_t i = 0; i < pdsConfig->config.itemsTemplate.variablesToAddSize; i++){ |
| 48987 | UA_PublishedVariableDataType_clear(p: &pdsConfig->config.itemsTemplate.variablesToAdd[i]); |
| 48988 | } |
| 48989 | UA_free(ptr: pdsConfig->config.itemsTemplate.variablesToAdd); |
| 48990 | } |
| 48991 | UA_DataSetMetaDataType_clear(p: &pdsConfig->config.itemsTemplate.metaData); |
| 48992 | break; |
| 48993 | default: |
| 48994 | break; |
| 48995 | } |
| 48996 | } |
| 48997 | |
| 48998 | void |
| 48999 | UA_PublishedDataSet_clear(UA_Server *server, UA_PublishedDataSet *publishedDataSet) { |
| 49000 | UA_DataSetField *field, *tmpField; |
| 49001 | TAILQ_FOREACH_SAFE(field, &publishedDataSet->fields, listEntry, tmpField) { |
| 49002 | /* Code in this block is a duplication of similar code in UA_DataSetField_remove, but |
| 49003 | * this is intentional. We don't want to call UA_DataSetField_remove here as that |
| 49004 | * function regenerates DataSetMetaData, which is not necessary if we want to |
| 49005 | * clear the whole PDS anyway. */ |
| 49006 | if(field->configurationFrozen) { |
| 49007 | UA_LOG_WARNING_DATASET(server->config.logging, publishedDataSet, |
| 49008 | "Clearing a frozen field."); |
| 49009 | } |
| 49010 | field->fieldMetaData.arrayDimensions = NULL; |
| 49011 | field->fieldMetaData.properties = NULL; |
| 49012 | field->fieldMetaData.name = UA_STRING_NULL; |
| 49013 | field->fieldMetaData.description.locale = UA_STRING_NULL; |
| 49014 | field->fieldMetaData.description.text = UA_STRING_NULL; |
| 49015 | UA_DataSetField_clear(field); |
| 49016 | TAILQ_REMOVE(&publishedDataSet->fields, field, listEntry); |
| 49017 | UA_free(ptr: field); |
| 49018 | } |
| 49019 | UA_PublishedDataSetConfig_clear(pdsConfig: &publishedDataSet->config); |
| 49020 | UA_DataSetMetaDataType_clear(p: &publishedDataSet->dataSetMetaData); |
| 49021 | UA_NodeId_clear(p: &publishedDataSet->identifier); |
| 49022 | } |
| 49023 | |
| 49024 | /* The fieldMetaData variable has to be cleaned up external in case of an error */ |
| 49025 | static UA_StatusCode |
| 49026 | generateFieldMetaData(UA_Server *server, UA_PublishedDataSet *pds, |
| 49027 | UA_DataSetField *field, UA_FieldMetaData *fieldMetaData) { |
| 49028 | if(field->config.dataSetFieldType != UA_PUBSUB_DATASETFIELD_VARIABLE) |
| 49029 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 49030 | |
| 49031 | /* Set the field identifier */ |
| 49032 | fieldMetaData->dataSetFieldId = UA_PubSubManager_generateUniqueGuid(server); |
| 49033 | |
| 49034 | /* Set the description */ |
| 49035 | fieldMetaData->description = UA_LOCALIZEDTEXT_ALLOC(locale: "", text: ""); |
| 49036 | |
| 49037 | /* Set the name */ |
| 49038 | const UA_DataSetVariableConfig *var = &field->config.field.variable; |
| 49039 | UA_StatusCode res = UA_String_copy(src: &var->fieldNameAlias, dst: &fieldMetaData->name); |
| 49040 | UA_CHECK_STATUS(res, return res); |
| 49041 | |
| 49042 | /* Static value source. ToDo after freeze PR, the value source must be |
| 49043 | * checked (other behavior for static value source) */ |
| 49044 | if(var->rtValueSource.rtFieldSourceEnabled && |
| 49045 | !var->rtValueSource.rtInformationModelNode) { |
| 49046 | const UA_DataValue *svs = *var->rtValueSource.staticValueSource; |
| 49047 | if(svs->value.arrayDimensionsSize > 0) { |
| 49048 | fieldMetaData->arrayDimensions = (UA_UInt32 *) |
| 49049 | UA_calloc(nmemb: svs->value.arrayDimensionsSize, size: sizeof(UA_UInt32)); |
| 49050 | if(fieldMetaData->arrayDimensions == NULL) |
| 49051 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 49052 | memcpy(dest: fieldMetaData->arrayDimensions, src: svs->value.arrayDimensions, |
| 49053 | n: sizeof(UA_UInt32) * svs->value.arrayDimensionsSize); |
| 49054 | } |
| 49055 | fieldMetaData->arrayDimensionsSize = svs->value.arrayDimensionsSize; |
| 49056 | |
| 49057 | if(svs->value.type) |
| 49058 | res = UA_NodeId_copy(src: &svs->value.type->typeId, dst: &fieldMetaData->dataType); |
| 49059 | UA_CHECK_STATUS(res, return res); |
| 49060 | |
| 49061 | //TODO collect value rank for the static field source |
| 49062 | fieldMetaData->properties = NULL; |
| 49063 | fieldMetaData->propertiesSize = 0; |
| 49064 | fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_NONE; |
| 49065 | return UA_STATUSCODE_GOOD; |
| 49066 | } |
| 49067 | |
| 49068 | /* Set the Array Dimensions */ |
| 49069 | const UA_PublishedVariableDataType *pp = &var->publishParameters; |
| 49070 | UA_Variant value; |
| 49071 | UA_Variant_init(p: &value); |
| 49072 | res = readWithReadValue(server, nodeId: &pp->publishedVariable, |
| 49073 | attributeId: UA_ATTRIBUTEID_ARRAYDIMENSIONS, v: &value); |
| 49074 | if(res != UA_STATUSCODE_GOOD) { |
| 49075 | UA_LOG_WARNING_DATASET(server->config.logging, pds, |
| 49076 | "PubSub meta data generation: Reading the array dimensions failed"); |
| 49077 | return res; |
| 49078 | } |
| 49079 | |
| 49080 | if(value.arrayDimensionsSize > 0) { |
| 49081 | fieldMetaData->arrayDimensions = (UA_UInt32 *) |
| 49082 | UA_calloc(nmemb: value.arrayDimensionsSize, size: sizeof(UA_UInt32)); |
| 49083 | if(!fieldMetaData->arrayDimensions) |
| 49084 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 49085 | memcpy(dest: fieldMetaData->arrayDimensions, src: value.arrayDimensions, |
| 49086 | n: sizeof(UA_UInt32)*value.arrayDimensionsSize); |
| 49087 | } |
| 49088 | fieldMetaData->arrayDimensionsSize = value.arrayDimensionsSize; |
| 49089 | |
| 49090 | UA_Variant_clear(p: &value); |
| 49091 | |
| 49092 | /* Set the DataType */ |
| 49093 | res = readWithReadValue(server, nodeId: &pp->publishedVariable, |
| 49094 | attributeId: UA_ATTRIBUTEID_DATATYPE, v: &fieldMetaData->dataType); |
| 49095 | if(res != UA_STATUSCODE_GOOD) { |
| 49096 | UA_LOG_WARNING_DATASET(server->config.logging, pds, |
| 49097 | "PubSub meta data generation: Reading the datatype failed"); |
| 49098 | return res; |
| 49099 | } |
| 49100 | |
| 49101 | if(!UA_NodeId_isNull(p: &fieldMetaData->dataType)) { |
| 49102 | const UA_DataType *currentDataType = |
| 49103 | UA_findDataTypeWithCustom(typeId: &fieldMetaData->dataType, |
| 49104 | customTypes: server->config.customDataTypes); |
| 49105 | #ifdef UA_ENABLE_TYPEDESCRIPTION |
| 49106 | UA_LOG_DEBUG_DATASET(server->config.logging, pds, |
| 49107 | "MetaData creation: Found DataType %s", |
| 49108 | currentDataType->typeName); |
| 49109 | #endif |
| 49110 | /* Check if the datatype is a builtInType, if yes set the builtinType. */ |
| 49111 | if(currentDataType->typeKind <= UA_DATATYPEKIND_ENUM) |
| 49112 | fieldMetaData->builtInType = (UA_Byte)currentDataType->typeId.identifier.numeric; |
| 49113 | /* set the maxStringLength attribute */ |
| 49114 | if(field->config.field.variable.maxStringLength != 0){ |
| 49115 | if(currentDataType->typeKind == UA_DATATYPEKIND_BYTESTRING || |
| 49116 | currentDataType->typeKind == UA_DATATYPEKIND_STRING || |
| 49117 | currentDataType->typeKind == UA_DATATYPEKIND_LOCALIZEDTEXT) { |
| 49118 | fieldMetaData->maxStringLength = field->config.field.variable.maxStringLength; |
| 49119 | } else { |
| 49120 | UA_LOG_WARNING_DATASET(server->config.logging, pds, |
| 49121 | "PubSub meta data generation: MaxStringLength with incompatible DataType configured."); |
| 49122 | } |
| 49123 | } |
| 49124 | } else { |
| 49125 | UA_LOG_WARNING_DATASET(server->config.logging, pds, |
| 49126 | "PubSub meta data generation: DataType is UA_NODEID_NULL"); |
| 49127 | } |
| 49128 | |
| 49129 | /* Set the ValueRank */ |
| 49130 | UA_Int32 valueRank; |
| 49131 | res = readWithReadValue(server, nodeId: &pp->publishedVariable, |
| 49132 | attributeId: UA_ATTRIBUTEID_VALUERANK, v: &valueRank); |
| 49133 | if(res != UA_STATUSCODE_GOOD) { |
| 49134 | UA_LOG_WARNING_DATASET(server->config.logging, pds, |
| 49135 | "PubSub meta data generation: Reading the value rank failed"); |
| 49136 | return res; |
| 49137 | } |
| 49138 | fieldMetaData->valueRank = valueRank; |
| 49139 | |
| 49140 | /* PromotedField? */ |
| 49141 | if(var->promotedField) |
| 49142 | fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_PROMOTEDFIELD; |
| 49143 | else |
| 49144 | fieldMetaData->fieldFlags = UA_DATASETFIELDFLAGS_NONE; |
| 49145 | |
| 49146 | /* Properties */ |
| 49147 | fieldMetaData->properties = NULL; |
| 49148 | fieldMetaData->propertiesSize = 0; |
| 49149 | |
| 49150 | //TODO collect the following fields*/ |
| 49151 | //fieldMetaData.builtInType |
| 49152 | //fieldMetaData.maxStringLength |
| 49153 | |
| 49154 | return UA_STATUSCODE_GOOD; |
| 49155 | } |
| 49156 | |
| 49157 | UA_DataSetFieldResult |
| 49158 | UA_DataSetField_create(UA_Server *server, const UA_NodeId publishedDataSet, |
| 49159 | const UA_DataSetFieldConfig *fieldConfig, |
| 49160 | UA_NodeId *fieldIdentifier) { |
| 49161 | UA_DataSetFieldResult result; |
| 49162 | memset(s: &result, c: 0, n: sizeof(UA_DataSetFieldResult)); |
| 49163 | if(!fieldConfig) { |
| 49164 | result.result = UA_STATUSCODE_BADINVALIDARGUMENT; |
| 49165 | return result; |
| 49166 | } |
| 49167 | |
| 49168 | UA_PublishedDataSet *currDS = |
| 49169 | UA_PublishedDataSet_findPDSbyId(server, identifier: publishedDataSet); |
| 49170 | if(!currDS) { |
| 49171 | result.result = UA_STATUSCODE_BADNOTFOUND; |
| 49172 | return result; |
| 49173 | } |
| 49174 | |
| 49175 | if(currDS->configurationFreezeCounter > 0) { |
| 49176 | UA_LOG_WARNING_DATASET(server->config.logging, currDS, |
| 49177 | "Adding DataSetField failed: PublishedDataSet is frozen"); |
| 49178 | result.result = UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 49179 | return result; |
| 49180 | } |
| 49181 | |
| 49182 | if(currDS->config.publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS) { |
| 49183 | result.result = UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 49184 | return result; |
| 49185 | } |
| 49186 | |
| 49187 | UA_DataSetField *newField = (UA_DataSetField*)UA_calloc(nmemb: 1, size: sizeof(UA_DataSetField)); |
| 49188 | if(!newField) { |
| 49189 | result.result = UA_STATUSCODE_BADINTERNALERROR; |
| 49190 | return result; |
| 49191 | } |
| 49192 | |
| 49193 | result.result = UA_DataSetFieldConfig_copy(src: fieldConfig, dst: &newField->config); |
| 49194 | if(result.result != UA_STATUSCODE_GOOD) { |
| 49195 | UA_free(ptr: newField); |
| 49196 | return result; |
| 49197 | } |
| 49198 | |
| 49199 | result.result = UA_NodeId_copy(src: &currDS->identifier, dst: &newField->publishedDataSet); |
| 49200 | if(result.result != UA_STATUSCODE_GOOD) { |
| 49201 | UA_DataSetFieldConfig_clear(dataSetFieldConfig: &newField->config); |
| 49202 | UA_free(ptr: newField); |
| 49203 | return result; |
| 49204 | } |
| 49205 | |
| 49206 | /* Initialize the field metadata. Also generates a FieldId */ |
| 49207 | UA_FieldMetaData fmd; |
| 49208 | UA_FieldMetaData_init(p: &fmd); |
| 49209 | result.result = generateFieldMetaData(server, pds: currDS, field: newField, fieldMetaData: &fmd); |
| 49210 | if(result.result != UA_STATUSCODE_GOOD) { |
| 49211 | UA_FieldMetaData_clear(p: &fmd); |
| 49212 | UA_DataSetFieldConfig_clear(dataSetFieldConfig: &newField->config); |
| 49213 | UA_NodeId_clear(p: &newField->publishedDataSet); |
| 49214 | UA_free(ptr: newField); |
| 49215 | return result; |
| 49216 | } |
| 49217 | |
| 49218 | /* Append to the metadata fields array. Point of last return. */ |
| 49219 | result.result = UA_Array_appendCopy(p: (void**)&currDS->dataSetMetaData.fields, |
| 49220 | size: &currDS->dataSetMetaData.fieldsSize, |
| 49221 | newElem: &fmd, type: &UA_TYPES[UA_TYPES_FIELDMETADATA]); |
| 49222 | if(result.result != UA_STATUSCODE_GOOD) { |
| 49223 | UA_FieldMetaData_clear(p: &fmd); |
| 49224 | UA_DataSetFieldConfig_clear(dataSetFieldConfig: &newField->config); |
| 49225 | UA_NodeId_clear(p: &newField->publishedDataSet); |
| 49226 | UA_free(ptr: newField); |
| 49227 | return result; |
| 49228 | } |
| 49229 | |
| 49230 | /* Copy the identifier from the metadata. Cannot fail with a guid NodeId. */ |
| 49231 | newField->identifier = UA_NODEID_GUID(nsIndex: 1, guid: fmd.dataSetFieldId); |
| 49232 | if(fieldIdentifier) |
| 49233 | UA_NodeId_copy(src: &newField->identifier, dst: fieldIdentifier); |
| 49234 | UA_FieldMetaData_clear(p: &fmd); |
| 49235 | |
| 49236 | /* Register the field. The order of DataSetFields should be the same in both |
| 49237 | * creating and publishing. So adding DataSetFields at the the end of the |
| 49238 | * DataSets using the TAILQ structure. */ |
| 49239 | TAILQ_INSERT_TAIL(&currDS->fields, newField, listEntry); |
| 49240 | currDS->fieldSize++; |
| 49241 | |
| 49242 | if(newField->config.field.variable.promotedField) |
| 49243 | currDS->promotedFieldsCount++; |
| 49244 | |
| 49245 | /* The values of the metadata are "borrowed" in a mirrored structure in the |
| 49246 | * pds. Reset them after resizing the array. */ |
| 49247 | size_t counter = 0; |
| 49248 | UA_DataSetField *dsf; |
| 49249 | TAILQ_FOREACH(dsf, &currDS->fields, listEntry) { |
| 49250 | dsf->fieldMetaData = currDS->dataSetMetaData.fields[counter++]; |
| 49251 | } |
| 49252 | |
| 49253 | /* Update major version of parent published data set */ |
| 49254 | currDS->dataSetMetaData.configurationVersion.majorVersion = |
| 49255 | UA_PubSubConfigurationVersionTimeDifference(); |
| 49256 | |
| 49257 | result.configurationVersion.majorVersion = |
| 49258 | currDS->dataSetMetaData.configurationVersion.majorVersion; |
| 49259 | result.configurationVersion.minorVersion = |
| 49260 | currDS->dataSetMetaData.configurationVersion.minorVersion; |
| 49261 | return result; |
| 49262 | } |
| 49263 | |
| 49264 | UA_DataSetFieldResult |
| 49265 | UA_Server_addDataSetField(UA_Server *server, const UA_NodeId publishedDataSet, |
| 49266 | const UA_DataSetFieldConfig *fieldConfig, |
| 49267 | UA_NodeId *fieldIdentifier) { |
| 49268 | lockServer(server); |
| 49269 | UA_DataSetFieldResult res = |
| 49270 | UA_DataSetField_create(server, publishedDataSet, fieldConfig, fieldIdentifier); |
| 49271 | unlockServer(server); |
| 49272 | return res; |
| 49273 | } |
| 49274 | |
| 49275 | UA_DataSetFieldResult |
| 49276 | UA_DataSetField_remove(UA_Server *server, UA_DataSetField *currentField) { |
| 49277 | UA_DataSetFieldResult result; |
| 49278 | memset(s: &result, c: 0, n: sizeof(UA_DataSetFieldResult)); |
| 49279 | |
| 49280 | UA_PublishedDataSet *pds = |
| 49281 | UA_PublishedDataSet_findPDSbyId(server, identifier: currentField->publishedDataSet); |
| 49282 | if(!pds) { |
| 49283 | result.result = UA_STATUSCODE_BADNOTFOUND; |
| 49284 | return result; |
| 49285 | } |
| 49286 | |
| 49287 | if(currentField->configurationFrozen) { |
| 49288 | UA_LOG_WARNING_DATASET(server->config.logging, pds, |
| 49289 | "Remove DataSetField failed: DataSetField is frozen"); |
| 49290 | result.result = UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 49291 | return result; |
| 49292 | } |
| 49293 | |
| 49294 | if(pds->configurationFreezeCounter > 0) { |
| 49295 | UA_LOG_WARNING_DATASET(server->config.logging, pds, |
| 49296 | "Remove DataSetField failed: PublishedDataSet is frozen"); |
| 49297 | result.result = UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 49298 | return result; |
| 49299 | } |
| 49300 | |
| 49301 | /* Reduce the counters before the config is cleaned up */ |
| 49302 | if(currentField->config.field.variable.promotedField) |
| 49303 | pds->promotedFieldsCount--; |
| 49304 | pds->fieldSize--; |
| 49305 | |
| 49306 | /* Update major version of PublishedDataSet */ |
| 49307 | pds->dataSetMetaData.configurationVersion.majorVersion = |
| 49308 | UA_PubSubConfigurationVersionTimeDifference(); |
| 49309 | |
| 49310 | /* Clean up */ |
| 49311 | currentField->fieldMetaData.arrayDimensions = NULL; |
| 49312 | currentField->fieldMetaData.properties = NULL; |
| 49313 | currentField->fieldMetaData.name = UA_STRING_NULL; |
| 49314 | currentField->fieldMetaData.description.locale = UA_STRING_NULL; |
| 49315 | currentField->fieldMetaData.description.text = UA_STRING_NULL; |
| 49316 | UA_DataSetField_clear(field: currentField); |
| 49317 | |
| 49318 | /* Remove */ |
| 49319 | TAILQ_REMOVE(&pds->fields, currentField, listEntry); |
| 49320 | UA_free(ptr: currentField); |
| 49321 | |
| 49322 | /* Regenerate DataSetMetaData */ |
| 49323 | pds->dataSetMetaData.fieldsSize--; |
| 49324 | if(pds->dataSetMetaData.fieldsSize > 0) { |
| 49325 | for(size_t i = 0; i < pds->dataSetMetaData.fieldsSize+1; i++) { |
| 49326 | UA_FieldMetaData_clear(p: &pds->dataSetMetaData.fields[i]); |
| 49327 | } |
| 49328 | UA_free(ptr: pds->dataSetMetaData.fields); |
| 49329 | UA_FieldMetaData *fieldMetaData = (UA_FieldMetaData *) |
| 49330 | UA_calloc(nmemb: pds->dataSetMetaData.fieldsSize, size: sizeof(UA_FieldMetaData)); |
| 49331 | if(!fieldMetaData) { |
| 49332 | result.result = UA_STATUSCODE_BADOUTOFMEMORY; |
| 49333 | return result; |
| 49334 | } |
| 49335 | UA_DataSetField *tmpDSF; |
| 49336 | size_t counter = 0; |
| 49337 | TAILQ_FOREACH(tmpDSF, &pds->fields, listEntry) { |
| 49338 | result.result = generateFieldMetaData(server, pds, field: tmpDSF, fieldMetaData: &fieldMetaData[counter]); |
| 49339 | if(result.result != UA_STATUSCODE_GOOD) { |
| 49340 | UA_FieldMetaData_clear(p: &fieldMetaData[counter]); |
| 49341 | UA_LOG_WARNING_DATASET(server->config.logging, pds, |
| 49342 | "PubSub MetaData regeneration failed " |
| 49343 | "after removing a field!"); |
| 49344 | break; |
| 49345 | } |
| 49346 | // The contents of the metadata is shared between the PDS and its fields. |
| 49347 | tmpDSF->fieldMetaData = fieldMetaData[counter++]; |
| 49348 | } |
| 49349 | pds->dataSetMetaData.fields = fieldMetaData; |
| 49350 | } else { |
| 49351 | UA_FieldMetaData_delete(p: pds->dataSetMetaData.fields); |
| 49352 | pds->dataSetMetaData.fields = NULL; |
| 49353 | } |
| 49354 | |
| 49355 | result.configurationVersion.majorVersion = |
| 49356 | pds->dataSetMetaData.configurationVersion.majorVersion; |
| 49357 | result.configurationVersion.minorVersion = |
| 49358 | pds->dataSetMetaData.configurationVersion.minorVersion; |
| 49359 | return result; |
| 49360 | } |
| 49361 | |
| 49362 | UA_DataSetFieldResult |
| 49363 | UA_Server_removeDataSetField(UA_Server *server, const UA_NodeId dsf) { |
| 49364 | lockServer(server); |
| 49365 | UA_DataSetFieldResult res; |
| 49366 | memset(s: &res, c: 0, n: sizeof(UA_DataSetFieldResult)); |
| 49367 | UA_DataSetField *field = UA_DataSetField_findDSFbyId(server, identifier: dsf); |
| 49368 | if(!field) { |
| 49369 | res.result = UA_STATUSCODE_BADNOTFOUND; |
| 49370 | unlockServer(server); |
| 49371 | return res; |
| 49372 | } |
| 49373 | res = UA_DataSetField_remove(server, currentField: field); |
| 49374 | unlockServer(server); |
| 49375 | return res; |
| 49376 | } |
| 49377 | |
| 49378 | UA_StatusCode |
| 49379 | UA_DataSetFieldConfig_copy(const UA_DataSetFieldConfig *src, |
| 49380 | UA_DataSetFieldConfig *dst) { |
| 49381 | if(src->dataSetFieldType != UA_PUBSUB_DATASETFIELD_VARIABLE) |
| 49382 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 49383 | memcpy(dest: dst, src: src, n: sizeof(UA_DataSetFieldConfig)); |
| 49384 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 49385 | res |= UA_String_copy(src: &src->field.variable.fieldNameAlias, |
| 49386 | dst: &dst->field.variable.fieldNameAlias); |
| 49387 | res |= UA_PublishedVariableDataType_copy(src: &src->field.variable.publishParameters, |
| 49388 | dst: &dst->field.variable.publishParameters); |
| 49389 | if(res != UA_STATUSCODE_GOOD) |
| 49390 | UA_DataSetFieldConfig_clear(dataSetFieldConfig: dst); |
| 49391 | return res; |
| 49392 | } |
| 49393 | |
| 49394 | UA_StatusCode |
| 49395 | UA_Server_getDataSetFieldConfig(UA_Server *server, const UA_NodeId dsf, |
| 49396 | UA_DataSetFieldConfig *config) { |
| 49397 | if(!config) |
| 49398 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 49399 | lockServer(server); |
| 49400 | UA_DataSetField *currentDataSetField = UA_DataSetField_findDSFbyId(server, identifier: dsf); |
| 49401 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 49402 | if(currentDataSetField) |
| 49403 | res = UA_DataSetFieldConfig_copy(src: ¤tDataSetField->config, dst: config); |
| 49404 | unlockServer(server); |
| 49405 | return res; |
| 49406 | } |
| 49407 | |
| 49408 | UA_DataSetField * |
| 49409 | UA_DataSetField_findDSFbyId(UA_Server *server, UA_NodeId identifier) { |
| 49410 | UA_PublishedDataSet *tmpPDS; |
| 49411 | TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry) { |
| 49412 | UA_DataSetField *tmpField; |
| 49413 | TAILQ_FOREACH(tmpField, &tmpPDS->fields, listEntry) { |
| 49414 | if(UA_NodeId_equal(p1: &tmpField->identifier, p2: &identifier)) |
| 49415 | return tmpField; |
| 49416 | } |
| 49417 | } |
| 49418 | return NULL; |
| 49419 | } |
| 49420 | |
| 49421 | void |
| 49422 | UA_DataSetFieldConfig_clear(UA_DataSetFieldConfig *dataSetFieldConfig) { |
| 49423 | if(dataSetFieldConfig->dataSetFieldType == UA_PUBSUB_DATASETFIELD_VARIABLE) { |
| 49424 | UA_String_clear(p: &dataSetFieldConfig->field.variable.fieldNameAlias); |
| 49425 | UA_PublishedVariableDataType_clear(p: &dataSetFieldConfig->field.variable.publishParameters); |
| 49426 | } |
| 49427 | } |
| 49428 | |
| 49429 | /* Obtain the latest value for a specific DataSetField. This method is currently |
| 49430 | * called inside the DataSetMessage generation process. */ |
| 49431 | void |
| 49432 | UA_PubSubDataSetField_sampleValue(UA_Server *server, UA_DataSetField *field, |
| 49433 | UA_DataValue *value) { |
| 49434 | UA_PublishedVariableDataType *params = &field->config.field.variable.publishParameters; |
| 49435 | |
| 49436 | /* Read the value */ |
| 49437 | if(field->config.field.variable.rtValueSource.rtInformationModelNode) { |
| 49438 | const UA_VariableNode *rtNode = (const UA_VariableNode *) |
| 49439 | UA_NODESTORE_GET(server, nodeId: ¶ms->publishedVariable); |
| 49440 | *value = **rtNode->valueBackend.backend.external.value; |
| 49441 | value->value.storageType = UA_VARIANT_DATA_NODELETE; |
| 49442 | UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode); |
| 49443 | } else if(field->config.field.variable.rtValueSource.rtFieldSourceEnabled == false){ |
| 49444 | UA_ReadValueId rvid; |
| 49445 | UA_ReadValueId_init(p: &rvid); |
| 49446 | rvid.nodeId = params->publishedVariable; |
| 49447 | rvid.attributeId = params->attributeId; |
| 49448 | rvid.indexRange = params->indexRange; |
| 49449 | *value = readWithSession(server, session: &server->adminSession, |
| 49450 | item: &rvid, timestampsToReturn: UA_TIMESTAMPSTORETURN_BOTH); |
| 49451 | } else { |
| 49452 | *value = **field->config.field.variable.rtValueSource.staticValueSource; |
| 49453 | value->value.storageType = UA_VARIANT_DATA_NODELETE; |
| 49454 | } |
| 49455 | } |
| 49456 | |
| 49457 | UA_AddPublishedDataSetResult |
| 49458 | UA_PublishedDataSet_create(UA_Server *server, |
| 49459 | const UA_PublishedDataSetConfig *publishedDataSetConfig, |
| 49460 | UA_NodeId *pdsIdentifier) { |
| 49461 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 49462 | |
| 49463 | UA_AddPublishedDataSetResult result = {UA_STATUSCODE_BADINVALIDARGUMENT, 0, NULL, {0, 0}}; |
| 49464 | if(!publishedDataSetConfig){ |
| 49465 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 49466 | msg: "PublishedDataSet creation failed. No config passed in."); |
| 49467 | return result; |
| 49468 | } |
| 49469 | |
| 49470 | if(publishedDataSetConfig->publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS){ |
| 49471 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 49472 | msg: "PublishedDataSet creation failed. Unsupported PublishedDataSet type."); |
| 49473 | return result; |
| 49474 | } |
| 49475 | |
| 49476 | if(UA_String_isEmpty(s: &publishedDataSetConfig->name)) { |
| 49477 | // DataSet has to have a valid name |
| 49478 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 49479 | msg: "PublishedDataSet creation failed. Invalid name."); |
| 49480 | return result; |
| 49481 | } |
| 49482 | |
| 49483 | if(UA_PublishedDataSet_findPDSbyName(server, name: publishedDataSetConfig->name)) { |
| 49484 | // DataSet name has to be unique in the publisher |
| 49485 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 49486 | msg: "PublishedDataSet creation failed. DataSet with the same name already exists."); |
| 49487 | result.addResult = UA_STATUSCODE_BADBROWSENAMEDUPLICATED; |
| 49488 | return result; |
| 49489 | } |
| 49490 | |
| 49491 | /* Create new PDS and add to UA_PubSubManager */ |
| 49492 | UA_PublishedDataSet *newPDS = (UA_PublishedDataSet *) |
| 49493 | UA_calloc(nmemb: 1, size: sizeof(UA_PublishedDataSet)); |
| 49494 | if(!newPDS) { |
| 49495 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 49496 | msg: "PublishedDataSet creation failed. Out of Memory."); |
| 49497 | result.addResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 49498 | return result; |
| 49499 | } |
| 49500 | TAILQ_INIT(&newPDS->fields); |
| 49501 | |
| 49502 | UA_PublishedDataSetConfig *newConfig = &newPDS->config; |
| 49503 | |
| 49504 | /* Deep copy the given connection config */ |
| 49505 | UA_StatusCode res = UA_PublishedDataSetConfig_copy(src: publishedDataSetConfig, dst: newConfig); |
| 49506 | if(res != UA_STATUSCODE_GOOD){ |
| 49507 | UA_free(ptr: newPDS); |
| 49508 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 49509 | msg: "PublishedDataSet creation failed. Configuration copy failed."); |
| 49510 | result.addResult = UA_STATUSCODE_BADINTERNALERROR; |
| 49511 | return result; |
| 49512 | } |
| 49513 | |
| 49514 | /* TODO: Parse template config and add fields (later PubSub batch) */ |
| 49515 | if(newConfig->publishedDataSetType == UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE) { |
| 49516 | } |
| 49517 | |
| 49518 | /* Fill the DataSetMetaData */ |
| 49519 | result.configurationVersion.majorVersion = UA_PubSubConfigurationVersionTimeDifference(); |
| 49520 | result.configurationVersion.minorVersion = UA_PubSubConfigurationVersionTimeDifference(); |
| 49521 | switch(newConfig->publishedDataSetType) { |
| 49522 | case UA_PUBSUB_DATASET_PUBLISHEDEVENTS_TEMPLATE: |
| 49523 | case UA_PUBSUB_DATASET_PUBLISHEDEVENTS: |
| 49524 | res = UA_STATUSCODE_BADNOTSUPPORTED; |
| 49525 | break; |
| 49526 | case UA_PUBSUB_DATASET_PUBLISHEDITEMS: |
| 49527 | newPDS->dataSetMetaData.configurationVersion.majorVersion = |
| 49528 | UA_PubSubConfigurationVersionTimeDifference(); |
| 49529 | newPDS->dataSetMetaData.configurationVersion.minorVersion = |
| 49530 | UA_PubSubConfigurationVersionTimeDifference(); |
| 49531 | newPDS->dataSetMetaData.description = UA_LOCALIZEDTEXT_ALLOC(locale: "", text: ""); |
| 49532 | newPDS->dataSetMetaData.dataSetClassId = UA_GUID_NULL; |
| 49533 | res = UA_String_copy(src: &newConfig->name, dst: &newPDS->dataSetMetaData.name); |
| 49534 | break; |
| 49535 | case UA_PUBSUB_DATASET_PUBLISHEDITEMS_TEMPLATE: |
| 49536 | res = UA_DataSetMetaDataType_copy(src: &newConfig->config.itemsTemplate.metaData, |
| 49537 | dst: &newPDS->dataSetMetaData); |
| 49538 | break; |
| 49539 | default: |
| 49540 | res = UA_STATUSCODE_BADINTERNALERROR; |
| 49541 | } |
| 49542 | |
| 49543 | /* Abort? */ |
| 49544 | result.addResult = res; |
| 49545 | if(result.addResult != UA_STATUSCODE_GOOD) { |
| 49546 | UA_PublishedDataSetConfig_clear(pdsConfig: newConfig); |
| 49547 | UA_free(ptr: newPDS); |
| 49548 | return result; |
| 49549 | } |
| 49550 | |
| 49551 | /* Insert into the queue of the manager */ |
| 49552 | TAILQ_INSERT_TAIL(&server->pubSubManager.publishedDataSets, newPDS, listEntry); |
| 49553 | server->pubSubManager.publishedDataSetsSize++; |
| 49554 | |
| 49555 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 49556 | /* Create representation and unique id */ |
| 49557 | addPublishedDataItemsRepresentation(server, publishedDataSet: newPDS); |
| 49558 | #else |
| 49559 | /* Generate unique nodeId */ |
| 49560 | UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, &newPDS->identifier); |
| 49561 | #endif |
| 49562 | if(pdsIdentifier) |
| 49563 | UA_NodeId_copy(src: &newPDS->identifier, dst: pdsIdentifier); |
| 49564 | |
| 49565 | return result; |
| 49566 | } |
| 49567 | |
| 49568 | UA_AddPublishedDataSetResult |
| 49569 | UA_Server_addPublishedDataSet(UA_Server *server, |
| 49570 | const UA_PublishedDataSetConfig *publishedDataSetConfig, |
| 49571 | UA_NodeId *pdsIdentifier) { |
| 49572 | lockServer(server); |
| 49573 | UA_AddPublishedDataSetResult res = |
| 49574 | UA_PublishedDataSet_create(server, publishedDataSetConfig, pdsIdentifier); |
| 49575 | unlockServer(server); |
| 49576 | return res; |
| 49577 | } |
| 49578 | |
| 49579 | UA_StatusCode |
| 49580 | UA_PublishedDataSet_remove(UA_Server *server, UA_PublishedDataSet *publishedDataSet) { |
| 49581 | if(publishedDataSet->configurationFreezeCounter > 0) { |
| 49582 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 49583 | msg: "Remove PublishedDataSet failed. PublishedDataSet is frozen."); |
| 49584 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 49585 | } |
| 49586 | |
| 49587 | //search for referenced writers -> delete this writers. (Standard: writer must be connected with PDS) |
| 49588 | UA_PubSubConnection *tmpConnectoin; |
| 49589 | TAILQ_FOREACH(tmpConnectoin, &server->pubSubManager.connections, listEntry){ |
| 49590 | UA_WriterGroup *writerGroup; |
| 49591 | LIST_FOREACH(writerGroup, &tmpConnectoin->writerGroups, listEntry){ |
| 49592 | UA_DataSetWriter *currentWriter, *tmpWriterGroup; |
| 49593 | LIST_FOREACH_SAFE(currentWriter, &writerGroup->writers, listEntry, tmpWriterGroup){ |
| 49594 | if(UA_NodeId_equal(p1: ¤tWriter->connectedDataSet, |
| 49595 | p2: &publishedDataSet->identifier)) { |
| 49596 | UA_DataSetWriter_remove(server, dataSetWriter: currentWriter); |
| 49597 | } |
| 49598 | } |
| 49599 | } |
| 49600 | } |
| 49601 | |
| 49602 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 49603 | deleteNode(server, nodeId: publishedDataSet->identifier, true); |
| 49604 | #endif |
| 49605 | |
| 49606 | UA_PublishedDataSet_clear(server, publishedDataSet); |
| 49607 | server->pubSubManager.publishedDataSetsSize--; |
| 49608 | |
| 49609 | TAILQ_REMOVE(&server->pubSubManager.publishedDataSets, publishedDataSet, listEntry); |
| 49610 | UA_free(ptr: publishedDataSet); |
| 49611 | return UA_STATUSCODE_GOOD; |
| 49612 | } |
| 49613 | |
| 49614 | UA_StatusCode |
| 49615 | UA_Server_removePublishedDataSet(UA_Server *server, const UA_NodeId pds) { |
| 49616 | lockServer(server); |
| 49617 | UA_PublishedDataSet *currentPDS = UA_PublishedDataSet_findPDSbyId(server, identifier: pds); |
| 49618 | if(!currentPDS) { |
| 49619 | unlockServer(server); |
| 49620 | return UA_STATUSCODE_BADNOTFOUND; |
| 49621 | } |
| 49622 | UA_StatusCode res = UA_PublishedDataSet_remove(server, publishedDataSet: currentPDS); |
| 49623 | unlockServer(server); |
| 49624 | return res; |
| 49625 | } |
| 49626 | |
| 49627 | |
| 49628 | UA_StandaloneSubscribedDataSet * |
| 49629 | UA_StandaloneSubscribedDataSet_findSDSbyId(UA_Server *server, UA_NodeId identifier) { |
| 49630 | UA_StandaloneSubscribedDataSet *subscribedDataSet; |
| 49631 | TAILQ_FOREACH(subscribedDataSet, &server->pubSubManager.subscribedDataSets, |
| 49632 | listEntry) { |
| 49633 | if(UA_NodeId_equal(p1: &identifier, p2: &subscribedDataSet->identifier)) |
| 49634 | return subscribedDataSet; |
| 49635 | } |
| 49636 | return NULL; |
| 49637 | } |
| 49638 | |
| 49639 | UA_StandaloneSubscribedDataSet * |
| 49640 | UA_StandaloneSubscribedDataSet_findSDSbyName(UA_Server *server, UA_String identifier) { |
| 49641 | UA_StandaloneSubscribedDataSet *subscribedDataSet; |
| 49642 | TAILQ_FOREACH(subscribedDataSet, &server->pubSubManager.subscribedDataSets, |
| 49643 | listEntry) { |
| 49644 | if(UA_String_equal(p1: &identifier, p2: &subscribedDataSet->config.name)) |
| 49645 | return subscribedDataSet; |
| 49646 | } |
| 49647 | return NULL; |
| 49648 | } |
| 49649 | |
| 49650 | UA_StatusCode |
| 49651 | UA_StandaloneSubscribedDataSetConfig_copy(const UA_StandaloneSubscribedDataSetConfig *src, |
| 49652 | UA_StandaloneSubscribedDataSetConfig *dst) { |
| 49653 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 49654 | memcpy(dest: dst, src: src, n: sizeof(UA_StandaloneSubscribedDataSetConfig)); |
| 49655 | res = UA_DataSetMetaDataType_copy(src: &src->dataSetMetaData, dst: &dst->dataSetMetaData); |
| 49656 | res |= UA_String_copy(src: &src->name, dst: &dst->name); |
| 49657 | res |= UA_Boolean_copy(src: &src->isConnected, dst: &dst->isConnected); |
| 49658 | res |= UA_TargetVariablesDataType_copy(src: &src->subscribedDataSet.target, |
| 49659 | dst: &dst->subscribedDataSet.target); |
| 49660 | |
| 49661 | if(res != UA_STATUSCODE_GOOD) |
| 49662 | UA_StandaloneSubscribedDataSetConfig_clear(sdsConfig: dst); |
| 49663 | return res; |
| 49664 | } |
| 49665 | |
| 49666 | void |
| 49667 | UA_StandaloneSubscribedDataSetConfig_clear( |
| 49668 | UA_StandaloneSubscribedDataSetConfig *sdsConfig) { |
| 49669 | UA_String_clear(p: &sdsConfig->name); |
| 49670 | UA_DataSetMetaDataType_clear(p: &sdsConfig->dataSetMetaData); |
| 49671 | UA_TargetVariablesDataType_clear(p: &sdsConfig->subscribedDataSet.target); |
| 49672 | } |
| 49673 | |
| 49674 | void |
| 49675 | UA_StandaloneSubscribedDataSet_clear(UA_Server *server, |
| 49676 | UA_StandaloneSubscribedDataSet *subscribedDataSet) { |
| 49677 | UA_StandaloneSubscribedDataSetConfig_clear(sdsConfig: &subscribedDataSet->config); |
| 49678 | UA_NodeId_clear(p: &subscribedDataSet->identifier); |
| 49679 | UA_NodeId_clear(p: &subscribedDataSet->connectedReader); |
| 49680 | } |
| 49681 | |
| 49682 | #endif /* UA_ENABLE_PUBSUB */ |
| 49683 | |
| 49684 | /**** amalgamated original file "/src/pubsub/ua_pubsub_writer.c" ****/ |
| 49685 | |
| 49686 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 49687 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 49688 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 49689 | * |
| 49690 | * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner) |
| 49691 | * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer) |
| 49692 | * Copyright (c) 2019-2021 Kalycito Infotech Private Limited |
| 49693 | * Copyright (c) 2020 Yannick Wallerer, Siemens AG |
| 49694 | * Copyright (c) 2020 Thomas Fischer, Siemens AG |
| 49695 | * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes) |
| 49696 | */ |
| 49697 | |
| 49698 | |
| 49699 | #ifdef UA_ENABLE_PUBSUB /* conditional compilation */ |
| 49700 | |
| 49701 | |
| 49702 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 49703 | #endif |
| 49704 | |
| 49705 | |
| 49706 | UA_StatusCode |
| 49707 | UA_DataSetWriterConfig_copy(const UA_DataSetWriterConfig *src, |
| 49708 | UA_DataSetWriterConfig *dst){ |
| 49709 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 49710 | memcpy(dest: dst, src: src, n: sizeof(UA_DataSetWriterConfig)); |
| 49711 | retVal |= UA_String_copy(src: &src->name, dst: &dst->name); |
| 49712 | retVal |= UA_String_copy(src: &src->dataSetName, dst: &dst->dataSetName); |
| 49713 | retVal |= UA_ExtensionObject_copy(src: &src->messageSettings, dst: &dst->messageSettings); |
| 49714 | retVal |= UA_KeyValueMap_copy(src: &src->dataSetWriterProperties, dst: &dst->dataSetWriterProperties); |
| 49715 | if(retVal != UA_STATUSCODE_GOOD) |
| 49716 | UA_DataSetWriterConfig_clear(pdsConfig: dst); |
| 49717 | return retVal; |
| 49718 | } |
| 49719 | |
| 49720 | UA_StatusCode |
| 49721 | UA_Server_getDataSetWriterConfig(UA_Server *server, const UA_NodeId dsw, |
| 49722 | UA_DataSetWriterConfig *config) { |
| 49723 | if(!config) |
| 49724 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 49725 | lockServer(server); |
| 49726 | UA_DataSetWriter *currentDataSetWriter = UA_DataSetWriter_findDSWbyId(server, identifier: dsw); |
| 49727 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 49728 | if(currentDataSetWriter) |
| 49729 | res = UA_DataSetWriterConfig_copy(src: ¤tDataSetWriter->config, dst: config); |
| 49730 | unlockServer(server); |
| 49731 | return res; |
| 49732 | } |
| 49733 | |
| 49734 | UA_StatusCode |
| 49735 | UA_Server_DataSetWriter_getState(UA_Server *server, UA_NodeId dataSetWriterIdentifier, |
| 49736 | UA_PubSubState *state) { |
| 49737 | if((server == NULL) || (state == NULL)) |
| 49738 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 49739 | lockServer(server); |
| 49740 | UA_DataSetWriter *currentDataSetWriter = |
| 49741 | UA_DataSetWriter_findDSWbyId(server, identifier: dataSetWriterIdentifier); |
| 49742 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 49743 | if(currentDataSetWriter) { |
| 49744 | *state = currentDataSetWriter->state; |
| 49745 | } else { |
| 49746 | res = UA_STATUSCODE_BADNOTFOUND; |
| 49747 | } |
| 49748 | unlockServer(server); |
| 49749 | return res; |
| 49750 | } |
| 49751 | |
| 49752 | UA_DataSetWriter * |
| 49753 | UA_DataSetWriter_findDSWbyId(UA_Server *server, UA_NodeId identifier) { |
| 49754 | UA_PubSubConnection *pubSubConnection; |
| 49755 | TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){ |
| 49756 | UA_WriterGroup *tmpWriterGroup; |
| 49757 | LIST_FOREACH(tmpWriterGroup, &pubSubConnection->writerGroups, listEntry){ |
| 49758 | UA_DataSetWriter *tmpWriter; |
| 49759 | LIST_FOREACH(tmpWriter, &tmpWriterGroup->writers, listEntry){ |
| 49760 | if(UA_NodeId_equal(p1: &tmpWriter->identifier, p2: &identifier)){ |
| 49761 | return tmpWriter; |
| 49762 | } |
| 49763 | } |
| 49764 | } |
| 49765 | } |
| 49766 | return NULL; |
| 49767 | } |
| 49768 | |
| 49769 | void |
| 49770 | UA_DataSetWriterConfig_clear(UA_DataSetWriterConfig *pdsConfig) { |
| 49771 | UA_String_clear(p: &pdsConfig->name); |
| 49772 | UA_String_clear(p: &pdsConfig->dataSetName); |
| 49773 | UA_KeyValueMap_clear(map: &pdsConfig->dataSetWriterProperties); |
| 49774 | UA_ExtensionObject_clear(p: &pdsConfig->messageSettings); |
| 49775 | memset(s: pdsConfig, c: 0, n: sizeof(UA_DataSetWriterConfig)); |
| 49776 | } |
| 49777 | |
| 49778 | //state machine methods not part of the open62541 state machine API |
| 49779 | UA_StatusCode |
| 49780 | UA_DataSetWriter_setPubSubState(UA_Server *server, |
| 49781 | UA_DataSetWriter *dataSetWriter, |
| 49782 | UA_PubSubState state, |
| 49783 | UA_StatusCode cause) { |
| 49784 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 49785 | UA_PubSubState oldState = dataSetWriter->state; |
| 49786 | switch(state){ |
| 49787 | case UA_PUBSUBSTATE_DISABLED: |
| 49788 | switch (dataSetWriter->state){ |
| 49789 | case UA_PUBSUBSTATE_DISABLED: |
| 49790 | break; |
| 49791 | case UA_PUBSUBSTATE_PAUSED: |
| 49792 | dataSetWriter->state = UA_PUBSUBSTATE_DISABLED; |
| 49793 | //no further action is required |
| 49794 | break; |
| 49795 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 49796 | dataSetWriter->state = UA_PUBSUBSTATE_DISABLED; |
| 49797 | break; |
| 49798 | case UA_PUBSUBSTATE_ERROR: |
| 49799 | break; |
| 49800 | default: |
| 49801 | UA_LOG_WARNING_WRITER(server->config.logging, dataSetWriter, |
| 49802 | "Received unknown PubSub state!"); |
| 49803 | } |
| 49804 | break; |
| 49805 | case UA_PUBSUBSTATE_PAUSED: |
| 49806 | switch (dataSetWriter->state){ |
| 49807 | case UA_PUBSUBSTATE_DISABLED: |
| 49808 | break; |
| 49809 | case UA_PUBSUBSTATE_PAUSED: |
| 49810 | break; |
| 49811 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 49812 | break; |
| 49813 | case UA_PUBSUBSTATE_ERROR: |
| 49814 | break; |
| 49815 | default: |
| 49816 | UA_LOG_WARNING_WRITER(server->config.logging, dataSetWriter, |
| 49817 | "Received unknown PubSub state!"); |
| 49818 | } |
| 49819 | break; |
| 49820 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 49821 | switch (dataSetWriter->state){ |
| 49822 | case UA_PUBSUBSTATE_DISABLED: |
| 49823 | dataSetWriter->state = UA_PUBSUBSTATE_OPERATIONAL; |
| 49824 | break; |
| 49825 | case UA_PUBSUBSTATE_PAUSED: |
| 49826 | break; |
| 49827 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 49828 | break; |
| 49829 | case UA_PUBSUBSTATE_ERROR: |
| 49830 | break; |
| 49831 | default: |
| 49832 | UA_LOG_WARNING_WRITER(server->config.logging, dataSetWriter, |
| 49833 | "Received unknown PubSub state!"); |
| 49834 | } |
| 49835 | break; |
| 49836 | case UA_PUBSUBSTATE_ERROR: |
| 49837 | switch (dataSetWriter->state){ |
| 49838 | case UA_PUBSUBSTATE_DISABLED: |
| 49839 | break; |
| 49840 | case UA_PUBSUBSTATE_PAUSED: |
| 49841 | break; |
| 49842 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 49843 | break; |
| 49844 | case UA_PUBSUBSTATE_ERROR: |
| 49845 | break; |
| 49846 | default: |
| 49847 | UA_LOG_WARNING_WRITER(server->config.logging, dataSetWriter, |
| 49848 | "Received unknown PubSub state!"); |
| 49849 | } |
| 49850 | break; |
| 49851 | default: |
| 49852 | UA_LOG_WARNING_WRITER(server->config.logging, dataSetWriter, |
| 49853 | "Received unknown PubSub state!"); |
| 49854 | } |
| 49855 | if (state != oldState) { |
| 49856 | /* inform application about state change */ |
| 49857 | UA_ServerConfig *pConfig = &server->config; |
| 49858 | if(pConfig->pubSubConfig.stateChangeCallback != 0) { |
| 49859 | pConfig->pubSubConfig. |
| 49860 | stateChangeCallback(server, &dataSetWriter->identifier, state, cause); |
| 49861 | } |
| 49862 | } |
| 49863 | return ret; |
| 49864 | } |
| 49865 | |
| 49866 | UA_StatusCode |
| 49867 | UA_DataSetWriter_create(UA_Server *server, |
| 49868 | const UA_NodeId writerGroup, const UA_NodeId dataSet, |
| 49869 | const UA_DataSetWriterConfig *dataSetWriterConfig, |
| 49870 | UA_NodeId *writerIdentifier) { |
| 49871 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 49872 | if(!dataSetWriterConfig) |
| 49873 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 49874 | |
| 49875 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: writerGroup); |
| 49876 | if(!wg) |
| 49877 | return UA_STATUSCODE_BADNOTFOUND; |
| 49878 | |
| 49879 | /* Make checks for a heartbeat */ |
| 49880 | if(UA_NodeId_isNull(p: &dataSet) && dataSetWriterConfig->keyFrameCount != 1) { |
| 49881 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 49882 | "Adding DataSetWriter failed: DataSet can be null only for " |
| 49883 | "a heartbeat in which case KeyFrameCount shall be 1"); |
| 49884 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 49885 | } |
| 49886 | |
| 49887 | if(wg->configurationFrozen) { |
| 49888 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 49889 | "Adding DataSetWriter failed: WriterGroup is frozen"); |
| 49890 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 49891 | } |
| 49892 | |
| 49893 | UA_PublishedDataSet *currentDataSetContext = NULL; |
| 49894 | |
| 49895 | if(!UA_NodeId_isNull(p: &dataSet)) { |
| 49896 | currentDataSetContext = UA_PublishedDataSet_findPDSbyId(server, identifier: dataSet); |
| 49897 | if(!currentDataSetContext) |
| 49898 | return UA_STATUSCODE_BADNOTFOUND; |
| 49899 | |
| 49900 | if(currentDataSetContext->configurationFreezeCounter > 0) { |
| 49901 | UA_LOG_WARNING_DATASET(server->config.logging, currentDataSetContext, |
| 49902 | "Adding DataSetWriter failed: PublishedDataSet is frozen"); |
| 49903 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 49904 | } |
| 49905 | |
| 49906 | if(wg->config.rtLevel != UA_PUBSUB_RT_NONE) { |
| 49907 | UA_DataSetField *tmpDSF; |
| 49908 | TAILQ_FOREACH(tmpDSF, ¤tDataSetContext->fields, listEntry) { |
| 49909 | if(!tmpDSF->config.field.variable.rtValueSource.rtFieldSourceEnabled && |
| 49910 | !tmpDSF->config.field.variable.rtValueSource.rtInformationModelNode) { |
| 49911 | UA_LOG_WARNING_DATASET(server->config.logging, currentDataSetContext, |
| 49912 | "Adding DataSetWriter failed: " |
| 49913 | "Fields in PDS are not RT capable"); |
| 49914 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 49915 | } |
| 49916 | } |
| 49917 | } |
| 49918 | } |
| 49919 | |
| 49920 | UA_DataSetWriter *newDataSetWriter = (UA_DataSetWriter *) |
| 49921 | UA_calloc(nmemb: 1, size: sizeof(UA_DataSetWriter)); |
| 49922 | if(!newDataSetWriter) |
| 49923 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 49924 | |
| 49925 | newDataSetWriter->componentType = UA_PUBSUB_COMPONENT_DATASETWRITER; |
| 49926 | |
| 49927 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 49928 | if(wg->state == UA_PUBSUBSTATE_OPERATIONAL) { |
| 49929 | res = UA_DataSetWriter_setPubSubState(server, dataSetWriter: newDataSetWriter, |
| 49930 | state: UA_PUBSUBSTATE_OPERATIONAL, |
| 49931 | UA_STATUSCODE_GOOD); |
| 49932 | if(res != UA_STATUSCODE_GOOD) { |
| 49933 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 49934 | "Add DataSetWriter failed: setPubSubState failed"); |
| 49935 | UA_free(ptr: newDataSetWriter); |
| 49936 | return res; |
| 49937 | } |
| 49938 | } |
| 49939 | |
| 49940 | /* Copy the config into the new dataSetWriter */ |
| 49941 | res = UA_DataSetWriterConfig_copy(src: dataSetWriterConfig, dst: &newDataSetWriter->config); |
| 49942 | UA_CHECK_STATUS(res, UA_free(newDataSetWriter); return res); |
| 49943 | |
| 49944 | if(!UA_NodeId_isNull(p: &dataSet) && currentDataSetContext != NULL) { |
| 49945 | /* Save the current version of the connected PublishedDataSet */ |
| 49946 | newDataSetWriter->connectedDataSetVersion = |
| 49947 | currentDataSetContext->dataSetMetaData.configurationVersion; |
| 49948 | |
| 49949 | if(server->config.pubSubConfig.enableDeltaFrames) { |
| 49950 | /* Initialize the queue for the last values */ |
| 49951 | if(currentDataSetContext->fieldSize > 0) { |
| 49952 | newDataSetWriter->lastSamples = (UA_DataSetWriterSample*) |
| 49953 | UA_calloc(nmemb: currentDataSetContext->fieldSize, size: sizeof(UA_DataSetWriterSample)); |
| 49954 | if(!newDataSetWriter->lastSamples) { |
| 49955 | UA_DataSetWriterConfig_clear(pdsConfig: &newDataSetWriter->config); |
| 49956 | UA_free(ptr: newDataSetWriter); |
| 49957 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 49958 | } |
| 49959 | newDataSetWriter->lastSamplesCount = currentDataSetContext->fieldSize; |
| 49960 | for(size_t i = 0; i < newDataSetWriter->lastSamplesCount; i++) { |
| 49961 | UA_DataValue_init(p: &newDataSetWriter->lastSamples[i].value); |
| 49962 | newDataSetWriter->lastSamples[i].valueChanged = false; |
| 49963 | } |
| 49964 | } |
| 49965 | } |
| 49966 | /* Connect PublishedDataSet with DataSetWriter */ |
| 49967 | newDataSetWriter->connectedDataSet = currentDataSetContext->identifier; |
| 49968 | } else { |
| 49969 | /* If the dataSet is NULL, we are adding a heartbeat writer */ |
| 49970 | newDataSetWriter->connectedDataSetVersion.majorVersion = 0; |
| 49971 | newDataSetWriter->connectedDataSetVersion.minorVersion = 0; |
| 49972 | newDataSetWriter->connectedDataSet = UA_NODEID_NULL; |
| 49973 | } |
| 49974 | |
| 49975 | newDataSetWriter->linkedWriterGroup = wg->identifier; |
| 49976 | |
| 49977 | /* Add the new writer to the group. Add to the end of the linked list to |
| 49978 | * ensure the order in the generated NetworkMessage is as expected. */ |
| 49979 | UA_DataSetWriter *after = LIST_FIRST(&wg->writers); |
| 49980 | if(!after) { |
| 49981 | LIST_INSERT_HEAD(&wg->writers, newDataSetWriter, listEntry); |
| 49982 | } else { |
| 49983 | while(LIST_NEXT(after, listEntry)) |
| 49984 | after = LIST_NEXT(after, listEntry); |
| 49985 | LIST_INSERT_AFTER(after, newDataSetWriter, listEntry); |
| 49986 | } |
| 49987 | wg->writersCount++; |
| 49988 | |
| 49989 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 49990 | res |= addDataSetWriterRepresentation(server, dataSetWriter: newDataSetWriter); |
| 49991 | #else |
| 49992 | UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, |
| 49993 | &newDataSetWriter->identifier); |
| 49994 | #endif |
| 49995 | if(writerIdentifier) |
| 49996 | UA_NodeId_copy(src: &newDataSetWriter->identifier, dst: writerIdentifier); |
| 49997 | return res; |
| 49998 | } |
| 49999 | |
| 50000 | UA_StatusCode |
| 50001 | UA_Server_addDataSetWriter(UA_Server *server, |
| 50002 | const UA_NodeId writerGroup, const UA_NodeId dataSet, |
| 50003 | const UA_DataSetWriterConfig *dataSetWriterConfig, |
| 50004 | UA_NodeId *writerIdentifier) { |
| 50005 | lockServer(server); |
| 50006 | /* Delete the reserved IDs if the related session no longer exists. */ |
| 50007 | UA_PubSubManager_freeIds(server); |
| 50008 | UA_StatusCode res = UA_DataSetWriter_create(server, writerGroup, dataSet, |
| 50009 | dataSetWriterConfig, writerIdentifier); |
| 50010 | unlockServer(server); |
| 50011 | return res; |
| 50012 | } |
| 50013 | |
| 50014 | void |
| 50015 | UA_DataSetWriter_freezeConfiguration(UA_Server *server, |
| 50016 | UA_DataSetWriter *dsw) { |
| 50017 | UA_PublishedDataSet *pds = |
| 50018 | UA_PublishedDataSet_findPDSbyId(server, identifier: dsw->connectedDataSet); |
| 50019 | if(pds) { /* Skip for heartbeat writers */ |
| 50020 | pds->configurationFreezeCounter++; |
| 50021 | UA_DataSetField *dsf; |
| 50022 | TAILQ_FOREACH(dsf, &pds->fields, listEntry) { |
| 50023 | dsf->configurationFrozen = true; |
| 50024 | } |
| 50025 | } |
| 50026 | dsw->configurationFrozen = true; |
| 50027 | } |
| 50028 | |
| 50029 | void |
| 50030 | UA_DataSetWriter_unfreezeConfiguration(UA_Server *server, |
| 50031 | UA_DataSetWriter *dsw) { |
| 50032 | UA_PublishedDataSet *pds = |
| 50033 | UA_PublishedDataSet_findPDSbyId(server, identifier: dsw->connectedDataSet); |
| 50034 | if(pds) { /* Skip for heartbeat writers */ |
| 50035 | pds->configurationFreezeCounter--; |
| 50036 | if(pds->configurationFreezeCounter == 0) { |
| 50037 | UA_DataSetField *dsf; |
| 50038 | TAILQ_FOREACH(dsf, &pds->fields, listEntry){ |
| 50039 | dsf->configurationFrozen = false; |
| 50040 | } |
| 50041 | } |
| 50042 | dsw->configurationFrozen = false; |
| 50043 | } |
| 50044 | } |
| 50045 | |
| 50046 | UA_StatusCode |
| 50047 | UA_DataSetWriter_prepareDataSet(UA_Server *server, UA_DataSetWriter *dsw, |
| 50048 | UA_DataSetMessage *dsm) { |
| 50049 | /* No PublishedDataSet defined -> Heartbeat messages only */ |
| 50050 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 50051 | if(UA_NodeId_isNull(p: &dsw->connectedDataSet)) { |
| 50052 | res = UA_DataSetWriter_generateDataSetMessage(server, dataSetMessage: dsm, dataSetWriter: dsw); |
| 50053 | if(res != UA_STATUSCODE_GOOD) { |
| 50054 | UA_LOG_WARNING_WRITER(server->config.logging, dsw, |
| 50055 | "PubSub-RT configuration fail: " |
| 50056 | "Heartbeat DataSetMessage creation failed"); |
| 50057 | } |
| 50058 | return res; |
| 50059 | } |
| 50060 | |
| 50061 | /* Get the PublishedDataSet */ |
| 50062 | UA_PublishedDataSet *pds = |
| 50063 | UA_PublishedDataSet_findPDSbyId(server, identifier: dsw->connectedDataSet); |
| 50064 | if(!pds) { |
| 50065 | UA_LOG_WARNING_WRITER(server->config.logging, dsw, |
| 50066 | "PubSub-RT configuration fail: " |
| 50067 | "PublishedDataSet not found"); |
| 50068 | return UA_STATUSCODE_BADINTERNALERROR; |
| 50069 | } |
| 50070 | |
| 50071 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: dsw->linkedWriterGroup); |
| 50072 | UA_assert(wg); |
| 50073 | |
| 50074 | /* Promoted Fields not allowed if RT is enabled */ |
| 50075 | if(wg->config.rtLevel > UA_PUBSUB_RT_NONE && |
| 50076 | pds->promotedFieldsCount > 0) { |
| 50077 | UA_LOG_WARNING_WRITER(server->config.logging, dsw, |
| 50078 | "PubSub-RT configuration fail: " |
| 50079 | "PDS contains promoted fields"); |
| 50080 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 50081 | } |
| 50082 | |
| 50083 | /* Test the DataSetFields */ |
| 50084 | UA_DataSetField *dsf; |
| 50085 | TAILQ_FOREACH(dsf, &pds->fields, listEntry) { |
| 50086 | UA_NodeId *publishedVariable = |
| 50087 | &dsf->config.field.variable.publishParameters.publishedVariable; |
| 50088 | |
| 50089 | /* Check that the target is a VariableNode */ |
| 50090 | const UA_VariableNode *rtNode = (const UA_VariableNode*) |
| 50091 | UA_NODESTORE_GET(server, nodeId: publishedVariable); |
| 50092 | if(rtNode && rtNode->head.nodeClass != UA_NODECLASS_VARIABLE) { |
| 50093 | UA_LOG_ERROR_WRITER(server->config.logging, dsw, |
| 50094 | "PubSub-RT configuration fail: " |
| 50095 | "PDS points to a node that is not a variable"); |
| 50096 | UA_NODESTORE_RELEASE(server, (const UA_Node *)rtNode); |
| 50097 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 50098 | } |
| 50099 | UA_NODESTORE_RELEASE(server, (const UA_Node *)rtNode); |
| 50100 | |
| 50101 | /* TODO: Get the External Value Source from the node instead of from the config */ |
| 50102 | |
| 50103 | /* If direct-value-access is enabled, the pointers need to be set */ |
| 50104 | if(wg->config.rtLevel & UA_PUBSUB_RT_DIRECT_VALUE_ACCESS && |
| 50105 | !dsf->config.field.variable.rtValueSource.rtFieldSourceEnabled) { |
| 50106 | UA_LOG_ERROR_WRITER(server->config.logging, dsw, |
| 50107 | "PubSub-RT configuration fail: PDS published-variable " |
| 50108 | "does not have an external data source"); |
| 50109 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 50110 | } |
| 50111 | |
| 50112 | /* Check that the values have a fixed size if fixed offsets are needed */ |
| 50113 | if(wg->config.rtLevel & UA_PUBSUB_RT_FIXED_SIZE) { |
| 50114 | if((UA_NodeId_equal(p1: &dsf->fieldMetaData.dataType, |
| 50115 | p2: &UA_TYPES[UA_TYPES_STRING].typeId) || |
| 50116 | UA_NodeId_equal(p1: &dsf->fieldMetaData.dataType, |
| 50117 | p2: &UA_TYPES[UA_TYPES_BYTESTRING].typeId)) && |
| 50118 | dsf->fieldMetaData.maxStringLength == 0) { |
| 50119 | UA_LOG_WARNING_WRITER(server->config.logging, dsw, |
| 50120 | "PubSub-RT configuration fail: " |
| 50121 | "PDS contains String/ByteString with dynamic length"); |
| 50122 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 50123 | } else if(!UA_DataType_isNumeric( |
| 50124 | type: UA_findDataType(typeId: &dsf->fieldMetaData.dataType)) && |
| 50125 | !UA_NodeId_equal(p1: &dsf->fieldMetaData.dataType, |
| 50126 | p2: &UA_TYPES[UA_TYPES_BOOLEAN].typeId)) { |
| 50127 | UA_LOG_WARNING_WRITER(server->config.logging, dsw, |
| 50128 | "PubSub-RT configuration fail: " |
| 50129 | "PDS contains variable with dynamic size"); |
| 50130 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 50131 | } |
| 50132 | } |
| 50133 | } |
| 50134 | |
| 50135 | /* Generate the DSM */ |
| 50136 | res = UA_DataSetWriter_generateDataSetMessage(server, dataSetMessage: dsm, dataSetWriter: dsw); |
| 50137 | if(res != UA_STATUSCODE_GOOD) { |
| 50138 | UA_LOG_WARNING_WRITER(server->config.logging, dsw, |
| 50139 | "PubSub-RT configuration fail: " |
| 50140 | "DataSetMessage buffering failed"); |
| 50141 | } |
| 50142 | |
| 50143 | return res; |
| 50144 | } |
| 50145 | |
| 50146 | UA_StatusCode |
| 50147 | UA_DataSetWriter_remove(UA_Server *server, UA_DataSetWriter *dataSetWriter) { |
| 50148 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 50149 | |
| 50150 | /* Frozen? */ |
| 50151 | if(dataSetWriter->configurationFrozen) { |
| 50152 | UA_LOG_WARNING_WRITER(server->config.logging, dataSetWriter, |
| 50153 | "Remove DataSetWriter failed: WriterGroup is frozen"); |
| 50154 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 50155 | } |
| 50156 | |
| 50157 | /* Remove from information model */ |
| 50158 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 50159 | deleteNode(server, nodeId: dataSetWriter->identifier, true); |
| 50160 | #endif |
| 50161 | |
| 50162 | /* Remove DataSetWriter from group */ |
| 50163 | UA_WriterGroup *linkedWriterGroup = |
| 50164 | UA_WriterGroup_findWGbyId(server, identifier: dataSetWriter->linkedWriterGroup); |
| 50165 | if(linkedWriterGroup) { |
| 50166 | LIST_REMOVE(dataSetWriter, listEntry); |
| 50167 | linkedWriterGroup->writersCount--; |
| 50168 | } |
| 50169 | |
| 50170 | UA_DataSetWriterConfig_clear(pdsConfig: &dataSetWriter->config); |
| 50171 | UA_NodeId_clear(p: &dataSetWriter->identifier); |
| 50172 | UA_NodeId_clear(p: &dataSetWriter->linkedWriterGroup); |
| 50173 | UA_NodeId_clear(p: &dataSetWriter->connectedDataSet); |
| 50174 | |
| 50175 | if(server->config.pubSubConfig.enableDeltaFrames) { |
| 50176 | /* Delete lastSamples store */ |
| 50177 | for(size_t i = 0; i < dataSetWriter->lastSamplesCount; i++) { |
| 50178 | UA_DataValue_clear(p: &dataSetWriter->lastSamples[i].value); |
| 50179 | } |
| 50180 | UA_free(ptr: dataSetWriter->lastSamples); |
| 50181 | dataSetWriter->lastSamples = NULL; |
| 50182 | dataSetWriter->lastSamplesCount = 0; |
| 50183 | } |
| 50184 | |
| 50185 | UA_free(ptr: dataSetWriter); |
| 50186 | return UA_STATUSCODE_GOOD; |
| 50187 | } |
| 50188 | |
| 50189 | UA_StatusCode |
| 50190 | UA_Server_removeDataSetWriter(UA_Server *server, const UA_NodeId dsw) { |
| 50191 | lockServer(server); |
| 50192 | UA_DataSetWriter *dataSetWriter = UA_DataSetWriter_findDSWbyId(server, identifier: dsw); |
| 50193 | if(!dataSetWriter) { |
| 50194 | unlockServer(server); |
| 50195 | return UA_STATUSCODE_BADNOTFOUND; |
| 50196 | } |
| 50197 | UA_StatusCode res = UA_DataSetWriter_remove(server, dataSetWriter); |
| 50198 | unlockServer(server); |
| 50199 | return res; |
| 50200 | } |
| 50201 | |
| 50202 | /*********************************************************/ |
| 50203 | /* PublishValues handling */ |
| 50204 | /*********************************************************/ |
| 50205 | |
| 50206 | /* Compare two variants. Internally used for value change detection. */ |
| 50207 | static UA_Boolean |
| 50208 | valueChangedVariant(UA_Variant *oldValue, UA_Variant *newValue) { |
| 50209 | if(!oldValue || !newValue) |
| 50210 | return false; |
| 50211 | |
| 50212 | size_t oldValueEncodingSize = UA_calcSizeBinary(p: oldValue, type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 50213 | size_t newValueEncodingSize = UA_calcSizeBinary(p: newValue, type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 50214 | if(oldValueEncodingSize == 0 || newValueEncodingSize == 0) |
| 50215 | return false; |
| 50216 | |
| 50217 | if(oldValueEncodingSize != newValueEncodingSize) |
| 50218 | return true; |
| 50219 | |
| 50220 | UA_ByteString oldValueEncoding = UA_BYTESTRING_NULL; |
| 50221 | UA_StatusCode res = UA_ByteString_allocBuffer(bs: &oldValueEncoding, length: oldValueEncodingSize); |
| 50222 | if(res != UA_STATUSCODE_GOOD) |
| 50223 | return false; |
| 50224 | |
| 50225 | UA_ByteString newValueEncoding = UA_BYTESTRING_NULL; |
| 50226 | res = UA_ByteString_allocBuffer(bs: &newValueEncoding, length: newValueEncodingSize); |
| 50227 | if(res != UA_STATUSCODE_GOOD) { |
| 50228 | UA_ByteString_clear(p: &oldValueEncoding); |
| 50229 | return false; |
| 50230 | } |
| 50231 | |
| 50232 | UA_Byte *bufPosOldValue = oldValueEncoding.data; |
| 50233 | const UA_Byte *bufEndOldValue = &oldValueEncoding.data[oldValueEncoding.length]; |
| 50234 | UA_Byte *bufPosNewValue = newValueEncoding.data; |
| 50235 | const UA_Byte *bufEndNewValue = &newValueEncoding.data[newValueEncoding.length]; |
| 50236 | |
| 50237 | UA_Boolean compareResult = false; /* default */ |
| 50238 | |
| 50239 | res = UA_encodeBinaryInternal(src: oldValue, type: &UA_TYPES[UA_TYPES_VARIANT], |
| 50240 | bufPos: &bufPosOldValue, bufEnd: &bufEndOldValue, NULL, NULL); |
| 50241 | if(res != UA_STATUSCODE_GOOD) |
| 50242 | goto cleanup; |
| 50243 | |
| 50244 | res = UA_encodeBinaryInternal(src: newValue, type: &UA_TYPES[UA_TYPES_VARIANT], |
| 50245 | bufPos: &bufPosNewValue, bufEnd: &bufEndNewValue, NULL, NULL); |
| 50246 | if(res != UA_STATUSCODE_GOOD) |
| 50247 | goto cleanup; |
| 50248 | |
| 50249 | oldValueEncoding.length = (uintptr_t)bufPosOldValue - (uintptr_t)oldValueEncoding.data; |
| 50250 | newValueEncoding.length = (uintptr_t)bufPosNewValue - (uintptr_t)newValueEncoding.data; |
| 50251 | compareResult = !UA_ByteString_equal(p1: &oldValueEncoding, p2: &newValueEncoding); |
| 50252 | |
| 50253 | cleanup: |
| 50254 | UA_ByteString_clear(p: &oldValueEncoding); |
| 50255 | UA_ByteString_clear(p: &newValueEncoding); |
| 50256 | return compareResult; |
| 50257 | } |
| 50258 | |
| 50259 | static UA_StatusCode |
| 50260 | UA_PubSubDataSetWriter_generateKeyFrameMessage(UA_Server *server, |
| 50261 | UA_DataSetMessage *dataSetMessage, |
| 50262 | UA_DataSetWriter *dataSetWriter) { |
| 50263 | UA_PublishedDataSet *currentDataSet = |
| 50264 | UA_PublishedDataSet_findPDSbyId(server, identifier: dataSetWriter->connectedDataSet); |
| 50265 | if(!currentDataSet) |
| 50266 | return UA_STATUSCODE_BADNOTFOUND; |
| 50267 | |
| 50268 | /* Prepare DataSetMessageContent */ |
| 50269 | dataSetMessage->header.dataSetMessageValid = true; |
| 50270 | dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME; |
| 50271 | dataSetMessage->data.keyFrameData.fieldCount = currentDataSet->fieldSize; |
| 50272 | dataSetMessage->data.keyFrameData.dataSetFields = (UA_DataValue *) |
| 50273 | UA_Array_new(size: currentDataSet->fieldSize, type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 50274 | UA_PublishedDataSet *pds = UA_PublishedDataSet_findPDSbyId(server, identifier: dataSetWriter->connectedDataSet); |
| 50275 | dataSetMessage->data.keyFrameData.dataSetMetaDataType = &pds->dataSetMetaData; |
| 50276 | if(!dataSetMessage->data.keyFrameData.dataSetFields) |
| 50277 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 50278 | |
| 50279 | #ifdef UA_ENABLE_JSON_ENCODING |
| 50280 | dataSetMessage->data.keyFrameData.fieldNames = (UA_String *) |
| 50281 | UA_Array_new(size: currentDataSet->fieldSize, type: &UA_TYPES[UA_TYPES_STRING]); |
| 50282 | if(!dataSetMessage->data.keyFrameData.fieldNames) { |
| 50283 | UA_DataSetMessage_clear(p: dataSetMessage); |
| 50284 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 50285 | } |
| 50286 | #endif |
| 50287 | |
| 50288 | /* Loop over the fields */ |
| 50289 | size_t counter = 0; |
| 50290 | UA_DataSetField *dsf; |
| 50291 | TAILQ_FOREACH(dsf, ¤tDataSet->fields, listEntry) { |
| 50292 | #ifdef UA_ENABLE_JSON_ENCODING |
| 50293 | /* Set the field name alias */ |
| 50294 | UA_String_copy(src: &dsf->config.field.variable.fieldNameAlias, |
| 50295 | dst: &dataSetMessage->data.keyFrameData.fieldNames[counter]); |
| 50296 | #endif |
| 50297 | |
| 50298 | /* Sample the value */ |
| 50299 | UA_DataValue *dfv = &dataSetMessage->data.keyFrameData.dataSetFields[counter]; |
| 50300 | UA_PubSubDataSetField_sampleValue(server, field: dsf, value: dfv); |
| 50301 | |
| 50302 | /* Deactivate statuscode? */ |
| 50303 | if(((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50304 | (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE) == 0) |
| 50305 | dfv->hasStatus = false; |
| 50306 | |
| 50307 | /* Deactivate timestamps */ |
| 50308 | if(((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50309 | (u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP) == 0) |
| 50310 | dfv->hasSourceTimestamp = false; |
| 50311 | if(((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50312 | (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS) == 0) |
| 50313 | dfv->hasSourcePicoseconds = false; |
| 50314 | if(((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50315 | (u64)UA_DATASETFIELDCONTENTMASK_SERVERTIMESTAMP) == 0) |
| 50316 | dfv->hasServerTimestamp = false; |
| 50317 | if(((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50318 | (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS) == 0) |
| 50319 | dfv->hasServerPicoseconds = false; |
| 50320 | |
| 50321 | if(server->config.pubSubConfig.enableDeltaFrames) { |
| 50322 | /* Update lastValue store */ |
| 50323 | UA_DataValue_clear(p: &dataSetWriter->lastSamples[counter].value); |
| 50324 | UA_DataValue_copy(src: dfv, dst: &dataSetWriter->lastSamples[counter].value); |
| 50325 | } |
| 50326 | counter++; |
| 50327 | } |
| 50328 | return UA_STATUSCODE_GOOD; |
| 50329 | } |
| 50330 | |
| 50331 | /* the input message is already initialized and that the method |
| 50332 | * must not be called twice for the same message */ |
| 50333 | static UA_StatusCode |
| 50334 | UA_PubSubDataSetWriter_generateDeltaFrameMessage(UA_Server *server, |
| 50335 | UA_DataSetMessage *dataSetMessage, |
| 50336 | UA_DataSetWriter *dataSetWriter) { |
| 50337 | UA_PublishedDataSet *currentDataSet = |
| 50338 | UA_PublishedDataSet_findPDSbyId(server, identifier: dataSetWriter->connectedDataSet); |
| 50339 | if(!currentDataSet) |
| 50340 | return UA_STATUSCODE_BADNOTFOUND; |
| 50341 | |
| 50342 | /* Prepare DataSetMessageContent */ |
| 50343 | dataSetMessage->header.dataSetMessageValid = true; |
| 50344 | dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATADELTAFRAME; |
| 50345 | if(currentDataSet->fieldSize == 0) |
| 50346 | return UA_STATUSCODE_GOOD; |
| 50347 | |
| 50348 | UA_DataSetField *dsf; |
| 50349 | UA_UInt16 counter = 0; |
| 50350 | TAILQ_FOREACH(dsf, ¤tDataSet->fields, listEntry) { |
| 50351 | /* Sample the value */ |
| 50352 | UA_DataValue value; |
| 50353 | UA_DataValue_init(p: &value); |
| 50354 | UA_PubSubDataSetField_sampleValue(server, field: dsf, value: &value); |
| 50355 | |
| 50356 | /* Check if the value has changed */ |
| 50357 | UA_DataSetWriterSample *ls = &dataSetWriter->lastSamples[counter]; |
| 50358 | if(valueChangedVariant(oldValue: &ls->value.value, newValue: &value.value)) { |
| 50359 | /* increase fieldCount for current delta message */ |
| 50360 | dataSetMessage->data.deltaFrameData.fieldCount++; |
| 50361 | ls->valueChanged = true; |
| 50362 | |
| 50363 | /* Update last stored sample */ |
| 50364 | UA_DataValue_clear(p: &ls->value); |
| 50365 | ls->value = value; |
| 50366 | } else { |
| 50367 | UA_DataValue_clear(p: &value); |
| 50368 | ls->valueChanged = false; |
| 50369 | } |
| 50370 | |
| 50371 | counter++; |
| 50372 | } |
| 50373 | |
| 50374 | /* Allocate DeltaFrameFields */ |
| 50375 | UA_DataSetMessage_DeltaFrameField *deltaFields = (UA_DataSetMessage_DeltaFrameField *) |
| 50376 | UA_calloc(nmemb: counter, size: sizeof(UA_DataSetMessage_DeltaFrameField)); |
| 50377 | if(!deltaFields) |
| 50378 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 50379 | |
| 50380 | dataSetMessage->data.deltaFrameData.deltaFrameFields = deltaFields; |
| 50381 | dataSetMessage->data.deltaFrameData.fieldCount = counter; |
| 50382 | |
| 50383 | size_t currentDeltaField = 0; |
| 50384 | for(size_t i = 0; i < currentDataSet->fieldSize; i++) { |
| 50385 | if(!dataSetWriter->lastSamples[i].valueChanged) |
| 50386 | continue; |
| 50387 | |
| 50388 | UA_DataSetMessage_DeltaFrameField *dff = &deltaFields[currentDeltaField]; |
| 50389 | |
| 50390 | dff->fieldIndex = (UA_UInt16) i; |
| 50391 | UA_DataValue_copy(src: &dataSetWriter->lastSamples[i].value, dst: &dff->fieldValue); |
| 50392 | |
| 50393 | /* Reset the changed flag */ |
| 50394 | dataSetWriter->lastSamples[i].valueChanged = false; |
| 50395 | |
| 50396 | /* Deactivate statuscode? */ |
| 50397 | if(((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50398 | (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE) == 0) |
| 50399 | dff->fieldValue.hasStatus = false; |
| 50400 | |
| 50401 | /* Deactivate timestamps? */ |
| 50402 | if(((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50403 | (u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP) == 0) |
| 50404 | dff->fieldValue.hasSourceTimestamp = false; |
| 50405 | if(((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50406 | (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS) == 0) |
| 50407 | dff->fieldValue.hasServerPicoseconds = false; |
| 50408 | if(((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50409 | (u64)UA_DATASETFIELDCONTENTMASK_SERVERTIMESTAMP) == 0) |
| 50410 | dff->fieldValue.hasServerTimestamp = false; |
| 50411 | if(((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50412 | (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS) == 0) |
| 50413 | dff->fieldValue.hasServerPicoseconds = false; |
| 50414 | |
| 50415 | currentDeltaField++; |
| 50416 | } |
| 50417 | return UA_STATUSCODE_GOOD; |
| 50418 | } |
| 50419 | |
| 50420 | /* Generate a DataSetMessage for the given writer. */ |
| 50421 | UA_StatusCode |
| 50422 | UA_DataSetWriter_generateDataSetMessage(UA_Server *server, |
| 50423 | UA_DataSetMessage *dataSetMessage, |
| 50424 | UA_DataSetWriter *dataSetWriter) { |
| 50425 | UA_Boolean heartbeat = false; |
| 50426 | UA_PublishedDataSet *currentDataSet = NULL; |
| 50427 | if(UA_NodeId_isNull(p: &dataSetWriter->connectedDataSet)){ |
| 50428 | heartbeat = true; |
| 50429 | } else { |
| 50430 | currentDataSet = |
| 50431 | UA_PublishedDataSet_findPDSbyId(server, identifier: dataSetWriter->connectedDataSet); |
| 50432 | if(!currentDataSet){ |
| 50433 | return UA_STATUSCODE_BADNOTFOUND; |
| 50434 | } |
| 50435 | } |
| 50436 | |
| 50437 | /* Reset the message */ |
| 50438 | memset(s: dataSetMessage, c: 0, n: sizeof(UA_DataSetMessage)); |
| 50439 | |
| 50440 | /* The configuration Flags are included |
| 50441 | * inside the std. defined UA_UadpDataSetWriterMessageDataType */ |
| 50442 | UA_UadpDataSetWriterMessageDataType defaultUadpConfiguration; |
| 50443 | UA_UadpDataSetWriterMessageDataType *dsm = NULL; |
| 50444 | UA_JsonDataSetWriterMessageDataType *jsonDsm = NULL; |
| 50445 | const UA_ExtensionObject *ms = &dataSetWriter->config.messageSettings; |
| 50446 | if((ms->encoding == UA_EXTENSIONOBJECT_DECODED || |
| 50447 | ms->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) && |
| 50448 | ms->content.decoded.type == &UA_TYPES[UA_TYPES_UADPDATASETWRITERMESSAGEDATATYPE]) { |
| 50449 | dsm = (UA_UadpDataSetWriterMessageDataType*)ms->content.decoded.data; /* type is UADP */ |
| 50450 | } else if((ms->encoding == UA_EXTENSIONOBJECT_DECODED || |
| 50451 | ms->encoding == UA_EXTENSIONOBJECT_DECODED_NODELETE) && |
| 50452 | ms->content.decoded.type == &UA_TYPES[UA_TYPES_JSONDATASETWRITERMESSAGEDATATYPE]) { |
| 50453 | jsonDsm = (UA_JsonDataSetWriterMessageDataType*)ms->content.decoded.data; /* type is JSON */ |
| 50454 | } else { |
| 50455 | /* Create default flag configuration if no |
| 50456 | * UadpDataSetWriterMessageDataType was passed in */ |
| 50457 | memset(s: &defaultUadpConfiguration, c: 0, n: sizeof(UA_UadpDataSetWriterMessageDataType)); |
| 50458 | defaultUadpConfiguration.dataSetMessageContentMask = (UA_UadpDataSetMessageContentMask) |
| 50459 | ((u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP | |
| 50460 | (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION | |
| 50461 | (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION); |
| 50462 | dsm = &defaultUadpConfiguration; /* type is UADP */ |
| 50463 | } |
| 50464 | |
| 50465 | /* The field encoding depends on the flags inside the writer config. */ |
| 50466 | if(dataSetWriter->config.dataSetFieldContentMask & |
| 50467 | (u64)UA_DATASETFIELDCONTENTMASK_RAWDATA) { |
| 50468 | dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_RAWDATA; |
| 50469 | } else if((u64)dataSetWriter->config.dataSetFieldContentMask & |
| 50470 | ((u64)UA_DATASETFIELDCONTENTMASK_SOURCETIMESTAMP | |
| 50471 | (u64)UA_DATASETFIELDCONTENTMASK_SERVERPICOSECONDS | |
| 50472 | (u64)UA_DATASETFIELDCONTENTMASK_SOURCEPICOSECONDS | |
| 50473 | (u64)UA_DATASETFIELDCONTENTMASK_STATUSCODE)) { |
| 50474 | dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE; |
| 50475 | } else { |
| 50476 | dataSetMessage->header.fieldEncoding = UA_FIELDENCODING_VARIANT; |
| 50477 | } |
| 50478 | |
| 50479 | if(dsm) { |
| 50480 | /* Sanity-test the configuration */ |
| 50481 | if(dsm->networkMessageNumber != 0 || |
| 50482 | dsm->dataSetOffset != 0 || |
| 50483 | dsm->configuredSize != 0) { |
| 50484 | UA_LOG_WARNING_WRITER(server->config.logging, dataSetWriter, |
| 50485 | "Static DSM configuration not supported, using defaults"); |
| 50486 | dsm->networkMessageNumber = 0; |
| 50487 | dsm->dataSetOffset = 0; |
| 50488 | // dsm->configuredSize = 0; |
| 50489 | } |
| 50490 | |
| 50491 | /* setting configured size in the dataSetMessage to add padding later on */ |
| 50492 | dataSetMessage->configuredSize = dsm->configuredSize; |
| 50493 | |
| 50494 | /* Std: 'The DataSetMessageContentMask defines the flags for the content |
| 50495 | * of the DataSetMessage header.' */ |
| 50496 | if((u64)dsm->dataSetMessageContentMask & |
| 50497 | (u64)UA_UADPDATASETMESSAGECONTENTMASK_MAJORVERSION) { |
| 50498 | dataSetMessage->header.configVersionMajorVersionEnabled = true; |
| 50499 | if(heartbeat){ |
| 50500 | dataSetMessage->header.configVersionMajorVersion = 0; |
| 50501 | } else { |
| 50502 | dataSetMessage->header.configVersionMajorVersion = |
| 50503 | currentDataSet->dataSetMetaData.configurationVersion.majorVersion; |
| 50504 | } |
| 50505 | } |
| 50506 | if((u64)dsm->dataSetMessageContentMask & |
| 50507 | (u64)UA_UADPDATASETMESSAGECONTENTMASK_MINORVERSION) { |
| 50508 | dataSetMessage->header.configVersionMinorVersionEnabled = true; |
| 50509 | if(heartbeat){ |
| 50510 | dataSetMessage->header.configVersionMinorVersion = 0; |
| 50511 | } else { |
| 50512 | dataSetMessage->header.configVersionMinorVersion = |
| 50513 | currentDataSet->dataSetMetaData.configurationVersion.minorVersion; |
| 50514 | } |
| 50515 | } |
| 50516 | |
| 50517 | if((u64)dsm->dataSetMessageContentMask & |
| 50518 | (u64)UA_UADPDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) { |
| 50519 | dataSetMessage->header.dataSetMessageSequenceNrEnabled = true; |
| 50520 | dataSetMessage->header.dataSetMessageSequenceNr = |
| 50521 | dataSetWriter->actualDataSetMessageSequenceCount; |
| 50522 | } |
| 50523 | |
| 50524 | if((u64)dsm->dataSetMessageContentMask & |
| 50525 | (u64)UA_UADPDATASETMESSAGECONTENTMASK_TIMESTAMP) { |
| 50526 | dataSetMessage->header.timestampEnabled = true; |
| 50527 | dataSetMessage->header.timestamp = UA_DateTime_now(); |
| 50528 | } |
| 50529 | |
| 50530 | /* TODO: Picoseconds resolution not supported atm */ |
| 50531 | if((u64)dsm->dataSetMessageContentMask & |
| 50532 | (u64)UA_UADPDATASETMESSAGECONTENTMASK_PICOSECONDS) { |
| 50533 | dataSetMessage->header.picoSecondsIncluded = false; |
| 50534 | } |
| 50535 | |
| 50536 | /* TODO: Statuscode not supported yet */ |
| 50537 | if((u64)dsm->dataSetMessageContentMask & |
| 50538 | (u64)UA_UADPDATASETMESSAGECONTENTMASK_STATUS) { |
| 50539 | dataSetMessage->header.statusEnabled = true; |
| 50540 | } |
| 50541 | } else if(jsonDsm) { |
| 50542 | if((u64)jsonDsm->dataSetMessageContentMask & |
| 50543 | (u64)UA_JSONDATASETMESSAGECONTENTMASK_METADATAVERSION) { |
| 50544 | dataSetMessage->header.configVersionMajorVersionEnabled = true; |
| 50545 | dataSetMessage->header.configVersionMinorVersionEnabled = true; |
| 50546 | if(heartbeat){ |
| 50547 | dataSetMessage->header.configVersionMajorVersion = 0; |
| 50548 | dataSetMessage->header.configVersionMinorVersion = 0; |
| 50549 | } else { |
| 50550 | dataSetMessage->header.configVersionMajorVersion = |
| 50551 | currentDataSet->dataSetMetaData.configurationVersion.majorVersion; |
| 50552 | dataSetMessage->header.configVersionMinorVersion = |
| 50553 | currentDataSet->dataSetMetaData.configurationVersion.minorVersion; |
| 50554 | } |
| 50555 | } |
| 50556 | |
| 50557 | if((u64)jsonDsm->dataSetMessageContentMask & |
| 50558 | (u64)UA_JSONDATASETMESSAGECONTENTMASK_SEQUENCENUMBER) { |
| 50559 | dataSetMessage->header.dataSetMessageSequenceNrEnabled = true; |
| 50560 | dataSetMessage->header.dataSetMessageSequenceNr = |
| 50561 | dataSetWriter->actualDataSetMessageSequenceCount; |
| 50562 | } |
| 50563 | |
| 50564 | if((u64)jsonDsm->dataSetMessageContentMask & |
| 50565 | (u64)UA_JSONDATASETMESSAGECONTENTMASK_TIMESTAMP) { |
| 50566 | dataSetMessage->header.timestampEnabled = true; |
| 50567 | dataSetMessage->header.timestamp = UA_DateTime_now(); |
| 50568 | } |
| 50569 | |
| 50570 | /* TODO: Statuscode not supported yet */ |
| 50571 | if((u64)jsonDsm->dataSetMessageContentMask & |
| 50572 | (u64)UA_JSONDATASETMESSAGECONTENTMASK_STATUS) { |
| 50573 | dataSetMessage->header.statusEnabled = true; |
| 50574 | } |
| 50575 | } |
| 50576 | |
| 50577 | /* Set the sequence count. Automatically rolls over to zero */ |
| 50578 | dataSetWriter->actualDataSetMessageSequenceCount++; |
| 50579 | |
| 50580 | if(heartbeat) { |
| 50581 | /* Prepare DataSetMessageContent */ |
| 50582 | dataSetMessage->header.dataSetMessageValid = true; |
| 50583 | dataSetMessage->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME; |
| 50584 | dataSetMessage->data.keyFrameData.fieldCount = 0; |
| 50585 | return UA_STATUSCODE_GOOD; |
| 50586 | } |
| 50587 | |
| 50588 | /* JSON does not differ between deltaframes and keyframes, only keyframes |
| 50589 | * are currently used. */ |
| 50590 | if(dsm && server->config.pubSubConfig.enableDeltaFrames) { |
| 50591 | /* Check if the PublishedDataSet version has changed -> if yes flush the |
| 50592 | * lastValue store and send a KeyFrame */ |
| 50593 | if(dataSetWriter->connectedDataSetVersion.majorVersion != |
| 50594 | currentDataSet->dataSetMetaData.configurationVersion.majorVersion || |
| 50595 | dataSetWriter->connectedDataSetVersion.minorVersion != |
| 50596 | currentDataSet->dataSetMetaData.configurationVersion.minorVersion) { |
| 50597 | /* Remove old samples */ |
| 50598 | for(size_t i = 0; i < dataSetWriter->lastSamplesCount; i++) |
| 50599 | UA_DataValue_clear(p: &dataSetWriter->lastSamples[i].value); |
| 50600 | |
| 50601 | /* Realloc PDS dependent memory */ |
| 50602 | dataSetWriter->lastSamplesCount = currentDataSet->fieldSize; |
| 50603 | UA_DataSetWriterSample *newSamplesArray = (UA_DataSetWriterSample * ) |
| 50604 | UA_realloc(ptr: dataSetWriter->lastSamples, |
| 50605 | size: sizeof(UA_DataSetWriterSample) * dataSetWriter->lastSamplesCount); |
| 50606 | if(!newSamplesArray) |
| 50607 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 50608 | dataSetWriter->lastSamples = newSamplesArray; |
| 50609 | memset(s: dataSetWriter->lastSamples, c: 0, |
| 50610 | n: sizeof(UA_DataSetWriterSample) * dataSetWriter->lastSamplesCount); |
| 50611 | |
| 50612 | dataSetWriter->connectedDataSetVersion = |
| 50613 | currentDataSet->dataSetMetaData.configurationVersion; |
| 50614 | UA_PubSubDataSetWriter_generateKeyFrameMessage(server, dataSetMessage, |
| 50615 | dataSetWriter); |
| 50616 | dataSetWriter->deltaFrameCounter = 0; |
| 50617 | return UA_STATUSCODE_GOOD; |
| 50618 | } |
| 50619 | |
| 50620 | /* The standard defines: if a PDS contains only one fields no delta messages |
| 50621 | * should be generated because they need more memory than a keyframe with 1 |
| 50622 | * field. */ |
| 50623 | if(currentDataSet->fieldSize > 1 && dataSetWriter->deltaFrameCounter > 0 && |
| 50624 | dataSetWriter->deltaFrameCounter <= dataSetWriter->config.keyFrameCount) { |
| 50625 | UA_PubSubDataSetWriter_generateDeltaFrameMessage(server, dataSetMessage, |
| 50626 | dataSetWriter); |
| 50627 | dataSetWriter->deltaFrameCounter++; |
| 50628 | return UA_STATUSCODE_GOOD; |
| 50629 | } |
| 50630 | |
| 50631 | dataSetWriter->deltaFrameCounter = 1; |
| 50632 | } |
| 50633 | |
| 50634 | return UA_PubSubDataSetWriter_generateKeyFrameMessage(server, dataSetMessage, |
| 50635 | dataSetWriter); |
| 50636 | } |
| 50637 | |
| 50638 | #endif /* UA_ENABLE_PUBSUB */ |
| 50639 | |
| 50640 | /**** amalgamated original file "/src/pubsub/ua_pubsub_writergroup.c" ****/ |
| 50641 | |
| 50642 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 50643 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 50644 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 50645 | * |
| 50646 | * Copyright (c) 2017-2019 Fraunhofer IOSB (Author: Andreas Ebner) |
| 50647 | * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer) |
| 50648 | * Copyright (c) 2019 Kalycito Infotech Private Limited |
| 50649 | * Copyright (c) 2020 Yannick Wallerer, Siemens AG |
| 50650 | * Copyright (c) 2020 Thomas Fischer, Siemens AG |
| 50651 | * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes) |
| 50652 | * Copyright (c) 2022 Linutronix GmbH (Author: Muddasir Shakil) |
| 50653 | */ |
| 50654 | |
| 50655 | |
| 50656 | #ifdef UA_ENABLE_PUBSUB /* conditional compilation */ |
| 50657 | |
| 50658 | |
| 50659 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 50660 | #endif |
| 50661 | |
| 50662 | #define UA_MAX_STACKBUF 128 /* Max size of network messages on the stack */ |
| 50663 | |
| 50664 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 50665 | static UA_StatusCode |
| 50666 | encryptAndSign(UA_WriterGroup *wg, const UA_NetworkMessage *nm, |
| 50667 | UA_Byte *signStart, UA_Byte *encryptStart, |
| 50668 | UA_Byte *msgEnd); |
| 50669 | |
| 50670 | #endif |
| 50671 | |
| 50672 | static UA_StatusCode |
| 50673 | generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg, |
| 50674 | UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount, |
| 50675 | UA_ExtensionObject *messageSettings, |
| 50676 | UA_ExtensionObject *transportSettings, |
| 50677 | UA_NetworkMessage *networkMessage); |
| 50678 | |
| 50679 | /* Add new publishCallback. The first execution is triggered directly after |
| 50680 | * creation. */ |
| 50681 | UA_StatusCode |
| 50682 | UA_WriterGroup_addPublishCallback(UA_Server *server, UA_WriterGroup *wg) { |
| 50683 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 50684 | |
| 50685 | /* Already registered */ |
| 50686 | if(wg->publishCallbackId != 0) |
| 50687 | return UA_STATUSCODE_BADINTERNALERROR; |
| 50688 | |
| 50689 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 50690 | if(wg->config.pubsubManagerCallback.addCustomCallback) { |
| 50691 | /* Use configured mechanism for cyclic callbacks */ |
| 50692 | retval = wg->config.pubsubManagerCallback. |
| 50693 | addCustomCallback(server, wg->identifier, |
| 50694 | (UA_ServerCallback)UA_WriterGroup_publishCallback, |
| 50695 | wg, wg->config.publishingInterval, |
| 50696 | NULL, UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, |
| 50697 | &wg->publishCallbackId); |
| 50698 | } else { |
| 50699 | /* Use EventLoop for cyclic callbacks */ |
| 50700 | UA_EventLoop *el = UA_PubSubConnection_getEL(server, c: wg->linkedConnection); |
| 50701 | retval = el->addCyclicCallback(el, (UA_Callback)UA_WriterGroup_publishCallback, |
| 50702 | server, wg, wg->config.publishingInterval, |
| 50703 | NULL /* TODO: use basetime */, |
| 50704 | UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, |
| 50705 | &wg->publishCallbackId); |
| 50706 | } |
| 50707 | if(retval != UA_STATUSCODE_GOOD) |
| 50708 | return retval; |
| 50709 | |
| 50710 | /* Run once after creation. The Publish callback itself takes the server |
| 50711 | * mutex. So we release it first. */ |
| 50712 | UA_WriterGroup_publishCallback(server, writerGroup: wg); |
| 50713 | return retval; |
| 50714 | } |
| 50715 | |
| 50716 | static void |
| 50717 | UA_WriterGroup_removePublishCallback(UA_Server *server, UA_WriterGroup *wg) { |
| 50718 | if(wg->publishCallbackId == 0) |
| 50719 | return; |
| 50720 | if(wg->config.pubsubManagerCallback.removeCustomCallback) { |
| 50721 | wg->config.pubsubManagerCallback. |
| 50722 | removeCustomCallback(server, wg->identifier, wg->publishCallbackId); |
| 50723 | } else { |
| 50724 | UA_EventLoop *el = UA_PubSubConnection_getEL(server, c: wg->linkedConnection); |
| 50725 | el->removeCyclicCallback(el, wg->publishCallbackId); |
| 50726 | } |
| 50727 | wg->publishCallbackId = 0; |
| 50728 | } |
| 50729 | |
| 50730 | UA_StatusCode |
| 50731 | UA_WriterGroup_create(UA_Server *server, const UA_NodeId connection, |
| 50732 | const UA_WriterGroupConfig *writerGroupConfig, |
| 50733 | UA_NodeId *writerGroupIdentifier) { |
| 50734 | /* Delete the reserved IDs if the related session no longer exists. */ |
| 50735 | UA_PubSubManager_freeIds(server); |
| 50736 | if(!writerGroupConfig) |
| 50737 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 50738 | |
| 50739 | /* Search the connection by the given connectionIdentifier */ |
| 50740 | UA_PubSubConnection *currentConnectionContext = |
| 50741 | UA_PubSubConnection_findConnectionbyId(server, connectionIdentifier: connection); |
| 50742 | if(!currentConnectionContext) |
| 50743 | return UA_STATUSCODE_BADNOTFOUND; |
| 50744 | |
| 50745 | if(currentConnectionContext->configurationFreezeCounter > 0) { |
| 50746 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 50747 | msg: "Adding WriterGroup failed. PubSubConnection is frozen."); |
| 50748 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 50749 | } |
| 50750 | |
| 50751 | /* Validate messageSettings type */ |
| 50752 | const UA_ExtensionObject *ms = &writerGroupConfig->messageSettings; |
| 50753 | if(ms->content.decoded.type) { |
| 50754 | if(writerGroupConfig->encodingMimeType == UA_PUBSUB_ENCODING_JSON && |
| 50755 | (ms->encoding != UA_EXTENSIONOBJECT_DECODED || |
| 50756 | ms->content.decoded.type != &UA_TYPES[UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE])) { |
| 50757 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 50758 | } |
| 50759 | |
| 50760 | if(writerGroupConfig->encodingMimeType == UA_PUBSUB_ENCODING_UADP && |
| 50761 | (ms->encoding != UA_EXTENSIONOBJECT_DECODED || |
| 50762 | ms->content.decoded.type != &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE])) { |
| 50763 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 50764 | } |
| 50765 | } |
| 50766 | |
| 50767 | /* Allocate new WriterGroup */ |
| 50768 | UA_WriterGroup *newWriterGroup = (UA_WriterGroup*)UA_calloc(nmemb: 1, size: sizeof(UA_WriterGroup)); |
| 50769 | if(!newWriterGroup) |
| 50770 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 50771 | |
| 50772 | memset(s: newWriterGroup, c: 0, n: sizeof(UA_WriterGroup)); |
| 50773 | newWriterGroup->componentType = UA_PUBSUB_COMPONENT_WRITERGROUP; |
| 50774 | newWriterGroup->linkedConnection = currentConnectionContext; |
| 50775 | |
| 50776 | /* Deep copy of the config */ |
| 50777 | UA_WriterGroupConfig *newConfig = &newWriterGroup->config; |
| 50778 | UA_StatusCode res = UA_WriterGroupConfig_copy(src: writerGroupConfig, dst: newConfig); |
| 50779 | if(res != UA_STATUSCODE_GOOD) { |
| 50780 | UA_free(ptr: newWriterGroup); |
| 50781 | return res; |
| 50782 | } |
| 50783 | |
| 50784 | /* Create the datatype value if not present */ |
| 50785 | if(!newConfig->messageSettings.content.decoded.type) { |
| 50786 | UA_UadpWriterGroupMessageDataType *wgm = UA_UadpWriterGroupMessageDataType_new(); |
| 50787 | newConfig->messageSettings.content.decoded.data = wgm; |
| 50788 | newConfig->messageSettings.content.decoded.type = |
| 50789 | &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]; |
| 50790 | newConfig->messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 50791 | } |
| 50792 | |
| 50793 | /* Attach to the connection */ |
| 50794 | LIST_INSERT_HEAD(¤tConnectionContext->writerGroups, newWriterGroup, listEntry); |
| 50795 | currentConnectionContext->writerGroupsSize++; |
| 50796 | |
| 50797 | /* Add representation / create unique identifier */ |
| 50798 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 50799 | res = addWriterGroupRepresentation(server, writerGroup: newWriterGroup); |
| 50800 | #else |
| 50801 | UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, |
| 50802 | &newWriterGroup->identifier); |
| 50803 | #endif |
| 50804 | |
| 50805 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 50806 | if(writerGroupConfig->securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 50807 | writerGroupConfig->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 50808 | if(!UA_String_isEmpty(&writerGroupConfig->securityGroupId) && |
| 50809 | writerGroupConfig->securityPolicy) { |
| 50810 | /* Does the key storage already exist? */ |
| 50811 | newWriterGroup->keyStorage = |
| 50812 | UA_PubSubKeyStorage_findKeyStorage(server, writerGroupConfig->securityGroupId); |
| 50813 | |
| 50814 | if(!newWriterGroup->keyStorage) { |
| 50815 | /* Create a new key storage */ |
| 50816 | newWriterGroup->keyStorage = (UA_PubSubKeyStorage *) |
| 50817 | UA_calloc(1, sizeof(UA_PubSubKeyStorage)); |
| 50818 | if(!newWriterGroup) |
| 50819 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 50820 | res = UA_PubSubKeyStorage_init(server, newWriterGroup->keyStorage, |
| 50821 | &writerGroupConfig->securityGroupId, |
| 50822 | writerGroupConfig->securityPolicy, 0, 0); |
| 50823 | if(res != UA_STATUSCODE_GOOD) { |
| 50824 | UA_free(newWriterGroup); |
| 50825 | return res; |
| 50826 | } |
| 50827 | } |
| 50828 | |
| 50829 | /* Increase the ref count */ |
| 50830 | newWriterGroup->keyStorage->referenceCount++; |
| 50831 | } |
| 50832 | } |
| 50833 | |
| 50834 | #endif |
| 50835 | |
| 50836 | if(writerGroupIdentifier) |
| 50837 | UA_NodeId_copy(src: &newWriterGroup->identifier, dst: writerGroupIdentifier); |
| 50838 | |
| 50839 | /* Trigger the connection to open a connection */ |
| 50840 | UA_PubSubConnection_setPubSubState(server, c: currentConnectionContext, |
| 50841 | state: currentConnectionContext->state, |
| 50842 | UA_STATUSCODE_GOOD); |
| 50843 | |
| 50844 | return res; |
| 50845 | } |
| 50846 | |
| 50847 | UA_StatusCode |
| 50848 | UA_Server_addWriterGroup(UA_Server *server, const UA_NodeId connection, |
| 50849 | const UA_WriterGroupConfig *writerGroupConfig, |
| 50850 | UA_NodeId *writerGroupIdentifier) { |
| 50851 | lockServer(server); |
| 50852 | UA_StatusCode res = UA_WriterGroup_create(server, connection, writerGroupConfig, |
| 50853 | writerGroupIdentifier); |
| 50854 | unlockServer(server); |
| 50855 | return res; |
| 50856 | } |
| 50857 | |
| 50858 | UA_StatusCode |
| 50859 | UA_WriterGroup_remove(UA_Server *server, UA_WriterGroup *wg) { |
| 50860 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 50861 | |
| 50862 | if(wg->configurationFrozen) { |
| 50863 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 50864 | "Deleting the WriterGroup failed. " |
| 50865 | "WriterGroup is frozen."); |
| 50866 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 50867 | } |
| 50868 | |
| 50869 | UA_PubSubConnection *connection = wg->linkedConnection; |
| 50870 | UA_assert(connection); |
| 50871 | if(connection->configurationFreezeCounter > 0) { |
| 50872 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 50873 | "Deleting the WriterGroup failed. " |
| 50874 | "PubSubConnection is frozen."); |
| 50875 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 50876 | } |
| 50877 | |
| 50878 | /* Disable (and disconnect) and set the deleteFlag. This prevents a |
| 50879 | * reconnect and triggers the deletion when the last open socket is |
| 50880 | * closed. */ |
| 50881 | wg->deleteFlag = true; |
| 50882 | UA_WriterGroup_setPubSubState(server, writerGroup: wg, state: UA_PUBSUBSTATE_DISABLED, UA_STATUSCODE_GOOD); |
| 50883 | |
| 50884 | UA_DataSetWriter *dsw, *dsw_tmp; |
| 50885 | LIST_FOREACH_SAFE(dsw, &wg->writers, listEntry, dsw_tmp) { |
| 50886 | UA_DataSetWriter_remove(server, dataSetWriter: dsw); |
| 50887 | } |
| 50888 | |
| 50889 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 50890 | if(wg->config.securityPolicy && wg->securityPolicyContext) { |
| 50891 | wg->config.securityPolicy->deleteContext(wg->securityPolicyContext); |
| 50892 | wg->securityPolicyContext = NULL; |
| 50893 | } |
| 50894 | #endif |
| 50895 | |
| 50896 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 50897 | if(wg->keyStorage) { |
| 50898 | UA_PubSubKeyStorage_detachKeyStorage(server, wg->keyStorage); |
| 50899 | wg->keyStorage = NULL; |
| 50900 | } |
| 50901 | #endif |
| 50902 | |
| 50903 | if(wg->sendChannel == 0) { |
| 50904 | /* Unlink from the connection */ |
| 50905 | LIST_REMOVE(wg, listEntry); |
| 50906 | connection->writerGroupsSize--; |
| 50907 | wg->linkedConnection = NULL; |
| 50908 | |
| 50909 | /* Actually remove the WriterGroup */ |
| 50910 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 50911 | deleteNode(server, nodeId: wg->identifier, true); |
| 50912 | #endif |
| 50913 | UA_WriterGroupConfig_clear(writerGroupConfig: &wg->config); |
| 50914 | UA_NodeId_clear(p: &wg->identifier); |
| 50915 | UA_NetworkMessageOffsetBuffer_clear(nmob: &wg->bufferedMessage); |
| 50916 | UA_free(ptr: wg); |
| 50917 | } |
| 50918 | |
| 50919 | /* Update the connection state */ |
| 50920 | UA_PubSubConnection_setPubSubState(server, c: connection, state: connection->state, |
| 50921 | UA_STATUSCODE_GOOD); |
| 50922 | |
| 50923 | return UA_STATUSCODE_GOOD; |
| 50924 | } |
| 50925 | |
| 50926 | UA_StatusCode |
| 50927 | UA_Server_removeWriterGroup(UA_Server *server, const UA_NodeId writerGroup) { |
| 50928 | lockServer(server); |
| 50929 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: writerGroup); |
| 50930 | if(!wg) { |
| 50931 | unlockServer(server); |
| 50932 | return UA_STATUSCODE_BADNOTFOUND; |
| 50933 | } |
| 50934 | UA_StatusCode res = UA_WriterGroup_remove(server, wg); |
| 50935 | unlockServer(server); |
| 50936 | return res; |
| 50937 | } |
| 50938 | |
| 50939 | UA_StatusCode |
| 50940 | UA_WriterGroup_freezeConfiguration(UA_Server *server, UA_WriterGroup *wg) { |
| 50941 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 50942 | |
| 50943 | if(wg->configurationFrozen) |
| 50944 | return UA_STATUSCODE_GOOD; |
| 50945 | |
| 50946 | /* Increase PubSubConnection freezeCounter */ |
| 50947 | UA_PubSubConnection *pubSubConnection = wg->linkedConnection; |
| 50948 | pubSubConnection->configurationFreezeCounter++; |
| 50949 | |
| 50950 | /* Freeze the WriterGroup */ |
| 50951 | wg->configurationFrozen = true; |
| 50952 | |
| 50953 | /* Freeze the DataSetWriter */ |
| 50954 | UA_DataSetWriter *dsw; |
| 50955 | LIST_FOREACH(dsw, &wg->writers, listEntry) { |
| 50956 | UA_DataSetWriter_freezeConfiguration(server, dsw); |
| 50957 | } |
| 50958 | |
| 50959 | /* Offset table enabled? */ |
| 50960 | if((wg->config.rtLevel & UA_PUBSUB_RT_FIXED_SIZE) == 0) |
| 50961 | return UA_STATUSCODE_GOOD; |
| 50962 | |
| 50963 | /* Offset table only possible for binary encoding */ |
| 50964 | if(wg->config.encodingMimeType != UA_PUBSUB_ENCODING_UADP) { |
| 50965 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 50966 | "PubSub-RT configuration fail: Non-RT capable encoding."); |
| 50967 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 50968 | } |
| 50969 | |
| 50970 | //TODO Clarify: should we only allow = maxEncapsulatedDataSetMessageCount == 1 with RT? |
| 50971 | //TODO Clarify: Behaviour if the finale size is more than MTU |
| 50972 | |
| 50973 | /* Define variables here for goto */ |
| 50974 | size_t msgSize; |
| 50975 | UA_ByteString buf; |
| 50976 | const UA_Byte *bufEnd; |
| 50977 | UA_Byte *bufPos; |
| 50978 | UA_NetworkMessage networkMessage; |
| 50979 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 50980 | UA_STACKARRAY(UA_UInt16, dsWriterIds, wg->writersCount); |
| 50981 | UA_STACKARRAY(UA_DataSetMessage, dsmStore, wg->writersCount); |
| 50982 | |
| 50983 | /* Validate the DataSetWriters and generate their DataSetMessage */ |
| 50984 | size_t dsmCount = 0; |
| 50985 | LIST_FOREACH(dsw, &wg->writers, listEntry) { |
| 50986 | dsWriterIds[dsmCount] = dsw->config.dataSetWriterId; |
| 50987 | res = UA_DataSetWriter_prepareDataSet(server, dsw, dsm: &dsmStore[dsmCount]); |
| 50988 | if(res != UA_STATUSCODE_GOOD) |
| 50989 | goto cleanup_dsm; |
| 50990 | dsmCount++; |
| 50991 | } |
| 50992 | |
| 50993 | /* Generate the NetworkMessage */ |
| 50994 | memset(s: &networkMessage, c: 0, n: sizeof(networkMessage)); |
| 50995 | res = generateNetworkMessage(connection: pubSubConnection, wg, dsm: dsmStore, writerIds: dsWriterIds, |
| 50996 | dsmCount: (UA_Byte) dsmCount, messageSettings: &wg->config.messageSettings, |
| 50997 | transportSettings: &wg->config.transportSettings, networkMessage: &networkMessage); |
| 50998 | if(res != UA_STATUSCODE_GOOD) |
| 50999 | goto cleanup_dsm; |
| 51000 | |
| 51001 | /* Compute the message length and generate the offset-table (done inside |
| 51002 | * calcSizeBinary) */ |
| 51003 | memset(s: &wg->bufferedMessage, c: 0, n: sizeof(UA_NetworkMessageOffsetBuffer)); |
| 51004 | msgSize = UA_NetworkMessage_calcSizeBinary(p: &networkMessage, offsetBuffer: &wg->bufferedMessage); |
| 51005 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51006 | if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) { |
| 51007 | UA_PubSubSecurityPolicy *sp = wg->config.securityPolicy; |
| 51008 | msgSize += sp->symmetricModule.cryptoModule. |
| 51009 | signatureAlgorithm.getLocalSignatureSize(sp->policyContext); |
| 51010 | } |
| 51011 | #endif |
| 51012 | |
| 51013 | /* Generate the buffer for the pre-encoded message */ |
| 51014 | res = UA_ByteString_allocBuffer(bs: &buf, length: msgSize); |
| 51015 | if(res != UA_STATUSCODE_GOOD) |
| 51016 | goto cleanup; |
| 51017 | wg->bufferedMessage.buffer = buf; |
| 51018 | |
| 51019 | /* Encode the NetworkMessage */ |
| 51020 | bufEnd = &wg->bufferedMessage.buffer.data[wg->bufferedMessage.buffer.length]; |
| 51021 | bufPos = wg->bufferedMessage.buffer.data; |
| 51022 | |
| 51023 | /* Preallocate the encryption buffer */ |
| 51024 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51025 | if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) { |
| 51026 | UA_Byte *payloadPosition; |
| 51027 | UA_NetworkMessage_encodeBinary(&networkMessage, &bufPos, bufEnd, &payloadPosition); |
| 51028 | wg->bufferedMessage.payloadPosition = payloadPosition; |
| 51029 | wg->bufferedMessage.nm = (UA_NetworkMessage *)UA_calloc(1,sizeof(UA_NetworkMessage)); |
| 51030 | wg->bufferedMessage.nm->securityHeader = networkMessage.securityHeader; |
| 51031 | UA_ByteString_allocBuffer(&wg->bufferedMessage.encryptBuffer, msgSize); |
| 51032 | } |
| 51033 | #endif |
| 51034 | |
| 51035 | if(wg->config.securityMode <= UA_MESSAGESECURITYMODE_NONE) |
| 51036 | UA_NetworkMessage_encodeBinary(src: &networkMessage, bufPos: &bufPos, bufEnd, NULL); |
| 51037 | |
| 51038 | /* Post-processing of the OffsetBuffer to set the external data source from |
| 51039 | * the DataSetField configuration */ |
| 51040 | if(wg->config.rtLevel & UA_PUBSUB_RT_DIRECT_VALUE_ACCESS) { |
| 51041 | size_t fieldPos = 0; |
| 51042 | LIST_FOREACH(dsw, &wg->writers, listEntry) { |
| 51043 | UA_PublishedDataSet *pds = |
| 51044 | UA_PublishedDataSet_findPDSbyId(server, identifier: dsw->connectedDataSet); |
| 51045 | if(!pds) |
| 51046 | continue; |
| 51047 | |
| 51048 | /* Loop over all DataSetFields */ |
| 51049 | UA_DataSetField *dsf; |
| 51050 | TAILQ_FOREACH(dsf, &pds->fields, listEntry) { |
| 51051 | UA_NetworkMessageOffsetType contentType; |
| 51052 | /* Move forward to the next payload-type offset field */ |
| 51053 | do { |
| 51054 | fieldPos++; |
| 51055 | contentType = wg->bufferedMessage.offsets[fieldPos].contentType; |
| 51056 | } while(contentType != UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE && |
| 51057 | contentType != UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT && |
| 51058 | contentType != UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW); |
| 51059 | UA_assert(fieldPos < wg->bufferedMessage.offsetsSize); |
| 51060 | |
| 51061 | if(!dsf->config.field.variable.rtValueSource.rtFieldSourceEnabled) |
| 51062 | continue; |
| 51063 | |
| 51064 | /* Set the external value soure in the offset buffer */ |
| 51065 | UA_DataValue_clear(p: &wg->bufferedMessage.offsets[fieldPos].content.value); |
| 51066 | wg->bufferedMessage.offsets[fieldPos].content.externalValue = |
| 51067 | dsf->config.field.variable.rtValueSource.staticValueSource; |
| 51068 | |
| 51069 | /* Update the content type to _EXTERNAL */ |
| 51070 | wg->bufferedMessage.offsets[fieldPos].contentType = |
| 51071 | (UA_NetworkMessageOffsetType)(contentType + 1); |
| 51072 | } |
| 51073 | } |
| 51074 | } |
| 51075 | |
| 51076 | cleanup: |
| 51077 | UA_free(ptr: networkMessage.payload.dataSetPayload.sizes); |
| 51078 | |
| 51079 | cleanup_dsm: |
| 51080 | /* Clean up DataSetMessages */ |
| 51081 | for(size_t i = 0; i < dsmCount; i++) { |
| 51082 | UA_DataSetMessage_clear(p: &dsmStore[i]); |
| 51083 | } |
| 51084 | return res; |
| 51085 | } |
| 51086 | |
| 51087 | UA_StatusCode |
| 51088 | UA_Server_freezeWriterGroupConfiguration(UA_Server *server, |
| 51089 | const UA_NodeId writerGroup) { |
| 51090 | lockServer(server); |
| 51091 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: writerGroup); |
| 51092 | if(!wg) { |
| 51093 | unlockServer(server); |
| 51094 | return UA_STATUSCODE_BADNOTFOUND; |
| 51095 | } |
| 51096 | UA_StatusCode res = UA_WriterGroup_freezeConfiguration(server, wg); |
| 51097 | unlockServer(server); |
| 51098 | return res; |
| 51099 | } |
| 51100 | |
| 51101 | UA_StatusCode |
| 51102 | UA_WriterGroup_unfreezeConfiguration(UA_Server *server, UA_WriterGroup *wg) { |
| 51103 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 51104 | |
| 51105 | /* Already unfrozen */ |
| 51106 | if(!wg->configurationFrozen) |
| 51107 | return UA_STATUSCODE_GOOD; |
| 51108 | |
| 51109 | UA_PubSubConnection *pubSubConnection = wg->linkedConnection; |
| 51110 | pubSubConnection->configurationFreezeCounter--; |
| 51111 | |
| 51112 | /* DataSetWriter unfreeze */ |
| 51113 | UA_DataSetWriter *dsw; |
| 51114 | LIST_FOREACH(dsw, &wg->writers, listEntry) { |
| 51115 | UA_DataSetWriter_unfreezeConfiguration(server, dsw); |
| 51116 | } |
| 51117 | |
| 51118 | UA_NetworkMessageOffsetBuffer_clear(nmob: &wg->bufferedMessage); |
| 51119 | wg->configurationFrozen = false; |
| 51120 | |
| 51121 | return UA_STATUSCODE_GOOD; |
| 51122 | } |
| 51123 | |
| 51124 | UA_StatusCode |
| 51125 | UA_Server_unfreezeWriterGroupConfiguration(UA_Server *server, |
| 51126 | const UA_NodeId writerGroup) { |
| 51127 | lockServer(server); |
| 51128 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: writerGroup); |
| 51129 | if(!wg) { |
| 51130 | unlockServer(server); |
| 51131 | return UA_STATUSCODE_BADNOTFOUND; |
| 51132 | } |
| 51133 | UA_StatusCode res = UA_WriterGroup_unfreezeConfiguration(server, wg); |
| 51134 | unlockServer(server); |
| 51135 | return res; |
| 51136 | } |
| 51137 | |
| 51138 | UA_StatusCode |
| 51139 | UA_Server_setWriterGroupOperational(UA_Server *server, |
| 51140 | const UA_NodeId writerGroup) { |
| 51141 | lockServer(server); |
| 51142 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 51143 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: writerGroup); |
| 51144 | if(wg) { |
| 51145 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 51146 | if(wg->keyStorage && wg->keyStorage->currentItem) { |
| 51147 | res = UA_PubSubKeyStorage_activateKeyToChannelContext( |
| 51148 | server, wg->identifier, wg->config.securityGroupId); |
| 51149 | if(res != UA_STATUSCODE_GOOD) { |
| 51150 | unlockServer(server); |
| 51151 | return res; |
| 51152 | } |
| 51153 | } |
| 51154 | #endif |
| 51155 | |
| 51156 | res = UA_WriterGroup_setPubSubState(server, writerGroup: wg, state: UA_PUBSUBSTATE_OPERATIONAL, |
| 51157 | UA_STATUSCODE_GOOD); |
| 51158 | } |
| 51159 | unlockServer(server); |
| 51160 | return res; |
| 51161 | } |
| 51162 | |
| 51163 | UA_StatusCode |
| 51164 | UA_Server_setWriterGroupDisabled(UA_Server *server, |
| 51165 | const UA_NodeId writerGroup) { |
| 51166 | lockServer(server); |
| 51167 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 51168 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: writerGroup); |
| 51169 | if(wg) |
| 51170 | res = UA_WriterGroup_setPubSubState(server, writerGroup: wg, state: UA_PUBSUBSTATE_DISABLED, |
| 51171 | UA_STATUSCODE_BADRESOURCEUNAVAILABLE); |
| 51172 | unlockServer(server); |
| 51173 | return res; |
| 51174 | } |
| 51175 | |
| 51176 | UA_StatusCode |
| 51177 | UA_WriterGroupConfig_copy(const UA_WriterGroupConfig *src, |
| 51178 | UA_WriterGroupConfig *dst) { |
| 51179 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 51180 | memcpy(dest: dst, src: src, n: sizeof(UA_WriterGroupConfig)); |
| 51181 | res |= UA_String_copy(src: &src->name, dst: &dst->name); |
| 51182 | res |= UA_ExtensionObject_copy(src: &src->transportSettings, dst: &dst->transportSettings); |
| 51183 | res |= UA_ExtensionObject_copy(src: &src->messageSettings, dst: &dst->messageSettings); |
| 51184 | res |= UA_KeyValueMap_copy(src: &src->groupProperties, dst: &dst->groupProperties); |
| 51185 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51186 | res |= UA_String_copy(&src->securityGroupId, &dst->securityGroupId); |
| 51187 | #endif |
| 51188 | if(res != UA_STATUSCODE_GOOD) |
| 51189 | UA_WriterGroupConfig_clear(writerGroupConfig: dst); |
| 51190 | return res; |
| 51191 | } |
| 51192 | |
| 51193 | UA_StatusCode |
| 51194 | UA_Server_getWriterGroupConfig(UA_Server *server, const UA_NodeId writerGroup, |
| 51195 | UA_WriterGroupConfig *config) { |
| 51196 | if(!config) |
| 51197 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 51198 | lockServer(server); |
| 51199 | UA_WriterGroup *currentWG = UA_WriterGroup_findWGbyId(server, identifier: writerGroup); |
| 51200 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 51201 | if(currentWG) |
| 51202 | res = UA_WriterGroupConfig_copy(src: ¤tWG->config, dst: config); |
| 51203 | unlockServer(server); |
| 51204 | return res; |
| 51205 | } |
| 51206 | |
| 51207 | UA_StatusCode |
| 51208 | UA_WriterGroup_updateConfig(UA_Server *server, UA_WriterGroup *wg, |
| 51209 | const UA_WriterGroupConfig *config) { |
| 51210 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 51211 | if(!config) |
| 51212 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 51213 | |
| 51214 | if(wg->configurationFrozen){ |
| 51215 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 51216 | "Modify WriterGroup failed. WriterGroup is frozen."); |
| 51217 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 51218 | } |
| 51219 | |
| 51220 | //The update functionality will be extended during the next PubSub batches. |
| 51221 | //Currently is only a change of the publishing interval possible. |
| 51222 | if(wg->config.maxEncapsulatedDataSetMessageCount != config->maxEncapsulatedDataSetMessageCount) { |
| 51223 | wg->config.maxEncapsulatedDataSetMessageCount = config->maxEncapsulatedDataSetMessageCount; |
| 51224 | if(wg->config.messageSettings.encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) { |
| 51225 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 51226 | "MaxEncapsulatedDataSetMessag need enabled " |
| 51227 | "'PayloadHeader' within the message settings."); |
| 51228 | } |
| 51229 | } |
| 51230 | |
| 51231 | if(wg->config.publishingInterval != config->publishingInterval) { |
| 51232 | wg->config.publishingInterval = config->publishingInterval; |
| 51233 | if(wg->config.rtLevel == UA_PUBSUB_RT_NONE && |
| 51234 | wg->state == UA_PUBSUBSTATE_OPERATIONAL) { |
| 51235 | UA_WriterGroup_removePublishCallback(server, wg); |
| 51236 | res = UA_WriterGroup_addPublishCallback(server, wg); |
| 51237 | if(res != UA_STATUSCODE_GOOD) { |
| 51238 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 51239 | "Modify WriterGroup failed. Adding publish callback failed" |
| 51240 | "with status code %s", UA_StatusCode_name(res)); |
| 51241 | return res; |
| 51242 | } |
| 51243 | } |
| 51244 | } |
| 51245 | |
| 51246 | if(wg->config.priority != config->priority) { |
| 51247 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 51248 | "Priority parameter is not yet " |
| 51249 | "supported for WriterGroup updates"); |
| 51250 | } |
| 51251 | |
| 51252 | return UA_STATUSCODE_GOOD; |
| 51253 | } |
| 51254 | |
| 51255 | UA_StatusCode |
| 51256 | UA_Server_updateWriterGroupConfig(UA_Server *server, UA_NodeId writerGroupIdentifier, |
| 51257 | const UA_WriterGroupConfig *config) { |
| 51258 | lockServer(server); |
| 51259 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: writerGroupIdentifier); |
| 51260 | if(!wg) { |
| 51261 | unlockServer(server); |
| 51262 | return UA_STATUSCODE_BADNOTFOUND; |
| 51263 | } |
| 51264 | |
| 51265 | UA_StatusCode res = UA_WriterGroup_updateConfig(server, wg, config); |
| 51266 | unlockServer(server); |
| 51267 | return res; |
| 51268 | } |
| 51269 | |
| 51270 | UA_StatusCode |
| 51271 | UA_Server_WriterGroup_getState(UA_Server *server, UA_NodeId writerGroupIdentifier, |
| 51272 | UA_PubSubState *state) { |
| 51273 | if((server == NULL) || (state == NULL)) |
| 51274 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 51275 | lockServer(server); |
| 51276 | UA_WriterGroup *currentWriterGroup = |
| 51277 | UA_WriterGroup_findWGbyId(server, identifier: writerGroupIdentifier); |
| 51278 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 51279 | if(currentWriterGroup) { |
| 51280 | *state = currentWriterGroup->state; |
| 51281 | } else { |
| 51282 | res = UA_STATUSCODE_BADNOTFOUND; |
| 51283 | } |
| 51284 | unlockServer(server); |
| 51285 | return res; |
| 51286 | } |
| 51287 | |
| 51288 | UA_StatusCode |
| 51289 | UA_Server_WriterGroup_publish(UA_Server *server, const UA_NodeId writerGroupIdentifier){ |
| 51290 | lockServer(server); |
| 51291 | |
| 51292 | //search WriterGroup ToDo create lookup table for more efficiency |
| 51293 | UA_WriterGroup *writerGroup; |
| 51294 | writerGroup = UA_WriterGroup_findWGbyId(server, identifier: writerGroupIdentifier); |
| 51295 | if(writerGroup == NULL){ |
| 51296 | unlockServer(server); |
| 51297 | return UA_STATUSCODE_BADNOTFOUND; |
| 51298 | } |
| 51299 | unlockServer(server); |
| 51300 | UA_WriterGroup_publishCallback(server, writerGroup); |
| 51301 | return UA_STATUSCODE_GOOD; |
| 51302 | } |
| 51303 | |
| 51304 | UA_StatusCode |
| 51305 | UA_WriterGroup_lastPublishTimestamp(UA_Server *server, const UA_NodeId writerGroupId, |
| 51306 | UA_DateTime *timestamp){ |
| 51307 | lockServer(server); |
| 51308 | //search WriterGroup ToDo create lookup table for more efficiency |
| 51309 | UA_WriterGroup *writerGroup; |
| 51310 | writerGroup = UA_WriterGroup_findWGbyId(server, identifier: writerGroupId); |
| 51311 | if(writerGroup == NULL){ |
| 51312 | unlockServer(server); |
| 51313 | return UA_STATUSCODE_BADNOTFOUND; |
| 51314 | } |
| 51315 | *timestamp = writerGroup->lastPublishTimeStamp; |
| 51316 | unlockServer(server); |
| 51317 | return UA_STATUSCODE_BADNOTFOUND; |
| 51318 | } |
| 51319 | |
| 51320 | UA_WriterGroup * |
| 51321 | UA_WriterGroup_findWGbyId(UA_Server *server, UA_NodeId identifier) { |
| 51322 | UA_PubSubConnection *tmpConnection; |
| 51323 | TAILQ_FOREACH(tmpConnection, &server->pubSubManager.connections, listEntry) { |
| 51324 | UA_WriterGroup *tmpWriterGroup; |
| 51325 | LIST_FOREACH(tmpWriterGroup, &tmpConnection->writerGroups, listEntry) { |
| 51326 | if(UA_NodeId_equal(p1: &identifier, p2: &tmpWriterGroup->identifier)) |
| 51327 | return tmpWriterGroup; |
| 51328 | } |
| 51329 | } |
| 51330 | return NULL; |
| 51331 | } |
| 51332 | |
| 51333 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51334 | UA_StatusCode |
| 51335 | setWriterGroupEncryptionKeys(UA_Server *server, const UA_NodeId writerGroup, |
| 51336 | UA_UInt32 securityTokenId, |
| 51337 | const UA_ByteString signingKey, |
| 51338 | const UA_ByteString encryptingKey, |
| 51339 | const UA_ByteString keyNonce) { |
| 51340 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroup); |
| 51341 | if(!wg) |
| 51342 | return UA_STATUSCODE_BADNOTFOUND; |
| 51343 | if(wg->config.encodingMimeType == UA_PUBSUB_ENCODING_JSON) { |
| 51344 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 51345 | "JSON encoding is enabled. The message security is only defined for the UADP message mapping."); |
| 51346 | return UA_STATUSCODE_BADINTERNALERROR; |
| 51347 | } |
| 51348 | if(!wg->config.securityPolicy) { |
| 51349 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, wg, |
| 51350 | "No SecurityPolicy configured for the WriterGroup"); |
| 51351 | return UA_STATUSCODE_BADINTERNALERROR; |
| 51352 | } |
| 51353 | |
| 51354 | if(securityTokenId != wg->securityTokenId) { |
| 51355 | wg->securityTokenId = securityTokenId; |
| 51356 | wg->nonceSequenceNumber = 1; |
| 51357 | } |
| 51358 | |
| 51359 | /* Create a new context */ |
| 51360 | if(!wg->securityPolicyContext) { |
| 51361 | return wg->config.securityPolicy-> |
| 51362 | newContext(wg->config.securityPolicy->policyContext, |
| 51363 | &signingKey, &encryptingKey, &keyNonce, |
| 51364 | &wg->securityPolicyContext); |
| 51365 | } |
| 51366 | |
| 51367 | /* Update the context */ |
| 51368 | return wg->config.securityPolicy-> |
| 51369 | setSecurityKeys(wg->securityPolicyContext, &signingKey, &encryptingKey, &keyNonce); |
| 51370 | } |
| 51371 | |
| 51372 | UA_StatusCode |
| 51373 | UA_Server_setWriterGroupEncryptionKeys(UA_Server *server, const UA_NodeId writerGroup, |
| 51374 | UA_UInt32 securityTokenId, |
| 51375 | const UA_ByteString signingKey, |
| 51376 | const UA_ByteString encryptingKey, |
| 51377 | const UA_ByteString keyNonce) { |
| 51378 | lockServer(server); |
| 51379 | UA_StatusCode res = setWriterGroupEncryptionKeys(server, writerGroup, securityTokenId, |
| 51380 | signingKey, encryptingKey, keyNonce); |
| 51381 | unlockServer(server); |
| 51382 | return res; |
| 51383 | } |
| 51384 | #endif |
| 51385 | |
| 51386 | void |
| 51387 | UA_WriterGroupConfig_clear(UA_WriterGroupConfig *writerGroupConfig) { |
| 51388 | UA_String_clear(p: &writerGroupConfig->name); |
| 51389 | UA_ExtensionObject_clear(p: &writerGroupConfig->transportSettings); |
| 51390 | UA_ExtensionObject_clear(p: &writerGroupConfig->messageSettings); |
| 51391 | UA_KeyValueMap_clear(map: &writerGroupConfig->groupProperties); |
| 51392 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51393 | UA_String_clear(&writerGroupConfig->securityGroupId); |
| 51394 | #endif |
| 51395 | memset(s: writerGroupConfig, c: 0, n: sizeof(UA_WriterGroupConfig)); |
| 51396 | } |
| 51397 | |
| 51398 | UA_StatusCode |
| 51399 | UA_WriterGroup_setPubSubState(UA_Server *server, UA_WriterGroup *writerGroup, |
| 51400 | UA_PubSubState state, UA_StatusCode cause) { |
| 51401 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 51402 | |
| 51403 | if(writerGroup->deleteFlag && state != UA_PUBSUBSTATE_DISABLED) { |
| 51404 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, writerGroup, |
| 51405 | "The WriterGroup is being deleted. Can only be disabled."); |
| 51406 | return UA_STATUSCODE_BADINTERNALERROR; |
| 51407 | } |
| 51408 | |
| 51409 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 51410 | UA_DataSetWriter *dataSetWriter; |
| 51411 | UA_PubSubState oldState = writerGroup->state; |
| 51412 | switch(state) { |
| 51413 | case UA_PUBSUBSTATE_DISABLED: |
| 51414 | UA_WriterGroup_disconnect(wg: writerGroup); |
| 51415 | switch (writerGroup->state){ |
| 51416 | case UA_PUBSUBSTATE_DISABLED: |
| 51417 | break; |
| 51418 | case UA_PUBSUBSTATE_PAUSED: |
| 51419 | break; |
| 51420 | case UA_PUBSUBSTATE_OPERATIONAL: { |
| 51421 | UA_WriterGroup_removePublishCallback(server, wg: writerGroup); |
| 51422 | LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry) { |
| 51423 | UA_DataSetWriter_setPubSubState(server, dataSetWriter, |
| 51424 | state: UA_PUBSUBSTATE_DISABLED, |
| 51425 | UA_STATUSCODE_BADRESOURCEUNAVAILABLE); |
| 51426 | } |
| 51427 | |
| 51428 | writerGroup->state = UA_PUBSUBSTATE_DISABLED; |
| 51429 | break; |
| 51430 | } |
| 51431 | case UA_PUBSUBSTATE_ERROR: |
| 51432 | break; |
| 51433 | default: |
| 51434 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, writerGroup, |
| 51435 | "Received unknown PubSub state!"); |
| 51436 | } |
| 51437 | break; |
| 51438 | case UA_PUBSUBSTATE_PAUSED: |
| 51439 | switch (writerGroup->state) { |
| 51440 | case UA_PUBSUBSTATE_DISABLED: |
| 51441 | break; |
| 51442 | case UA_PUBSUBSTATE_PAUSED: |
| 51443 | break; |
| 51444 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 51445 | break; |
| 51446 | case UA_PUBSUBSTATE_ERROR: |
| 51447 | break; |
| 51448 | default: |
| 51449 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, writerGroup, |
| 51450 | "Received unknown PubSub state!"); |
| 51451 | } |
| 51452 | break; |
| 51453 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 51454 | switch (writerGroup->state) { |
| 51455 | case UA_PUBSUBSTATE_DISABLED: { |
| 51456 | writerGroup->state = UA_PUBSUBSTATE_OPERATIONAL; |
| 51457 | UA_WriterGroup_removePublishCallback(server, wg: writerGroup); |
| 51458 | LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry) { |
| 51459 | UA_DataSetWriter_setPubSubState(server, dataSetWriter, |
| 51460 | state: UA_PUBSUBSTATE_OPERATIONAL, cause); |
| 51461 | } |
| 51462 | |
| 51463 | ret = UA_WriterGroup_connect(server, wg: writerGroup, false); |
| 51464 | if(ret != UA_STATUSCODE_GOOD) { |
| 51465 | UA_WriterGroup_setPubSubState(server, writerGroup, |
| 51466 | state: UA_PUBSUBSTATE_ERROR, cause: ret); |
| 51467 | break; |
| 51468 | } |
| 51469 | ret = UA_WriterGroup_addPublishCallback(server, wg: writerGroup); |
| 51470 | if(ret != UA_STATUSCODE_GOOD) { |
| 51471 | UA_WriterGroup_setPubSubState(server, writerGroup, |
| 51472 | state: UA_PUBSUBSTATE_ERROR, cause: ret); |
| 51473 | break; |
| 51474 | } |
| 51475 | break; |
| 51476 | } |
| 51477 | case UA_PUBSUBSTATE_PAUSED: |
| 51478 | break; |
| 51479 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 51480 | break; |
| 51481 | case UA_PUBSUBSTATE_ERROR: |
| 51482 | break; |
| 51483 | default: |
| 51484 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, writerGroup, |
| 51485 | "Received unknown PubSub state!"); |
| 51486 | } |
| 51487 | |
| 51488 | UA_PubSubConnection *c = writerGroup->linkedConnection; |
| 51489 | ret = UA_PubSubConnection_setPubSubState(server, c, |
| 51490 | state: UA_PUBSUBSTATE_OPERATIONAL, |
| 51491 | UA_STATUSCODE_GOOD); |
| 51492 | if(ret != UA_STATUSCODE_GOOD || |
| 51493 | (c->state != UA_PUBSUBSTATE_OPERATIONAL && |
| 51494 | c->state != UA_PUBSUBSTATE_PREOPERATIONAL)) { |
| 51495 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, writerGroup, |
| 51496 | "Connection not operational"); |
| 51497 | return UA_STATUSCODE_BADINTERNALERROR; |
| 51498 | } |
| 51499 | break; |
| 51500 | case UA_PUBSUBSTATE_ERROR: { |
| 51501 | switch (writerGroup->state){ |
| 51502 | case UA_PUBSUBSTATE_DISABLED: |
| 51503 | break; |
| 51504 | case UA_PUBSUBSTATE_PAUSED: |
| 51505 | break; |
| 51506 | case UA_PUBSUBSTATE_OPERATIONAL: { |
| 51507 | UA_WriterGroup_removePublishCallback(server, wg: writerGroup); |
| 51508 | LIST_FOREACH(dataSetWriter, &writerGroup->writers, listEntry){ |
| 51509 | UA_DataSetWriter_setPubSubState(server, dataSetWriter, |
| 51510 | state: UA_PUBSUBSTATE_ERROR, |
| 51511 | UA_STATUSCODE_GOOD); |
| 51512 | } |
| 51513 | break; |
| 51514 | } |
| 51515 | case UA_PUBSUBSTATE_ERROR: |
| 51516 | break; |
| 51517 | default: |
| 51518 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, writerGroup, |
| 51519 | "Received unknown PubSub state!"); |
| 51520 | } |
| 51521 | writerGroup->state = UA_PUBSUBSTATE_ERROR; |
| 51522 | break; |
| 51523 | } |
| 51524 | default: |
| 51525 | UA_LOG_WARNING_WRITERGROUP(server->config.logging, writerGroup, |
| 51526 | "Received unknown PubSub state!"); |
| 51527 | } |
| 51528 | |
| 51529 | if(state != oldState) { |
| 51530 | /* inform application about state change */ |
| 51531 | UA_ServerConfig *pConfig = &server->config; |
| 51532 | if(pConfig->pubSubConfig.stateChangeCallback != 0) { |
| 51533 | pConfig->pubSubConfig. |
| 51534 | stateChangeCallback(server, &writerGroup->identifier, state, cause); |
| 51535 | } |
| 51536 | } |
| 51537 | return ret; |
| 51538 | } |
| 51539 | |
| 51540 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51541 | static UA_StatusCode |
| 51542 | encryptAndSign(UA_WriterGroup *wg, const UA_NetworkMessage *nm, |
| 51543 | UA_Byte *signStart, UA_Byte *encryptStart, |
| 51544 | UA_Byte *msgEnd) { |
| 51545 | UA_StatusCode rv; |
| 51546 | void *channelContext = wg->securityPolicyContext; |
| 51547 | |
| 51548 | if(nm->securityHeader.networkMessageEncrypted) { |
| 51549 | /* Set the temporary MessageNonce in the SecurityPolicy */ |
| 51550 | const UA_ByteString nonce = { |
| 51551 | (size_t)nm->securityHeader.messageNonceSize, |
| 51552 | (UA_Byte*)(uintptr_t)nm->securityHeader.messageNonce |
| 51553 | }; |
| 51554 | rv = wg->config.securityPolicy->setMessageNonce(channelContext, &nonce); |
| 51555 | UA_CHECK_STATUS(rv, return rv); |
| 51556 | |
| 51557 | /* The encryption is done in-place, no need to encode again */ |
| 51558 | UA_ByteString toBeEncrypted = |
| 51559 | {(uintptr_t)msgEnd - (uintptr_t)encryptStart, encryptStart}; |
| 51560 | rv = wg->config.securityPolicy->symmetricModule.cryptoModule.encryptionAlgorithm. |
| 51561 | encrypt(channelContext, &toBeEncrypted); |
| 51562 | UA_CHECK_STATUS(rv, return rv); |
| 51563 | } |
| 51564 | |
| 51565 | if(nm->securityHeader.networkMessageSigned) { |
| 51566 | UA_ByteString toBeSigned = {(uintptr_t)msgEnd - (uintptr_t)signStart, |
| 51567 | signStart}; |
| 51568 | |
| 51569 | size_t sigSize = wg->config.securityPolicy->symmetricModule.cryptoModule. |
| 51570 | signatureAlgorithm.getLocalSignatureSize(channelContext); |
| 51571 | UA_ByteString signature = {sigSize, msgEnd}; |
| 51572 | |
| 51573 | rv = wg->config.securityPolicy->symmetricModule.cryptoModule. |
| 51574 | signatureAlgorithm.sign(channelContext, &toBeSigned, &signature); |
| 51575 | UA_CHECK_STATUS(rv, return rv); |
| 51576 | } |
| 51577 | return UA_STATUSCODE_GOOD; |
| 51578 | } |
| 51579 | #endif |
| 51580 | |
| 51581 | static UA_StatusCode |
| 51582 | encodeNetworkMessage(UA_WriterGroup *wg, UA_NetworkMessage *nm, |
| 51583 | UA_ByteString *buf) { |
| 51584 | UA_Byte *bufPos = buf->data; |
| 51585 | UA_Byte *bufEnd = &buf->data[buf->length]; |
| 51586 | |
| 51587 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51588 | UA_Byte *networkMessageStart = bufPos; |
| 51589 | #endif |
| 51590 | UA_StatusCode rv = UA_NetworkMessage_encodeHeaders(src: nm, bufPos: &bufPos, bufEnd); |
| 51591 | UA_CHECK_STATUS(rv, return rv); |
| 51592 | |
| 51593 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51594 | UA_Byte *payloadStart = bufPos; |
| 51595 | #endif |
| 51596 | rv = UA_NetworkMessage_encodePayload(src: nm, bufPos: &bufPos, bufEnd); |
| 51597 | UA_CHECK_STATUS(rv, return rv); |
| 51598 | |
| 51599 | rv = UA_NetworkMessage_encodeFooters(src: nm, bufPos: &bufPos, bufEnd); |
| 51600 | UA_CHECK_STATUS(rv, return rv); |
| 51601 | |
| 51602 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51603 | /* Encrypt and Sign the message */ |
| 51604 | UA_Byte *footerEnd = bufPos; |
| 51605 | rv = encryptAndSign(wg, nm, networkMessageStart, payloadStart, footerEnd); |
| 51606 | UA_CHECK_STATUS(rv, return rv); |
| 51607 | #endif |
| 51608 | |
| 51609 | return UA_STATUSCODE_GOOD; |
| 51610 | } |
| 51611 | |
| 51612 | static void |
| 51613 | sendNetworkMessageBuffer(UA_Server *server, UA_WriterGroup *wg, |
| 51614 | UA_PubSubConnection *connection, uintptr_t connectionId, |
| 51615 | UA_ByteString *buffer) { |
| 51616 | UA_StatusCode res = connection->cm-> |
| 51617 | sendWithConnection(connection->cm, connectionId, |
| 51618 | &UA_KEYVALUEMAP_NULL, buffer); |
| 51619 | |
| 51620 | /* Failure, set the WriterGroup into an error mode */ |
| 51621 | if(res != UA_STATUSCODE_GOOD) { |
| 51622 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 51623 | "Sending NetworkMessage failed"); |
| 51624 | UA_WriterGroup_setPubSubState(server, writerGroup: wg, state: UA_PUBSUBSTATE_ERROR, cause: res); |
| 51625 | UA_PubSubConnection_setPubSubState(server, c: connection, state: UA_PUBSUBSTATE_ERROR, cause: res); |
| 51626 | return; |
| 51627 | } |
| 51628 | |
| 51629 | /* Sending successful - increase the sequence number */ |
| 51630 | wg->sequenceNumber++; |
| 51631 | } |
| 51632 | |
| 51633 | #ifdef UA_ENABLE_JSON_ENCODING |
| 51634 | static UA_StatusCode |
| 51635 | sendNetworkMessageJson(UA_Server *server, UA_PubSubConnection *connection, UA_WriterGroup *wg, |
| 51636 | UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) { |
| 51637 | /* Prepare the NetworkMessage */ |
| 51638 | UA_NetworkMessage nm; |
| 51639 | memset(s: &nm, c: 0, n: sizeof(UA_NetworkMessage)); |
| 51640 | nm.version = 1; |
| 51641 | nm.networkMessageType = UA_NETWORKMESSAGE_DATASET; |
| 51642 | nm.payloadHeaderEnabled = true; |
| 51643 | nm.payloadHeader.dataSetPayloadHeader.count = dsmCount; |
| 51644 | nm.payloadHeader.dataSetPayloadHeader.dataSetWriterIds = writerIds; |
| 51645 | nm.payload.dataSetPayload.dataSetMessages = dsm; |
| 51646 | nm.publisherIdEnabled = true; |
| 51647 | nm.publisherIdType = connection->config.publisherIdType; |
| 51648 | nm.publisherId = connection->config.publisherId; |
| 51649 | |
| 51650 | /* Compute the message length */ |
| 51651 | size_t msgSize = UA_NetworkMessage_calcSizeJson(src: &nm, NULL, namespaceSize: 0, NULL, serverUriSize: 0, true); |
| 51652 | |
| 51653 | UA_ConnectionManager *cm = connection->cm; |
| 51654 | if(!cm) |
| 51655 | return UA_STATUSCODE_BADINTERNALERROR; |
| 51656 | |
| 51657 | /* Select the wg sendchannel if configured */ |
| 51658 | uintptr_t sendChannel = connection->sendChannel; |
| 51659 | if(wg->sendChannel != 0) |
| 51660 | sendChannel = wg->sendChannel; |
| 51661 | if(sendChannel == 0) { |
| 51662 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 51663 | "Cannot send, no open connection"); |
| 51664 | return UA_STATUSCODE_BADINTERNALERROR; |
| 51665 | } |
| 51666 | |
| 51667 | /* Allocate the buffer */ |
| 51668 | UA_ByteString buf; |
| 51669 | UA_StatusCode res = cm->allocNetworkBuffer(cm, sendChannel, &buf, msgSize); |
| 51670 | UA_CHECK_STATUS(res, return res); |
| 51671 | |
| 51672 | /* Encode the message */ |
| 51673 | UA_Byte *bufPos = buf.data; |
| 51674 | const UA_Byte *bufEnd = &buf.data[msgSize]; |
| 51675 | res = UA_NetworkMessage_encodeJson(src: &nm, bufPos: &bufPos, bufEnd: &bufEnd, NULL, namespaceSize: 0, NULL, serverUriSize: 0, true); |
| 51676 | if(res != UA_STATUSCODE_GOOD) { |
| 51677 | cm->freeNetworkBuffer(cm, sendChannel, &buf); |
| 51678 | return res; |
| 51679 | } |
| 51680 | UA_assert(bufPos == bufEnd); |
| 51681 | |
| 51682 | /* Send the prepared messages */ |
| 51683 | sendNetworkMessageBuffer(server, wg, connection, connectionId: sendChannel, buffer: &buf); |
| 51684 | return UA_STATUSCODE_GOOD; |
| 51685 | } |
| 51686 | #endif |
| 51687 | |
| 51688 | static UA_StatusCode |
| 51689 | generateNetworkMessage(UA_PubSubConnection *connection, UA_WriterGroup *wg, |
| 51690 | UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount, |
| 51691 | UA_ExtensionObject *messageSettings, |
| 51692 | UA_ExtensionObject *transportSettings, |
| 51693 | UA_NetworkMessage *networkMessage) { |
| 51694 | if(messageSettings->content.decoded.type != |
| 51695 | &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]) |
| 51696 | return UA_STATUSCODE_BADINTERNALERROR; |
| 51697 | UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*) |
| 51698 | messageSettings->content.decoded.data; |
| 51699 | |
| 51700 | networkMessage->publisherIdEnabled = |
| 51701 | ((u64)wgm->networkMessageContentMask & |
| 51702 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID) != 0; |
| 51703 | networkMessage->groupHeaderEnabled = |
| 51704 | ((u64)wgm->networkMessageContentMask & |
| 51705 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER) != 0; |
| 51706 | networkMessage->groupHeader.writerGroupIdEnabled = |
| 51707 | ((u64)wgm->networkMessageContentMask & |
| 51708 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID) != 0; |
| 51709 | networkMessage->groupHeader.groupVersionEnabled = |
| 51710 | ((u64)wgm->networkMessageContentMask & |
| 51711 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPVERSION) != 0; |
| 51712 | networkMessage->groupHeader.networkMessageNumberEnabled = |
| 51713 | ((u64)wgm->networkMessageContentMask & |
| 51714 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_NETWORKMESSAGENUMBER) != 0; |
| 51715 | networkMessage->groupHeader.sequenceNumberEnabled = |
| 51716 | ((u64)wgm->networkMessageContentMask & |
| 51717 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_SEQUENCENUMBER) != 0; |
| 51718 | networkMessage->payloadHeaderEnabled = |
| 51719 | ((u64)wgm->networkMessageContentMask & |
| 51720 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER) != 0; |
| 51721 | networkMessage->timestampEnabled = |
| 51722 | ((u64)wgm->networkMessageContentMask & |
| 51723 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_TIMESTAMP) != 0; |
| 51724 | networkMessage->picosecondsEnabled = |
| 51725 | ((u64)wgm->networkMessageContentMask & |
| 51726 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PICOSECONDS) != 0; |
| 51727 | networkMessage->dataSetClassIdEnabled = |
| 51728 | ((u64)wgm->networkMessageContentMask & |
| 51729 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_DATASETCLASSID) != 0; |
| 51730 | networkMessage->promotedFieldsEnabled = |
| 51731 | ((u64)wgm->networkMessageContentMask & |
| 51732 | (u64)UA_UADPNETWORKMESSAGECONTENTMASK_PROMOTEDFIELDS) != 0; |
| 51733 | |
| 51734 | /* Set the SecurityHeader */ |
| 51735 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51736 | if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) { |
| 51737 | networkMessage->securityEnabled = true; |
| 51738 | networkMessage->securityHeader.networkMessageSigned = true; |
| 51739 | if(wg->config.securityMode >= UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 51740 | networkMessage->securityHeader.networkMessageEncrypted = true; |
| 51741 | networkMessage->securityHeader.securityTokenId = wg->securityTokenId; |
| 51742 | |
| 51743 | /* Generate the MessageNonce. Four random bytes followed by a four-byte |
| 51744 | * sequence number */ |
| 51745 | UA_ByteString nonce = {4, networkMessage->securityHeader.messageNonce}; |
| 51746 | UA_StatusCode rv = wg->config.securityPolicy->symmetricModule. |
| 51747 | generateNonce(wg->config.securityPolicy->policyContext, &nonce); |
| 51748 | if(rv != UA_STATUSCODE_GOOD) |
| 51749 | return rv; |
| 51750 | UA_Byte *pos = &networkMessage->securityHeader.messageNonce[4]; |
| 51751 | const UA_Byte *end = &networkMessage->securityHeader.messageNonce[8]; |
| 51752 | UA_UInt32_encodeBinary(&wg->nonceSequenceNumber, &pos, end); |
| 51753 | networkMessage->securityHeader.messageNonceSize = 8; |
| 51754 | } |
| 51755 | #endif |
| 51756 | |
| 51757 | networkMessage->version = 1; |
| 51758 | networkMessage->networkMessageType = UA_NETWORKMESSAGE_DATASET; |
| 51759 | networkMessage->publisherIdType = connection->config.publisherIdType; |
| 51760 | /* shallow copy of the PublisherId from connection configuration |
| 51761 | -> the configuration needs to be stable during publishing process |
| 51762 | -> it must not be cleaned after network message has been sent */ |
| 51763 | networkMessage->publisherId = connection->config.publisherId; |
| 51764 | |
| 51765 | if(networkMessage->groupHeader.sequenceNumberEnabled) |
| 51766 | networkMessage->groupHeader.sequenceNumber = wg->sequenceNumber; |
| 51767 | |
| 51768 | if(networkMessage->groupHeader.groupVersionEnabled) |
| 51769 | networkMessage->groupHeader.groupVersion = wgm->groupVersion; |
| 51770 | |
| 51771 | /* Compute the length of the dsm separately for the header */ |
| 51772 | UA_UInt16 *dsmLengths = (UA_UInt16 *) UA_calloc(nmemb: dsmCount, size: sizeof(UA_UInt16)); |
| 51773 | if(!dsmLengths) |
| 51774 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 51775 | for(UA_Byte i = 0; i < dsmCount; i++) |
| 51776 | dsmLengths[i] = (UA_UInt16) UA_DataSetMessage_calcSizeBinary(p: &dsm[i], NULL, currentOffset: 0); |
| 51777 | |
| 51778 | networkMessage->payloadHeader.dataSetPayloadHeader.count = dsmCount; |
| 51779 | networkMessage->payloadHeader.dataSetPayloadHeader.dataSetWriterIds = writerIds; |
| 51780 | networkMessage->groupHeader.writerGroupId = wg->config.writerGroupId; |
| 51781 | /* number of the NetworkMessage inside a PublishingInterval */ |
| 51782 | networkMessage->groupHeader.networkMessageNumber = 1; |
| 51783 | networkMessage->payload.dataSetPayload.sizes = dsmLengths; |
| 51784 | networkMessage->payload.dataSetPayload.dataSetMessages = dsm; |
| 51785 | return UA_STATUSCODE_GOOD; |
| 51786 | } |
| 51787 | |
| 51788 | static UA_StatusCode |
| 51789 | sendNetworkMessageBinary(UA_Server *server, UA_PubSubConnection *connection, UA_WriterGroup *wg, |
| 51790 | UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) { |
| 51791 | UA_NetworkMessage nm; |
| 51792 | memset(s: &nm, c: 0, n: sizeof(UA_NetworkMessage)); |
| 51793 | |
| 51794 | /* Fill the message structure */ |
| 51795 | UA_StatusCode rv = |
| 51796 | generateNetworkMessage(connection, wg, dsm, writerIds, dsmCount, |
| 51797 | messageSettings: &wg->config.messageSettings, |
| 51798 | transportSettings: &wg->config.transportSettings, networkMessage: &nm); |
| 51799 | UA_CHECK_STATUS(rv, return rv); |
| 51800 | |
| 51801 | /* Compute the message size. Add the overhead for the security signature. |
| 51802 | * There is no padding and the encryption incurs no size overhead. */ |
| 51803 | size_t msgSize = UA_NetworkMessage_calcSizeBinary(p: &nm, NULL); |
| 51804 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51805 | if(wg->config.securityMode > UA_MESSAGESECURITYMODE_NONE) { |
| 51806 | UA_PubSubSecurityPolicy *sp = wg->config.securityPolicy; |
| 51807 | msgSize += sp->symmetricModule.cryptoModule. |
| 51808 | signatureAlgorithm.getLocalSignatureSize(sp->policyContext); |
| 51809 | } |
| 51810 | #endif |
| 51811 | |
| 51812 | UA_ConnectionManager *cm = connection->cm; |
| 51813 | if(!cm) |
| 51814 | return UA_STATUSCODE_BADINTERNALERROR; |
| 51815 | |
| 51816 | /* Select the wg sendchannel if configured */ |
| 51817 | uintptr_t sendChannel = connection->sendChannel; |
| 51818 | if(wg->sendChannel != 0) |
| 51819 | sendChannel = wg->sendChannel; |
| 51820 | if(sendChannel == 0) { |
| 51821 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 51822 | "Cannot send, no open connection"); |
| 51823 | return UA_STATUSCODE_BADINTERNALERROR; |
| 51824 | } |
| 51825 | |
| 51826 | /* Allocate the buffer. Allocate on the stack if the buffer is small. */ |
| 51827 | UA_ByteString buf = UA_BYTESTRING_NULL; |
| 51828 | rv = cm->allocNetworkBuffer(cm, sendChannel, &buf, msgSize); |
| 51829 | UA_CHECK_STATUS(rv, return rv); |
| 51830 | |
| 51831 | /* Encode and encrypt the message */ |
| 51832 | rv = encodeNetworkMessage(wg, nm: &nm, buf: &buf); |
| 51833 | if(rv != UA_STATUSCODE_GOOD) { |
| 51834 | cm->freeNetworkBuffer(cm, sendChannel, &buf); |
| 51835 | UA_free(ptr: nm.payload.dataSetPayload.sizes); |
| 51836 | return rv; |
| 51837 | } |
| 51838 | |
| 51839 | /* Send out the message */ |
| 51840 | sendNetworkMessageBuffer(server, wg, connection, connectionId: sendChannel, buffer: &buf); |
| 51841 | |
| 51842 | UA_free(ptr: nm.payload.dataSetPayload.sizes); |
| 51843 | return UA_STATUSCODE_GOOD; |
| 51844 | } |
| 51845 | |
| 51846 | static void |
| 51847 | sampleOffsetPublishingValues(UA_Server *server, UA_WriterGroup *wg) { |
| 51848 | lockServer(server); |
| 51849 | |
| 51850 | size_t fieldPos = 0; |
| 51851 | UA_DataSetWriter *dsw; |
| 51852 | LIST_FOREACH(dsw, &wg->writers, listEntry) { |
| 51853 | UA_PublishedDataSet *pds = |
| 51854 | UA_PublishedDataSet_findPDSbyId(server, identifier: dsw->connectedDataSet); |
| 51855 | if(!pds) |
| 51856 | continue; |
| 51857 | |
| 51858 | /* Loop over the fields */ |
| 51859 | UA_DataSetField *dsf; |
| 51860 | TAILQ_FOREACH(dsf, &pds->fields, listEntry) { |
| 51861 | /* Get the matching offset table entry */ |
| 51862 | UA_NetworkMessageOffsetType contentType; |
| 51863 | do { |
| 51864 | fieldPos++; |
| 51865 | contentType = wg->bufferedMessage.offsets[fieldPos].contentType; |
| 51866 | } while(contentType != UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE && |
| 51867 | contentType != UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE_EXTERNAL && |
| 51868 | contentType != UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT && |
| 51869 | contentType != UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT_EXTERNAL && |
| 51870 | contentType != UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW && |
| 51871 | contentType != UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW_EXTERNAL); |
| 51872 | |
| 51873 | /* External data source is never sampled, but accessed directly in |
| 51874 | * the encoding */ |
| 51875 | if(contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_DATAVALUE_EXTERNAL || |
| 51876 | contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_VARIANT_EXTERNAL || |
| 51877 | contentType == UA_PUBSUB_OFFSETTYPE_PAYLOAD_RAW_EXTERNAL) |
| 51878 | continue; |
| 51879 | |
| 51880 | /* Sample the value into the offset table */ |
| 51881 | UA_DataValue *dfv = &wg->bufferedMessage.offsets[fieldPos].content.value; |
| 51882 | UA_DataValue_clear(p: dfv); |
| 51883 | UA_PubSubDataSetField_sampleValue(server, field: dsf, value: dfv); |
| 51884 | } |
| 51885 | } |
| 51886 | |
| 51887 | unlockServer(server); |
| 51888 | } |
| 51889 | |
| 51890 | static void |
| 51891 | publishWithOffsets(UA_Server *server, UA_WriterGroup *writerGroup, |
| 51892 | UA_PubSubConnection *connection) { |
| 51893 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 51894 | UA_assert(writerGroup->configurationFrozen); |
| 51895 | |
| 51896 | /* Fixed size but no direct value access. Sample to get recent values into |
| 51897 | * the offset buffer structure. */ |
| 51898 | if((writerGroup->config.rtLevel & UA_PUBSUB_RT_DIRECT_VALUE_ACCESS) == 0) |
| 51899 | sampleOffsetPublishingValues(server, wg: writerGroup); |
| 51900 | |
| 51901 | UA_StatusCode res = |
| 51902 | UA_NetworkMessage_updateBufferedMessage(buffer: &writerGroup->bufferedMessage); |
| 51903 | |
| 51904 | if(res != UA_STATUSCODE_GOOD) { |
| 51905 | UA_LOG_DEBUG_WRITERGROUP(server->config.logging, writerGroup, |
| 51906 | "PubSub sending. Unknown field type."); |
| 51907 | return; |
| 51908 | } |
| 51909 | |
| 51910 | UA_ByteString *buf = &writerGroup->bufferedMessage.buffer; |
| 51911 | |
| 51912 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 51913 | /* Send the encrypted buffered message if PubSub encryption is enabled */ |
| 51914 | if(writerGroup->config.securityMode > UA_MESSAGESECURITYMODE_NONE) { |
| 51915 | size_t sigSize = writerGroup->config.securityPolicy->symmetricModule.cryptoModule. |
| 51916 | signatureAlgorithm.getLocalSignatureSize(writerGroup->securityPolicyContext); |
| 51917 | |
| 51918 | UA_Byte payloadOffset = (UA_Byte)(writerGroup->bufferedMessage.payloadPosition - |
| 51919 | writerGroup->bufferedMessage.buffer.data); |
| 51920 | memcpy(writerGroup->bufferedMessage.encryptBuffer.data, |
| 51921 | writerGroup->bufferedMessage.buffer.data, |
| 51922 | writerGroup->bufferedMessage.buffer.length); |
| 51923 | res = encryptAndSign(writerGroup, writerGroup->bufferedMessage.nm, |
| 51924 | writerGroup->bufferedMessage.encryptBuffer.data, |
| 51925 | writerGroup->bufferedMessage.encryptBuffer.data + payloadOffset, |
| 51926 | writerGroup->bufferedMessage.encryptBuffer.data + |
| 51927 | writerGroup->bufferedMessage.encryptBuffer.length - sigSize); |
| 51928 | |
| 51929 | if(res != UA_STATUSCODE_GOOD) { |
| 51930 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, writerGroup, |
| 51931 | "PubSub Encryption failed"); |
| 51932 | return; |
| 51933 | } |
| 51934 | |
| 51935 | buf = &writerGroup->bufferedMessage.encryptBuffer; |
| 51936 | } |
| 51937 | #endif |
| 51938 | |
| 51939 | UA_ConnectionManager *cm = connection->cm; |
| 51940 | if(!cm) |
| 51941 | return; |
| 51942 | |
| 51943 | /* Select the wg sendchannel if configured */ |
| 51944 | uintptr_t sendChannel = connection->sendChannel; |
| 51945 | if(writerGroup->sendChannel != 0) |
| 51946 | sendChannel = writerGroup->sendChannel; |
| 51947 | if(sendChannel == 0) { |
| 51948 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, writerGroup, |
| 51949 | "Cannot send, no open connection"); |
| 51950 | return; |
| 51951 | } |
| 51952 | |
| 51953 | /* Copy into the network buffer */ |
| 51954 | UA_ByteString outBuf; |
| 51955 | res = cm->allocNetworkBuffer(cm, sendChannel, &outBuf, buf->length); |
| 51956 | if(res != UA_STATUSCODE_GOOD) { |
| 51957 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, writerGroup, |
| 51958 | "PubSub message memory allocation failed"); |
| 51959 | return; |
| 51960 | } |
| 51961 | memcpy(dest: outBuf.data, src: buf->data, n: buf->length); |
| 51962 | sendNetworkMessageBuffer(server, wg: writerGroup, connection, connectionId: sendChannel, buffer: &outBuf); |
| 51963 | } |
| 51964 | |
| 51965 | static void |
| 51966 | sendNetworkMessage(UA_Server *server, UA_WriterGroup *wg, UA_PubSubConnection *connection, |
| 51967 | UA_DataSetMessage *dsm, UA_UInt16 *writerIds, UA_Byte dsmCount) { |
| 51968 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 51969 | switch(wg->config.encodingMimeType) { |
| 51970 | case UA_PUBSUB_ENCODING_UADP: |
| 51971 | res = sendNetworkMessageBinary(server, connection, wg, dsm, writerIds, dsmCount); |
| 51972 | break; |
| 51973 | #ifdef UA_ENABLE_JSON_ENCODING |
| 51974 | case UA_PUBSUB_ENCODING_JSON: |
| 51975 | res = sendNetworkMessageJson(server, connection, wg, dsm, writerIds, dsmCount); |
| 51976 | break; |
| 51977 | #endif |
| 51978 | default: |
| 51979 | res = UA_STATUSCODE_BADNOTSUPPORTED; |
| 51980 | break; |
| 51981 | } |
| 51982 | |
| 51983 | /* If sending failed, disable all writer of the writergroup */ |
| 51984 | if(res != UA_STATUSCODE_GOOD) { |
| 51985 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, wg, |
| 51986 | "PubSub Publish: Could not send a NetworkMessage " |
| 51987 | "with status code %s", UA_StatusCode_name(res)); |
| 51988 | UA_WriterGroup_setPubSubState(server, writerGroup: wg, state: UA_PUBSUBSTATE_ERROR, cause: res); |
| 51989 | } |
| 51990 | } |
| 51991 | |
| 51992 | /* This callback triggers the collection and publish of NetworkMessages and the |
| 51993 | * contained DataSetMessages. */ |
| 51994 | void |
| 51995 | UA_WriterGroup_publishCallback(UA_Server *server, UA_WriterGroup *writerGroup) { |
| 51996 | UA_assert(writerGroup != NULL); |
| 51997 | UA_assert(server != NULL); |
| 51998 | |
| 51999 | lockServer(server); |
| 52000 | |
| 52001 | UA_LOG_DEBUG_WRITERGROUP(server->config.logging, writerGroup, "Publish Callback"); |
| 52002 | |
| 52003 | /* Find the connection associated with the writer */ |
| 52004 | UA_PubSubConnection *connection = writerGroup->linkedConnection; |
| 52005 | if(!connection) { |
| 52006 | UA_LOG_ERROR_WRITERGROUP(server->config.logging, writerGroup, |
| 52007 | "Publish failed. PubSubConnection invalid"); |
| 52008 | UA_WriterGroup_setPubSubState(server, writerGroup, state: UA_PUBSUBSTATE_ERROR, |
| 52009 | UA_STATUSCODE_BADNOTCONNECTED); |
| 52010 | unlockServer(server); |
| 52011 | return; |
| 52012 | } |
| 52013 | |
| 52014 | /* Realtime path - update the buffer message and send directly */ |
| 52015 | if(writerGroup->config.rtLevel & UA_PUBSUB_RT_FIXED_SIZE) { |
| 52016 | publishWithOffsets(server, writerGroup, connection); |
| 52017 | unlockServer(server); |
| 52018 | return; |
| 52019 | } |
| 52020 | |
| 52021 | /* Nothing to do? */ |
| 52022 | if(writerGroup->writersCount == 0) { |
| 52023 | unlockServer(server); |
| 52024 | return; |
| 52025 | } |
| 52026 | |
| 52027 | /* How many DSM can be sent in one NM? */ |
| 52028 | UA_Byte maxDSM = (UA_Byte)writerGroup->config.maxEncapsulatedDataSetMessageCount; |
| 52029 | if(writerGroup->config.maxEncapsulatedDataSetMessageCount > UA_BYTE_MAX) |
| 52030 | maxDSM = UA_BYTE_MAX; |
| 52031 | if(maxDSM == 0) |
| 52032 | maxDSM = 1; /* Send at least one dsm */ |
| 52033 | |
| 52034 | /* It is possible to put several DataSetMessages into one NetworkMessage. |
| 52035 | * But only if they do not contain promoted fields. NM with promoted fields |
| 52036 | * are sent out right away. The others are kept in a buffer for |
| 52037 | * "batching". */ |
| 52038 | size_t dsmCount = 0; |
| 52039 | UA_STACKARRAY(UA_UInt16, dsWriterIds, writerGroup->writersCount); |
| 52040 | UA_STACKARRAY(UA_DataSetMessage, dsmStore, writerGroup->writersCount); |
| 52041 | |
| 52042 | UA_DataSetWriter *dsw; |
| 52043 | LIST_FOREACH(dsw, &writerGroup->writers, listEntry) { |
| 52044 | if(dsw->state != UA_PUBSUBSTATE_OPERATIONAL) |
| 52045 | continue; |
| 52046 | |
| 52047 | /* Heartbeats are send when no dataset is attached */ |
| 52048 | UA_Boolean heartbeat = UA_NodeId_isNull(p: &dsw->connectedDataSet); |
| 52049 | UA_PublishedDataSet *pds = (heartbeat) ? NULL : |
| 52050 | UA_PublishedDataSet_findPDSbyId(server, identifier: dsw->connectedDataSet); |
| 52051 | if(!heartbeat && !pds) { |
| 52052 | UA_LOG_ERROR_WRITER(server->config.logging, dsw, |
| 52053 | "PubSub Publish: PublishedDataSet not found"); |
| 52054 | UA_DataSetWriter_setPubSubState(server, dataSetWriter: dsw, state: UA_PUBSUBSTATE_ERROR, |
| 52055 | UA_STATUSCODE_BADINTERNALERROR); |
| 52056 | continue; |
| 52057 | } |
| 52058 | |
| 52059 | /* Generate the DSM */ |
| 52060 | dsWriterIds[dsmCount] = dsw->config.dataSetWriterId; |
| 52061 | UA_StatusCode res = |
| 52062 | UA_DataSetWriter_generateDataSetMessage(server, dataSetMessage: &dsmStore[dsmCount], dataSetWriter: dsw); |
| 52063 | if(res != UA_STATUSCODE_GOOD) { |
| 52064 | UA_LOG_ERROR_WRITER(server->config.logging, dsw, |
| 52065 | "PubSub Publish: DataSetMessage creation failed"); |
| 52066 | UA_DataSetWriter_setPubSubState(server, dataSetWriter: dsw, state: UA_PUBSUBSTATE_ERROR, cause: res); |
| 52067 | continue; |
| 52068 | } |
| 52069 | |
| 52070 | /* There is no promoted field -> send right away */ |
| 52071 | if(pds && pds->promotedFieldsCount > 0) { |
| 52072 | writerGroup->lastPublishTimeStamp = UA_DateTime_nowMonotonic(); |
| 52073 | sendNetworkMessage(server, wg: writerGroup, connection, dsm: &dsmStore[dsmCount], |
| 52074 | writerIds: &dsWriterIds[dsmCount], dsmCount: 1); |
| 52075 | |
| 52076 | /* Clean up the current store entry */ |
| 52077 | if(writerGroup->config.rtLevel & UA_PUBSUB_RT_DIRECT_VALUE_ACCESS && |
| 52078 | dsmStore[dsmCount].header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) { |
| 52079 | for(size_t i = 0; i < dsmStore[dsmCount].data.keyFrameData.fieldCount; ++i) { |
| 52080 | dsmStore[dsmCount].data.keyFrameData.dataSetFields[i].value.data = NULL; |
| 52081 | } |
| 52082 | } |
| 52083 | UA_DataSetMessage_clear(p: &dsmStore[dsmCount]); |
| 52084 | |
| 52085 | continue; /* Don't increase the dsmCount, reuse the slot */ |
| 52086 | } |
| 52087 | |
| 52088 | dsmCount++; |
| 52089 | } |
| 52090 | |
| 52091 | /* Send the NetworkMessages with batched DataSetMessages */ |
| 52092 | UA_Byte nmDsmCount = 0; |
| 52093 | for(size_t i = 0; i < dsmCount; i += nmDsmCount) { |
| 52094 | /* How many dsm are batched in this iteration? */ |
| 52095 | nmDsmCount = (i + maxDSM > dsmCount) ? (UA_Byte)(dsmCount - i) : maxDSM; |
| 52096 | |
| 52097 | writerGroup->lastPublishTimeStamp = UA_DateTime_nowMonotonic(); |
| 52098 | /* Send the batched messages */ |
| 52099 | sendNetworkMessage(server, wg: writerGroup, connection, dsm: &dsmStore[i], |
| 52100 | writerIds: &dsWriterIds[i], dsmCount: nmDsmCount); |
| 52101 | } |
| 52102 | |
| 52103 | /* Clean up DSM */ |
| 52104 | for(size_t i = 0; i < dsmCount; i++) { |
| 52105 | if(writerGroup->config.rtLevel & UA_PUBSUB_RT_DIRECT_VALUE_ACCESS && |
| 52106 | dsmStore[i].header.dataSetMessageType == UA_DATASETMESSAGE_DATAKEYFRAME) { |
| 52107 | for(size_t j = 0; j < dsmStore[i].data.keyFrameData.fieldCount; ++j) { |
| 52108 | dsmStore[i].data.keyFrameData.dataSetFields[j].value.data = NULL; |
| 52109 | } |
| 52110 | } |
| 52111 | UA_DataSetMessage_clear(p: &dsmStore[i]); |
| 52112 | } |
| 52113 | |
| 52114 | unlockServer(server); |
| 52115 | } |
| 52116 | |
| 52117 | #endif /* UA_ENABLE_PUBSUB */ |
| 52118 | |
| 52119 | /**** amalgamated original file "/src/pubsub/ua_pubsub_reader.c" ****/ |
| 52120 | |
| 52121 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 52122 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 52123 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 52124 | * |
| 52125 | * Copyright (c) 2017-2022 Fraunhofer IOSB (Author: Andreas Ebner) |
| 52126 | * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer) |
| 52127 | * Copyright (c) 2019 Kalycito Infotech Private Limited |
| 52128 | * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes) |
| 52129 | * Copyright (c) 2022 Siemens AG (Author: Thomas Fischer) |
| 52130 | * Copyright (c) 2022 Fraunhofer IOSB (Author: Noel Graf) |
| 52131 | */ |
| 52132 | |
| 52133 | |
| 52134 | #ifdef UA_ENABLE_PUBSUB /* conditional compilation */ |
| 52135 | |
| 52136 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 52137 | #endif |
| 52138 | |
| 52139 | |
| 52140 | #ifdef UA_ENABLE_PUBSUB_BUFMALLOC |
| 52141 | #endif |
| 52142 | |
| 52143 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 52144 | static void |
| 52145 | UA_DataSetReader_checkMessageReceiveTimeout(UA_Server *server, UA_DataSetReader *dsr); |
| 52146 | |
| 52147 | static void |
| 52148 | UA_DataSetReader_handleMessageReceiveTimeout(UA_Server *server, UA_DataSetReader *dsr); |
| 52149 | #endif |
| 52150 | |
| 52151 | static UA_Boolean |
| 52152 | publisherIdIsMatching(UA_NetworkMessage *msg, UA_Variant publisherId) { |
| 52153 | if(!msg->publisherIdEnabled) { |
| 52154 | return true; |
| 52155 | } |
| 52156 | switch(msg->publisherIdType) { |
| 52157 | case UA_PUBLISHERIDTYPE_BYTE: |
| 52158 | return (publisherId.type == &UA_TYPES[UA_TYPES_BYTE] && |
| 52159 | msg->publisherId.byte == *(UA_Byte*)publisherId.data); |
| 52160 | case UA_PUBLISHERIDTYPE_UINT16: |
| 52161 | return (publisherId.type == &UA_TYPES[UA_TYPES_UINT16] && |
| 52162 | msg->publisherId.uint16 == *(UA_UInt16*)publisherId.data); |
| 52163 | case UA_PUBLISHERIDTYPE_UINT32: |
| 52164 | return (publisherId.type == &UA_TYPES[UA_TYPES_UINT32] && |
| 52165 | msg->publisherId.uint32 == *(UA_UInt32*)publisherId.data); |
| 52166 | case UA_PUBLISHERIDTYPE_UINT64: |
| 52167 | return (publisherId.type == &UA_TYPES[UA_TYPES_UINT64] && |
| 52168 | msg->publisherId.uint64 == *(UA_UInt64*)publisherId.data); |
| 52169 | case UA_PUBLISHERIDTYPE_STRING: |
| 52170 | return (publisherId.type == &UA_TYPES[UA_TYPES_STRING] && |
| 52171 | UA_String_equal(p1: &msg->publisherId.string, p2: (UA_String*)publisherId.data)); |
| 52172 | default: |
| 52173 | return false; |
| 52174 | } |
| 52175 | return true; |
| 52176 | } |
| 52177 | |
| 52178 | UA_StatusCode |
| 52179 | UA_DataSetReader_checkIdentifier(UA_Server *server, UA_NetworkMessage *msg, |
| 52180 | UA_DataSetReader *reader, |
| 52181 | UA_ReaderGroupConfig readerGroupConfig) { |
| 52182 | if(readerGroupConfig.encodingMimeType != UA_PUBSUB_ENCODING_JSON){ |
| 52183 | if(!publisherIdIsMatching(msg, publisherId: reader->config.publisherId)) { |
| 52184 | return UA_STATUSCODE_BADNOTFOUND; |
| 52185 | } |
| 52186 | if(msg->groupHeaderEnabled && msg->groupHeader.writerGroupIdEnabled) { |
| 52187 | if(reader->config.writerGroupId != msg->groupHeader.writerGroupId) { |
| 52188 | UA_LOG_INFO_READER(server->config.logging, reader, |
| 52189 | "WriterGroupId doesn't match"); |
| 52190 | return UA_STATUSCODE_BADNOTFOUND; |
| 52191 | } |
| 52192 | } |
| 52193 | if(msg->payloadHeaderEnabled) { |
| 52194 | UA_Byte totalDataSets = msg->payloadHeader.dataSetPayloadHeader.count; |
| 52195 | UA_Byte iterator = 0; |
| 52196 | for(iterator = 0; iterator < totalDataSets; iterator++) { |
| 52197 | if(reader->config.dataSetWriterId == msg->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[iterator]) { |
| 52198 | return UA_STATUSCODE_GOOD; |
| 52199 | } |
| 52200 | } |
| 52201 | if (iterator == totalDataSets) { |
| 52202 | UA_LOG_INFO_READER(server->config.logging, reader, "DataSetWriterId doesn't match"); |
| 52203 | return UA_STATUSCODE_BADNOTFOUND; |
| 52204 | } |
| 52205 | } |
| 52206 | return UA_STATUSCODE_GOOD; |
| 52207 | } else { |
| 52208 | if (!publisherIdIsMatching(msg, publisherId: reader->config.publisherId)) |
| 52209 | return UA_STATUSCODE_BADNOTFOUND; |
| 52210 | |
| 52211 | if(reader->config.dataSetWriterId == *msg->payloadHeader.dataSetPayloadHeader.dataSetWriterIds) { |
| 52212 | UA_LOG_DEBUG(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 52213 | msg: "DataSetReader found. Process NetworkMessage"); |
| 52214 | return UA_STATUSCODE_GOOD; |
| 52215 | } |
| 52216 | } |
| 52217 | return UA_STATUSCODE_BADNOTFOUND; |
| 52218 | } |
| 52219 | |
| 52220 | UA_StatusCode |
| 52221 | UA_DataSetReader_create(UA_Server *server, UA_NodeId readerGroupIdentifier, |
| 52222 | const UA_DataSetReaderConfig *dataSetReaderConfig, |
| 52223 | UA_NodeId *readerIdentifier) { |
| 52224 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 52225 | |
| 52226 | /* Search the reader group by the given readerGroupIdentifier */ |
| 52227 | UA_ReaderGroup *readerGroup = UA_ReaderGroup_findRGbyId(server, identifier: readerGroupIdentifier); |
| 52228 | if(readerGroup == NULL) |
| 52229 | return UA_STATUSCODE_BADNOTFOUND; |
| 52230 | |
| 52231 | if(!dataSetReaderConfig) |
| 52232 | return UA_STATUSCODE_BADNOTFOUND; |
| 52233 | |
| 52234 | if(readerGroup->configurationFrozen) { |
| 52235 | UA_LOG_WARNING_READERGROUP(server->config.logging, readerGroup, |
| 52236 | "Add DataSetReader failed, Subscriber configuration is frozen"); |
| 52237 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 52238 | } |
| 52239 | |
| 52240 | /* Allocate memory for new DataSetReader */ |
| 52241 | UA_DataSetReader *newDataSetReader = (UA_DataSetReader *) |
| 52242 | UA_calloc(nmemb: 1, size: sizeof(UA_DataSetReader)); |
| 52243 | if(!newDataSetReader) |
| 52244 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 52245 | |
| 52246 | newDataSetReader->componentType = UA_PUBSUB_COMPONENT_DATASETREADER; |
| 52247 | |
| 52248 | /* Copy the config into the new dataSetReader */ |
| 52249 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 52250 | UA_DataSetReaderConfig_copy(src: dataSetReaderConfig, dst: &newDataSetReader->config); |
| 52251 | newDataSetReader->linkedReaderGroup = readerGroup->identifier; |
| 52252 | |
| 52253 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 52254 | retVal = addDataSetReaderRepresentation(server, dataSetReader: newDataSetReader); |
| 52255 | if(retVal != UA_STATUSCODE_GOOD) { |
| 52256 | UA_LOG_ERROR_READERGROUP(server->config.logging, readerGroup, |
| 52257 | "Add DataSetReader failed, addDataSetReaderRepresentation failed"); |
| 52258 | UA_DataSetReaderConfig_clear(cfg: &newDataSetReader->config); |
| 52259 | UA_free(ptr: newDataSetReader); |
| 52260 | newDataSetReader = 0; |
| 52261 | return retVal; |
| 52262 | } |
| 52263 | #else |
| 52264 | UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, |
| 52265 | &newDataSetReader->identifier); |
| 52266 | #endif |
| 52267 | |
| 52268 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 52269 | /* Create message receive timeout timer */ |
| 52270 | retVal = server->config.pubSubConfig.monitoringInterface. |
| 52271 | createMonitoring(server, newDataSetReader->identifier, |
| 52272 | UA_PUBSUB_COMPONENT_DATASETREADER, |
| 52273 | UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, |
| 52274 | newDataSetReader, |
| 52275 | (void (*)(UA_Server *, void *)) |
| 52276 | UA_DataSetReader_handleMessageReceiveTimeout); |
| 52277 | if(retVal != UA_STATUSCODE_GOOD) { |
| 52278 | UA_LOG_ERROR_READERGROUP(server->config.logging, readerGroup, |
| 52279 | "Add DataSetReader failed, create message " |
| 52280 | "receive timeout timer failed"); |
| 52281 | UA_DataSetReaderConfig_clear(&newDataSetReader->config); |
| 52282 | UA_free(newDataSetReader); |
| 52283 | newDataSetReader = 0; |
| 52284 | return retVal; |
| 52285 | } |
| 52286 | #endif /* UA_ENABLE_PUBSUB_MONITORING */ |
| 52287 | |
| 52288 | /* Add the new reader to the group. Add to the end of the linked list to |
| 52289 | * ensure the order for the realtime offsets is as expected. The received |
| 52290 | * DataSetMessages are matched via UA_DataSetReader_checkIdentifier for the |
| 52291 | * non-RT path. */ |
| 52292 | UA_DataSetReader *after = LIST_FIRST(&readerGroup->readers); |
| 52293 | if(!after) { |
| 52294 | LIST_INSERT_HEAD(&readerGroup->readers, newDataSetReader, listEntry); |
| 52295 | } else { |
| 52296 | while(LIST_NEXT(after, listEntry)) |
| 52297 | after = LIST_NEXT(after, listEntry); |
| 52298 | LIST_INSERT_AFTER(after, newDataSetReader, listEntry); |
| 52299 | } |
| 52300 | readerGroup->readersCount++; |
| 52301 | |
| 52302 | if(!UA_String_isEmpty(s: &newDataSetReader->config.linkedStandaloneSubscribedDataSetName)) { |
| 52303 | // find sds by name |
| 52304 | UA_StandaloneSubscribedDataSet *subscribedDataSet = |
| 52305 | UA_StandaloneSubscribedDataSet_findSDSbyName(server, |
| 52306 | identifier: newDataSetReader->config.linkedStandaloneSubscribedDataSetName); |
| 52307 | if(subscribedDataSet != NULL) { |
| 52308 | if(subscribedDataSet->config.subscribedDataSetType != UA_PUBSUB_SDS_TARGET) { |
| 52309 | UA_LOG_ERROR_READER(server->config.logging, newDataSetReader, |
| 52310 | "Not implemented! Currently only SubscribedDataSet as " |
| 52311 | "TargetVariables is implemented"); |
| 52312 | } else { |
| 52313 | if(subscribedDataSet->config.isConnected) { |
| 52314 | UA_LOG_ERROR_READER(server->config.logging, newDataSetReader, |
| 52315 | "SubscribedDataSet is already connected"); |
| 52316 | } else { |
| 52317 | UA_LOG_DEBUG_READER(server->config.logging, newDataSetReader, |
| 52318 | "Found SubscribedDataSet"); |
| 52319 | subscribedDataSet->config.isConnected = true; |
| 52320 | UA_DataSetMetaDataType_copy( |
| 52321 | src: &subscribedDataSet->config.dataSetMetaData, |
| 52322 | dst: &newDataSetReader->config.dataSetMetaData); |
| 52323 | UA_FieldTargetVariable *targetVars = |
| 52324 | (UA_FieldTargetVariable *)UA_calloc( |
| 52325 | nmemb: subscribedDataSet->config.subscribedDataSet.target |
| 52326 | .targetVariablesSize, |
| 52327 | size: sizeof(UA_FieldTargetVariable)); |
| 52328 | for(size_t index = 0; |
| 52329 | index < subscribedDataSet->config.subscribedDataSet.target |
| 52330 | .targetVariablesSize; |
| 52331 | index++) { |
| 52332 | UA_FieldTargetDataType_copy( |
| 52333 | src: &subscribedDataSet->config.subscribedDataSet.target |
| 52334 | .targetVariables[index], |
| 52335 | dst: &targetVars[index].targetVariable); |
| 52336 | } |
| 52337 | |
| 52338 | DataSetReader_createTargetVariables(server, dsr: newDataSetReader, |
| 52339 | targetVariablesSize: subscribedDataSet->config.subscribedDataSet. |
| 52340 | target.targetVariablesSize, targetVariables: targetVars); |
| 52341 | subscribedDataSet->connectedReader = newDataSetReader->identifier; |
| 52342 | |
| 52343 | for(size_t index = 0; |
| 52344 | index < subscribedDataSet->config.subscribedDataSet.target |
| 52345 | .targetVariablesSize; |
| 52346 | index++) { |
| 52347 | UA_FieldTargetDataType_clear(p: &targetVars[index].targetVariable); |
| 52348 | } |
| 52349 | |
| 52350 | UA_free(ptr: targetVars); |
| 52351 | |
| 52352 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 52353 | connectDataSetReaderToDataSet(server, dsrId: newDataSetReader->identifier, |
| 52354 | standaloneSdsId: subscribedDataSet->identifier); |
| 52355 | #endif |
| 52356 | } |
| 52357 | } |
| 52358 | } |
| 52359 | } |
| 52360 | |
| 52361 | if(readerIdentifier) |
| 52362 | UA_NodeId_copy(src: &newDataSetReader->identifier, dst: readerIdentifier); |
| 52363 | |
| 52364 | /* Set the ReaderGroup state after finalizing the configuration */ |
| 52365 | if(readerGroup->state == UA_PUBSUBSTATE_OPERATIONAL || |
| 52366 | readerGroup->state == UA_PUBSUBSTATE_PREOPERATIONAL) { |
| 52367 | retVal = UA_DataSetReader_setPubSubState(server, dataSetReader: newDataSetReader, state: readerGroup->state, |
| 52368 | UA_STATUSCODE_GOOD); |
| 52369 | if(retVal != UA_STATUSCODE_GOOD) { |
| 52370 | UA_LOG_ERROR_READERGROUP(server->config.logging, readerGroup, |
| 52371 | "Add DataSetReader failed, setPubSubState failed"); |
| 52372 | } |
| 52373 | } |
| 52374 | |
| 52375 | |
| 52376 | return UA_STATUSCODE_GOOD; |
| 52377 | } |
| 52378 | |
| 52379 | UA_StatusCode |
| 52380 | UA_Server_addDataSetReader(UA_Server *server, UA_NodeId readerGroupIdentifier, |
| 52381 | const UA_DataSetReaderConfig *dataSetReaderConfig, |
| 52382 | UA_NodeId *readerIdentifier) { |
| 52383 | lockServer(server); |
| 52384 | UA_StatusCode res = UA_DataSetReader_create(server, readerGroupIdentifier, |
| 52385 | dataSetReaderConfig, readerIdentifier); |
| 52386 | unlockServer(server); |
| 52387 | return res; |
| 52388 | } |
| 52389 | |
| 52390 | UA_StatusCode |
| 52391 | UA_DataSetReader_remove(UA_Server *server, UA_DataSetReader *dsr) { |
| 52392 | if(dsr->configurationFrozen) { |
| 52393 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 52394 | "Remove DataSetReader failed, " |
| 52395 | "Subscriber configuration is frozen"); |
| 52396 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 52397 | } |
| 52398 | |
| 52399 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 52400 | deleteNode(server, nodeId: dsr->identifier, true); |
| 52401 | #endif |
| 52402 | |
| 52403 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 52404 | /* Stop and remove message receive timeout timer */ |
| 52405 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 52406 | if(dsr->msgRcvTimeoutTimerRunning) { |
| 52407 | res = server->config.pubSubConfig.monitoringInterface. |
| 52408 | stopMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER, |
| 52409 | UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr); |
| 52410 | if(res != UA_STATUSCODE_GOOD) { |
| 52411 | UA_LOG_ERROR_READER(server->config.logging, dsr, |
| 52412 | "Remove DataSetReader failed. Stop message " |
| 52413 | "receive timeout timer of DataSetReader '%.*s' failed.", |
| 52414 | (int) dsr->config.name.length, dsr->config.name.data); |
| 52415 | } |
| 52416 | } |
| 52417 | |
| 52418 | res |= server->config.pubSubConfig.monitoringInterface. |
| 52419 | deleteMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER, |
| 52420 | UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr); |
| 52421 | if(res != UA_STATUSCODE_GOOD) { |
| 52422 | UA_LOG_ERROR_READER(server->config.logging, dsr, |
| 52423 | "Remove DataSetReader failed. Delete message receive " |
| 52424 | "timeout timer of DataSetReader '%.*s' failed.", |
| 52425 | (int) dsr->config.name.length, dsr->config.name.data); |
| 52426 | } |
| 52427 | #endif /* UA_ENABLE_PUBSUB_MONITORING */ |
| 52428 | /* check if a Standalone-SubscribedDataSet is associated with this reader and disconnect it*/ |
| 52429 | if(!UA_String_isEmpty(s: &dsr->config.linkedStandaloneSubscribedDataSetName)) { |
| 52430 | UA_StandaloneSubscribedDataSet *subscribedDataSet = |
| 52431 | UA_StandaloneSubscribedDataSet_findSDSbyName( |
| 52432 | server, identifier: dsr->config.linkedStandaloneSubscribedDataSetName); |
| 52433 | if(subscribedDataSet != NULL) { |
| 52434 | subscribedDataSet->config.isConnected = false; |
| 52435 | } |
| 52436 | } |
| 52437 | |
| 52438 | /* Delete DataSetReader config */ |
| 52439 | UA_DataSetReaderConfig_clear(cfg: &dsr->config); |
| 52440 | |
| 52441 | /* Get the ReaderGroup. This must succeed since all Readers are removed from |
| 52442 | * the group before it is deleted in UA_ReaderGroup_remove.*/ |
| 52443 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, identifier: dsr->linkedReaderGroup); |
| 52444 | UA_assert(rg); |
| 52445 | |
| 52446 | /* Remove DataSetReader from group */ |
| 52447 | LIST_REMOVE(dsr, listEntry); |
| 52448 | rg->readersCount--; |
| 52449 | |
| 52450 | /* THe offset buffer is only set when the dsr is frozen |
| 52451 | * UA_NetworkMessageOffsetBuffer_clear(&dsr->bufferedMessage); */ |
| 52452 | |
| 52453 | UA_NodeId_clear(p: &dsr->identifier); |
| 52454 | UA_NodeId_clear(p: &dsr->linkedReaderGroup); |
| 52455 | |
| 52456 | /* Free memory allocated for DataSetReader */ |
| 52457 | UA_free(ptr: dsr); |
| 52458 | |
| 52459 | return UA_STATUSCODE_GOOD; |
| 52460 | } |
| 52461 | |
| 52462 | UA_StatusCode |
| 52463 | UA_Server_removeDataSetReader(UA_Server *server, UA_NodeId readerIdentifier) { |
| 52464 | lockServer(server); |
| 52465 | UA_DataSetReader *dsr = UA_ReaderGroup_findDSRbyId(server, identifier: readerIdentifier); |
| 52466 | if(!dsr) { |
| 52467 | unlockServer(server); |
| 52468 | return UA_STATUSCODE_BADNOTFOUND; |
| 52469 | } |
| 52470 | UA_StatusCode res = UA_DataSetReader_remove(server, dsr); |
| 52471 | unlockServer(server); |
| 52472 | return res; |
| 52473 | } |
| 52474 | |
| 52475 | static UA_StatusCode |
| 52476 | DataSetReader_updateConfig(UA_Server *server, UA_ReaderGroup *rg, UA_DataSetReader *dsr, |
| 52477 | const UA_DataSetReaderConfig *config) { |
| 52478 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 52479 | |
| 52480 | if(dsr->configurationFrozen) { |
| 52481 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 52482 | "Update DataSetReader config failed. " |
| 52483 | "Subscriber configuration is frozen."); |
| 52484 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 52485 | } |
| 52486 | |
| 52487 | if(rg->configurationFrozen) { |
| 52488 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 52489 | "Update DataSetReader config failed. " |
| 52490 | "Subscriber configuration is frozen."); |
| 52491 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 52492 | } |
| 52493 | |
| 52494 | if(dsr->config.subscribedDataSetType != UA_PUBSUB_SDS_TARGET) { |
| 52495 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 52496 | "Unsupported SubscribedDataSetType."); |
| 52497 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 52498 | } |
| 52499 | |
| 52500 | /* The update functionality will be extended during the next PubSub batches. |
| 52501 | * Currently changes for writerGroupId, dataSetWriterId and TargetVariables are possible. */ |
| 52502 | if(dsr->config.writerGroupId != config->writerGroupId) |
| 52503 | dsr->config.writerGroupId = config->writerGroupId; |
| 52504 | if(dsr->config.dataSetWriterId != config->dataSetWriterId) |
| 52505 | dsr->config.dataSetWriterId = config->dataSetWriterId; |
| 52506 | |
| 52507 | UA_TargetVariables *oldTV = &dsr->config.subscribedDataSet.subscribedDataSetTarget; |
| 52508 | const UA_TargetVariables *newTV = &config->subscribedDataSet.subscribedDataSetTarget; |
| 52509 | if(oldTV->targetVariablesSize == newTV->targetVariablesSize) { |
| 52510 | for(size_t i = 0; i < newTV->targetVariablesSize; i++) { |
| 52511 | if(!UA_NodeId_equal(p1: &oldTV->targetVariables[i].targetVariable.targetNodeId, |
| 52512 | p2: &newTV->targetVariables[i].targetVariable.targetNodeId)) { |
| 52513 | DataSetReader_createTargetVariables(server, dsr, |
| 52514 | targetVariablesSize: newTV->targetVariablesSize, |
| 52515 | targetVariables: newTV->targetVariables); |
| 52516 | break; |
| 52517 | } |
| 52518 | } |
| 52519 | } else { |
| 52520 | DataSetReader_createTargetVariables(server, dsr, targetVariablesSize: newTV->targetVariablesSize, |
| 52521 | targetVariables: newTV->targetVariables); |
| 52522 | } |
| 52523 | |
| 52524 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 52525 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 52526 | if(dsr->config.messageReceiveTimeout != config->messageReceiveTimeout) { |
| 52527 | /* Update message receive timeout timer interval */ |
| 52528 | dsr->config.messageReceiveTimeout = config->messageReceiveTimeout; |
| 52529 | res = server->config.pubSubConfig.monitoringInterface. |
| 52530 | updateMonitoringInterval(server, dsr->identifier, |
| 52531 | UA_PUBSUB_COMPONENT_DATASETREADER, |
| 52532 | UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, |
| 52533 | dsr); |
| 52534 | if(res != UA_STATUSCODE_GOOD) { |
| 52535 | UA_LOG_ERROR_READER(server->config.logging, dsr, |
| 52536 | "Update DataSetReader message receive timeout timer failed."); |
| 52537 | } |
| 52538 | } |
| 52539 | #endif /* UA_ENABLE_PUBSUB_MONITORING */ |
| 52540 | return res; |
| 52541 | } |
| 52542 | |
| 52543 | UA_StatusCode |
| 52544 | UA_Server_DataSetReader_updateConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier, |
| 52545 | UA_NodeId readerGroupIdentifier, |
| 52546 | const UA_DataSetReaderConfig *config) { |
| 52547 | if(config == NULL) |
| 52548 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 52549 | |
| 52550 | lockServer(server); |
| 52551 | UA_DataSetReader *dsr = UA_ReaderGroup_findDSRbyId(server, identifier: dataSetReaderIdentifier); |
| 52552 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, identifier: readerGroupIdentifier); |
| 52553 | if(!dsr || !rg) { |
| 52554 | unlockServer(server); |
| 52555 | return UA_STATUSCODE_BADNOTFOUND; |
| 52556 | } |
| 52557 | UA_StatusCode res = DataSetReader_updateConfig(server, rg, dsr, config); |
| 52558 | unlockServer(server); |
| 52559 | return res; |
| 52560 | } |
| 52561 | |
| 52562 | UA_StatusCode |
| 52563 | UA_Server_DataSetReader_getConfig(UA_Server *server, UA_NodeId dataSetReaderIdentifier, |
| 52564 | UA_DataSetReaderConfig *config) { |
| 52565 | if(!config) |
| 52566 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 52567 | lockServer(server); |
| 52568 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 52569 | UA_DataSetReader *dsr = UA_ReaderGroup_findDSRbyId(server, identifier: dataSetReaderIdentifier); |
| 52570 | if(dsr) |
| 52571 | res = UA_DataSetReaderConfig_copy(src: &dsr->config, dst: config); |
| 52572 | unlockServer(server); |
| 52573 | return res; |
| 52574 | } |
| 52575 | |
| 52576 | UA_StatusCode |
| 52577 | UA_DataSetReaderConfig_copy(const UA_DataSetReaderConfig *src, |
| 52578 | UA_DataSetReaderConfig *dst) { |
| 52579 | memset(s: dst, c: 0, n: sizeof(UA_DataSetReaderConfig)); |
| 52580 | UA_StatusCode retVal = UA_String_copy(src: &src->name, dst: &dst->name); |
| 52581 | if(retVal != UA_STATUSCODE_GOOD) |
| 52582 | return retVal; |
| 52583 | |
| 52584 | retVal = UA_Variant_copy(src: &src->publisherId, dst: &dst->publisherId); |
| 52585 | if(retVal != UA_STATUSCODE_GOOD) |
| 52586 | return retVal; |
| 52587 | |
| 52588 | dst->writerGroupId = src->writerGroupId; |
| 52589 | dst->dataSetWriterId = src->dataSetWriterId; |
| 52590 | dst->expectedEncoding = src->expectedEncoding; |
| 52591 | retVal = UA_DataSetMetaDataType_copy(src: &src->dataSetMetaData, dst: &dst->dataSetMetaData); |
| 52592 | if(retVal != UA_STATUSCODE_GOOD) |
| 52593 | return retVal; |
| 52594 | |
| 52595 | dst->dataSetFieldContentMask = src->dataSetFieldContentMask; |
| 52596 | dst->messageReceiveTimeout = src->messageReceiveTimeout; |
| 52597 | |
| 52598 | retVal = UA_ExtensionObject_copy(src: &src->messageSettings, dst: &dst->messageSettings); |
| 52599 | if(retVal != UA_STATUSCODE_GOOD) |
| 52600 | return retVal; |
| 52601 | |
| 52602 | retVal = UA_ExtensionObject_copy(src: &src->transportSettings, dst: &dst->transportSettings); |
| 52603 | if(retVal != UA_STATUSCODE_GOOD) |
| 52604 | return retVal; |
| 52605 | |
| 52606 | if(src->subscribedDataSetType == UA_PUBSUB_SDS_TARGET) { |
| 52607 | retVal = UA_TargetVariables_copy(src: &src->subscribedDataSet.subscribedDataSetTarget, |
| 52608 | dst: &dst->subscribedDataSet.subscribedDataSetTarget); |
| 52609 | if(retVal != UA_STATUSCODE_GOOD) { |
| 52610 | return retVal; |
| 52611 | } |
| 52612 | } |
| 52613 | |
| 52614 | retVal = UA_String_copy(src: &src->linkedStandaloneSubscribedDataSetName, dst: &dst->linkedStandaloneSubscribedDataSetName); |
| 52615 | |
| 52616 | return retVal; |
| 52617 | } |
| 52618 | |
| 52619 | void |
| 52620 | UA_DataSetReaderConfig_clear(UA_DataSetReaderConfig *cfg) { |
| 52621 | UA_String_clear(p: &cfg->name); |
| 52622 | UA_String_clear(p: &cfg->linkedStandaloneSubscribedDataSetName); |
| 52623 | UA_Variant_clear(p: &cfg->publisherId); |
| 52624 | UA_DataSetMetaDataType_clear(p: &cfg->dataSetMetaData); |
| 52625 | UA_ExtensionObject_clear(p: &cfg->messageSettings); |
| 52626 | UA_ExtensionObject_clear(p: &cfg->transportSettings); |
| 52627 | if(cfg->subscribedDataSetType == UA_PUBSUB_SDS_TARGET) { |
| 52628 | UA_TargetVariables_clear(subscribedDataSetTarget: &cfg->subscribedDataSet.subscribedDataSetTarget); |
| 52629 | } |
| 52630 | } |
| 52631 | |
| 52632 | UA_StatusCode |
| 52633 | UA_Server_DataSetReader_getState(UA_Server *server, UA_NodeId dataSetReaderIdentifier, |
| 52634 | UA_PubSubState *state) { |
| 52635 | if(!server || !state) |
| 52636 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 52637 | |
| 52638 | lockServer(server); |
| 52639 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 52640 | UA_DataSetReader *dsr = UA_ReaderGroup_findDSRbyId(server, identifier: dataSetReaderIdentifier); |
| 52641 | if(dsr) { |
| 52642 | res = UA_STATUSCODE_GOOD; |
| 52643 | *state = dsr->state; |
| 52644 | } |
| 52645 | unlockServer(server); |
| 52646 | return res; |
| 52647 | } |
| 52648 | |
| 52649 | static UA_StatusCode |
| 52650 | UA_DataSetReader_setState_disabled(UA_Server *server, UA_DataSetReader *dsr) { |
| 52651 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 52652 | switch(dsr->state) { |
| 52653 | case UA_PUBSUBSTATE_DISABLED: |
| 52654 | return UA_STATUSCODE_GOOD; |
| 52655 | case UA_PUBSUBSTATE_PAUSED: |
| 52656 | dsr->state = UA_PUBSUBSTATE_DISABLED; |
| 52657 | return UA_STATUSCODE_GOOD; |
| 52658 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 52659 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 52660 | /* Stop MessageReceiveTimeout timer */ |
| 52661 | if(dsr->msgRcvTimeoutTimerRunning == true) { |
| 52662 | ret = server->config.pubSubConfig.monitoringInterface. |
| 52663 | stopMonitoring(server, dsr->identifier, |
| 52664 | UA_PUBSUB_COMPONENT_DATASETREADER, |
| 52665 | UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr); |
| 52666 | if(ret == UA_STATUSCODE_GOOD) { |
| 52667 | dsr->msgRcvTimeoutTimerRunning = false; |
| 52668 | } else { |
| 52669 | UA_LOG_ERROR_READER(server->config.logging, dsr, |
| 52670 | "Disable ReaderGroup failed. Stop message receive " |
| 52671 | "timeout timer of DataSetReader '%.*s' failed.", |
| 52672 | (int) dsr->config.name.length, dsr->config.name.data); |
| 52673 | } |
| 52674 | } |
| 52675 | #endif /* UA_ENABLE_PUBSUB_MONITORING */ |
| 52676 | if(ret == UA_STATUSCODE_GOOD) |
| 52677 | dsr->state = UA_PUBSUBSTATE_DISABLED; |
| 52678 | return ret; |
| 52679 | case UA_PUBSUBSTATE_ERROR: |
| 52680 | break; |
| 52681 | default: |
| 52682 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 52683 | "Received unknown PubSub state!"); |
| 52684 | } |
| 52685 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 52686 | } |
| 52687 | |
| 52688 | /* State machine methods not part of the open62541 state machine API */ |
| 52689 | UA_StatusCode |
| 52690 | UA_DataSetReader_setPubSubState(UA_Server *server, |
| 52691 | UA_DataSetReader *dataSetReader, |
| 52692 | UA_PubSubState state, |
| 52693 | UA_StatusCode cause) { |
| 52694 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 52695 | UA_PubSubState oldState = dataSetReader->state; |
| 52696 | switch(state) { |
| 52697 | case UA_PUBSUBSTATE_DISABLED: |
| 52698 | ret = UA_DataSetReader_setState_disabled(server, dsr: dataSetReader); |
| 52699 | break; |
| 52700 | case UA_PUBSUBSTATE_PAUSED: |
| 52701 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 52702 | break; |
| 52703 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 52704 | case UA_PUBSUBSTATE_PREOPERATIONAL: |
| 52705 | case UA_PUBSUBSTATE_ERROR: |
| 52706 | dataSetReader->state = state; |
| 52707 | break; |
| 52708 | default: |
| 52709 | UA_LOG_WARNING_READER(server->config.logging, dataSetReader, |
| 52710 | "Received unknown PubSub state!"); |
| 52711 | ret = UA_STATUSCODE_BADINVALIDARGUMENT; |
| 52712 | break; |
| 52713 | } |
| 52714 | if (state != oldState) { |
| 52715 | /* inform application about state change */ |
| 52716 | UA_ServerConfig *config = &server->config; |
| 52717 | if(config->pubSubConfig.stateChangeCallback != 0) { |
| 52718 | config->pubSubConfig. |
| 52719 | stateChangeCallback(server, &dataSetReader->identifier, state, cause); |
| 52720 | } |
| 52721 | } |
| 52722 | return ret; |
| 52723 | } |
| 52724 | |
| 52725 | UA_StatusCode |
| 52726 | UA_FieldTargetVariable_copy(const UA_FieldTargetVariable *src, UA_FieldTargetVariable *dst) { |
| 52727 | /* Do a simple memcpy */ |
| 52728 | memcpy(dest: dst, src: src, n: sizeof(UA_FieldTargetVariable)); |
| 52729 | return UA_FieldTargetDataType_copy(src: &src->targetVariable, dst: &dst->targetVariable); |
| 52730 | } |
| 52731 | |
| 52732 | UA_StatusCode |
| 52733 | UA_TargetVariables_copy(const UA_TargetVariables *src, UA_TargetVariables *dst) { |
| 52734 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 52735 | memcpy(dest: dst, src: src, n: sizeof(UA_TargetVariables)); |
| 52736 | if(src->targetVariablesSize > 0) { |
| 52737 | dst->targetVariables = (UA_FieldTargetVariable*) |
| 52738 | UA_calloc(nmemb: src->targetVariablesSize, size: sizeof(UA_FieldTargetVariable)); |
| 52739 | if(!dst->targetVariables) |
| 52740 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 52741 | for(size_t i = 0; i < src->targetVariablesSize; i++) |
| 52742 | retVal |= UA_FieldTargetVariable_copy(src: &src->targetVariables[i], dst: &dst->targetVariables[i]); |
| 52743 | } |
| 52744 | return retVal; |
| 52745 | } |
| 52746 | |
| 52747 | void |
| 52748 | UA_TargetVariables_clear(UA_TargetVariables *subscribedDataSetTarget) { |
| 52749 | for(size_t i = 0; i < subscribedDataSetTarget->targetVariablesSize; i++) { |
| 52750 | UA_FieldTargetDataType_clear(p: &subscribedDataSetTarget->targetVariables[i].targetVariable); |
| 52751 | } |
| 52752 | if(subscribedDataSetTarget->targetVariablesSize > 0) |
| 52753 | UA_free(ptr: subscribedDataSetTarget->targetVariables); |
| 52754 | memset(s: subscribedDataSetTarget, c: 0, n: sizeof(UA_TargetVariables)); |
| 52755 | } |
| 52756 | |
| 52757 | /* This Method is used to initially set the SubscribedDataSet to |
| 52758 | * TargetVariablesType and to create the list of target Variables of a |
| 52759 | * SubscribedDataSetType. */ |
| 52760 | UA_StatusCode |
| 52761 | DataSetReader_createTargetVariables(UA_Server *server, UA_DataSetReader *dsr, |
| 52762 | size_t targetVariablesSize, |
| 52763 | const UA_FieldTargetVariable *targetVariables) { |
| 52764 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 52765 | |
| 52766 | if(dsr->configurationFrozen) { |
| 52767 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 52768 | "Create Target Variables failed. " |
| 52769 | "Subscriber configuration is frozen."); |
| 52770 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 52771 | } |
| 52772 | |
| 52773 | if(dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize > 0) |
| 52774 | UA_TargetVariables_clear(subscribedDataSetTarget: &dsr->config.subscribedDataSet.subscribedDataSetTarget); |
| 52775 | |
| 52776 | /* Set subscribed dataset to TargetVariableType */ |
| 52777 | dsr->config.subscribedDataSetType = UA_PUBSUB_SDS_TARGET; |
| 52778 | UA_TargetVariables tmp; |
| 52779 | tmp.targetVariablesSize = targetVariablesSize; |
| 52780 | tmp.targetVariables = (UA_FieldTargetVariable*)(uintptr_t)targetVariables; |
| 52781 | return UA_TargetVariables_copy(src: &tmp, dst: &dsr->config.subscribedDataSet.subscribedDataSetTarget); |
| 52782 | } |
| 52783 | |
| 52784 | UA_StatusCode |
| 52785 | UA_Server_DataSetReader_createTargetVariables(UA_Server *server, |
| 52786 | UA_NodeId dataSetReaderIdentifier, |
| 52787 | size_t targetVariablesSize, |
| 52788 | const UA_FieldTargetVariable *targetVariables) { |
| 52789 | lockServer(server); |
| 52790 | UA_DataSetReader *dataSetReader = UA_ReaderGroup_findDSRbyId(server, identifier: dataSetReaderIdentifier); |
| 52791 | if(!dataSetReader) { |
| 52792 | unlockServer(server); |
| 52793 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 52794 | } |
| 52795 | UA_StatusCode res = DataSetReader_createTargetVariables(server, dsr: dataSetReader, |
| 52796 | targetVariablesSize, targetVariables); |
| 52797 | unlockServer(server); |
| 52798 | return res; |
| 52799 | } |
| 52800 | |
| 52801 | /* This functionality of this API will be used in future to create mirror Variables - TODO */ |
| 52802 | /* UA_StatusCode |
| 52803 | UA_Server_DataSetReader_createDataSetMirror(UA_Server *server, UA_String *parentObjectNodeName, |
| 52804 | UA_NodeId dataSetReaderIdentifier) { |
| 52805 | if((server == NULL) || (parentNode == NULL)) { |
| 52806 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 52807 | } |
| 52808 | |
| 52809 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 52810 | UA_DataSetReader* pDataSetReader = UA_ReaderGroup_findDSRbyId(server, dataSetReaderIdentifier); |
| 52811 | if(pDataSetReader == NULL) { |
| 52812 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 52813 | } |
| 52814 | |
| 52815 | if(pDataSetReader->configurationFrozen) { |
| 52816 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 52817 | "Add Target Variables failed. Subscriber configuration is frozen."); |
| 52818 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 52819 | } // TODO: Frozen configuration variable in TargetVariable structure |
| 52820 | |
| 52821 | UA_TargetVariables targetVars; |
| 52822 | targetVars.targetVariablesSize = pDataSetReader->config.dataSetMetaData.fieldsSize; |
| 52823 | targetVars.targetVariables = (UA_FieldTargetVariable *) |
| 52824 | UA_calloc(targetVars.targetVariablesSize, sizeof(UA_FieldTargetVariable)); |
| 52825 | |
| 52826 | for(size_t i = 0; i < pDataSetReader->config.dataSetMetaData.fieldsSize; i++) { |
| 52827 | UA_VariableAttributes vAttr = UA_VariableAttributes_default; |
| 52828 | vAttr.valueRank = pDataSetReader->config.dataSetMetaData.fields[i].valueRank; |
| 52829 | if(pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensionsSize > 0) { |
| 52830 | retval = UA_Array_copy(pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensions, |
| 52831 | pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensionsSize, |
| 52832 | (void**)&vAttr.arrayDimensions, &UA_TYPES[UA_TYPES_UINT32]); |
| 52833 | if(retval == UA_STATUSCODE_GOOD) { |
| 52834 | vAttr.arrayDimensionsSize = |
| 52835 | pDataSetReader->config.dataSetMetaData.fields[i].arrayDimensionsSize; |
| 52836 | } |
| 52837 | |
| 52838 | } |
| 52839 | |
| 52840 | vAttr.dataType = pDataSetReader->config.dataSetMetaData.fields[i].dataType; |
| 52841 | |
| 52842 | vAttr.accessLevel = UA_ACCESSLEVELMASK_READ; |
| 52843 | UA_LocalizedText_copy(&pDataSetReader->config.dataSetMetaData.fields[i].description, |
| 52844 | &vAttr.description); |
| 52845 | UA_QualifiedName qn; |
| 52846 | UA_QualifiedName_init(&qn); |
| 52847 | char szTmpName[UA_MAX_SIZENAME]; |
| 52848 | if(pDataSetReader->config.dataSetMetaData.fields[i].name.length > 0) { |
| 52849 | UA_UInt16 slen = UA_MAX_SIZENAME -1; |
| 52850 | vAttr.displayName.locale = UA_STRING("en-US"); |
| 52851 | vAttr.displayName.text = pDataSetReader->config.dataSetMetaData.fields[i].name; |
| 52852 | if(pDataSetReader->config.dataSetMetaData.fields[i].name.length < slen) { |
| 52853 | slen = (UA_UInt16)pDataSetReader->config.dataSetMetaData.fields[i].name.length; |
| 52854 | mp_snprintf(szTmpName, sizeof(szTmpName), "%.*s", (int)slen, |
| 52855 | (const char*)pDataSetReader->config.dataSetMetaData.fields[i].name.data); |
| 52856 | } |
| 52857 | |
| 52858 | szTmpName[slen] = '\0'; |
| 52859 | qn = UA_QUALIFIEDNAME(1, szTmpName); |
| 52860 | } |
| 52861 | else { |
| 52862 | strcpy(szTmpName, "SubscribedVariable"); |
| 52863 | vAttr.displayName = UA_LOCALIZEDTEXT("en-US", szTmpName); |
| 52864 | qn = UA_QUALIFIEDNAME(1, "SubscribedVariable"); |
| 52865 | } |
| 52866 | |
| 52867 | // Add variable to the given parent node |
| 52868 | UA_NodeId newNode; |
| 52869 | retval = UA_Server_addVariableNode(server, UA_NODEID_NULL, *parentNode, |
| 52870 | UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT), qn, |
| 52871 | UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE), |
| 52872 | vAttr, NULL, &newNode); |
| 52873 | if(retval == UA_STATUSCODE_GOOD) { |
| 52874 | UA_LOG_INFO(server->config.logging, UA_LOGCATEGORY_USERLAND, |
| 52875 | "addVariableNode %s succeeded", szTmpName); |
| 52876 | } |
| 52877 | else { |
| 52878 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_USERLAND, |
| 52879 | "addVariableNode: error 0x%" PRIx32, retval); |
| 52880 | } |
| 52881 | |
| 52882 | targetVars.targetVariables[i].targetVariable.attributeId = UA_ATTRIBUTEID_VALUE; |
| 52883 | UA_NodeId_copy(&newNode, &targetVars.targetVariables[i].targetVariable.targetNodeId); |
| 52884 | UA_NodeId_clear(&newNode); |
| 52885 | if(vAttr.arrayDimensionsSize > 0) { |
| 52886 | UA_Array_delete(vAttr.arrayDimensions, vAttr.arrayDimensionsSize, |
| 52887 | &UA_TYPES[UA_TYPES_UINT32]); |
| 52888 | } |
| 52889 | } |
| 52890 | |
| 52891 | UA_TargetVariables_clear(&targetVars); |
| 52892 | return retval; |
| 52893 | }*/ |
| 52894 | |
| 52895 | static void |
| 52896 | DataSetReader_processRaw(UA_Server *server, UA_ReaderGroup *rg, |
| 52897 | UA_DataSetReader *dsr, UA_DataSetMessage* msg) { |
| 52898 | UA_LOG_TRACE_READER(server->config.logging, dsr, "Received RAW Frame"); |
| 52899 | msg->data.keyFrameData.fieldCount = (UA_UInt16) |
| 52900 | dsr->config.dataSetMetaData.fieldsSize; |
| 52901 | |
| 52902 | /* Start iteration from beginning of rawFields buffer */ |
| 52903 | size_t offset = 0; |
| 52904 | msg->data.keyFrameData.rawFields.length = 0; |
| 52905 | for(size_t i = 0; i < dsr->config.dataSetMetaData.fieldsSize; i++) { |
| 52906 | /* TODO The datatype reference should be part of the internal |
| 52907 | * pubsub configuration to avoid the time-expensive lookup */ |
| 52908 | const UA_DataType *type = |
| 52909 | UA_findDataTypeWithCustom(typeId: &dsr->config.dataSetMetaData.fields[i].dataType, |
| 52910 | customTypes: server->config.customDataTypes); |
| 52911 | msg->data.keyFrameData.rawFields.length += type->memSize; |
| 52912 | UA_STACKARRAY(UA_Byte, value, type->memSize); |
| 52913 | UA_StatusCode res = |
| 52914 | UA_decodeBinaryInternal(src: &msg->data.keyFrameData.rawFields, |
| 52915 | offset: &offset, dst: value, type, NULL); |
| 52916 | if(dsr->config.dataSetMetaData.fields[i].maxStringLength != 0) { |
| 52917 | if(type->typeKind == UA_DATATYPEKIND_STRING || |
| 52918 | type->typeKind == UA_DATATYPEKIND_BYTESTRING) { |
| 52919 | UA_ByteString *bs = (UA_ByteString *) value; |
| 52920 | /* Check if length < maxStringLength, The types ByteString and |
| 52921 | * String are equal in their base definition */ |
| 52922 | size_t lengthDifference = |
| 52923 | dsr->config.dataSetMetaData.fields[i].maxStringLength - bs->length; |
| 52924 | offset += lengthDifference; |
| 52925 | } |
| 52926 | } |
| 52927 | if(res != UA_STATUSCODE_GOOD) { |
| 52928 | UA_LOG_INFO_READER(server->config.logging, dsr, |
| 52929 | "Error during Raw-decode KeyFrame field %u: %s", |
| 52930 | (unsigned)i, UA_StatusCode_name(res)); |
| 52931 | return; |
| 52932 | } |
| 52933 | |
| 52934 | UA_FieldTargetVariable *tv = |
| 52935 | &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i]; |
| 52936 | |
| 52937 | if(tv->externalDataValue) { |
| 52938 | if(tv->beforeWrite) |
| 52939 | tv->beforeWrite(server, &dsr->identifier, &dsr->linkedReaderGroup, |
| 52940 | &tv->targetVariable.targetNodeId, |
| 52941 | tv->targetVariableContext, tv->externalDataValue); |
| 52942 | memcpy(dest: (*tv->externalDataValue)->value.data, src: value, n: type->memSize); |
| 52943 | if(tv->afterWrite) |
| 52944 | tv->afterWrite(server, &dsr->identifier, &dsr->linkedReaderGroup, |
| 52945 | &tv->targetVariable.targetNodeId, |
| 52946 | tv->targetVariableContext, tv->externalDataValue); |
| 52947 | continue; /* No dynamic allocation for fixed-size msg, no need to _clear */ |
| 52948 | } |
| 52949 | |
| 52950 | UA_WriteValue writeVal; |
| 52951 | UA_WriteValue_init(p: &writeVal); |
| 52952 | writeVal.attributeId = tv->targetVariable.attributeId; |
| 52953 | writeVal.indexRange = tv->targetVariable.receiverIndexRange; |
| 52954 | writeVal.nodeId = tv->targetVariable.targetNodeId; |
| 52955 | UA_Variant_setScalar(v: &writeVal.value.value, p: value, type); |
| 52956 | writeVal.value.hasValue = true; |
| 52957 | Operation_Write(server, session: &server->adminSession, NULL, wv: &writeVal, result: &res); |
| 52958 | UA_clear(p: value, type); |
| 52959 | if(res != UA_STATUSCODE_GOOD) { |
| 52960 | UA_LOG_INFO_READER(server->config.logging, dsr, |
| 52961 | "Error writing KeyFrame field %u: %s", |
| 52962 | (unsigned)i, UA_StatusCode_name(res)); |
| 52963 | } |
| 52964 | } |
| 52965 | } |
| 52966 | |
| 52967 | void |
| 52968 | UA_DataSetReader_process(UA_Server *server, UA_ReaderGroup *rg, |
| 52969 | UA_DataSetReader *dsr, UA_DataSetMessage *msg) { |
| 52970 | if(!dsr || !rg || !msg || !server) |
| 52971 | return; |
| 52972 | |
| 52973 | UA_LOG_DEBUG_READER(server->config.logging, dsr, "Received a network message"); |
| 52974 | |
| 52975 | if(!msg->header.dataSetMessageValid) { |
| 52976 | UA_LOG_INFO_READER(server->config.logging, dsr, |
| 52977 | "DataSetMessage is discarded: message is not valid"); |
| 52978 | return; |
| 52979 | } |
| 52980 | |
| 52981 | /* TODO: Check ConfigurationVersion */ |
| 52982 | /* if(msg->header.configVersionMajorVersionEnabled) { |
| 52983 | * if(msg->header.configVersionMajorVersion != |
| 52984 | * dsr->config.dataSetMetaData.configurationVersion.majorVersion) { |
| 52985 | * UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 52986 | * "DataSetMessage is discarded: ConfigurationVersion " |
| 52987 | * "MajorVersion does not match"); |
| 52988 | * return; |
| 52989 | * } |
| 52990 | * } */ |
| 52991 | |
| 52992 | if(msg->header.dataSetMessageType != UA_DATASETMESSAGE_DATAKEYFRAME) { |
| 52993 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 52994 | "DataSetMessage is discarded: Only keyframes are supported"); |
| 52995 | return; |
| 52996 | } |
| 52997 | |
| 52998 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 52999 | UA_DataSetReader_checkMessageReceiveTimeout(server, dsr); |
| 53000 | #endif |
| 53001 | |
| 53002 | if(dsr->state != UA_PUBSUBSTATE_OPERATIONAL && |
| 53003 | dsr->state != UA_PUBSUBSTATE_PREOPERATIONAL) { |
| 53004 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 53005 | "Received a network message but not operational"); |
| 53006 | return; |
| 53007 | } |
| 53008 | |
| 53009 | /* Process message with raw encoding. We have no field-count information for |
| 53010 | * the message. */ |
| 53011 | if(msg->header.fieldEncoding == UA_FIELDENCODING_RAWDATA) { |
| 53012 | DataSetReader_processRaw(server, rg, dsr, msg); |
| 53013 | return; |
| 53014 | } |
| 53015 | |
| 53016 | /* Received a heartbeat with no fields */ |
| 53017 | if(msg->data.keyFrameData.fieldCount == 0) { |
| 53018 | dsr->lastHeartbeatReceived = UA_DateTime_nowMonotonic(); |
| 53019 | return; |
| 53020 | } |
| 53021 | |
| 53022 | /* Check whether the field count matches the configuration */ |
| 53023 | size_t fieldCount = msg->data.keyFrameData.fieldCount; |
| 53024 | if(dsr->config.dataSetMetaData.fieldsSize != fieldCount) { |
| 53025 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 53026 | "Number of fields does not match the DataSetMetaData configuration"); |
| 53027 | return; |
| 53028 | } |
| 53029 | |
| 53030 | if(dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariablesSize != fieldCount) { |
| 53031 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 53032 | "Number of fields does not match the TargetVariables configuration"); |
| 53033 | return; |
| 53034 | } |
| 53035 | |
| 53036 | /* Write the message fields. RT has the external data value configured. */ |
| 53037 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 53038 | for(size_t i = 0; i < fieldCount; i++) { |
| 53039 | UA_DataValue *field = &msg->data.keyFrameData.dataSetFields[i]; |
| 53040 | if(!field->hasValue) |
| 53041 | continue; |
| 53042 | |
| 53043 | UA_FieldTargetVariable *tv = |
| 53044 | &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i]; |
| 53045 | |
| 53046 | /* RT-path: write directly into the target memory */ |
| 53047 | if(tv->externalDataValue) { |
| 53048 | if(field->value.type != (*tv->externalDataValue)->value.type) { |
| 53049 | UA_LOG_WARNING_READER(server->config.logging, dsr, "Mismatching type"); |
| 53050 | continue; |
| 53051 | } |
| 53052 | |
| 53053 | if(tv->beforeWrite) |
| 53054 | tv->beforeWrite(server, &dsr->identifier, &dsr->linkedReaderGroup, |
| 53055 | &tv->targetVariable.targetNodeId, |
| 53056 | tv->targetVariableContext, tv->externalDataValue); |
| 53057 | memcpy(dest: (*tv->externalDataValue)->value.data, |
| 53058 | src: field->value.data, n: field->value.type->memSize); |
| 53059 | if(tv->afterWrite) |
| 53060 | tv->afterWrite(server, &dsr->identifier, &dsr->linkedReaderGroup, |
| 53061 | &tv->targetVariable.targetNodeId, |
| 53062 | tv->targetVariableContext, tv->externalDataValue); |
| 53063 | continue; |
| 53064 | } |
| 53065 | |
| 53066 | /* Write via the Write-Service */ |
| 53067 | UA_WriteValue writeVal; |
| 53068 | UA_WriteValue_init(p: &writeVal); |
| 53069 | writeVal.attributeId = tv->targetVariable.attributeId; |
| 53070 | writeVal.indexRange = tv->targetVariable.receiverIndexRange; |
| 53071 | writeVal.nodeId = tv->targetVariable.targetNodeId; |
| 53072 | writeVal.value = *field; |
| 53073 | Operation_Write(server, session: &server->adminSession, NULL, wv: &writeVal, result: &res); |
| 53074 | if(res != UA_STATUSCODE_GOOD) |
| 53075 | UA_LOG_INFO_READER(server->config.logging, dsr, |
| 53076 | "Error writing KeyFrame field %u: %s", |
| 53077 | (unsigned)i, UA_StatusCode_name(res)); |
| 53078 | } |
| 53079 | } |
| 53080 | |
| 53081 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 53082 | |
| 53083 | static void |
| 53084 | UA_DataSetReader_checkMessageReceiveTimeout(UA_Server *server, |
| 53085 | UA_DataSetReader *dsr) { |
| 53086 | UA_assert(server != 0); |
| 53087 | UA_assert(dsr != 0); |
| 53088 | |
| 53089 | /* If previous reader state was error (because we haven't received messages |
| 53090 | * and ran into timeout) we should set the state back to operational */ |
| 53091 | if(dsr->state == UA_PUBSUBSTATE_ERROR) { |
| 53092 | UA_DataSetReader_setPubSubState(server, dsr, UA_PUBSUBSTATE_OPERATIONAL, |
| 53093 | UA_STATUSCODE_GOOD); |
| 53094 | } |
| 53095 | |
| 53096 | /* Stop message receive timeout timer */ |
| 53097 | UA_StatusCode res; |
| 53098 | if(dsr->msgRcvTimeoutTimerRunning) { |
| 53099 | res = server->config.pubSubConfig.monitoringInterface. |
| 53100 | stopMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER, |
| 53101 | UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr); |
| 53102 | if(res == UA_STATUSCODE_GOOD) { |
| 53103 | dsr->msgRcvTimeoutTimerRunning = false; |
| 53104 | } else { |
| 53105 | UA_LOG_ERROR_READER(server->config.logging, dsr, |
| 53106 | "DataSetReader '%.*s': stop receive timeout timer failed", |
| 53107 | (int)dsr->config.name.length, dsr->config.name.data); |
| 53108 | UA_DataSetReader_setPubSubState(server, dsr, UA_PUBSUBSTATE_ERROR, |
| 53109 | UA_STATUSCODE_BADINTERNALERROR); |
| 53110 | } |
| 53111 | } |
| 53112 | |
| 53113 | /* Start message receive timeout timer */ |
| 53114 | res = server->config.pubSubConfig.monitoringInterface. |
| 53115 | startMonitoring(server, dsr->identifier, UA_PUBSUB_COMPONENT_DATASETREADER, |
| 53116 | UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT, dsr); |
| 53117 | if(res == UA_STATUSCODE_GOOD) { |
| 53118 | UA_LOG_DEBUG_READER(server->config.logging, dsr, |
| 53119 | "Info: DataSetReader '%.*s': start receive timeout timer", |
| 53120 | (int)dsr->config.name.length, dsr->config.name.data); |
| 53121 | dsr->msgRcvTimeoutTimerRunning = true; |
| 53122 | } else { |
| 53123 | UA_LOG_ERROR_READER(server->config.logging, dsr, |
| 53124 | "Starting Message Receive Timeout timer failed."); |
| 53125 | UA_DataSetReader_setPubSubState(server, dsr, UA_PUBSUBSTATE_ERROR, |
| 53126 | UA_STATUSCODE_BADINTERNALERROR); |
| 53127 | } |
| 53128 | } |
| 53129 | |
| 53130 | /* Timeout callback for DataSetReader MessageReceiveTimeout handling */ |
| 53131 | static void |
| 53132 | UA_DataSetReader_handleMessageReceiveTimeout(UA_Server *server, UA_DataSetReader *dsr) { |
| 53133 | UA_assert(server); |
| 53134 | UA_assert(dsr); |
| 53135 | |
| 53136 | if(dsr->componentType != UA_PUBSUB_COMPONENT_DATASETREADER) { |
| 53137 | UA_LOG_ERROR_READER(server->config.logging, dsr, |
| 53138 | "UA_DataSetReader_handleMessageReceiveTimeout(): " |
| 53139 | "input param is not of type DataSetReader"); |
| 53140 | return; |
| 53141 | } |
| 53142 | |
| 53143 | UA_LOG_DEBUG_READER(server->config.logging, dsr, |
| 53144 | "UA_DataSetReader_handleMessageReceiveTimeout(): " |
| 53145 | "MessageReceiveTimeout occurred at DataSetReader " |
| 53146 | "'%.*s': MessageReceiveTimeout = %f Timer Id = %u ", |
| 53147 | (int)dsr->config.name.length, dsr->config.name.data, |
| 53148 | dsr->config.messageReceiveTimeout, |
| 53149 | (UA_UInt32) dsr->msgRcvTimeoutTimerId); |
| 53150 | |
| 53151 | UA_StatusCode res = |
| 53152 | UA_DataSetReader_setPubSubState(server, dsr, UA_PUBSUBSTATE_ERROR, |
| 53153 | UA_STATUSCODE_BADTIMEOUT); |
| 53154 | if(res != UA_STATUSCODE_GOOD) { |
| 53155 | UA_LOG_ERROR_READER(server->config.logging, dsr, |
| 53156 | "UA_DataSetReader_handleMessageReceiveTimeout(): " |
| 53157 | "setting pubsub state failed"); |
| 53158 | } |
| 53159 | } |
| 53160 | #endif /* UA_ENABLE_PUBSUB_MONITORING */ |
| 53161 | |
| 53162 | static void |
| 53163 | processMessageWithReader(UA_Server *server, UA_ReaderGroup *readerGroup, |
| 53164 | UA_DataSetReader *reader, UA_NetworkMessage *msg) { |
| 53165 | UA_Byte totalDataSets = 1; |
| 53166 | if(msg->payloadHeaderEnabled) |
| 53167 | totalDataSets = msg->payloadHeader.dataSetPayloadHeader.count; |
| 53168 | |
| 53169 | for(UA_Byte i = 0; i < totalDataSets; i++) { |
| 53170 | /* Map dataset reader to dataset message since multiple dataset reader |
| 53171 | * may read this network message. Otherwise the dataset message may be |
| 53172 | * written to the wrong dataset reader. */ |
| 53173 | if(!msg->payloadHeaderEnabled || |
| 53174 | (reader->config.dataSetWriterId == msg->payloadHeader.dataSetPayloadHeader.dataSetWriterIds[i])) { |
| 53175 | UA_LOG_DEBUG_READER(server->config.logging, reader, |
| 53176 | "Process Msg with DataSetReader!"); |
| 53177 | UA_DataSetReader_process(server, rg: readerGroup, dsr: reader, |
| 53178 | msg: &msg->payload.dataSetPayload.dataSetMessages[i]); |
| 53179 | } |
| 53180 | } |
| 53181 | } |
| 53182 | |
| 53183 | UA_Boolean |
| 53184 | UA_ReaderGroup_process(UA_Server *server, UA_ReaderGroup *readerGroup, |
| 53185 | UA_NetworkMessage *nm) { |
| 53186 | UA_Boolean processed = false; |
| 53187 | UA_DataSetReader *reader; |
| 53188 | |
| 53189 | /* Received a (first) message for the ReaderGroup. |
| 53190 | * Transition from PreOperational to Operational. */ |
| 53191 | if(readerGroup->state == UA_PUBSUBSTATE_PREOPERATIONAL) { |
| 53192 | readerGroup->state = UA_PUBSUBSTATE_OPERATIONAL; |
| 53193 | UA_ServerConfig *config = &server->config; |
| 53194 | if(config->pubSubConfig.stateChangeCallback != 0) { |
| 53195 | config->pubSubConfig.stateChangeCallback(server, &readerGroup->identifier, |
| 53196 | readerGroup->state, UA_STATUSCODE_GOOD); |
| 53197 | } |
| 53198 | } |
| 53199 | LIST_FOREACH(reader, &readerGroup->readers, listEntry) { |
| 53200 | UA_StatusCode res = |
| 53201 | UA_DataSetReader_checkIdentifier(server, msg: nm, reader, readerGroupConfig: readerGroup->config); |
| 53202 | if(res != UA_STATUSCODE_GOOD) |
| 53203 | continue; |
| 53204 | processed = true; |
| 53205 | processMessageWithReader(server, readerGroup, reader, msg: nm); |
| 53206 | } |
| 53207 | return processed; |
| 53208 | } |
| 53209 | |
| 53210 | /******************************************************************************** |
| 53211 | * Functionality related to decoding, decrypting and processing network messages |
| 53212 | * as a subscriber |
| 53213 | ********************************************************************************/ |
| 53214 | |
| 53215 | static UA_StatusCode |
| 53216 | prepareOffsetBuffer(UA_Server *server, UA_DataSetReader *reader, |
| 53217 | UA_ByteString *buf, size_t *pos) { |
| 53218 | UA_NetworkMessage *nm = (UA_NetworkMessage*)UA_calloc(nmemb: 1, size: sizeof(UA_NetworkMessage)); |
| 53219 | if(!nm) |
| 53220 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 53221 | |
| 53222 | /* Decode using the non-rt decoding */ |
| 53223 | UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(src: buf, offset: pos, dst: nm); |
| 53224 | if(rv != UA_STATUSCODE_GOOD) { |
| 53225 | UA_NetworkMessage_clear(p: nm); |
| 53226 | UA_free(ptr: nm); |
| 53227 | return rv; |
| 53228 | } |
| 53229 | rv |= UA_NetworkMessage_decodePayload(src: buf, offset: pos, dst: nm, customTypes: server->config.customDataTypes, dsm: &reader->config.dataSetMetaData); |
| 53230 | rv |= UA_NetworkMessage_decodeFooters(src: buf, offset: pos, dst: nm); |
| 53231 | if(rv != UA_STATUSCODE_GOOD) { |
| 53232 | UA_NetworkMessage_clear(p: nm); |
| 53233 | UA_free(ptr: nm); |
| 53234 | return rv; |
| 53235 | } |
| 53236 | |
| 53237 | /* Compute and store the offsets necessary to decode */ |
| 53238 | size_t nmSize = UA_NetworkMessage_calcSizeBinary(p: nm, offsetBuffer: &reader->bufferedMessage); |
| 53239 | if(nmSize == 0) { |
| 53240 | UA_NetworkMessage_clear(p: nm); |
| 53241 | UA_free(ptr: nm); |
| 53242 | return UA_STATUSCODE_BADINTERNALERROR; |
| 53243 | } |
| 53244 | |
| 53245 | /* Set the offset buffer in the reader */ |
| 53246 | reader->bufferedMessage.nm = nm; |
| 53247 | |
| 53248 | return rv; |
| 53249 | } |
| 53250 | |
| 53251 | /*******************************/ |
| 53252 | /* Realtime Message Processing */ |
| 53253 | /*******************************/ |
| 53254 | |
| 53255 | UA_Boolean |
| 53256 | UA_ReaderGroup_decodeAndProcessRT(UA_Server *server, UA_ReaderGroup *readerGroup, |
| 53257 | UA_ByteString *buf) { |
| 53258 | #ifdef UA_ENABLE_PUBSUB_BUFMALLOC |
| 53259 | useMembufAlloc(); |
| 53260 | #endif |
| 53261 | |
| 53262 | size_t i = 0; |
| 53263 | size_t pos = 0; |
| 53264 | UA_Boolean match = false; |
| 53265 | UA_DataSetReader *dsr; |
| 53266 | UA_STACKARRAY(UA_Boolean, matches, readerGroup->readersCount); |
| 53267 | #ifdef __clang_analyzer__ |
| 53268 | memset(matches, 0, sizeof(UA_Boolean)* readerGroup->readersCount); /* Pacify warning */ |
| 53269 | #endif |
| 53270 | |
| 53271 | /* Decode headers necessary for checking identifier. This can use malloc. |
| 53272 | * So enable membufAlloc if you need RT timings. */ |
| 53273 | UA_NetworkMessage currentNetworkMessage; |
| 53274 | memset(s: ¤tNetworkMessage, c: 0, n: sizeof(UA_NetworkMessage)); |
| 53275 | UA_StatusCode rv = UA_NetworkMessage_decodeHeaders(src: buf, offset: &pos, dst: ¤tNetworkMessage); |
| 53276 | if(rv != UA_STATUSCODE_GOOD) { |
| 53277 | UA_LOG_WARNING_READERGROUP(server->config.logging, readerGroup, |
| 53278 | "PubSub receive. decoding headers failed"); |
| 53279 | goto error; |
| 53280 | } |
| 53281 | |
| 53282 | /* Check if the message is intended for each reader individually */ |
| 53283 | LIST_FOREACH(dsr, &readerGroup->readers, listEntry) { |
| 53284 | rv = UA_DataSetReader_checkIdentifier(server, msg: ¤tNetworkMessage, reader: dsr, readerGroupConfig: readerGroup->config); |
| 53285 | matches[i] = (rv == UA_STATUSCODE_GOOD); |
| 53286 | i++; |
| 53287 | if(rv != UA_STATUSCODE_GOOD) { |
| 53288 | UA_LOG_INFO_READER(server->config.logging, dsr, |
| 53289 | "PubSub receive. Message intended for a different reader."); |
| 53290 | continue; |
| 53291 | } |
| 53292 | match = true; |
| 53293 | } |
| 53294 | if(!match) |
| 53295 | goto error; |
| 53296 | UA_assert(i == readerGroup->readersCount); |
| 53297 | |
| 53298 | /* Decrypt the message once for all readers */ |
| 53299 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 53300 | /* Keep pos to right after the header */ |
| 53301 | rv = verifyAndDecryptNetworkMessage(server->config.logging, buf, &pos, |
| 53302 | ¤tNetworkMessage, readerGroup); |
| 53303 | if(rv != UA_STATUSCODE_GOOD) { |
| 53304 | UA_LOG_WARNING_READERGROUP(server->config.logging, readerGroup, |
| 53305 | "Subscribe failed. verify and decrypt network " |
| 53306 | "message failed."); |
| 53307 | goto error; |
| 53308 | } |
| 53309 | #endif |
| 53310 | |
| 53311 | /* Reset back to the normal malloc before processing the message. |
| 53312 | * Any changes from here may be persisted longer than this. |
| 53313 | * The userland (from callbacks) might rely on that. */ |
| 53314 | UA_NetworkMessage_clear(p: ¤tNetworkMessage); |
| 53315 | #ifdef UA_ENABLE_PUBSUB_BUFMALLOC |
| 53316 | useNormalAlloc(); |
| 53317 | #endif |
| 53318 | |
| 53319 | /* Decode message for every reader. If this fails for one reader, abort overall. */ |
| 53320 | i = 0; |
| 53321 | LIST_FOREACH(dsr, &readerGroup->readers, listEntry) { |
| 53322 | UA_assert(i < readerGroup->readersCount); |
| 53323 | UA_Boolean match = matches[i]; |
| 53324 | i++; |
| 53325 | if(!match) |
| 53326 | continue; |
| 53327 | |
| 53328 | pos = 0; /* reset */ |
| 53329 | if(!dsr->bufferedMessage.nm) { |
| 53330 | /* This is the first message being received for the RT fastpath. |
| 53331 | * Prepare the offset buffer and set operational. */ |
| 53332 | rv = prepareOffsetBuffer(server, reader: dsr, buf, pos: &pos); |
| 53333 | } else { |
| 53334 | /* Decode with offset information and update the networkMessage */ |
| 53335 | rv = UA_NetworkMessage_updateBufferedNwMessage(buffer: &dsr->bufferedMessage, src: buf, bufferPosition: &pos); |
| 53336 | } |
| 53337 | if(rv != UA_STATUSCODE_GOOD) { |
| 53338 | UA_LOG_INFO_READER(server->config.logging, dsr, |
| 53339 | "PubSub decoding failed. Could not decode with " |
| 53340 | "status code %s.", UA_StatusCode_name(rv)); |
| 53341 | return false; |
| 53342 | } else if (readerGroup->state == UA_PUBSUBSTATE_PREOPERATIONAL) { |
| 53343 | /* If pre-operational, set to operational after the first message was |
| 53344 | * processed */ |
| 53345 | readerGroup->state = UA_PUBSUBSTATE_OPERATIONAL; |
| 53346 | UA_ServerConfig *config = &server->config; |
| 53347 | if(config->pubSubConfig.stateChangeCallback != 0) { |
| 53348 | config->pubSubConfig.stateChangeCallback(server, &readerGroup->identifier, |
| 53349 | readerGroup->state, UA_STATUSCODE_GOOD); |
| 53350 | } |
| 53351 | } |
| 53352 | } |
| 53353 | |
| 53354 | /* Process the decoded messages */ |
| 53355 | i = 0; |
| 53356 | LIST_FOREACH(dsr, &readerGroup->readers, listEntry) { |
| 53357 | UA_assert(i < readerGroup->readersCount); |
| 53358 | UA_Boolean match = matches[i]; |
| 53359 | i++; |
| 53360 | if(!match) |
| 53361 | continue; |
| 53362 | UA_DataSetReader_process(server, rg: readerGroup, dsr, |
| 53363 | msg: dsr->bufferedMessage.nm->payload.dataSetPayload.dataSetMessages); |
| 53364 | } |
| 53365 | |
| 53366 | return match; |
| 53367 | |
| 53368 | error: |
| 53369 | UA_NetworkMessage_clear(p: ¤tNetworkMessage); |
| 53370 | #ifdef UA_ENABLE_PUBSUB_BUFMALLOC |
| 53371 | useNormalAlloc(); |
| 53372 | #endif |
| 53373 | return false; |
| 53374 | } |
| 53375 | |
| 53376 | #endif /* UA_ENABLE_PUBSUB */ |
| 53377 | |
| 53378 | /**** amalgamated original file "/src/pubsub/ua_pubsub_readergroup.c" ****/ |
| 53379 | |
| 53380 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 53381 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 53382 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 53383 | * |
| 53384 | * Copyright (c) 2017-2018 Fraunhofer IOSB (Author: Andreas Ebner) |
| 53385 | * Copyright (c) 2019 Fraunhofer IOSB (Author: Julius Pfrommer) |
| 53386 | * Copyright (c) 2019 Kalycito Infotech Private Limited |
| 53387 | * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes) |
| 53388 | * Copyright (c) 2022 Linutronix GmbH (Author: Muddasir Shakil) |
| 53389 | * |
| 53390 | */ |
| 53391 | |
| 53392 | |
| 53393 | #ifdef UA_ENABLE_PUBSUB /* conditional compilation */ |
| 53394 | |
| 53395 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 53396 | #endif |
| 53397 | |
| 53398 | UA_ReaderGroup * |
| 53399 | UA_ReaderGroup_findRGbyId(UA_Server *server, UA_NodeId identifier) { |
| 53400 | UA_PubSubConnection *pubSubConnection; |
| 53401 | TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){ |
| 53402 | UA_ReaderGroup* readerGroup = NULL; |
| 53403 | LIST_FOREACH(readerGroup, &pubSubConnection->readerGroups, listEntry) { |
| 53404 | if(UA_NodeId_equal(p1: &identifier, p2: &readerGroup->identifier)) |
| 53405 | return readerGroup; |
| 53406 | } |
| 53407 | } |
| 53408 | return NULL; |
| 53409 | } |
| 53410 | |
| 53411 | UA_DataSetReader * |
| 53412 | UA_ReaderGroup_findDSRbyId(UA_Server *server, UA_NodeId identifier) { |
| 53413 | UA_PubSubConnection *pubSubConnection; |
| 53414 | TAILQ_FOREACH(pubSubConnection, &server->pubSubManager.connections, listEntry){ |
| 53415 | UA_ReaderGroup* readerGroup = NULL; |
| 53416 | LIST_FOREACH(readerGroup, &pubSubConnection->readerGroups, listEntry) { |
| 53417 | UA_DataSetReader *tmpReader; |
| 53418 | LIST_FOREACH(tmpReader, &readerGroup->readers, listEntry) { |
| 53419 | if(UA_NodeId_equal(p1: &tmpReader->identifier, p2: &identifier)) |
| 53420 | return tmpReader; |
| 53421 | } |
| 53422 | } |
| 53423 | } |
| 53424 | return NULL; |
| 53425 | } |
| 53426 | |
| 53427 | /* ReaderGroup Config Handling */ |
| 53428 | |
| 53429 | UA_StatusCode |
| 53430 | UA_ReaderGroupConfig_copy(const UA_ReaderGroupConfig *src, |
| 53431 | UA_ReaderGroupConfig *dst) { |
| 53432 | memcpy(dest: dst, src: src, n: sizeof(UA_ReaderGroupConfig)); |
| 53433 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 53434 | res |= UA_String_copy(src: &src->name, dst: &dst->name); |
| 53435 | res |= UA_KeyValueMap_copy(src: &src->groupProperties, dst: &dst->groupProperties); |
| 53436 | res |= UA_ExtensionObject_copy(src: &src->transportSettings, dst: &dst->transportSettings); |
| 53437 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 53438 | res = UA_String_copy(&src->securityGroupId, &dst->securityGroupId); |
| 53439 | #endif |
| 53440 | if(res != UA_STATUSCODE_GOOD) |
| 53441 | UA_ReaderGroupConfig_clear(readerGroupConfig: dst); |
| 53442 | return res; |
| 53443 | } |
| 53444 | |
| 53445 | void |
| 53446 | UA_ReaderGroupConfig_clear(UA_ReaderGroupConfig *readerGroupConfig) { |
| 53447 | UA_String_clear(p: &readerGroupConfig->name); |
| 53448 | UA_KeyValueMap_clear(map: &readerGroupConfig->groupProperties); |
| 53449 | UA_ExtensionObject_clear(p: &readerGroupConfig->transportSettings); |
| 53450 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 53451 | UA_String_clear(&readerGroupConfig->securityGroupId); |
| 53452 | #endif |
| 53453 | } |
| 53454 | |
| 53455 | /* ReaderGroup Lifecycle */ |
| 53456 | |
| 53457 | UA_StatusCode |
| 53458 | UA_ReaderGroup_create(UA_Server *server, UA_NodeId connectionId, |
| 53459 | const UA_ReaderGroupConfig *rgc, |
| 53460 | UA_NodeId *readerGroupId) { |
| 53461 | /* Check for valid readergroup configuration */ |
| 53462 | if(!rgc) |
| 53463 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 53464 | |
| 53465 | /* Search the connection by the given connectionIdentifier */ |
| 53466 | UA_PubSubConnection *connection = |
| 53467 | UA_PubSubConnection_findConnectionbyId(server, connectionIdentifier: connectionId); |
| 53468 | if(!connection) |
| 53469 | return UA_STATUSCODE_BADNOTFOUND; |
| 53470 | |
| 53471 | if(connection->configurationFreezeCounter > 0) { |
| 53472 | UA_LOG_WARNING_CONNECTION(server->config.logging, connection, |
| 53473 | "Adding ReaderGroup failed. " |
| 53474 | "Connection configuration is frozen."); |
| 53475 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 53476 | } |
| 53477 | |
| 53478 | /* Allocate memory for new reader group and add settings */ |
| 53479 | UA_ReaderGroup *newGroup = (UA_ReaderGroup *)UA_calloc(nmemb: 1, size: sizeof(UA_ReaderGroup)); |
| 53480 | if(!newGroup) |
| 53481 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 53482 | |
| 53483 | newGroup->componentType = UA_PUBSUB_COMPONENT_READERGROUP; |
| 53484 | |
| 53485 | /* Deep copy of the config */ |
| 53486 | UA_StatusCode retval = UA_ReaderGroupConfig_copy(src: rgc, dst: &newGroup->config); |
| 53487 | if(retval != UA_STATUSCODE_GOOD) { |
| 53488 | UA_free(ptr: newGroup); |
| 53489 | return retval; |
| 53490 | } |
| 53491 | |
| 53492 | newGroup->linkedConnection = connection; |
| 53493 | |
| 53494 | /* Add to the connection */ |
| 53495 | LIST_INSERT_HEAD(&connection->readerGroups, newGroup, listEntry); |
| 53496 | connection->readerGroupsSize++; |
| 53497 | |
| 53498 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 53499 | if(rgc->securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 53500 | rgc->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 53501 | if(!UA_String_isEmpty(&rgc->securityGroupId) && rgc->securityPolicy) { |
| 53502 | /* Does the key storage already exist? */ |
| 53503 | newGroup->keyStorage = |
| 53504 | UA_PubSubKeyStorage_findKeyStorage(server, rgc->securityGroupId); |
| 53505 | |
| 53506 | if(!newGroup->keyStorage) { |
| 53507 | /* Create a new key storage */ |
| 53508 | newGroup->keyStorage = (UA_PubSubKeyStorage *) |
| 53509 | UA_calloc(1, sizeof(UA_PubSubKeyStorage)); |
| 53510 | if(!newGroup->keyStorage) |
| 53511 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 53512 | retval = UA_PubSubKeyStorage_init(server, newGroup->keyStorage, |
| 53513 | &rgc->securityGroupId, |
| 53514 | rgc->securityPolicy, 0, 0); |
| 53515 | if(retval != UA_STATUSCODE_GOOD) { |
| 53516 | UA_ReaderGroupConfig_clear(&newGroup->config); |
| 53517 | UA_free(newGroup); |
| 53518 | return retval; |
| 53519 | } |
| 53520 | } |
| 53521 | |
| 53522 | /* Increase the ref count */ |
| 53523 | newGroup->keyStorage->referenceCount++; |
| 53524 | } |
| 53525 | } |
| 53526 | #endif |
| 53527 | |
| 53528 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 53529 | retval |= addReaderGroupRepresentation(server, readerGroup: newGroup); |
| 53530 | #else |
| 53531 | UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, |
| 53532 | &newGroup->identifier); |
| 53533 | #endif |
| 53534 | |
| 53535 | |
| 53536 | if(readerGroupId) |
| 53537 | UA_NodeId_copy(src: &newGroup->identifier, dst: readerGroupId); |
| 53538 | |
| 53539 | /* Trigger the connection to open a connection */ |
| 53540 | UA_PubSubConnection_setPubSubState(server, c: connection, |
| 53541 | state: connection->state, UA_STATUSCODE_GOOD); |
| 53542 | |
| 53543 | /* If the connection is operational, we still reset the state. We might open |
| 53544 | * a different (recv) connection internally when a readergroup is |
| 53545 | * present. */ |
| 53546 | if(connection->state == UA_PUBSUBSTATE_OPERATIONAL || |
| 53547 | connection->state == UA_PUBSUBSTATE_PREOPERATIONAL) |
| 53548 | UA_PubSubConnection_setPubSubState(server, c: connection, |
| 53549 | state: UA_PUBSUBSTATE_OPERATIONAL, UA_STATUSCODE_GOOD); |
| 53550 | |
| 53551 | return retval; |
| 53552 | } |
| 53553 | |
| 53554 | UA_StatusCode |
| 53555 | UA_Server_addReaderGroup(UA_Server *server, UA_NodeId connectionIdentifier, |
| 53556 | const UA_ReaderGroupConfig *readerGroupConfig, |
| 53557 | UA_NodeId *readerGroupIdentifier) { |
| 53558 | lockServer(server); |
| 53559 | UA_StatusCode res = |
| 53560 | UA_ReaderGroup_create(server, connectionId: connectionIdentifier, |
| 53561 | rgc: readerGroupConfig, readerGroupId: readerGroupIdentifier); |
| 53562 | unlockServer(server); |
| 53563 | return res; |
| 53564 | } |
| 53565 | |
| 53566 | UA_StatusCode |
| 53567 | UA_ReaderGroup_remove(UA_Server *server, UA_ReaderGroup *rg) { |
| 53568 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 53569 | |
| 53570 | if(rg->configurationFrozen) { |
| 53571 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, |
| 53572 | "Remove ReaderGroup failed. " |
| 53573 | "Subscriber configuration is frozen."); |
| 53574 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 53575 | } |
| 53576 | |
| 53577 | UA_PubSubConnection *connection = rg->linkedConnection; |
| 53578 | UA_assert(connection); |
| 53579 | if(connection->configurationFreezeCounter > 0) { |
| 53580 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, |
| 53581 | "Deleting the ReaderGroup failed. " |
| 53582 | "PubSubConnection is frozen."); |
| 53583 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 53584 | } |
| 53585 | |
| 53586 | /* Disable (and disconnect) and set the deleteFlag. This prevents a |
| 53587 | * reconnect and triggers the deletion when the last open socket is |
| 53588 | * closed. */ |
| 53589 | rg->deleteFlag = true; |
| 53590 | UA_ReaderGroup_setPubSubState(server, readerGroup: rg, state: UA_PUBSUBSTATE_DISABLED, UA_STATUSCODE_GOOD); |
| 53591 | |
| 53592 | UA_DataSetReader *dsr, *tmp_dsr; |
| 53593 | LIST_FOREACH_SAFE(dsr, &rg->readers, listEntry, tmp_dsr) { |
| 53594 | UA_DataSetReader_remove(server, dsr); |
| 53595 | } |
| 53596 | |
| 53597 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 53598 | if(rg->config.securityPolicy && rg->securityPolicyContext) { |
| 53599 | rg->config.securityPolicy->deleteContext(rg->securityPolicyContext); |
| 53600 | rg->securityPolicyContext = NULL; |
| 53601 | } |
| 53602 | #endif |
| 53603 | |
| 53604 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 53605 | if(rg->keyStorage) { |
| 53606 | UA_PubSubKeyStorage_detachKeyStorage(server, rg->keyStorage); |
| 53607 | rg->keyStorage = NULL; |
| 53608 | } |
| 53609 | #endif |
| 53610 | |
| 53611 | if(rg->recvChannelsSize == 0) { |
| 53612 | /* Unlink from the connection */ |
| 53613 | LIST_REMOVE(rg, listEntry); |
| 53614 | connection->readerGroupsSize--; |
| 53615 | rg->linkedConnection = NULL; |
| 53616 | |
| 53617 | /* Actually remove the ReaderGroup */ |
| 53618 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 53619 | deleteNode(server, nodeId: rg->identifier, true); |
| 53620 | #endif |
| 53621 | UA_ReaderGroupConfig_clear(readerGroupConfig: &rg->config); |
| 53622 | UA_NodeId_clear(p: &rg->identifier); |
| 53623 | UA_free(ptr: rg); |
| 53624 | } |
| 53625 | |
| 53626 | /* Update the connection state */ |
| 53627 | UA_PubSubConnection_setPubSubState(server, c: connection, state: connection->state, |
| 53628 | UA_STATUSCODE_GOOD); |
| 53629 | |
| 53630 | return UA_STATUSCODE_GOOD; |
| 53631 | } |
| 53632 | |
| 53633 | UA_StatusCode |
| 53634 | UA_Server_removeReaderGroup(UA_Server *server, UA_NodeId groupIdentifier) { |
| 53635 | lockServer(server); |
| 53636 | UA_ReaderGroup* readerGroup = |
| 53637 | UA_ReaderGroup_findRGbyId(server, identifier: groupIdentifier); |
| 53638 | if(!readerGroup) { |
| 53639 | unlockServer(server); |
| 53640 | return UA_STATUSCODE_BADNOTFOUND; |
| 53641 | } |
| 53642 | UA_StatusCode res = UA_ReaderGroup_remove(server, rg: readerGroup); |
| 53643 | unlockServer(server); |
| 53644 | return res; |
| 53645 | } |
| 53646 | |
| 53647 | UA_StatusCode |
| 53648 | UA_Server_ReaderGroup_getConfig(UA_Server *server, UA_NodeId readerGroupIdentifier, |
| 53649 | UA_ReaderGroupConfig *config) { |
| 53650 | if(!config) |
| 53651 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 53652 | |
| 53653 | lockServer(server); |
| 53654 | |
| 53655 | /* Identify the readergroup through the readerGroupIdentifier */ |
| 53656 | UA_ReaderGroup *currentReaderGroup = |
| 53657 | UA_ReaderGroup_findRGbyId(server, identifier: readerGroupIdentifier); |
| 53658 | if(!currentReaderGroup) { |
| 53659 | unlockServer(server); |
| 53660 | return UA_STATUSCODE_BADNOTFOUND; |
| 53661 | } |
| 53662 | |
| 53663 | UA_StatusCode ret = |
| 53664 | UA_ReaderGroupConfig_copy(src: ¤tReaderGroup->config, dst: config); |
| 53665 | |
| 53666 | unlockServer(server); |
| 53667 | return ret; |
| 53668 | } |
| 53669 | |
| 53670 | UA_StatusCode |
| 53671 | UA_Server_ReaderGroup_getState(UA_Server *server, UA_NodeId readerGroupIdentifier, |
| 53672 | UA_PubSubState *state) { |
| 53673 | if((server == NULL) || (state == NULL)) |
| 53674 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 53675 | lockServer(server); |
| 53676 | UA_StatusCode ret = UA_STATUSCODE_BADNOTFOUND; |
| 53677 | UA_ReaderGroup *rg = |
| 53678 | UA_ReaderGroup_findRGbyId(server, identifier: readerGroupIdentifier); |
| 53679 | if(rg) { |
| 53680 | *state = rg->state; |
| 53681 | ret = UA_STATUSCODE_GOOD; |
| 53682 | } |
| 53683 | unlockServer(server); |
| 53684 | return ret; |
| 53685 | } |
| 53686 | |
| 53687 | /* ReaderGroup State */ |
| 53688 | |
| 53689 | static UA_StatusCode |
| 53690 | UA_ReaderGroup_setPubSubState_disable(UA_Server *server, |
| 53691 | UA_ReaderGroup *rg, |
| 53692 | UA_StatusCode cause) { |
| 53693 | /* Disconnect if not already done */ |
| 53694 | UA_ReaderGroup_disconnect(rg); |
| 53695 | |
| 53696 | UA_DataSetReader *dataSetReader; |
| 53697 | switch(rg->state) { |
| 53698 | case UA_PUBSUBSTATE_DISABLED: |
| 53699 | return UA_STATUSCODE_GOOD; |
| 53700 | case UA_PUBSUBSTATE_PAUSED: |
| 53701 | break; |
| 53702 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 53703 | case UA_PUBSUBSTATE_PREOPERATIONAL: |
| 53704 | LIST_FOREACH(dataSetReader, &rg->readers, listEntry) { |
| 53705 | UA_DataSetReader_setPubSubState(server, dataSetReader, |
| 53706 | state: UA_PUBSUBSTATE_DISABLED, cause); |
| 53707 | } |
| 53708 | rg->state = UA_PUBSUBSTATE_DISABLED; |
| 53709 | break; |
| 53710 | case UA_PUBSUBSTATE_ERROR: |
| 53711 | break; |
| 53712 | default: |
| 53713 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, |
| 53714 | "Unknown PubSub state!"); |
| 53715 | return UA_STATUSCODE_BADINTERNALERROR; |
| 53716 | } |
| 53717 | return UA_STATUSCODE_GOOD; |
| 53718 | } |
| 53719 | |
| 53720 | static UA_StatusCode |
| 53721 | UA_ReaderGroup_setPubSubState_paused(UA_Server *server, |
| 53722 | UA_ReaderGroup *rg, |
| 53723 | UA_StatusCode cause) { |
| 53724 | UA_LOG_DEBUG_READERGROUP(server->config.logging, rg, |
| 53725 | "PubSub state paused is unsupported at the moment!"); |
| 53726 | (void)cause; |
| 53727 | switch(rg->state) { |
| 53728 | case UA_PUBSUBSTATE_DISABLED: |
| 53729 | break; |
| 53730 | case UA_PUBSUBSTATE_PAUSED: |
| 53731 | return UA_STATUSCODE_GOOD; |
| 53732 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 53733 | case UA_PUBSUBSTATE_PREOPERATIONAL: |
| 53734 | break; |
| 53735 | case UA_PUBSUBSTATE_ERROR: |
| 53736 | break; |
| 53737 | default: |
| 53738 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, "Unknown PubSub state!"); |
| 53739 | return UA_STATUSCODE_BADINTERNALERROR; |
| 53740 | } |
| 53741 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 53742 | } |
| 53743 | |
| 53744 | static UA_StatusCode |
| 53745 | UA_ReaderGroup_setPubSubState_operational(UA_Server *server, |
| 53746 | UA_ReaderGroup *rg, |
| 53747 | UA_StatusCode cause) { |
| 53748 | UA_PubSubConnection *pubSubConnection = rg->linkedConnection; |
| 53749 | UA_StatusCode ret = |
| 53750 | UA_PubSubConnection_setPubSubState(server, c: pubSubConnection, |
| 53751 | state: UA_PUBSUBSTATE_OPERATIONAL, |
| 53752 | UA_STATUSCODE_GOOD); |
| 53753 | if(ret != UA_STATUSCODE_GOOD || |
| 53754 | (pubSubConnection->state != UA_PUBSUBSTATE_OPERATIONAL && |
| 53755 | pubSubConnection->state != UA_PUBSUBSTATE_PREOPERATIONAL)) { |
| 53756 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, |
| 53757 | "Connection not operational"); |
| 53758 | return UA_STATUSCODE_BADINTERNALERROR; |
| 53759 | } |
| 53760 | |
| 53761 | /* Connect if the ReaderGroup has dedicated connections */ |
| 53762 | if(rg->recvChannelsSize == 0) |
| 53763 | ret = UA_ReaderGroup_connect(server, rg, false); |
| 53764 | if(ret != UA_STATUSCODE_GOOD) { |
| 53765 | UA_LOG_ERROR_READERGROUP(server->config.logging, rg, "Could not connect"); |
| 53766 | UA_PubSubConnection_setPubSubState(server, c: pubSubConnection, |
| 53767 | state: UA_PUBSUBSTATE_ERROR, cause: ret); |
| 53768 | } |
| 53769 | |
| 53770 | /* Set to preoperational until the first message was received */ |
| 53771 | if(rg->state != UA_PUBSUBSTATE_OPERATIONAL) |
| 53772 | rg->state = UA_PUBSUBSTATE_PREOPERATIONAL; |
| 53773 | |
| 53774 | /* Set all readers operational */ |
| 53775 | UA_DataSetReader *dsr; |
| 53776 | LIST_FOREACH(dsr, &rg->readers, listEntry) { |
| 53777 | UA_DataSetReader_setPubSubState(server, dataSetReader: dsr, |
| 53778 | state: UA_PUBSUBSTATE_OPERATIONAL, cause); |
| 53779 | } |
| 53780 | |
| 53781 | return UA_STATUSCODE_GOOD; |
| 53782 | } |
| 53783 | |
| 53784 | static UA_StatusCode |
| 53785 | UA_ReaderGroup_setPubSubState_error(UA_Server *server, |
| 53786 | UA_ReaderGroup *rg, |
| 53787 | UA_StatusCode cause) { |
| 53788 | UA_DataSetReader *dataSetReader; |
| 53789 | switch(rg->state) { |
| 53790 | case UA_PUBSUBSTATE_DISABLED: |
| 53791 | break; |
| 53792 | case UA_PUBSUBSTATE_PAUSED: |
| 53793 | break; |
| 53794 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 53795 | case UA_PUBSUBSTATE_PREOPERATIONAL: |
| 53796 | LIST_FOREACH(dataSetReader, &rg->readers, listEntry){ |
| 53797 | UA_DataSetReader_setPubSubState(server, dataSetReader, state: UA_PUBSUBSTATE_ERROR, |
| 53798 | cause); |
| 53799 | } |
| 53800 | break; |
| 53801 | case UA_PUBSUBSTATE_ERROR: |
| 53802 | return UA_STATUSCODE_GOOD; |
| 53803 | default: |
| 53804 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, "Unknown PubSub state!"); |
| 53805 | return UA_STATUSCODE_BADINTERNALERROR; |
| 53806 | } |
| 53807 | rg->state = UA_PUBSUBSTATE_ERROR; |
| 53808 | return UA_STATUSCODE_GOOD; |
| 53809 | } |
| 53810 | |
| 53811 | UA_StatusCode |
| 53812 | UA_ReaderGroup_setPubSubState(UA_Server *server, |
| 53813 | UA_ReaderGroup *readerGroup, |
| 53814 | UA_PubSubState state, |
| 53815 | UA_StatusCode cause) { |
| 53816 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 53817 | |
| 53818 | if(readerGroup->deleteFlag && state != UA_PUBSUBSTATE_DISABLED) { |
| 53819 | UA_LOG_WARNING_READERGROUP(server->config.logging, readerGroup, |
| 53820 | "The ReaderGroup is being deleted. Can only be disabled."); |
| 53821 | return UA_STATUSCODE_BADINTERNALERROR; |
| 53822 | } |
| 53823 | |
| 53824 | UA_StatusCode ret = UA_STATUSCODE_BADINVALIDARGUMENT; |
| 53825 | UA_PubSubState oldState = readerGroup->state; |
| 53826 | switch(state) { |
| 53827 | case UA_PUBSUBSTATE_DISABLED: |
| 53828 | ret = UA_ReaderGroup_setPubSubState_disable(server, rg: readerGroup, cause); |
| 53829 | break; |
| 53830 | case UA_PUBSUBSTATE_PAUSED: |
| 53831 | ret = UA_ReaderGroup_setPubSubState_paused(server, rg: readerGroup, cause); |
| 53832 | break; |
| 53833 | case UA_PUBSUBSTATE_OPERATIONAL: |
| 53834 | ret = UA_ReaderGroup_setPubSubState_operational(server, rg: readerGroup, cause); |
| 53835 | break; |
| 53836 | case UA_PUBSUBSTATE_ERROR: |
| 53837 | ret = UA_ReaderGroup_setPubSubState_error(server, rg: readerGroup, cause); |
| 53838 | break; |
| 53839 | default: |
| 53840 | UA_LOG_WARNING_READERGROUP(server->config.logging, readerGroup, |
| 53841 | "Received unknown PubSub state!"); |
| 53842 | break; |
| 53843 | } |
| 53844 | |
| 53845 | /* inform application about state change */ |
| 53846 | if(readerGroup->state != oldState) { |
| 53847 | UA_ServerConfig *pConfig = &server->config; |
| 53848 | if(pConfig->pubSubConfig.stateChangeCallback != 0) { |
| 53849 | pConfig->pubSubConfig. |
| 53850 | stateChangeCallback(server, &readerGroup->identifier, |
| 53851 | readerGroup->state, cause); |
| 53852 | } |
| 53853 | } |
| 53854 | return ret; |
| 53855 | } |
| 53856 | |
| 53857 | UA_StatusCode |
| 53858 | UA_Server_setReaderGroupOperational(UA_Server *server, |
| 53859 | const UA_NodeId readerGroupId) { |
| 53860 | lockServer(server); |
| 53861 | UA_StatusCode ret = UA_STATUSCODE_BADNOTFOUND; |
| 53862 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, identifier: readerGroupId); |
| 53863 | if(rg) { |
| 53864 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 53865 | if(rg->keyStorage && rg->keyStorage->currentItem) { |
| 53866 | UA_StatusCode retval = UA_PubSubKeyStorage_activateKeyToChannelContext( |
| 53867 | server, rg->identifier, rg->config.securityGroupId); |
| 53868 | if(retval != UA_STATUSCODE_GOOD) { |
| 53869 | unlockServer(server); |
| 53870 | return retval; |
| 53871 | } |
| 53872 | } |
| 53873 | #endif |
| 53874 | ret = UA_ReaderGroup_setPubSubState(server, readerGroup: rg, state: UA_PUBSUBSTATE_OPERATIONAL, |
| 53875 | UA_STATUSCODE_GOOD); |
| 53876 | } |
| 53877 | unlockServer(server); |
| 53878 | return ret; |
| 53879 | } |
| 53880 | |
| 53881 | UA_StatusCode |
| 53882 | UA_Server_setReaderGroupDisabled(UA_Server *server, |
| 53883 | const UA_NodeId readerGroupId) { |
| 53884 | lockServer(server); |
| 53885 | UA_StatusCode ret = UA_STATUSCODE_BADNOTFOUND; |
| 53886 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, identifier: readerGroupId); |
| 53887 | if(rg) |
| 53888 | ret = UA_ReaderGroup_setPubSubState(server, readerGroup: rg, state: UA_PUBSUBSTATE_DISABLED, |
| 53889 | UA_STATUSCODE_BADRESOURCEUNAVAILABLE); |
| 53890 | unlockServer(server); |
| 53891 | return ret; |
| 53892 | } |
| 53893 | |
| 53894 | #ifdef UA_ENABLE_PUBSUB_ENCRYPTION |
| 53895 | UA_StatusCode |
| 53896 | setReaderGroupEncryptionKeys(UA_Server *server, const UA_NodeId readerGroup, |
| 53897 | UA_UInt32 securityTokenId, |
| 53898 | const UA_ByteString signingKey, |
| 53899 | const UA_ByteString encryptingKey, |
| 53900 | const UA_ByteString keyNonce) { |
| 53901 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroup); |
| 53902 | UA_CHECK_MEM(rg, return UA_STATUSCODE_BADNOTFOUND); |
| 53903 | if(rg->config.encodingMimeType == UA_PUBSUB_ENCODING_JSON) { |
| 53904 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, |
| 53905 | "JSON encoding is enabled. The message security is " |
| 53906 | "only defined for the UADP message mapping."); |
| 53907 | return UA_STATUSCODE_BADINTERNALERROR; |
| 53908 | } |
| 53909 | if(!rg->config.securityPolicy) { |
| 53910 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, |
| 53911 | "No SecurityPolicy configured for the ReaderGroup"); |
| 53912 | return UA_STATUSCODE_BADINTERNALERROR; |
| 53913 | } |
| 53914 | |
| 53915 | if(securityTokenId != rg->securityTokenId) { |
| 53916 | rg->securityTokenId = securityTokenId; |
| 53917 | rg->nonceSequenceNumber = 1; |
| 53918 | } |
| 53919 | |
| 53920 | /* Create a new context */ |
| 53921 | if(!rg->securityPolicyContext) { |
| 53922 | return rg->config.securityPolicy-> |
| 53923 | newContext(rg->config.securityPolicy->policyContext, |
| 53924 | &signingKey, &encryptingKey, &keyNonce, |
| 53925 | &rg->securityPolicyContext); |
| 53926 | } |
| 53927 | |
| 53928 | /* Update the context */ |
| 53929 | return rg->config.securityPolicy-> |
| 53930 | setSecurityKeys(rg->securityPolicyContext, &signingKey, |
| 53931 | &encryptingKey, &keyNonce); |
| 53932 | } |
| 53933 | |
| 53934 | UA_StatusCode |
| 53935 | UA_Server_setReaderGroupEncryptionKeys(UA_Server *server, |
| 53936 | const UA_NodeId readerGroup, |
| 53937 | UA_UInt32 securityTokenId, |
| 53938 | const UA_ByteString signingKey, |
| 53939 | const UA_ByteString encryptingKey, |
| 53940 | const UA_ByteString keyNonce) { |
| 53941 | lockServer(server); |
| 53942 | UA_StatusCode res = setReaderGroupEncryptionKeys(server, readerGroup, |
| 53943 | securityTokenId, signingKey, |
| 53944 | encryptingKey, keyNonce); |
| 53945 | unlockServer(server); |
| 53946 | return res; |
| 53947 | } |
| 53948 | #endif |
| 53949 | |
| 53950 | /* Freezing of the configuration */ |
| 53951 | |
| 53952 | UA_StatusCode |
| 53953 | UA_ReaderGroup_freezeConfiguration(UA_Server *server, UA_ReaderGroup *rg) { |
| 53954 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 53955 | if(rg->configurationFrozen) |
| 53956 | return UA_STATUSCODE_GOOD; |
| 53957 | |
| 53958 | /* PubSubConnection freezeCounter++ */ |
| 53959 | UA_PubSubConnection *pubSubConnection = rg->linkedConnection; |
| 53960 | pubSubConnection->configurationFreezeCounter++; |
| 53961 | |
| 53962 | /* ReaderGroup freeze */ |
| 53963 | /* TODO: Clarify on the freeze functionality in multiple DSR, multiple |
| 53964 | * networkMessage conf in a RG */ |
| 53965 | rg->configurationFrozen = true; |
| 53966 | |
| 53967 | /* DataSetReader freeze */ |
| 53968 | UA_DataSetReader *dsr; |
| 53969 | UA_UInt16 dsrCount = 0; |
| 53970 | LIST_FOREACH(dsr, &rg->readers, listEntry){ |
| 53971 | dsr->configurationFrozen = true; |
| 53972 | dsrCount++; |
| 53973 | /* TODO: Configuration frozen for subscribedDataSet once |
| 53974 | * UA_Server_DataSetReader_addTargetVariables API modified to support |
| 53975 | * adding target variable one by one or in a group stored in a list. */ |
| 53976 | } |
| 53977 | |
| 53978 | /* Not rt, we don't have to adjust anything */ |
| 53979 | if((rg->config.rtLevel & UA_PUBSUB_RT_FIXED_SIZE) == 0) |
| 53980 | return UA_STATUSCODE_GOOD; |
| 53981 | |
| 53982 | if(dsrCount > 1) { |
| 53983 | UA_LOG_WARNING_READERGROUP(server->config.logging, rg, |
| 53984 | "Multiple DSR in a readerGroup not supported in RT " |
| 53985 | "fixed size configuration"); |
| 53986 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 53987 | } |
| 53988 | |
| 53989 | dsr = LIST_FIRST(&rg->readers); |
| 53990 | |
| 53991 | /* Support only to UADP encoding */ |
| 53992 | if(dsr->config.messageSettings.content.decoded.type != |
| 53993 | &UA_TYPES[UA_TYPES_UADPDATASETREADERMESSAGEDATATYPE]) { |
| 53994 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 53995 | "PubSub-RT configuration fail: Non-RT capable encoding."); |
| 53996 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 53997 | } |
| 53998 | |
| 53999 | /* Don't support string PublisherId for the fast-path (at this time) */ |
| 54000 | if(!dsr->config.publisherId.type->pointerFree) { |
| 54001 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 54002 | "PubSub-RT configuration fail: String PublisherId"); |
| 54003 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 54004 | } |
| 54005 | |
| 54006 | size_t fieldsSize = dsr->config.dataSetMetaData.fieldsSize; |
| 54007 | for(size_t i = 0; i < fieldsSize; i++) { |
| 54008 | /* TODO: Use the datasource from the node */ |
| 54009 | /* UA_FieldTargetVariable *tv = */ |
| 54010 | /* &dsr->config.subscribedDataSet.subscribedDataSetTarget.targetVariables[i]; */ |
| 54011 | /* const UA_VariableNode *rtNode = (const UA_VariableNode *) */ |
| 54012 | /* UA_NODESTORE_GET(server, &tv->targetVariable.targetNodeId); */ |
| 54013 | /* if(!rtNode || */ |
| 54014 | /* rtNode->valueBackend.backendType != UA_VALUEBACKENDTYPE_EXTERNAL) { */ |
| 54015 | /* UA_LOG_WARNING_READER(server->config.logging, dsr, */ |
| 54016 | /* "PubSub-RT configuration fail: PDS contains field " */ |
| 54017 | /* "without external data source."); */ |
| 54018 | /* UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode); */ |
| 54019 | /* return UA_STATUSCODE_BADNOTSUPPORTED; */ |
| 54020 | /* } */ |
| 54021 | |
| 54022 | /* /\* Set the external data source in the tv *\/ */ |
| 54023 | /* tv->externalDataValue = rtNode->valueBackend.backend.external.value; */ |
| 54024 | |
| 54025 | /* UA_NODESTORE_RELEASE(server, (const UA_Node *) rtNode); */ |
| 54026 | |
| 54027 | UA_FieldMetaData *field = &dsr->config.dataSetMetaData.fields[i]; |
| 54028 | if((UA_NodeId_equal(p1: &field->dataType, p2: &UA_TYPES[UA_TYPES_STRING].typeId) || |
| 54029 | UA_NodeId_equal(p1: &field->dataType, p2: &UA_TYPES[UA_TYPES_BYTESTRING].typeId)) && |
| 54030 | field->maxStringLength == 0) { |
| 54031 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 54032 | "PubSub-RT configuration fail: " |
| 54033 | "PDS contains String/ByteString with dynamic length."); |
| 54034 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 54035 | } else if(!UA_DataType_isNumeric(type: UA_findDataType(typeId: &field->dataType)) && |
| 54036 | !UA_NodeId_equal(p1: &field->dataType, p2: &UA_TYPES[UA_TYPES_BOOLEAN].typeId)) { |
| 54037 | UA_LOG_WARNING_READER(server->config.logging, dsr, |
| 54038 | "PubSub-RT configuration fail: " |
| 54039 | "PDS contains variable with dynamic size."); |
| 54040 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 54041 | } |
| 54042 | } |
| 54043 | |
| 54044 | /* Reset the OffsetBuffer. The OffsetBuffer for a frozen configuration is |
| 54045 | * generated when the first message is received. So we know the exact |
| 54046 | * settings which headers are present, etc. Until then the ReaderGroup is |
| 54047 | * "PreOperational". */ |
| 54048 | UA_NetworkMessageOffsetBuffer_clear(nmob: &dsr->bufferedMessage); |
| 54049 | |
| 54050 | /* Set the current state again. This can move the state from Operational to |
| 54051 | * PreOperational. */ |
| 54052 | return UA_ReaderGroup_setPubSubState(server, readerGroup: rg, state: rg->state, UA_STATUSCODE_GOOD); |
| 54053 | } |
| 54054 | |
| 54055 | UA_StatusCode |
| 54056 | UA_Server_freezeReaderGroupConfiguration(UA_Server *server, |
| 54057 | const UA_NodeId readerGroupId) { |
| 54058 | lockServer(server); |
| 54059 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, identifier: readerGroupId); |
| 54060 | if(!rg) { |
| 54061 | unlockServer(server); |
| 54062 | return UA_STATUSCODE_BADNOTFOUND; |
| 54063 | } |
| 54064 | UA_StatusCode res = UA_ReaderGroup_freezeConfiguration(server, rg); |
| 54065 | unlockServer(server); |
| 54066 | return res; |
| 54067 | } |
| 54068 | |
| 54069 | UA_StatusCode |
| 54070 | UA_ReaderGroup_unfreezeConfiguration(UA_Server *server, UA_ReaderGroup *rg) { |
| 54071 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 54072 | |
| 54073 | /* Already unfrozen */ |
| 54074 | if(!rg->configurationFrozen) |
| 54075 | return UA_STATUSCODE_GOOD; |
| 54076 | |
| 54077 | /* PubSubConnection freezeCounter-- */ |
| 54078 | UA_PubSubConnection *pubSubConnection = rg->linkedConnection; |
| 54079 | pubSubConnection->configurationFreezeCounter--; |
| 54080 | |
| 54081 | /* ReaderGroup unfreeze */ |
| 54082 | rg->configurationFrozen = false; |
| 54083 | |
| 54084 | /* DataSetReader unfreeze */ |
| 54085 | UA_DataSetReader *dataSetReader; |
| 54086 | LIST_FOREACH(dataSetReader, &rg->readers, listEntry) { |
| 54087 | dataSetReader->configurationFrozen = false; |
| 54088 | UA_NetworkMessageOffsetBuffer_clear(nmob: &dataSetReader->bufferedMessage); |
| 54089 | } |
| 54090 | |
| 54091 | return UA_STATUSCODE_GOOD; |
| 54092 | } |
| 54093 | |
| 54094 | UA_StatusCode |
| 54095 | UA_Server_unfreezeReaderGroupConfiguration(UA_Server *server, |
| 54096 | const UA_NodeId readerGroupId) { |
| 54097 | lockServer(server); |
| 54098 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, identifier: readerGroupId); |
| 54099 | if(!rg) { |
| 54100 | unlockServer(server); |
| 54101 | return UA_STATUSCODE_BADNOTFOUND; |
| 54102 | } |
| 54103 | UA_StatusCode res = UA_ReaderGroup_unfreezeConfiguration(server, rg); |
| 54104 | unlockServer(server); |
| 54105 | return res; |
| 54106 | } |
| 54107 | |
| 54108 | #endif /* UA_ENABLE_PUBSUB */ |
| 54109 | |
| 54110 | /**** amalgamated original file "/src/pubsub/ua_pubsub_manager.c" ****/ |
| 54111 | |
| 54112 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 54113 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 54114 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 54115 | * |
| 54116 | * Copyright (c) 2017-2022 Fraunhofer IOSB (Author: Andreas Ebner) |
| 54117 | * Copyright (c) 2018 Fraunhofer IOSB (Author: Julius Pfrommer) |
| 54118 | * Copyright (c) 2021 Fraunhofer IOSB (Author: Jan Hermes) |
| 54119 | * Copyright (c) 2022 Siemens AG (Author: Thomas Fischer) |
| 54120 | * Copyright (c) 2022 Fraunhofer IOSB (Author: Noel Graf) |
| 54121 | * Copyright (c) 2022 Linutronix GmbH (Author: Muddasir Shakil) |
| 54122 | */ |
| 54123 | |
| 54124 | |
| 54125 | #ifdef UA_ENABLE_PUBSUB /* conditional compilation */ |
| 54126 | |
| 54127 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 54128 | #endif |
| 54129 | |
| 54130 | #define UA_DATETIMESTAMP_2000 125911584000000000 |
| 54131 | #define UA_RESERVEID_FIRST_ID 0x8000 |
| 54132 | |
| 54133 | static void |
| 54134 | UA_PubSubManager_addTopic(UA_PubSubManager *pubSubManager, UA_TopicAssign *topicAssign) { |
| 54135 | TAILQ_INSERT_TAIL(&pubSubManager->topicAssign, topicAssign, listEntry); |
| 54136 | pubSubManager->topicAssignSize++; |
| 54137 | } |
| 54138 | |
| 54139 | static UA_TopicAssign * |
| 54140 | UA_TopicAssign_new(UA_ReaderGroup *readerGroup, |
| 54141 | UA_String topic, const UA_Logger *logger) { |
| 54142 | UA_TopicAssign *topicAssign = (UA_TopicAssign *) |
| 54143 | UA_calloc(nmemb: 1, size: sizeof(UA_TopicAssign)); |
| 54144 | if(!topicAssign) { |
| 54145 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SERVER, |
| 54146 | msg: "PubSub TopicAssign creation failed. Out of Memory."); |
| 54147 | return NULL; |
| 54148 | } |
| 54149 | topicAssign->rgIdentifier = readerGroup; |
| 54150 | topicAssign->topic = topic; |
| 54151 | return topicAssign; |
| 54152 | } |
| 54153 | |
| 54154 | UA_StatusCode |
| 54155 | UA_PubSubManager_addPubSubTopicAssign(UA_Server *server, UA_ReaderGroup *readerGroup, UA_String topic) { |
| 54156 | UA_PubSubManager *pubSubManager = &server->pubSubManager; |
| 54157 | UA_TopicAssign *topicAssign = UA_TopicAssign_new(readerGroup, topic, logger: server->config.logging); |
| 54158 | UA_PubSubManager_addTopic(pubSubManager, topicAssign); |
| 54159 | return UA_STATUSCODE_GOOD; |
| 54160 | } |
| 54161 | |
| 54162 | static enum ZIP_CMP |
| 54163 | cmpReserveId(const void *a, const void *b) { |
| 54164 | const UA_ReserveId *aa = (const UA_ReserveId*)a; |
| 54165 | const UA_ReserveId *bb = (const UA_ReserveId*)b; |
| 54166 | if(aa->id != bb->id) |
| 54167 | return (aa->id < bb->id) ? ZIP_CMP_LESS : ZIP_CMP_MORE; |
| 54168 | if(aa->reserveIdType != bb->reserveIdType) |
| 54169 | return (aa->reserveIdType < bb->reserveIdType) ? ZIP_CMP_LESS : ZIP_CMP_MORE; |
| 54170 | return (enum ZIP_CMP)UA_order(p1: &aa->transportProfileUri, |
| 54171 | p2: &bb->transportProfileUri, type: &UA_TYPES[UA_TYPES_STRING]); |
| 54172 | } |
| 54173 | |
| 54174 | ZIP_FUNCTIONS(UA_ReserveIdTree, UA_ReserveId, treeEntry, UA_ReserveId, id, cmpReserveId) |
| 54175 | |
| 54176 | static UA_ReserveId * |
| 54177 | UA_ReserveId_new(UA_Server *server, UA_UInt16 id, UA_String transportProfileUri, |
| 54178 | UA_ReserveIdType reserveIdType, UA_NodeId sessionId) { |
| 54179 | UA_ReserveId *reserveId = (UA_ReserveId *) |
| 54180 | UA_calloc(nmemb: 1, size: sizeof(UA_ReserveId)); |
| 54181 | if(!reserveId) { |
| 54182 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54183 | msg: "PubSub ReserveId creation failed. Out of Memory."); |
| 54184 | return NULL; |
| 54185 | } |
| 54186 | reserveId->id = id; |
| 54187 | reserveId->reserveIdType = reserveIdType; |
| 54188 | UA_String_copy(src: &transportProfileUri, dst: &reserveId->transportProfileUri); |
| 54189 | reserveId->sessionId = sessionId; |
| 54190 | |
| 54191 | return reserveId; |
| 54192 | } |
| 54193 | |
| 54194 | static UA_Boolean |
| 54195 | UA_ReserveId_isFree(UA_Server *server, UA_UInt16 id, |
| 54196 | UA_String transportProfileUri, UA_ReserveIdType reserveIdType) { |
| 54197 | UA_PubSubManager *pubSubManager = &server->pubSubManager; |
| 54198 | |
| 54199 | /* Is the id already in use? */ |
| 54200 | UA_ReserveId compare; |
| 54201 | compare.id = id; |
| 54202 | compare.reserveIdType = reserveIdType; |
| 54203 | compare.transportProfileUri = transportProfileUri; |
| 54204 | if(ZIP_FIND(UA_ReserveIdTree, &pubSubManager->reserveIds, &compare)) |
| 54205 | return false; |
| 54206 | |
| 54207 | UA_PubSubConnection *tmpConnection; |
| 54208 | TAILQ_FOREACH(tmpConnection, &server->pubSubManager.connections, listEntry) { |
| 54209 | UA_WriterGroup *writerGroup; |
| 54210 | LIST_FOREACH(writerGroup, &tmpConnection->writerGroups, listEntry) { |
| 54211 | if(reserveIdType == UA_WRITER_GROUP) { |
| 54212 | if(UA_String_equal(p1: &tmpConnection->config.transportProfileUri, |
| 54213 | p2: &transportProfileUri) && |
| 54214 | writerGroup->config.writerGroupId == id) |
| 54215 | return false; |
| 54216 | /* reserveIdType == UA_DATA_SET_WRITER */ |
| 54217 | } else { |
| 54218 | UA_DataSetWriter *currentWriter; |
| 54219 | LIST_FOREACH(currentWriter, &writerGroup->writers, listEntry) { |
| 54220 | if(UA_String_equal(p1: &tmpConnection->config.transportProfileUri, |
| 54221 | p2: &transportProfileUri) && |
| 54222 | currentWriter->config.dataSetWriterId == id) |
| 54223 | return false; |
| 54224 | } |
| 54225 | } |
| 54226 | } |
| 54227 | } |
| 54228 | return true; |
| 54229 | } |
| 54230 | |
| 54231 | static UA_UInt16 |
| 54232 | UA_ReserveId_createId(UA_Server *server, UA_NodeId sessionId, |
| 54233 | UA_String transportProfileUri, UA_ReserveIdType reserveIdType) { |
| 54234 | /* Total number of possible Ids */ |
| 54235 | UA_UInt16 numberOfIds = 0x8000; |
| 54236 | /* Contains next possible free Id */ |
| 54237 | static UA_UInt16 next_id_writerGroup = UA_RESERVEID_FIRST_ID; |
| 54238 | static UA_UInt16 next_id_writer = UA_RESERVEID_FIRST_ID; |
| 54239 | UA_UInt16 next_id; |
| 54240 | UA_Boolean is_free = false; |
| 54241 | |
| 54242 | if(reserveIdType == UA_WRITER_GROUP) |
| 54243 | next_id = next_id_writerGroup; |
| 54244 | else |
| 54245 | next_id = next_id_writer; |
| 54246 | |
| 54247 | for(;numberOfIds > 0;numberOfIds--) { |
| 54248 | if(next_id < UA_RESERVEID_FIRST_ID) |
| 54249 | next_id = UA_RESERVEID_FIRST_ID; |
| 54250 | is_free = UA_ReserveId_isFree(server, id: next_id, transportProfileUri, reserveIdType); |
| 54251 | if(is_free) |
| 54252 | break; |
| 54253 | next_id++; |
| 54254 | } |
| 54255 | if(!is_free) { |
| 54256 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54257 | msg: "PubSub ReserveId creation failed. No free ID could be found."); |
| 54258 | return 0; |
| 54259 | } |
| 54260 | |
| 54261 | if(reserveIdType == UA_WRITER_GROUP) |
| 54262 | next_id_writerGroup = (UA_UInt16)(next_id + 1); |
| 54263 | else |
| 54264 | next_id_writer = (UA_UInt16)(next_id + 1); |
| 54265 | |
| 54266 | UA_ReserveId *reserveId = |
| 54267 | UA_ReserveId_new(server, id: next_id, transportProfileUri, reserveIdType, sessionId); |
| 54268 | if(!reserveId) |
| 54269 | return 0; |
| 54270 | UA_PubSubManager *pubSubManager = &server->pubSubManager; |
| 54271 | ZIP_INSERT(UA_ReserveIdTree, &pubSubManager->reserveIds, reserveId); |
| 54272 | pubSubManager->reserveIdsSize++; |
| 54273 | return next_id; |
| 54274 | } |
| 54275 | |
| 54276 | static void * |
| 54277 | removeReserveId(void *context, UA_ReserveId *elem) { |
| 54278 | UA_String_clear(p: &elem->transportProfileUri); |
| 54279 | UA_free(ptr: elem); |
| 54280 | return NULL; |
| 54281 | } |
| 54282 | |
| 54283 | struct RemoveInactiveReserveIdContext { |
| 54284 | UA_Server *server; |
| 54285 | UA_ReserveIdTree newTree; |
| 54286 | }; |
| 54287 | |
| 54288 | /* Remove ReserveIds that are not attached to any session */ |
| 54289 | static void * |
| 54290 | removeInactiveReserveId(void *context, UA_ReserveId *elem) { |
| 54291 | struct RemoveInactiveReserveIdContext *ctx = |
| 54292 | (struct RemoveInactiveReserveIdContext*)context; |
| 54293 | |
| 54294 | if(UA_NodeId_equal(p1: &ctx->server->adminSession.sessionId, p2: &elem->sessionId)) |
| 54295 | goto still_active; |
| 54296 | |
| 54297 | session_list_entry *session; |
| 54298 | LIST_FOREACH(session, &ctx->server->sessions, pointers) { |
| 54299 | if(UA_NodeId_equal(p1: &session->session.sessionId, p2: &elem->sessionId)) |
| 54300 | goto still_active; |
| 54301 | } |
| 54302 | |
| 54303 | ctx->server->pubSubManager.reserveIdsSize--; |
| 54304 | UA_String_clear(p: &elem->transportProfileUri); |
| 54305 | UA_free(ptr: elem); |
| 54306 | return NULL; |
| 54307 | |
| 54308 | still_active: |
| 54309 | ZIP_INSERT(UA_ReserveIdTree, &ctx->newTree, elem); |
| 54310 | return NULL; |
| 54311 | } |
| 54312 | |
| 54313 | void |
| 54314 | UA_PubSubManager_freeIds(UA_Server *server) { |
| 54315 | struct RemoveInactiveReserveIdContext removeCtx; |
| 54316 | removeCtx.server = server; |
| 54317 | removeCtx.newTree.root = NULL; |
| 54318 | ZIP_ITER(UA_ReserveIdTree, &server->pubSubManager.reserveIds, |
| 54319 | removeInactiveReserveId, &removeCtx); |
| 54320 | server->pubSubManager.reserveIds = removeCtx.newTree; |
| 54321 | } |
| 54322 | |
| 54323 | UA_StatusCode |
| 54324 | UA_PubSubManager_reserveIds(UA_Server *server, UA_NodeId sessionId, UA_UInt16 numRegWriterGroupIds, |
| 54325 | UA_UInt16 numRegDataSetWriterIds, UA_String transportProfileUri, |
| 54326 | UA_UInt16 **writerGroupIds, UA_UInt16 **dataSetWriterIds) { |
| 54327 | UA_PubSubManager_freeIds(server); |
| 54328 | |
| 54329 | /* Check the validation of the transportProfileUri */ |
| 54330 | UA_String profile_1 = UA_STRING(chars: "http://opcfoundation.org/UA-Profile/Transport/pubsub-mqtt-uadp"); |
| 54331 | UA_String profile_2 = UA_STRING(chars: "http://opcfoundation.org/UA-Profile/Transport/pubsub-mqtt-json"); |
| 54332 | UA_String profile_3 = UA_STRING(chars: "http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); |
| 54333 | if(!UA_String_equal(p1: &transportProfileUri, p2: &profile_1) && |
| 54334 | !UA_String_equal(p1: &transportProfileUri, p2: &profile_2) && |
| 54335 | !UA_String_equal(p1: &transportProfileUri, p2: &profile_3)) { |
| 54336 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54337 | msg: "PubSub ReserveId creation failed. No valid transport profile uri."); |
| 54338 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 54339 | } |
| 54340 | *writerGroupIds = (UA_UInt16*)UA_Array_new(size: numRegWriterGroupIds, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 54341 | *dataSetWriterIds = (UA_UInt16*)UA_Array_new(size: numRegDataSetWriterIds, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 54342 | |
| 54343 | for(int i = 0; i < numRegWriterGroupIds; i++) { |
| 54344 | (*writerGroupIds)[i] = |
| 54345 | UA_ReserveId_createId(server, sessionId, transportProfileUri, reserveIdType: UA_WRITER_GROUP); |
| 54346 | } |
| 54347 | for(int i = 0; i < numRegDataSetWriterIds; i++) { |
| 54348 | (*dataSetWriterIds)[i] = |
| 54349 | UA_ReserveId_createId(server, sessionId, transportProfileUri, reserveIdType: UA_DATA_SET_WRITER); |
| 54350 | } |
| 54351 | return UA_STATUSCODE_GOOD; |
| 54352 | } |
| 54353 | |
| 54354 | /* Calculate the time difference between current time and UTC (00:00) on January |
| 54355 | * 1, 2000. */ |
| 54356 | UA_UInt32 |
| 54357 | UA_PubSubConfigurationVersionTimeDifference(void) { |
| 54358 | UA_UInt32 timeDiffSince2000 = (UA_UInt32) (UA_DateTime_now() - UA_DATETIMESTAMP_2000); |
| 54359 | return timeDiffSince2000; |
| 54360 | } |
| 54361 | |
| 54362 | static UA_StatusCode |
| 54363 | addStandaloneSubscribedDataSet(UA_Server *server, |
| 54364 | const UA_StandaloneSubscribedDataSetConfig *sdsConfig, |
| 54365 | UA_NodeId *sdsIdentifier) { |
| 54366 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 54367 | |
| 54368 | if(!sdsConfig){ |
| 54369 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54370 | msg: "SubscribedDataSet creation failed. No config passed in."); |
| 54371 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 54372 | } |
| 54373 | |
| 54374 | UA_StandaloneSubscribedDataSetConfig tmpSubscribedDataSetConfig; |
| 54375 | memset(s: &tmpSubscribedDataSetConfig, c: 0, n: sizeof(UA_StandaloneSubscribedDataSetConfig)); |
| 54376 | if(UA_StandaloneSubscribedDataSetConfig_copy(src: sdsConfig, dst: &tmpSubscribedDataSetConfig) != UA_STATUSCODE_GOOD){ |
| 54377 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54378 | msg: "SubscribedDataSet creation failed. Configuration copy failed."); |
| 54379 | return UA_STATUSCODE_BADINTERNALERROR; |
| 54380 | } |
| 54381 | //create new PDS and add to UA_PubSubManager |
| 54382 | UA_StandaloneSubscribedDataSet *newSubscribedDataSet = (UA_StandaloneSubscribedDataSet *) |
| 54383 | UA_calloc(nmemb: 1, size: sizeof(UA_StandaloneSubscribedDataSet)); |
| 54384 | if(!newSubscribedDataSet) { |
| 54385 | UA_StandaloneSubscribedDataSetConfig_clear(sdsConfig: &tmpSubscribedDataSetConfig); |
| 54386 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54387 | msg: "SubscribedDataSet creation failed. Out of Memory."); |
| 54388 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 54389 | } |
| 54390 | |
| 54391 | newSubscribedDataSet->config = tmpSubscribedDataSetConfig; |
| 54392 | newSubscribedDataSet->connectedReader = UA_NODEID_NULL; |
| 54393 | |
| 54394 | TAILQ_INSERT_TAIL(&server->pubSubManager.subscribedDataSets, newSubscribedDataSet, listEntry); |
| 54395 | server->pubSubManager.subscribedDataSetsSize++; |
| 54396 | |
| 54397 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 54398 | addStandaloneSubscribedDataSetRepresentation(server, subscribedDataSet: newSubscribedDataSet); |
| 54399 | #else |
| 54400 | UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, &newSubscribedDataSet->identifier); |
| 54401 | #endif |
| 54402 | |
| 54403 | if(sdsIdentifier) |
| 54404 | UA_NodeId_copy(src: &newSubscribedDataSet->identifier, dst: sdsIdentifier); |
| 54405 | |
| 54406 | return UA_STATUSCODE_GOOD; |
| 54407 | } |
| 54408 | |
| 54409 | UA_StatusCode |
| 54410 | UA_Server_addStandaloneSubscribedDataSet(UA_Server *server, |
| 54411 | const UA_StandaloneSubscribedDataSetConfig *sdsConfig, |
| 54412 | UA_NodeId *sdsIdentifier) { |
| 54413 | lockServer(server); |
| 54414 | UA_StatusCode res = addStandaloneSubscribedDataSet(server, sdsConfig, sdsIdentifier); |
| 54415 | unlockServer(server); |
| 54416 | return res; |
| 54417 | } |
| 54418 | |
| 54419 | static UA_StatusCode |
| 54420 | removeStandaloneSubscribedDataSet(UA_Server *server, const UA_NodeId sds) { |
| 54421 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 54422 | |
| 54423 | UA_StandaloneSubscribedDataSet *subscribedDataSet = |
| 54424 | UA_StandaloneSubscribedDataSet_findSDSbyId(server, identifier: sds); |
| 54425 | if(!subscribedDataSet){ |
| 54426 | return UA_STATUSCODE_BADNOTFOUND; |
| 54427 | } |
| 54428 | |
| 54429 | //search for referenced readers. |
| 54430 | UA_PubSubConnection *tmpConnectoin; |
| 54431 | TAILQ_FOREACH(tmpConnectoin, &server->pubSubManager.connections, listEntry){ |
| 54432 | UA_ReaderGroup *readerGroup; |
| 54433 | LIST_FOREACH(readerGroup, &tmpConnectoin->readerGroups, listEntry){ |
| 54434 | UA_DataSetReader *currentReader, *tmpReader; |
| 54435 | LIST_FOREACH_SAFE(currentReader, &readerGroup->readers, listEntry, tmpReader){ |
| 54436 | if(UA_NodeId_equal(p1: ¤tReader->identifier, p2: &subscribedDataSet->connectedReader)){ |
| 54437 | UA_DataSetReader_remove(server, dsr: currentReader); |
| 54438 | goto done; |
| 54439 | } |
| 54440 | } |
| 54441 | } |
| 54442 | } |
| 54443 | |
| 54444 | done: |
| 54445 | |
| 54446 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 54447 | deleteNode(server, nodeId: subscribedDataSet->identifier, true); |
| 54448 | #endif |
| 54449 | |
| 54450 | UA_StandaloneSubscribedDataSet_clear(server, subscribedDataSet); |
| 54451 | server->pubSubManager.subscribedDataSetsSize--; |
| 54452 | |
| 54453 | TAILQ_REMOVE(&server->pubSubManager.subscribedDataSets, subscribedDataSet, listEntry); |
| 54454 | UA_free(ptr: subscribedDataSet); |
| 54455 | return UA_STATUSCODE_GOOD; |
| 54456 | } |
| 54457 | |
| 54458 | UA_StatusCode |
| 54459 | UA_Server_removeStandaloneSubscribedDataSet(UA_Server *server, const UA_NodeId sds) { |
| 54460 | lockServer(server); |
| 54461 | UA_StatusCode res = removeStandaloneSubscribedDataSet(server, sds); |
| 54462 | unlockServer(server); |
| 54463 | return res; |
| 54464 | } |
| 54465 | |
| 54466 | /* Generate a new unique NodeId. This NodeId will be used for the information |
| 54467 | * model representation of PubSub entities. */ |
| 54468 | #ifndef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 54469 | void |
| 54470 | UA_PubSubManager_generateUniqueNodeId(UA_PubSubManager *psm, UA_NodeId *nodeId) { |
| 54471 | *nodeId = UA_NODEID_NUMERIC(1, ++psm->uniqueIdCount); |
| 54472 | } |
| 54473 | #endif |
| 54474 | |
| 54475 | UA_Guid |
| 54476 | UA_PubSubManager_generateUniqueGuid(UA_Server *server) { |
| 54477 | while(true) { |
| 54478 | UA_NodeId testId = UA_NODEID_GUID(nsIndex: 1, guid: UA_Guid_random()); |
| 54479 | const UA_Node *testNode = UA_NODESTORE_GET(server, nodeId: &testId); |
| 54480 | if(!testNode) |
| 54481 | return testId.identifier.guid; |
| 54482 | UA_NODESTORE_RELEASE(server, testNode); |
| 54483 | } |
| 54484 | } |
| 54485 | |
| 54486 | static UA_UInt64 |
| 54487 | generateRandomUInt64(UA_Server *server) { |
| 54488 | UA_UInt64 id = 0; |
| 54489 | UA_Guid ident = UA_Guid_random(); |
| 54490 | |
| 54491 | id = id + ident.data1; |
| 54492 | id = (id << 32) + ident.data2; |
| 54493 | id = (id << 16) + ident.data3; |
| 54494 | return id; |
| 54495 | } |
| 54496 | |
| 54497 | /* Initialization the PubSub configuration. */ |
| 54498 | void |
| 54499 | UA_PubSubManager_init(UA_Server *server, UA_PubSubManager *pubSubManager) { |
| 54500 | //TODO: Using the Mac address to generate the defaultPublisherId. |
| 54501 | // In the future, this can be retrieved from the eventloop. |
| 54502 | pubSubManager->defaultPublisherId = generateRandomUInt64(server); |
| 54503 | |
| 54504 | TAILQ_INIT(&pubSubManager->connections); |
| 54505 | TAILQ_INIT(&pubSubManager->publishedDataSets); |
| 54506 | TAILQ_INIT(&pubSubManager->subscribedDataSets); |
| 54507 | TAILQ_INIT(&pubSubManager->topicAssign); |
| 54508 | |
| 54509 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 54510 | TAILQ_INIT(&pubSubManager->securityGroups); |
| 54511 | #endif |
| 54512 | } |
| 54513 | |
| 54514 | void |
| 54515 | UA_PubSubManager_shutdown(UA_Server *server, UA_PubSubManager *pubSubManager) { |
| 54516 | UA_PubSubConnection *tmpConnection; |
| 54517 | TAILQ_FOREACH(tmpConnection, &server->pubSubManager.connections, listEntry) { |
| 54518 | UA_PubSubConnection_setPubSubState(server, c: tmpConnection, |
| 54519 | state: UA_PUBSUBSTATE_DISABLED, UA_STATUSCODE_GOOD); |
| 54520 | } |
| 54521 | } |
| 54522 | |
| 54523 | /* Delete the current PubSub configuration including all nested members. This |
| 54524 | * action also delete the configured PubSub transport Layers. */ |
| 54525 | void |
| 54526 | UA_PubSubManager_delete(UA_Server *server, UA_PubSubManager *pubSubManager) { |
| 54527 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54528 | msg: "PubSub cleanup was called."); |
| 54529 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 54530 | |
| 54531 | /* Remove Connections - this also remove WriterGroups and ReaderGroups */ |
| 54532 | UA_PubSubConnection *tmpConnection1, *tmpConnection2; |
| 54533 | TAILQ_FOREACH_SAFE(tmpConnection1, &server->pubSubManager.connections, |
| 54534 | listEntry, tmpConnection2) { |
| 54535 | UA_PubSubConnection_delete(server, c: tmpConnection1); |
| 54536 | } |
| 54537 | |
| 54538 | /* Remove the DataSets */ |
| 54539 | UA_PublishedDataSet *tmpPDS1, *tmpPDS2; |
| 54540 | TAILQ_FOREACH_SAFE(tmpPDS1, &server->pubSubManager.publishedDataSets, |
| 54541 | listEntry, tmpPDS2){ |
| 54542 | UA_PublishedDataSet_remove(server, publishedDataSet: tmpPDS1); |
| 54543 | } |
| 54544 | |
| 54545 | /* Remove the TopicAssigns */ |
| 54546 | UA_TopicAssign *tmpTopicAssign1, *tmpTopicAssign2; |
| 54547 | TAILQ_FOREACH_SAFE(tmpTopicAssign1, &server->pubSubManager.topicAssign, |
| 54548 | listEntry, tmpTopicAssign2){ |
| 54549 | server->pubSubManager.topicAssignSize--; |
| 54550 | TAILQ_REMOVE(&server->pubSubManager.topicAssign, tmpTopicAssign1, listEntry); |
| 54551 | UA_free(ptr: tmpTopicAssign1); |
| 54552 | } |
| 54553 | |
| 54554 | /* Remove the ReserveIds*/ |
| 54555 | ZIP_ITER(UA_ReserveIdTree, &server->pubSubManager.reserveIds, removeReserveId, NULL); |
| 54556 | server->pubSubManager.reserveIdsSize = 0; |
| 54557 | |
| 54558 | /* Delete subscribed datasets */ |
| 54559 | UA_StandaloneSubscribedDataSet *tmpSDS1, *tmpSDS2; |
| 54560 | TAILQ_FOREACH_SAFE(tmpSDS1, &server->pubSubManager.subscribedDataSets, listEntry, tmpSDS2){ |
| 54561 | removeStandaloneSubscribedDataSet(server, sds: tmpSDS1->identifier); |
| 54562 | } |
| 54563 | |
| 54564 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 54565 | /* Remove the SecurityGroups */ |
| 54566 | UA_SecurityGroup *tmpSG1, *tmpSG2; |
| 54567 | TAILQ_FOREACH_SAFE(tmpSG1, &server->pubSubManager.securityGroups, listEntry, tmpSG2) { |
| 54568 | removeSecurityGroup(server, tmpSG1); |
| 54569 | } |
| 54570 | |
| 54571 | /* Remove the keyStorages */ |
| 54572 | UA_PubSubKeyStorage *ks, *ksTmp; |
| 54573 | LIST_FOREACH_SAFE(ks, &server->pubSubManager.pubSubKeyList, keyStorageList, ksTmp) { |
| 54574 | UA_PubSubKeyStorage_delete(server, ks); |
| 54575 | } |
| 54576 | #endif |
| 54577 | } |
| 54578 | |
| 54579 | #ifdef UA_ENABLE_PUBSUB_MONITORING |
| 54580 | |
| 54581 | static UA_StatusCode |
| 54582 | UA_PubSubComponent_createMonitoring(UA_Server *server, UA_NodeId Id, UA_PubSubComponentEnumType eComponentType, |
| 54583 | UA_PubSubMonitoringType eMonitoringType, void *data, UA_ServerCallback callback) { |
| 54584 | |
| 54585 | if(!server || !data) |
| 54586 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 54587 | |
| 54588 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 54589 | switch (eComponentType) { |
| 54590 | case UA_PUBSUB_COMPONENT_DATASETREADER: { |
| 54591 | UA_DataSetReader *reader = (UA_DataSetReader*) data; |
| 54592 | switch (eMonitoringType) { |
| 54593 | case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: |
| 54594 | UA_LOG_DEBUG(server->config.logging, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' " |
| 54595 | "- MessageReceiveTimeout", (UA_Int32) reader->config.name.length, reader->config.name.data); |
| 54596 | reader->msgRcvTimeoutTimerCallback = callback; |
| 54597 | break; |
| 54598 | default: |
| 54599 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' " |
| 54600 | "DataSetReader does not support timeout type '%i'", (UA_Int32) reader->config.name.length, reader->config.name.data, |
| 54601 | eMonitoringType); |
| 54602 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 54603 | break; |
| 54604 | } |
| 54605 | break; |
| 54606 | } |
| 54607 | default: |
| 54608 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54609 | "Error UA_PubSubComponent_createMonitoring(): PubSub component type '%i' is not supported", eComponentType); |
| 54610 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 54611 | break; |
| 54612 | } |
| 54613 | return ret; |
| 54614 | } |
| 54615 | |
| 54616 | static void |
| 54617 | monitoringReceiveTimeoutOnce(UA_Server *server, void *data) { |
| 54618 | UA_DataSetReader *reader = (UA_DataSetReader*)data; |
| 54619 | reader->msgRcvTimeoutTimerCallback(server, reader); |
| 54620 | UA_EventLoop *el = server->config.eventLoop; |
| 54621 | el->removeCyclicCallback(el, reader->msgRcvTimeoutTimerId); |
| 54622 | reader->msgRcvTimeoutTimerId = 0; |
| 54623 | } |
| 54624 | |
| 54625 | static UA_StatusCode |
| 54626 | UA_PubSubComponent_startMonitoring(UA_Server *server, UA_NodeId Id, |
| 54627 | UA_PubSubComponentEnumType eComponentType, |
| 54628 | UA_PubSubMonitoringType eMonitoringType, void *data) { |
| 54629 | if(!server || !data) |
| 54630 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 54631 | |
| 54632 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 54633 | switch (eComponentType) { |
| 54634 | case UA_PUBSUB_COMPONENT_DATASETREADER: { |
| 54635 | UA_DataSetReader *reader = (UA_DataSetReader*) data; |
| 54636 | switch (eMonitoringType) { |
| 54637 | case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: { |
| 54638 | if(reader->config.messageReceiveTimeout == 0) { |
| 54639 | UA_LOG_WARNING_READER(server->config.logging, reader, |
| 54640 | "Cannot monitor timeout for messageReceiveTimeout == 0"); |
| 54641 | return UA_STATUSCODE_GOOD; |
| 54642 | } |
| 54643 | |
| 54644 | /* use a timed callback, because one notification is enough, |
| 54645 | * we assume that MessageReceiveTimeout configuration is in |
| 54646 | * [ms], we do not handle or check fractions */ |
| 54647 | UA_EventLoop *el = server->config.eventLoop; |
| 54648 | ret = el->addCyclicCallback(el, (UA_Callback)monitoringReceiveTimeoutOnce, |
| 54649 | server, reader, reader->config.messageReceiveTimeout, |
| 54650 | NULL, UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, |
| 54651 | &reader->msgRcvTimeoutTimerId); |
| 54652 | if(ret == UA_STATUSCODE_GOOD) { |
| 54653 | UA_LOG_DEBUG(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54654 | "UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s'- " |
| 54655 | "MessageReceiveTimeout: MessageReceiveTimeout = '%f' " |
| 54656 | "Timer Id = '%u'", (UA_Int32) reader->config.name.length, |
| 54657 | reader->config.name.data, reader->config.messageReceiveTimeout, |
| 54658 | (UA_UInt32) reader->msgRcvTimeoutTimerId); |
| 54659 | } else { |
| 54660 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54661 | "Error UA_PubSubComponent_startMonitoring(): DataSetReader " |
| 54662 | "'%.*s' - MessageReceiveTimeout: start timer failed", |
| 54663 | (UA_Int32) reader->config.name.length, reader->config.name.data); |
| 54664 | } |
| 54665 | break; |
| 54666 | } |
| 54667 | default: |
| 54668 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54669 | "UA_PubSubComponent_startMonitoring(): DataSetReader '%.*s' " |
| 54670 | "DataSetReader does not support timeout type '%i'", |
| 54671 | (UA_Int32) reader->config.name.length, reader->config.name.data, |
| 54672 | eMonitoringType); |
| 54673 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 54674 | break; |
| 54675 | } |
| 54676 | break; |
| 54677 | } |
| 54678 | default: |
| 54679 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54680 | "Error UA_PubSubComponent_startMonitoring(): PubSub component " |
| 54681 | "type '%i' is not supported", eComponentType); |
| 54682 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 54683 | break; |
| 54684 | } |
| 54685 | return ret; |
| 54686 | } |
| 54687 | |
| 54688 | static UA_StatusCode |
| 54689 | UA_PubSubComponent_stopMonitoring(UA_Server *server, UA_NodeId Id, |
| 54690 | UA_PubSubComponentEnumType eComponentType, |
| 54691 | UA_PubSubMonitoringType eMonitoringType, void *data) { |
| 54692 | if(!server || !data) |
| 54693 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 54694 | |
| 54695 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 54696 | switch (eComponentType) { |
| 54697 | case UA_PUBSUB_COMPONENT_DATASETREADER: { |
| 54698 | UA_DataSetReader *reader = (UA_DataSetReader*) data; |
| 54699 | switch (eMonitoringType) { |
| 54700 | case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: { |
| 54701 | UA_EventLoop *el = server->config.eventLoop; |
| 54702 | el->removeCyclicCallback(el, reader->msgRcvTimeoutTimerId); |
| 54703 | UA_LOG_DEBUG(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54704 | "UA_PubSubComponent_stopMonitoring(): DataSetReader '%.*s' - " |
| 54705 | "MessageReceiveTimeout: MessageReceiveTimeout = '%f' " |
| 54706 | "Timer Id = '%u'", (UA_Int32) reader->config.name.length, |
| 54707 | reader->config.name.data, reader->config.messageReceiveTimeout, |
| 54708 | (UA_UInt32) reader->msgRcvTimeoutTimerId); |
| 54709 | break; |
| 54710 | } |
| 54711 | default: |
| 54712 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54713 | "UA_PubSubComponent_stopMonitoring(): DataSetReader '%.*s' " |
| 54714 | "DataSetReader does not support timeout type '%i'", |
| 54715 | (UA_Int32) reader->config.name.length, reader->config.name.data, |
| 54716 | eMonitoringType); |
| 54717 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 54718 | break; |
| 54719 | } |
| 54720 | break; |
| 54721 | } |
| 54722 | default: |
| 54723 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54724 | "Error UA_PubSubComponent_stopMonitoring(): PubSub component type '%i' " |
| 54725 | "is not supported", eComponentType); |
| 54726 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 54727 | break; |
| 54728 | } |
| 54729 | return ret; |
| 54730 | } |
| 54731 | |
| 54732 | static UA_StatusCode |
| 54733 | UA_PubSubComponent_updateMonitoringInterval(UA_Server *server, UA_NodeId Id, |
| 54734 | UA_PubSubComponentEnumType eComponentType, |
| 54735 | UA_PubSubMonitoringType eMonitoringType, void *data) { |
| 54736 | if(!server || !data) |
| 54737 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 54738 | |
| 54739 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 54740 | switch (eComponentType) { |
| 54741 | case UA_PUBSUB_COMPONENT_DATASETREADER: { |
| 54742 | UA_DataSetReader *reader = (UA_DataSetReader*) data; |
| 54743 | switch (eMonitoringType) { |
| 54744 | case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: { |
| 54745 | UA_EventLoop *el = server->config.eventLoop; |
| 54746 | ret = el->modifyCyclicCallback(el, reader->msgRcvTimeoutTimerId, |
| 54747 | reader->config.messageReceiveTimeout, NULL, |
| 54748 | UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME); |
| 54749 | if (ret == UA_STATUSCODE_GOOD) { |
| 54750 | UA_LOG_DEBUG(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54751 | "UA_PubSubComponent_updateMonitoringInterval(): " |
| 54752 | "DataSetReader '%.*s' - MessageReceiveTimeout: new " |
| 54753 | "MessageReceiveTimeout = '%f' Timer Id = '%u'", |
| 54754 | (UA_Int32) reader->config.name.length, reader->config.name.data, |
| 54755 | reader->config.messageReceiveTimeout, |
| 54756 | (UA_UInt32) reader->msgRcvTimeoutTimerId); |
| 54757 | } else { |
| 54758 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54759 | "Error UA_PubSubComponent_updateMonitoringInterval(): " |
| 54760 | "DataSetReader '%.*s': update timer interval failed", |
| 54761 | (UA_Int32) reader->config.name.length, reader->config.name.data); |
| 54762 | } |
| 54763 | break; |
| 54764 | } |
| 54765 | default: |
| 54766 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54767 | "UA_PubSubComponent_createMonitoring(): DataSetReader '%.*s' " |
| 54768 | "DataSetReader does not support timeout type '%i'", |
| 54769 | (UA_Int32) reader->config.name.length, reader->config.name.data, |
| 54770 | eMonitoringType); |
| 54771 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 54772 | break; |
| 54773 | } |
| 54774 | break; |
| 54775 | } |
| 54776 | default: |
| 54777 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54778 | "Error UA_PubSubComponent_updateMonitoringInterval(): " |
| 54779 | "PubSub component type '%i' is not supported", eComponentType); |
| 54780 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 54781 | break; |
| 54782 | } |
| 54783 | return ret; |
| 54784 | } |
| 54785 | |
| 54786 | static UA_StatusCode |
| 54787 | UA_PubSubComponent_deleteMonitoring(UA_Server *server, UA_NodeId Id, |
| 54788 | UA_PubSubComponentEnumType eComponentType, |
| 54789 | UA_PubSubMonitoringType eMonitoringType, void *data) { |
| 54790 | |
| 54791 | if(!server || !data) |
| 54792 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 54793 | |
| 54794 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 54795 | switch (eComponentType) { |
| 54796 | case UA_PUBSUB_COMPONENT_DATASETREADER: { |
| 54797 | UA_DataSetReader *reader = (UA_DataSetReader*) data; |
| 54798 | switch (eMonitoringType) { |
| 54799 | case UA_PUBSUB_MONITORING_MESSAGE_RECEIVE_TIMEOUT: |
| 54800 | UA_LOG_DEBUG(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54801 | "UA_PubSubComponent_deleteMonitoring(): DataSetReader '%.*s' - " |
| 54802 | "MessageReceiveTimeout: Timer Id = '%u'", |
| 54803 | (UA_Int32)reader->config.name.length, reader->config.name.data, |
| 54804 | (UA_UInt32) reader->msgRcvTimeoutTimerId); |
| 54805 | break; |
| 54806 | default: |
| 54807 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54808 | "UA_PubSubComponent_deleteMonitoring(): DataSetReader '%.*s' " |
| 54809 | "DataSetReader does not support timeout type '%i'", |
| 54810 | (UA_Int32) reader->config.name.length, reader->config.name.data, |
| 54811 | eMonitoringType); |
| 54812 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 54813 | break; |
| 54814 | } |
| 54815 | break; |
| 54816 | } |
| 54817 | default: |
| 54818 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 54819 | "Error UA_PubSubComponent_deleteMonitoring(): PubSub component type " |
| 54820 | "'%i' is not supported", eComponentType); |
| 54821 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 54822 | break; |
| 54823 | } |
| 54824 | return ret; |
| 54825 | } |
| 54826 | |
| 54827 | UA_StatusCode |
| 54828 | UA_PubSubManager_setDefaultMonitoringCallbacks(UA_PubSubMonitoringInterface *monitoringInterface) { |
| 54829 | if (monitoringInterface == NULL) { |
| 54830 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 54831 | } |
| 54832 | monitoringInterface->createMonitoring = UA_PubSubComponent_createMonitoring; |
| 54833 | monitoringInterface->startMonitoring = UA_PubSubComponent_startMonitoring; |
| 54834 | monitoringInterface->stopMonitoring = UA_PubSubComponent_stopMonitoring; |
| 54835 | monitoringInterface->updateMonitoringInterval = UA_PubSubComponent_updateMonitoringInterval; |
| 54836 | monitoringInterface->deleteMonitoring = UA_PubSubComponent_deleteMonitoring; |
| 54837 | return UA_STATUSCODE_GOOD; |
| 54838 | } |
| 54839 | |
| 54840 | #endif /* UA_ENABLE_PUBSUB_MONITORING */ |
| 54841 | |
| 54842 | #endif /* UA_ENABLE_PUBSUB */ |
| 54843 | |
| 54844 | /**** amalgamated original file "/src/pubsub/ua_pubsub_ns0.c" ****/ |
| 54845 | |
| 54846 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 54847 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 54848 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 54849 | * |
| 54850 | * Copyright (c) 2017-2022 Fraunhofer IOSB (Author: Andreas Ebner) |
| 54851 | * Copyright (c) 2019-2021 Kalycito Infotech Private Limited |
| 54852 | * Copyright (c) 2020 Yannick Wallerer, Siemens AG |
| 54853 | * Copyright (c) 2020-2022 Thomas Fischer, Siemens AG |
| 54854 | * Copyright (c) 2022 Linutronix GmbH (Author: Muddasir Shakil) |
| 54855 | */ |
| 54856 | |
| 54857 | |
| 54858 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL /* conditional compilation */ |
| 54859 | |
| 54860 | typedef struct { |
| 54861 | UA_NodeId parentNodeId; |
| 54862 | UA_UInt32 parentClassifier; |
| 54863 | UA_UInt32 elementClassiefier; |
| 54864 | } UA_NodePropertyContext; |
| 54865 | |
| 54866 | static UA_StatusCode |
| 54867 | writePubSubNs0VariableArray(UA_Server *server, const UA_NodeId id, void *v, |
| 54868 | size_t length, const UA_DataType *type) { |
| 54869 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 54870 | UA_Variant var; |
| 54871 | UA_Variant_init(p: &var); |
| 54872 | UA_Variant_setArray(v: &var, array: v, arraySize: length, type); |
| 54873 | return writeValueAttribute(server, nodeId: id, value: &var); |
| 54874 | } |
| 54875 | |
| 54876 | static UA_NodeId |
| 54877 | findSingleChildNode(UA_Server *server, UA_QualifiedName targetName, |
| 54878 | UA_NodeId referenceTypeId, UA_NodeId startingNode){ |
| 54879 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 54880 | UA_NodeId resultNodeId; |
| 54881 | UA_RelativePathElement rpe; |
| 54882 | UA_RelativePathElement_init(p: &rpe); |
| 54883 | rpe.referenceTypeId = referenceTypeId; |
| 54884 | rpe.isInverse = false; |
| 54885 | rpe.includeSubtypes = false; |
| 54886 | rpe.targetName = targetName; |
| 54887 | UA_BrowsePath bp; |
| 54888 | UA_BrowsePath_init(p: &bp); |
| 54889 | bp.startingNode = startingNode; |
| 54890 | bp.relativePath.elementsSize = 1; |
| 54891 | bp.relativePath.elements = &rpe; |
| 54892 | UA_BrowsePathResult bpr = translateBrowsePathToNodeIds(server, browsePath: &bp); |
| 54893 | if(bpr.statusCode != UA_STATUSCODE_GOOD || |
| 54894 | bpr.targetsSize < 1) |
| 54895 | return UA_NODEID_NULL; |
| 54896 | UA_StatusCode res = UA_NodeId_copy(src: &bpr.targets[0].targetId.nodeId, dst: &resultNodeId); |
| 54897 | if(res != UA_STATUSCODE_GOOD){ |
| 54898 | UA_BrowsePathResult_clear(p: &bpr); |
| 54899 | return UA_NODEID_NULL; |
| 54900 | } |
| 54901 | UA_BrowsePathResult_clear(p: &bpr); |
| 54902 | return resultNodeId; |
| 54903 | } |
| 54904 | |
| 54905 | static void |
| 54906 | onReadLocked(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 54907 | const UA_NodeId *nodeid, void *context, |
| 54908 | const UA_NumericRange *range, const UA_DataValue *data) { |
| 54909 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 54910 | |
| 54911 | const UA_NodePropertyContext *nodeContext = (const UA_NodePropertyContext*)context; |
| 54912 | const UA_NodeId *myNodeId = &nodeContext->parentNodeId; |
| 54913 | |
| 54914 | UA_PublishedVariableDataType *pvd = NULL; |
| 54915 | UA_PublishedDataSet *publishedDataSet = NULL; |
| 54916 | |
| 54917 | UA_Variant value; |
| 54918 | UA_Variant_init(p: &value); |
| 54919 | |
| 54920 | switch(nodeContext->parentClassifier){ |
| 54921 | case UA_NS0ID_PUBSUBCONNECTIONTYPE: { |
| 54922 | UA_PubSubConnection *pubSubConnection = |
| 54923 | UA_PubSubConnection_findConnectionbyId(server, connectionIdentifier: *myNodeId); |
| 54924 | switch(nodeContext->elementClassiefier) { |
| 54925 | case UA_NS0ID_PUBSUBCONNECTIONTYPE_PUBLISHERID: |
| 54926 | switch (pubSubConnection->config.publisherIdType) { |
| 54927 | case UA_PUBLISHERIDTYPE_BYTE: |
| 54928 | UA_Variant_setScalar(v: &value, p: &pubSubConnection->config.publisherId.byte, |
| 54929 | type: &UA_TYPES[UA_TYPES_BYTE]); |
| 54930 | break; |
| 54931 | case UA_PUBLISHERIDTYPE_UINT16: |
| 54932 | UA_Variant_setScalar(v: &value, p: &pubSubConnection->config.publisherId.uint16, |
| 54933 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 54934 | break; |
| 54935 | case UA_PUBLISHERIDTYPE_UINT32: |
| 54936 | UA_Variant_setScalar(v: &value, p: &pubSubConnection->config.publisherId.uint32, |
| 54937 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 54938 | break; |
| 54939 | case UA_PUBLISHERIDTYPE_UINT64: |
| 54940 | UA_Variant_setScalar(v: &value, p: &pubSubConnection->config.publisherId.uint64, |
| 54941 | type: &UA_TYPES[UA_TYPES_UINT64]); |
| 54942 | break; |
| 54943 | case UA_PUBLISHERIDTYPE_STRING: |
| 54944 | UA_Variant_setScalar(v: &value, p: &pubSubConnection->config.publisherId.string, |
| 54945 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 54946 | break; |
| 54947 | default: |
| 54948 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54949 | msg: "Read error! Unknown PublisherId type."); |
| 54950 | } |
| 54951 | break; |
| 54952 | default: |
| 54953 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54954 | msg: "Read error! Unknown property."); |
| 54955 | } |
| 54956 | break; |
| 54957 | } |
| 54958 | case UA_NS0ID_DATASETREADERTYPE: { |
| 54959 | UA_DataSetReader *dataSetReader = UA_ReaderGroup_findDSRbyId(server, identifier: *myNodeId); |
| 54960 | if(!dataSetReader) |
| 54961 | return; |
| 54962 | |
| 54963 | switch(nodeContext->elementClassiefier) { |
| 54964 | case UA_NS0ID_DATASETREADERTYPE_PUBLISHERID: |
| 54965 | UA_Variant_setScalar(v: &value, p: dataSetReader->config.publisherId.data, |
| 54966 | type: dataSetReader->config.publisherId.type); |
| 54967 | break; |
| 54968 | default: |
| 54969 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54970 | msg: "Read error! Unknown property."); |
| 54971 | } |
| 54972 | break; |
| 54973 | } |
| 54974 | case UA_NS0ID_WRITERGROUPTYPE: { |
| 54975 | UA_WriterGroup *writerGroup = UA_WriterGroup_findWGbyId(server, identifier: *myNodeId); |
| 54976 | if(!writerGroup) |
| 54977 | return; |
| 54978 | switch(nodeContext->elementClassiefier){ |
| 54979 | case UA_NS0ID_WRITERGROUPTYPE_PUBLISHINGINTERVAL: |
| 54980 | UA_Variant_setScalar(v: &value, p: &writerGroup->config.publishingInterval, |
| 54981 | type: &UA_TYPES[UA_TYPES_DURATION]); |
| 54982 | break; |
| 54983 | default: |
| 54984 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 54985 | msg: "Read error! Unknown property."); |
| 54986 | } |
| 54987 | break; |
| 54988 | } |
| 54989 | case UA_NS0ID_DATASETWRITERTYPE: { |
| 54990 | UA_DataSetWriter *dataSetWriter = UA_DataSetWriter_findDSWbyId(server, identifier: *myNodeId); |
| 54991 | if(!dataSetWriter) |
| 54992 | return; |
| 54993 | |
| 54994 | switch(nodeContext->elementClassiefier) { |
| 54995 | case UA_NS0ID_DATASETWRITERTYPE_DATASETWRITERID: |
| 54996 | UA_Variant_setScalar(v: &value, p: &dataSetWriter->config.dataSetWriterId, |
| 54997 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 54998 | break; |
| 54999 | default: |
| 55000 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55001 | msg: "Read error! Unknown property."); |
| 55002 | } |
| 55003 | break; |
| 55004 | } |
| 55005 | case UA_NS0ID_PUBLISHEDDATAITEMSTYPE: { |
| 55006 | publishedDataSet = UA_PublishedDataSet_findPDSbyId(server, identifier: *myNodeId); |
| 55007 | if(!publishedDataSet) |
| 55008 | return; |
| 55009 | switch(nodeContext->elementClassiefier) { |
| 55010 | case UA_NS0ID_PUBLISHEDDATAITEMSTYPE_PUBLISHEDDATA: { |
| 55011 | pvd = (UA_PublishedVariableDataType *) |
| 55012 | UA_calloc(nmemb: publishedDataSet->fieldSize, size: sizeof(UA_PublishedVariableDataType)); |
| 55013 | size_t counter = 0; |
| 55014 | UA_DataSetField *field; |
| 55015 | TAILQ_FOREACH(field, &publishedDataSet->fields, listEntry) { |
| 55016 | pvd[counter].attributeId = UA_ATTRIBUTEID_VALUE; |
| 55017 | pvd[counter].publishedVariable = |
| 55018 | field->config.field.variable.publishParameters.publishedVariable; |
| 55019 | UA_NodeId_copy(src: &field->config.field.variable.publishParameters.publishedVariable, |
| 55020 | dst: &pvd[counter].publishedVariable); |
| 55021 | counter++; |
| 55022 | } |
| 55023 | UA_Variant_setArray(v: &value, array: pvd, arraySize: publishedDataSet->fieldSize, |
| 55024 | type: &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE]); |
| 55025 | break; |
| 55026 | } |
| 55027 | case UA_NS0ID_PUBLISHEDDATAITEMSTYPE_DATASETMETADATA: { |
| 55028 | UA_Variant_setScalar(v: &value, p: &publishedDataSet->dataSetMetaData, |
| 55029 | type: &UA_TYPES[UA_TYPES_DATASETMETADATATYPE]); |
| 55030 | break; |
| 55031 | } |
| 55032 | case UA_NS0ID_PUBLISHEDDATAITEMSTYPE_CONFIGURATIONVERSION: { |
| 55033 | UA_Variant_setScalar(v: &value, p: &publishedDataSet->dataSetMetaData.configurationVersion, |
| 55034 | type: &UA_TYPES[UA_TYPES_CONFIGURATIONVERSIONDATATYPE]); |
| 55035 | break; |
| 55036 | } |
| 55037 | default: |
| 55038 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55039 | msg: "Read error! Unknown property."); |
| 55040 | } |
| 55041 | break; |
| 55042 | } |
| 55043 | case UA_NS0ID_STANDALONESUBSCRIBEDDATASETREFDATATYPE: { |
| 55044 | UA_StandaloneSubscribedDataSet *sds = |
| 55045 | UA_StandaloneSubscribedDataSet_findSDSbyId(server, identifier: *myNodeId); |
| 55046 | switch(nodeContext->elementClassiefier) { |
| 55047 | case UA_NS0ID_STANDALONESUBSCRIBEDDATASETTYPE_ISCONNECTED: { |
| 55048 | UA_Variant_setScalar(v: &value, p: &sds->config.isConnected, |
| 55049 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 55050 | break; |
| 55051 | } |
| 55052 | case UA_NS0ID_STANDALONESUBSCRIBEDDATASETTYPE_DATASETMETADATA: { |
| 55053 | UA_Variant_setScalar(v: &value, p: &sds->config.dataSetMetaData, |
| 55054 | type: &UA_TYPES[UA_TYPES_DATASETMETADATATYPE]); |
| 55055 | break; |
| 55056 | } |
| 55057 | default: |
| 55058 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55059 | msg: "Read error! Unknown property."); |
| 55060 | } |
| 55061 | break; |
| 55062 | } |
| 55063 | default: |
| 55064 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55065 | msg: "Read error! Unknown parent element."); |
| 55066 | } |
| 55067 | |
| 55068 | writeValueAttribute(server, nodeId: *nodeid, value: &value); |
| 55069 | if(pvd && publishedDataSet) { |
| 55070 | UA_Array_delete(p: pvd, size: publishedDataSet->fieldSize, |
| 55071 | type: &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE]); |
| 55072 | } |
| 55073 | } |
| 55074 | |
| 55075 | static void |
| 55076 | onRead(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 55077 | const UA_NodeId *nodeid, void *context, |
| 55078 | const UA_NumericRange *range, const UA_DataValue *data) { |
| 55079 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55080 | onReadLocked(server, sessionId, sessionContext, nodeid, context, range, data); |
| 55081 | } |
| 55082 | |
| 55083 | static void |
| 55084 | onWriteLocked(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 55085 | const UA_NodeId *nodeId, void *nodeContext, |
| 55086 | const UA_NumericRange *range, const UA_DataValue *data) { |
| 55087 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55088 | UA_NodePropertyContext *npc = (UA_NodePropertyContext *)nodeContext; |
| 55089 | |
| 55090 | UA_WriterGroup *writerGroup = NULL; |
| 55091 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 55092 | switch(npc->parentClassifier) { |
| 55093 | case UA_NS0ID_PUBSUBCONNECTIONTYPE: |
| 55094 | //no runtime writable attributes |
| 55095 | break; |
| 55096 | case UA_NS0ID_WRITERGROUPTYPE: { |
| 55097 | writerGroup = UA_WriterGroup_findWGbyId(server, identifier: npc->parentNodeId); |
| 55098 | if(!writerGroup) |
| 55099 | return; |
| 55100 | UA_WriterGroupConfig writerGroupConfig; |
| 55101 | memset(s: &writerGroupConfig, c: 0, n: sizeof(writerGroupConfig)); |
| 55102 | switch(npc->elementClassiefier) { |
| 55103 | case UA_NS0ID_WRITERGROUPTYPE_PUBLISHINGINTERVAL: |
| 55104 | if(!UA_Variant_hasScalarType(v: &data->value, type: &UA_TYPES[UA_TYPES_DURATION]) && |
| 55105 | !UA_Variant_hasScalarType(v: &data->value, type: &UA_TYPES[UA_TYPES_DOUBLE])) { |
| 55106 | res = UA_STATUSCODE_BADTYPEMISMATCH; |
| 55107 | goto cleanup; |
| 55108 | } |
| 55109 | res = UA_WriterGroupConfig_copy(src: &writerGroup->config, dst: &writerGroupConfig); |
| 55110 | if(res != UA_STATUSCODE_GOOD) |
| 55111 | goto cleanup; |
| 55112 | writerGroupConfig.publishingInterval = *((UA_Duration *) data->value.data); |
| 55113 | UA_WriterGroup_updateConfig(server, wg: writerGroup, config: &writerGroupConfig); |
| 55114 | UA_WriterGroupConfig_clear(writerGroupConfig: &writerGroupConfig); |
| 55115 | break; |
| 55116 | default: |
| 55117 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55118 | msg: "Write error! Unknown property element."); |
| 55119 | } |
| 55120 | break; |
| 55121 | } |
| 55122 | default: |
| 55123 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55124 | msg: "Read error! Unknown parent element."); |
| 55125 | } |
| 55126 | |
| 55127 | cleanup: |
| 55128 | if(res != UA_STATUSCODE_GOOD) { |
| 55129 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55130 | msg: "Changing the ReaderGroupConfig failed with status %s", |
| 55131 | UA_StatusCode_name(code: res)); |
| 55132 | } |
| 55133 | } |
| 55134 | |
| 55135 | static void |
| 55136 | onWrite(UA_Server *server, const UA_NodeId *sessionId, void *sessionContext, |
| 55137 | const UA_NodeId *nodeId, void *nodeContext, |
| 55138 | const UA_NumericRange *range, const UA_DataValue *data) { |
| 55139 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55140 | onWriteLocked(server, sessionId, sessionContext, nodeId, nodeContext, range, data); |
| 55141 | } |
| 55142 | |
| 55143 | static UA_StatusCode |
| 55144 | addVariableValueSource(UA_Server *server, UA_ValueCallback valueCallback, |
| 55145 | UA_NodeId node, UA_NodePropertyContext *context){ |
| 55146 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55147 | setNodeContext(server, nodeId: node, nodeContext: context); |
| 55148 | return setVariableNode_valueCallback(server, nodeId: node, callback: valueCallback); |
| 55149 | } |
| 55150 | |
| 55151 | static UA_StatusCode |
| 55152 | addPubSubConnectionConfig(UA_Server *server, UA_PubSubConnectionDataType *pubsubConnection, |
| 55153 | UA_NodeId *connectionId) { |
| 55154 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55155 | |
| 55156 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55157 | UA_NetworkAddressUrlDataType networkAddressUrl; |
| 55158 | memset(s: &networkAddressUrl, c: 0, n: sizeof(networkAddressUrl)); |
| 55159 | UA_ExtensionObject *eo = &pubsubConnection->address; |
| 55160 | if(eo->encoding == UA_EXTENSIONOBJECT_DECODED && |
| 55161 | eo->content.decoded.type == &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]) { |
| 55162 | void *data = eo->content.decoded.data; |
| 55163 | retVal = |
| 55164 | UA_NetworkAddressUrlDataType_copy(src: (UA_NetworkAddressUrlDataType *)data, |
| 55165 | dst: &networkAddressUrl); |
| 55166 | if(retVal != UA_STATUSCODE_GOOD) |
| 55167 | return retVal; |
| 55168 | } |
| 55169 | |
| 55170 | UA_PubSubConnectionConfig connectionConfig; |
| 55171 | memset(s: &connectionConfig, c: 0, n: sizeof(UA_PubSubConnectionConfig)); |
| 55172 | connectionConfig.transportProfileUri = pubsubConnection->transportProfileUri; |
| 55173 | connectionConfig.name = pubsubConnection->name; |
| 55174 | //TODO set real connection state |
| 55175 | connectionConfig.enabled = pubsubConnection->enabled; |
| 55176 | //connectionConfig.enabled = pubSubConnection.enabled; |
| 55177 | UA_Variant_setScalar(v: &connectionConfig.address, p: &networkAddressUrl, |
| 55178 | type: &UA_TYPES[UA_TYPES_NETWORKADDRESSURLDATATYPE]); |
| 55179 | |
| 55180 | if (pubsubConnection->publisherId.type == &UA_TYPES[UA_TYPES_BYTE]) { |
| 55181 | connectionConfig.publisherIdType = UA_PUBLISHERIDTYPE_BYTE; |
| 55182 | connectionConfig.publisherId.byte = *((UA_Byte*)pubsubConnection->publisherId.data); |
| 55183 | } else if (pubsubConnection->publisherId.type == &UA_TYPES[UA_TYPES_UINT16]) { |
| 55184 | connectionConfig.publisherIdType = UA_PUBLISHERIDTYPE_UINT16; |
| 55185 | connectionConfig.publisherId.uint16 = *((UA_UInt16*)pubsubConnection->publisherId.data); |
| 55186 | } else if (pubsubConnection->publisherId.type == &UA_TYPES[UA_TYPES_UINT32]) { |
| 55187 | connectionConfig.publisherIdType = UA_PUBLISHERIDTYPE_UINT32; |
| 55188 | connectionConfig.publisherId.uint32 = *((UA_UInt32*)pubsubConnection->publisherId.data); |
| 55189 | } else if (pubsubConnection->publisherId.type == &UA_TYPES[UA_TYPES_UINT64]) { |
| 55190 | connectionConfig.publisherIdType = UA_PUBLISHERIDTYPE_UINT64; |
| 55191 | connectionConfig.publisherId.uint64 = *((UA_UInt64*)pubsubConnection->publisherId.data); |
| 55192 | } else if (pubsubConnection->publisherId.type == &UA_TYPES[UA_TYPES_STRING]) { |
| 55193 | connectionConfig.publisherIdType = UA_PUBLISHERIDTYPE_STRING; |
| 55194 | UA_String_copy(src: (UA_String *) pubsubConnection->publisherId.data, |
| 55195 | dst: &connectionConfig.publisherId.string); |
| 55196 | } else { |
| 55197 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55198 | msg: "Unsupported PublisherId Type used."); |
| 55199 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 55200 | } |
| 55201 | |
| 55202 | retVal |= UA_PubSubConnection_create(server, cc: &connectionConfig, cId: connectionId); |
| 55203 | UA_NetworkAddressUrlDataType_clear(p: &networkAddressUrl); |
| 55204 | return retVal; |
| 55205 | } |
| 55206 | |
| 55207 | /** |
| 55208 | * **WriterGroup handling** |
| 55209 | * |
| 55210 | * The WriterGroup (WG) is part of the connection and contains the primary |
| 55211 | * configuration parameters for the message creation. */ |
| 55212 | static UA_StatusCode |
| 55213 | addWriterGroupConfig(UA_Server *server, UA_NodeId connectionId, |
| 55214 | UA_WriterGroupDataType *writerGroup, UA_NodeId *writerGroupId){ |
| 55215 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55216 | |
| 55217 | /* Now we create a new WriterGroupConfig and add the group to the existing |
| 55218 | * PubSubConnection. */ |
| 55219 | UA_WriterGroupConfig writerGroupConfig; |
| 55220 | memset(s: &writerGroupConfig, c: 0, n: sizeof(UA_WriterGroupConfig)); |
| 55221 | writerGroupConfig.name = writerGroup->name; |
| 55222 | writerGroupConfig.publishingInterval = writerGroup->publishingInterval; |
| 55223 | writerGroupConfig.enabled = writerGroup->enabled; |
| 55224 | writerGroupConfig.writerGroupId = writerGroup->writerGroupId; |
| 55225 | writerGroupConfig.priority = writerGroup->priority; |
| 55226 | |
| 55227 | UA_ExtensionObject *eoWG = &writerGroup->messageSettings; |
| 55228 | UA_UadpWriterGroupMessageDataType uadpWriterGroupMessage; |
| 55229 | UA_JsonWriterGroupMessageDataType jsonWriterGroupMessage; |
| 55230 | if(eoWG->encoding == UA_EXTENSIONOBJECT_DECODED){ |
| 55231 | writerGroupConfig.messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 55232 | if(eoWG->content.decoded.type == &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]){ |
| 55233 | writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP; |
| 55234 | if(UA_UadpWriterGroupMessageDataType_copy( |
| 55235 | src: (UA_UadpWriterGroupMessageDataType *)eoWG->content.decoded.data, |
| 55236 | dst: &uadpWriterGroupMessage) != UA_STATUSCODE_GOOD) { |
| 55237 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 55238 | } |
| 55239 | writerGroupConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]; |
| 55240 | writerGroupConfig.messageSettings.content.decoded.data = &uadpWriterGroupMessage; |
| 55241 | } else if(eoWG->content.decoded.type == &UA_TYPES[UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE]) { |
| 55242 | writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_JSON; |
| 55243 | if(UA_JsonWriterGroupMessageDataType_copy( |
| 55244 | src: (UA_JsonWriterGroupMessageDataType *)eoWG->content.decoded.data, |
| 55245 | dst: &jsonWriterGroupMessage) != UA_STATUSCODE_GOOD) { |
| 55246 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 55247 | } |
| 55248 | writerGroupConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE]; |
| 55249 | writerGroupConfig.messageSettings.content.decoded.data = &jsonWriterGroupMessage; |
| 55250 | } |
| 55251 | } |
| 55252 | |
| 55253 | eoWG = &writerGroup->transportSettings; |
| 55254 | UA_BrokerWriterGroupTransportDataType brokerWriterGroupTransport; |
| 55255 | UA_DatagramWriterGroupTransportDataType datagramWriterGroupTransport; |
| 55256 | if(eoWG->encoding == UA_EXTENSIONOBJECT_DECODED) { |
| 55257 | writerGroupConfig.transportSettings.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 55258 | if(eoWG->content.decoded.type == &UA_TYPES[UA_TYPES_BROKERWRITERGROUPTRANSPORTDATATYPE]) { |
| 55259 | if(UA_BrokerWriterGroupTransportDataType_copy( |
| 55260 | src: (UA_BrokerWriterGroupTransportDataType*)eoWG->content.decoded.data, |
| 55261 | dst: &brokerWriterGroupTransport) != UA_STATUSCODE_GOOD) { |
| 55262 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 55263 | } |
| 55264 | writerGroupConfig.transportSettings.content.decoded.type = &UA_TYPES[UA_TYPES_BROKERWRITERGROUPTRANSPORTDATATYPE]; |
| 55265 | writerGroupConfig.transportSettings.content.decoded.data = &brokerWriterGroupTransport; |
| 55266 | } else if(eoWG->content.decoded.type == &UA_TYPES[UA_TYPES_DATAGRAMWRITERGROUPTRANSPORTDATATYPE]) { |
| 55267 | if(UA_DatagramWriterGroupTransportDataType_copy( |
| 55268 | src: (UA_DatagramWriterGroupTransportDataType *)eoWG->content.decoded.data, |
| 55269 | dst: &datagramWriterGroupTransport) != UA_STATUSCODE_GOOD) { |
| 55270 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 55271 | } |
| 55272 | writerGroupConfig.transportSettings.content.decoded.type = &UA_TYPES[UA_TYPES_DATAGRAMWRITERGROUPTRANSPORTDATATYPE]; |
| 55273 | writerGroupConfig.transportSettings.content.decoded.data = &datagramWriterGroupTransport; |
| 55274 | } |
| 55275 | } |
| 55276 | if (writerGroupConfig.encodingMimeType == UA_PUBSUB_ENCODING_JSON |
| 55277 | && (writerGroupConfig.transportSettings.encoding != UA_EXTENSIONOBJECT_DECODED || |
| 55278 | writerGroupConfig.transportSettings.content.decoded.type != |
| 55279 | &UA_TYPES[UA_TYPES_BROKERWRITERGROUPTRANSPORTDATATYPE])) { |
| 55280 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55281 | msg: "JSON encoding is supported only for MQTT transport"); |
| 55282 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 55283 | } |
| 55284 | |
| 55285 | return UA_WriterGroup_create(server, connection: connectionId, writerGroupConfig: &writerGroupConfig, writerGroupIdentifier: writerGroupId); |
| 55286 | } |
| 55287 | |
| 55288 | /** |
| 55289 | * **DataSetWriter handling** |
| 55290 | * |
| 55291 | * A DataSetWriter (DSW) is the glue between the WG and the PDS. The DSW is |
| 55292 | * linked to exactly one PDS and contains additional informations for the |
| 55293 | * message generation. */ |
| 55294 | static UA_StatusCode |
| 55295 | addDataSetWriterConfig(UA_Server *server, const UA_NodeId *writerGroupId, |
| 55296 | UA_DataSetWriterDataType *dataSetWriter, |
| 55297 | UA_NodeId *dataSetWriterId) { |
| 55298 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55299 | |
| 55300 | UA_NodeId publishedDataSetId = UA_NODEID_NULL; |
| 55301 | UA_PublishedDataSet *tmpPDS; |
| 55302 | TAILQ_FOREACH(tmpPDS, &server->pubSubManager.publishedDataSets, listEntry){ |
| 55303 | if(UA_String_equal(p1: &dataSetWriter->dataSetName, p2: &tmpPDS->config.name)) { |
| 55304 | publishedDataSetId = tmpPDS->identifier; |
| 55305 | break; |
| 55306 | } |
| 55307 | } |
| 55308 | |
| 55309 | if(UA_NodeId_isNull(p: &publishedDataSetId)) |
| 55310 | return UA_STATUSCODE_BADPARENTNODEIDINVALID; |
| 55311 | |
| 55312 | /* We need now a DataSetWriter within the WriterGroup. This means we must |
| 55313 | * create a new DataSetWriterConfig and add call the addWriterGroup function. */ |
| 55314 | UA_DataSetWriterConfig dataSetWriterConfig; |
| 55315 | memset(s: &dataSetWriterConfig, c: 0, n: sizeof(UA_DataSetWriterConfig)); |
| 55316 | dataSetWriterConfig.name = dataSetWriter->name; |
| 55317 | dataSetWriterConfig.dataSetWriterId = dataSetWriter->dataSetWriterId; |
| 55318 | dataSetWriterConfig.keyFrameCount = dataSetWriter->keyFrameCount; |
| 55319 | dataSetWriterConfig.dataSetFieldContentMask = dataSetWriter->dataSetFieldContentMask; |
| 55320 | return UA_DataSetWriter_create(server, writerGroup: *writerGroupId, dataSet: publishedDataSetId, |
| 55321 | dataSetWriterConfig: &dataSetWriterConfig, writerIdentifier: dataSetWriterId); |
| 55322 | } |
| 55323 | |
| 55324 | /** |
| 55325 | * **ReaderGroup** |
| 55326 | * |
| 55327 | * ReaderGroup is used to group a list of DataSetReaders. All ReaderGroups are |
| 55328 | * created within a PubSubConnection and automatically deleted if the connection |
| 55329 | * is removed. All network message related filters are only available in the DataSetReader. */ |
| 55330 | /* Add ReaderGroup to the created connection */ |
| 55331 | static UA_StatusCode |
| 55332 | addReaderGroupConfig(UA_Server *server, UA_NodeId connectionId, |
| 55333 | UA_ReaderGroupDataType *readerGroup, |
| 55334 | UA_NodeId *readerGroupId) { |
| 55335 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55336 | |
| 55337 | UA_ReaderGroupConfig readerGroupConfig; |
| 55338 | memset(s: &readerGroupConfig, c: 0, n: sizeof(UA_ReaderGroupConfig)); |
| 55339 | readerGroupConfig.name = readerGroup->name; |
| 55340 | return UA_ReaderGroup_create(server, connectionId, |
| 55341 | rgc: &readerGroupConfig, readerGroupId); |
| 55342 | } |
| 55343 | |
| 55344 | /** |
| 55345 | * **SubscribedDataSet** |
| 55346 | * |
| 55347 | * Set SubscribedDataSet type to TargetVariables data type. |
| 55348 | * Add subscribedvariables to the DataSetReader */ |
| 55349 | static UA_StatusCode |
| 55350 | addSubscribedVariables(UA_Server *server, UA_NodeId dataSetReaderId, |
| 55351 | UA_DataSetReaderDataType *dataSetReader, |
| 55352 | UA_DataSetMetaDataType *pMetaData) { |
| 55353 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55354 | |
| 55355 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55356 | UA_ExtensionObject *eoTargetVar = &dataSetReader->subscribedDataSet; |
| 55357 | if(eoTargetVar->encoding != UA_EXTENSIONOBJECT_DECODED || |
| 55358 | eoTargetVar->content.decoded.type != &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]) |
| 55359 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 55360 | |
| 55361 | const UA_TargetVariablesDataType *targetVars = |
| 55362 | (UA_TargetVariablesDataType*)eoTargetVar->content.decoded.data; |
| 55363 | |
| 55364 | UA_NodeId folderId; |
| 55365 | UA_String folderName = pMetaData->name; |
| 55366 | UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; |
| 55367 | UA_QualifiedName folderBrowseName; |
| 55368 | if(folderName.length > 0) { |
| 55369 | oAttr.displayName.locale = UA_STRING(chars: ""); |
| 55370 | oAttr.displayName.text = folderName; |
| 55371 | folderBrowseName.namespaceIndex = 1; |
| 55372 | folderBrowseName.name = folderName; |
| 55373 | } else { |
| 55374 | oAttr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Subscribed Variables"); |
| 55375 | folderBrowseName = UA_QUALIFIEDNAME(nsIndex: 1, chars: "Subscribed Variables"); |
| 55376 | } |
| 55377 | |
| 55378 | addNode(server, nodeClass: UA_NODECLASS_OBJECT, requestedNewNodeId: UA_NODEID_NULL, |
| 55379 | parentNodeId: UA_NODEID_NUMERIC (nsIndex: 0, UA_NS0ID_OBJECTSFOLDER), |
| 55380 | referenceTypeId: UA_NODEID_NUMERIC (nsIndex: 0, UA_NS0ID_ORGANIZES), |
| 55381 | browseName: folderBrowseName, |
| 55382 | typeDefinition: UA_NODEID_NUMERIC (nsIndex: 0, UA_NS0ID_BASEOBJECTTYPE), |
| 55383 | attr: &oAttr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 55384 | NULL, outNewNodeId: &folderId); |
| 55385 | |
| 55386 | /* The SubscribedDataSet option TargetVariables defines a list of Variable |
| 55387 | * mappings between received DataSet fields and target Variables in the |
| 55388 | * Subscriber AddressSpace. The values subscribed from the Publisher are |
| 55389 | * updated in the value field of these variables */ |
| 55390 | |
| 55391 | /* Create the TargetVariables with respect to DataSetMetaData fields */ |
| 55392 | UA_FieldTargetVariable *targetVarsData = (UA_FieldTargetVariable *) |
| 55393 | UA_calloc(nmemb: targetVars->targetVariablesSize, size: sizeof(UA_FieldTargetVariable)); |
| 55394 | for(size_t i = 0; i < targetVars->targetVariablesSize; i++) { |
| 55395 | /* Prepare the output structure */ |
| 55396 | UA_FieldTargetDataType_init(p: &targetVarsData[i].targetVariable); |
| 55397 | targetVarsData[i].targetVariable.attributeId = targetVars->targetVariables[i].attributeId; |
| 55398 | |
| 55399 | /* Add variable for the field */ |
| 55400 | UA_VariableAttributes vAttr = UA_VariableAttributes_default; |
| 55401 | vAttr.description = pMetaData->fields[i].description; |
| 55402 | vAttr.displayName.locale = UA_STRING(chars: ""); |
| 55403 | vAttr.displayName.text = pMetaData->fields[i].name; |
| 55404 | vAttr.dataType = pMetaData->fields[i].dataType; |
| 55405 | UA_QualifiedName varname = {1, pMetaData->fields[i].name}; |
| 55406 | retVal |= addNode(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 55407 | requestedNewNodeId: targetVars->targetVariables[i].targetNodeId, |
| 55408 | parentNodeId: folderId, referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55409 | browseName: varname, typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEDATAVARIABLETYPE), |
| 55410 | attr: &vAttr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], |
| 55411 | NULL, outNewNodeId: &targetVarsData[i].targetVariable.targetNodeId); |
| 55412 | |
| 55413 | } |
| 55414 | UA_DataSetReader *dsr = UA_ReaderGroup_findDSRbyId(server, identifier: dataSetReaderId); |
| 55415 | if(dsr) { |
| 55416 | retVal = DataSetReader_createTargetVariables(server, dsr, |
| 55417 | targetVariablesSize: targetVars->targetVariablesSize, |
| 55418 | targetVariables: targetVarsData); |
| 55419 | } else { |
| 55420 | retVal = UA_STATUSCODE_BADINTERNALERROR; |
| 55421 | } |
| 55422 | for(size_t j = 0; j < targetVars->targetVariablesSize; j++) |
| 55423 | UA_FieldTargetDataType_clear(p: &targetVarsData[j].targetVariable); |
| 55424 | UA_free(ptr: targetVarsData); |
| 55425 | return retVal; |
| 55426 | } |
| 55427 | |
| 55428 | /** |
| 55429 | * **DataSetReader** |
| 55430 | * |
| 55431 | * DataSetReader can receive NetworkMessages with the DataSetMessage |
| 55432 | * of interest sent by the Publisher. DataSetReader provides |
| 55433 | * the configuration necessary to receive and process DataSetMessages |
| 55434 | * on the Subscriber side. DataSetReader must be linked with a |
| 55435 | * SubscribedDataSet and be contained within a ReaderGroup. */ |
| 55436 | static UA_StatusCode |
| 55437 | addDataSetReaderConfig(UA_Server *server, UA_NodeId readerGroupId, |
| 55438 | UA_DataSetReaderDataType *dataSetReader, |
| 55439 | UA_NodeId *dataSetReaderId) { |
| 55440 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55441 | |
| 55442 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55443 | UA_DataSetReaderConfig readerConfig; |
| 55444 | memset(s: &readerConfig, c: 0, n: sizeof(UA_DataSetReaderConfig)); |
| 55445 | readerConfig.name = dataSetReader->name; |
| 55446 | readerConfig.publisherId = dataSetReader->publisherId; |
| 55447 | readerConfig.writerGroupId = dataSetReader->writerGroupId; |
| 55448 | readerConfig.dataSetWriterId = dataSetReader->dataSetWriterId; |
| 55449 | |
| 55450 | /* Setting up Meta data configuration in DataSetReader */ |
| 55451 | UA_DataSetMetaDataType *pMetaData; |
| 55452 | pMetaData = &readerConfig.dataSetMetaData; |
| 55453 | UA_DataSetMetaDataType_init (p: pMetaData); |
| 55454 | pMetaData->name = dataSetReader->dataSetMetaData.name; |
| 55455 | pMetaData->fieldsSize = dataSetReader->dataSetMetaData.fieldsSize; |
| 55456 | pMetaData->fields = (UA_FieldMetaData*)UA_Array_new (size: pMetaData->fieldsSize, |
| 55457 | type: &UA_TYPES[UA_TYPES_FIELDMETADATA]); |
| 55458 | for(size_t i = 0; i < pMetaData->fieldsSize; i++){ |
| 55459 | UA_FieldMetaData_init (p: &pMetaData->fields[i]); |
| 55460 | UA_NodeId_copy (src: &dataSetReader->dataSetMetaData.fields[i].dataType, |
| 55461 | dst: &pMetaData->fields[i].dataType); |
| 55462 | pMetaData->fields[i].builtInType = dataSetReader->dataSetMetaData.fields[i].builtInType; |
| 55463 | pMetaData->fields[i].name = dataSetReader->dataSetMetaData.fields[i].name; |
| 55464 | pMetaData->fields[i].valueRank = dataSetReader->dataSetMetaData.fields[i].valueRank; |
| 55465 | } |
| 55466 | |
| 55467 | retVal |= UA_DataSetReader_create(server, readerGroupIdentifier: readerGroupId, |
| 55468 | dataSetReaderConfig: &readerConfig, readerIdentifier: dataSetReaderId); |
| 55469 | if(retVal != UA_STATUSCODE_GOOD) { |
| 55470 | UA_free(ptr: pMetaData->fields); |
| 55471 | return retVal; |
| 55472 | } |
| 55473 | |
| 55474 | retVal |= addSubscribedVariables(server, dataSetReaderId: *dataSetReaderId, dataSetReader, pMetaData); |
| 55475 | UA_free(ptr: pMetaData->fields); |
| 55476 | return retVal; |
| 55477 | } |
| 55478 | |
| 55479 | /*************************************************/ |
| 55480 | /* PubSubConnection */ |
| 55481 | /*************************************************/ |
| 55482 | |
| 55483 | UA_StatusCode |
| 55484 | addPubSubConnectionRepresentation(UA_Server *server, UA_PubSubConnection *connection) { |
| 55485 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55486 | if(connection->config.name.length > 512) |
| 55487 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 55488 | char connectionName[513]; |
| 55489 | memcpy(dest: connectionName, src: connection->config.name.data, n: connection->config.name.length); |
| 55490 | connectionName[connection->config.name.length] = '\0'; |
| 55491 | |
| 55492 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 55493 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: connectionName); |
| 55494 | retVal |= addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 55495 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), /* Generate a new id */ |
| 55496 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE), |
| 55497 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPUBSUBCONNECTION), |
| 55498 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: connectionName), |
| 55499 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBSUBCONNECTIONTYPE), |
| 55500 | attr: (const UA_NodeAttributes*)&attr, |
| 55501 | attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 55502 | NULL, outNewNodeId: &connection->identifier); |
| 55503 | |
| 55504 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Address"); |
| 55505 | retVal |= addNode(server, nodeClass: UA_NODECLASS_OBJECT, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), |
| 55506 | parentNodeId: connection->identifier, referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55507 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "Address"), |
| 55508 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_NETWORKADDRESSURLTYPE), |
| 55509 | attr: &attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], NULL, NULL); |
| 55510 | |
| 55511 | retVal |= addNode_finish(server, session: &server->adminSession, nodeId: &connection->identifier); |
| 55512 | |
| 55513 | UA_NodeId addressNode = |
| 55514 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "Address"), |
| 55515 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55516 | startingNode: connection->identifier); |
| 55517 | UA_NodeId urlNode = |
| 55518 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "Url"), |
| 55519 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), startingNode: addressNode); |
| 55520 | UA_NodeId interfaceNode = |
| 55521 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "NetworkInterface"), |
| 55522 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), startingNode: addressNode); |
| 55523 | UA_NodeId publisherIdNode = |
| 55524 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PublisherId"), |
| 55525 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: connection->identifier); |
| 55526 | UA_NodeId connectionPropertyNode = |
| 55527 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "ConnectionProperties"), |
| 55528 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 55529 | startingNode: connection->identifier); |
| 55530 | UA_NodeId transportProfileUri = |
| 55531 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "TransportProfileUri"), |
| 55532 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55533 | startingNode: connection->identifier); |
| 55534 | |
| 55535 | if(UA_NodeId_isNull(p: &addressNode) || UA_NodeId_isNull(p: &urlNode) || |
| 55536 | UA_NodeId_isNull(p: &interfaceNode) || UA_NodeId_isNull(p: &publisherIdNode) || |
| 55537 | UA_NodeId_isNull(p: &connectionPropertyNode) || |
| 55538 | UA_NodeId_isNull(p: &transportProfileUri)) { |
| 55539 | return UA_STATUSCODE_BADNOTFOUND; |
| 55540 | } |
| 55541 | |
| 55542 | retVal |= writePubSubNs0VariableArray(server, id: connectionPropertyNode, |
| 55543 | v: connection->config.connectionProperties.map, |
| 55544 | length: connection->config.connectionProperties.mapSize, |
| 55545 | type: &UA_TYPES[UA_TYPES_KEYVALUEPAIR]); |
| 55546 | |
| 55547 | UA_NetworkAddressUrlDataType *networkAddressUrl= |
| 55548 | ((UA_NetworkAddressUrlDataType*)connection->config.address.data); |
| 55549 | UA_Variant value; |
| 55550 | UA_Variant_init(p: &value); |
| 55551 | |
| 55552 | UA_Variant_setScalar(v: &value, p: &networkAddressUrl->url, type: &UA_TYPES[UA_TYPES_STRING]); |
| 55553 | writeValueAttribute(server, nodeId: urlNode, value: &value); |
| 55554 | |
| 55555 | UA_Variant_setScalar(v: &value, p: &networkAddressUrl->networkInterface, type: &UA_TYPES[UA_TYPES_STRING]); |
| 55556 | writeValueAttribute(server, nodeId: interfaceNode, value: &value); |
| 55557 | |
| 55558 | UA_Variant_setScalar(v: &value, p: &connection->config.transportProfileUri, type: &UA_TYPES[UA_TYPES_STRING]); |
| 55559 | writeValueAttribute(server, nodeId: transportProfileUri, value: &value); |
| 55560 | |
| 55561 | UA_NodePropertyContext *connectionPublisherIdContext = |
| 55562 | (UA_NodePropertyContext *)UA_malloc(size: sizeof(UA_NodePropertyContext)); |
| 55563 | connectionPublisherIdContext->parentNodeId = connection->identifier; |
| 55564 | connectionPublisherIdContext->parentClassifier = UA_NS0ID_PUBSUBCONNECTIONTYPE; |
| 55565 | connectionPublisherIdContext->elementClassiefier = |
| 55566 | UA_NS0ID_PUBSUBCONNECTIONTYPE_PUBLISHERID; |
| 55567 | UA_ValueCallback valueCallback; |
| 55568 | valueCallback.onRead = onRead; |
| 55569 | valueCallback.onWrite = NULL; |
| 55570 | retVal |= addVariableValueSource(server, valueCallback, node: publisherIdNode, |
| 55571 | context: connectionPublisherIdContext); |
| 55572 | |
| 55573 | if(server->config.pubSubConfig.enableInformationModelMethods) { |
| 55574 | retVal |= addRef(server, sourceId: connection->identifier, |
| 55575 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55576 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP), true); |
| 55577 | retVal |= addRef(server, sourceId: connection->identifier, |
| 55578 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55579 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP), true); |
| 55580 | retVal |= addRef(server, sourceId: connection->identifier, |
| 55581 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55582 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP), true); |
| 55583 | } |
| 55584 | return retVal; |
| 55585 | } |
| 55586 | |
| 55587 | static UA_StatusCode |
| 55588 | addPubSubConnectionLocked(UA_Server *server, |
| 55589 | const UA_NodeId *sessionId, void *sessionHandle, |
| 55590 | const UA_NodeId *methodId, void *methodContext, |
| 55591 | const UA_NodeId *objectId, void *objectContext, |
| 55592 | size_t inputSize, const UA_Variant *input, |
| 55593 | size_t outputSize, UA_Variant *output) { |
| 55594 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55595 | |
| 55596 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55597 | UA_PubSubConnectionDataType *pubSubConnection = |
| 55598 | (UA_PubSubConnectionDataType *) input[0].data; |
| 55599 | |
| 55600 | //call API function and create the connection |
| 55601 | UA_NodeId connectionId; |
| 55602 | retVal |= addPubSubConnectionConfig(server, pubsubConnection: pubSubConnection, connectionId: &connectionId); |
| 55603 | if(retVal != UA_STATUSCODE_GOOD) { |
| 55604 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55605 | msg: "addPubSubConnection failed"); |
| 55606 | return retVal; |
| 55607 | } |
| 55608 | |
| 55609 | for(size_t i = 0; i < pubSubConnection->writerGroupsSize; i++) { |
| 55610 | UA_NodeId writerGroupId; |
| 55611 | UA_WriterGroupDataType *writerGroup = &pubSubConnection->writerGroups[i]; |
| 55612 | retVal |= addWriterGroupConfig(server, connectionId, writerGroup, writerGroupId: &writerGroupId); |
| 55613 | if(retVal != UA_STATUSCODE_GOOD) { |
| 55614 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55615 | msg: "addWriterGroup failed"); |
| 55616 | return retVal; |
| 55617 | } |
| 55618 | |
| 55619 | for(size_t j = 0; j < writerGroup->dataSetWritersSize; j++) { |
| 55620 | UA_DataSetWriterDataType *dataSetWriter = &writerGroup->dataSetWriters[j]; |
| 55621 | retVal |= addDataSetWriterConfig(server, writerGroupId: &writerGroupId, dataSetWriter, NULL); |
| 55622 | if(retVal != UA_STATUSCODE_GOOD) { |
| 55623 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55624 | msg: "addDataSetWriter failed"); |
| 55625 | return retVal; |
| 55626 | } |
| 55627 | } |
| 55628 | |
| 55629 | /* TODO: Need to handle the UA_Server_setWriterGroupOperational based on |
| 55630 | * the status variable in information model */ |
| 55631 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: writerGroupId); |
| 55632 | if(!wg) |
| 55633 | continue; |
| 55634 | if(pubSubConnection->enabled) { |
| 55635 | UA_WriterGroup_freezeConfiguration(server, wg); |
| 55636 | UA_WriterGroup_setPubSubState(server, writerGroup: wg, state: UA_PUBSUBSTATE_OPERATIONAL, |
| 55637 | UA_STATUSCODE_GOOD); |
| 55638 | } else { |
| 55639 | UA_WriterGroup_setPubSubState(server, writerGroup: wg, state: UA_PUBSUBSTATE_DISABLED, |
| 55640 | UA_STATUSCODE_BADINTERNALERROR); |
| 55641 | } |
| 55642 | } |
| 55643 | |
| 55644 | for(size_t i = 0; i < pubSubConnection->readerGroupsSize; i++){ |
| 55645 | UA_NodeId readerGroupId; |
| 55646 | UA_ReaderGroupDataType *readerGroup = &pubSubConnection->readerGroups[i]; |
| 55647 | retVal |= addReaderGroupConfig(server, connectionId, readerGroup, readerGroupId: &readerGroupId); |
| 55648 | if(retVal != UA_STATUSCODE_GOOD) { |
| 55649 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55650 | msg: "addReaderGroup failed"); |
| 55651 | return retVal; |
| 55652 | } |
| 55653 | |
| 55654 | for(size_t j = 0; j < readerGroup->dataSetReadersSize; j++) { |
| 55655 | UA_NodeId dataSetReaderId; |
| 55656 | UA_DataSetReaderDataType *dataSetReader = &readerGroup->dataSetReaders[j]; |
| 55657 | retVal |= addDataSetReaderConfig(server, readerGroupId, |
| 55658 | dataSetReader, dataSetReaderId: &dataSetReaderId); |
| 55659 | if(retVal != UA_STATUSCODE_GOOD) { |
| 55660 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55661 | msg: "addDataSetReader failed"); |
| 55662 | return retVal; |
| 55663 | } |
| 55664 | |
| 55665 | } |
| 55666 | |
| 55667 | /* TODO: Need to handle the UA_Server_setReaderGroupOperational based on |
| 55668 | * the status variable in information model */ |
| 55669 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, identifier: readerGroupId); |
| 55670 | if(!rg) |
| 55671 | continue; |
| 55672 | if(pubSubConnection->enabled) { |
| 55673 | UA_ReaderGroup_freezeConfiguration(server, rg); |
| 55674 | UA_ReaderGroup_setPubSubState(server, readerGroup: rg, state: UA_PUBSUBSTATE_OPERATIONAL, |
| 55675 | UA_STATUSCODE_GOOD); |
| 55676 | } else { |
| 55677 | UA_ReaderGroup_setPubSubState(server, readerGroup: rg, state: UA_PUBSUBSTATE_DISABLED, |
| 55678 | UA_STATUSCODE_BADINTERNALERROR); |
| 55679 | } |
| 55680 | } |
| 55681 | |
| 55682 | /* Set ouput value */ |
| 55683 | UA_Variant_setScalarCopy(v: output, p: &connectionId, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 55684 | return UA_STATUSCODE_GOOD; |
| 55685 | } |
| 55686 | |
| 55687 | static UA_StatusCode |
| 55688 | addPubSubConnectionAction(UA_Server *server, |
| 55689 | const UA_NodeId *sessionId, void *sessionHandle, |
| 55690 | const UA_NodeId *methodId, void *methodContext, |
| 55691 | const UA_NodeId *objectId, void *objectContext, |
| 55692 | size_t inputSize, const UA_Variant *input, |
| 55693 | size_t outputSize, UA_Variant *output) { |
| 55694 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55695 | return addPubSubConnectionLocked(server, sessionId, sessionHandle, |
| 55696 | methodId, methodContext, |
| 55697 | objectId, objectContext, |
| 55698 | inputSize, input, outputSize, output); |
| 55699 | } |
| 55700 | |
| 55701 | static UA_StatusCode |
| 55702 | removeConnectionAction(UA_Server *server, |
| 55703 | const UA_NodeId *sessionId, void *sessionHandle, |
| 55704 | const UA_NodeId *methodId, void *methodContext, |
| 55705 | const UA_NodeId *objectId, void *objectContext, |
| 55706 | size_t inputSize, const UA_Variant *input, |
| 55707 | size_t outputSize, UA_Variant *output){ |
| 55708 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55709 | UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data); |
| 55710 | retVal |= UA_Server_removePubSubConnection(server, connection: nodeToRemove); |
| 55711 | if(retVal == UA_STATUSCODE_BADNOTFOUND) |
| 55712 | retVal = UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 55713 | return retVal; |
| 55714 | } |
| 55715 | |
| 55716 | /**********************************************/ |
| 55717 | /* DataSetReader */ |
| 55718 | /**********************************************/ |
| 55719 | |
| 55720 | UA_StatusCode |
| 55721 | addDataSetReaderRepresentation(UA_Server *server, UA_DataSetReader *dataSetReader){ |
| 55722 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55723 | |
| 55724 | if(dataSetReader->config.name.length > 512) |
| 55725 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 55726 | |
| 55727 | char dsrName[513]; |
| 55728 | memcpy(dest: dsrName, src: dataSetReader->config.name.data, n: dataSetReader->config.name.length); |
| 55729 | dsrName[dataSetReader->config.name.length] = '\0'; |
| 55730 | |
| 55731 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55732 | UA_NodeId publisherIdNode, writerGroupIdNode, dataSetwriterIdNode; |
| 55733 | |
| 55734 | UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; |
| 55735 | object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: dsrName); |
| 55736 | retVal = addNode(server, nodeClass: UA_NODECLASS_OBJECT, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), /* create an id */ |
| 55737 | parentNodeId: dataSetReader->linkedReaderGroup, |
| 55738 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASDATASETREADER), |
| 55739 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: dsrName), |
| 55740 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETREADERTYPE), |
| 55741 | attr: &object_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 55742 | NULL, outNewNodeId: &dataSetReader->identifier); |
| 55743 | |
| 55744 | /* Add childNodes such as PublisherId, WriterGroupId and DataSetWriterId in |
| 55745 | * DataSetReader object */ |
| 55746 | publisherIdNode = findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PublisherId"), |
| 55747 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 55748 | startingNode: dataSetReader->identifier); |
| 55749 | writerGroupIdNode = findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "WriterGroupId"), |
| 55750 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 55751 | startingNode: dataSetReader->identifier); |
| 55752 | dataSetwriterIdNode = findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetWriterId"), |
| 55753 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 55754 | startingNode: dataSetReader->identifier); |
| 55755 | |
| 55756 | if(UA_NodeId_isNull(p: &publisherIdNode) || |
| 55757 | UA_NodeId_isNull(p: &writerGroupIdNode) || |
| 55758 | UA_NodeId_isNull(p: &dataSetwriterIdNode)) { |
| 55759 | return UA_STATUSCODE_BADNOTFOUND; |
| 55760 | } |
| 55761 | |
| 55762 | UA_NodePropertyContext *dataSetReaderPublisherIdContext = |
| 55763 | (UA_NodePropertyContext *) UA_malloc(size: sizeof(UA_NodePropertyContext)); |
| 55764 | dataSetReaderPublisherIdContext->parentNodeId = dataSetReader->identifier; |
| 55765 | dataSetReaderPublisherIdContext->parentClassifier = UA_NS0ID_DATASETREADERTYPE; |
| 55766 | dataSetReaderPublisherIdContext->elementClassiefier = UA_NS0ID_DATASETREADERTYPE_PUBLISHERID; |
| 55767 | UA_ValueCallback valueCallback; |
| 55768 | valueCallback.onRead = onRead; |
| 55769 | valueCallback.onWrite = NULL; |
| 55770 | retVal |= addVariableValueSource(server, valueCallback, node: publisherIdNode, |
| 55771 | context: dataSetReaderPublisherIdContext); |
| 55772 | |
| 55773 | /* Update childNode with values from Publisher */ |
| 55774 | UA_Variant value; |
| 55775 | UA_Variant_init(p: &value); |
| 55776 | UA_Variant_setScalar(v: &value, p: &dataSetReader->config.writerGroupId, |
| 55777 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 55778 | writeValueAttribute(server, nodeId: writerGroupIdNode, value: &value); |
| 55779 | UA_Variant_setScalar(v: &value, p: &dataSetReader->config.dataSetWriterId, |
| 55780 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 55781 | writeValueAttribute(server, nodeId: dataSetwriterIdNode, value: &value); |
| 55782 | return retVal; |
| 55783 | } |
| 55784 | |
| 55785 | static UA_StatusCode |
| 55786 | addDataSetReaderLocked(UA_Server *server, |
| 55787 | const UA_NodeId *sessionId, void *sessionHandle, |
| 55788 | const UA_NodeId *methodId, void *methodContext, |
| 55789 | const UA_NodeId *objectId, void *objectContext, |
| 55790 | size_t inputSize, const UA_Variant *input, |
| 55791 | size_t outputSize, UA_Variant *output){ |
| 55792 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55793 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55794 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, identifier: *objectId); |
| 55795 | if(rg->configurationFrozen) { |
| 55796 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55797 | msg: "AddDataSetReader cannot be done because ReaderGroup config frozen"); |
| 55798 | return UA_STATUSCODE_BAD; |
| 55799 | } |
| 55800 | |
| 55801 | UA_NodeId dataSetReaderId; |
| 55802 | UA_DataSetReaderDataType *dataSetReader= (UA_DataSetReaderDataType *) input[0].data; |
| 55803 | retVal |= addDataSetReaderConfig(server, readerGroupId: *objectId, dataSetReader, dataSetReaderId: &dataSetReaderId); |
| 55804 | if(retVal != UA_STATUSCODE_GOOD) { |
| 55805 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 55806 | msg: "AddDataSetReader failed"); |
| 55807 | return retVal; |
| 55808 | } |
| 55809 | |
| 55810 | UA_Variant_setScalarCopy(v: output, p: &dataSetReaderId, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 55811 | return retVal; |
| 55812 | } |
| 55813 | |
| 55814 | static UA_StatusCode |
| 55815 | addDataSetReaderAction(UA_Server *server, |
| 55816 | const UA_NodeId *sessionId, void *sessionHandle, |
| 55817 | const UA_NodeId *methodId, void *methodContext, |
| 55818 | const UA_NodeId *objectId, void *objectContext, |
| 55819 | size_t inputSize, const UA_Variant *input, |
| 55820 | size_t outputSize, UA_Variant *output){ |
| 55821 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55822 | return addDataSetReaderLocked(server, sessionId, sessionHandle, |
| 55823 | methodId, methodContext, objectId, objectContext, |
| 55824 | inputSize, input, outputSize, output); |
| 55825 | } |
| 55826 | |
| 55827 | static UA_StatusCode |
| 55828 | removeDataSetReaderAction(UA_Server *server, |
| 55829 | const UA_NodeId *sessionId, void *sessionHandle, |
| 55830 | const UA_NodeId *methodId, void *methodContext, |
| 55831 | const UA_NodeId *objectId, void *objectContext, |
| 55832 | size_t inputSize, const UA_Variant *input, |
| 55833 | size_t outputSize, UA_Variant *output){ |
| 55834 | UA_NodeId nodeToRemove = *((UA_NodeId *)input[0].data); |
| 55835 | return UA_Server_removeDataSetReader(server, readerIdentifier: nodeToRemove); |
| 55836 | } |
| 55837 | |
| 55838 | /*************************************************/ |
| 55839 | /* PublishedDataSet */ |
| 55840 | /*************************************************/ |
| 55841 | static UA_StatusCode |
| 55842 | addDataSetFolderAction(UA_Server *server, |
| 55843 | const UA_NodeId *sessionId, void *sessionHandle, |
| 55844 | const UA_NodeId *methodId, void *methodContext, |
| 55845 | const UA_NodeId *objectId, void *objectContext, |
| 55846 | size_t inputSize, const UA_Variant *input, |
| 55847 | size_t outputSize, UA_Variant *output){ |
| 55848 | /* defined in R 1.04 9.1.4.5.7 */ |
| 55849 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55850 | UA_String newFolderName = *((UA_String *) input[0].data); |
| 55851 | UA_NodeId generatedId; |
| 55852 | UA_ObjectAttributes objectAttributes = UA_ObjectAttributes_default; |
| 55853 | UA_LocalizedText name = {UA_STRING(chars: ""), newFolderName}; |
| 55854 | objectAttributes.displayName = name; |
| 55855 | retVal |= UA_Server_addObjectNode(server, requestedNewNodeId: UA_NODEID_NULL, parentNodeId: *objectId, |
| 55856 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0,UA_NS0ID_ORGANIZES), |
| 55857 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetFolder"), |
| 55858 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE), |
| 55859 | attr: objectAttributes, NULL, outNewNodeId: &generatedId); |
| 55860 | UA_Variant_setScalarCopy(v: output, p: &generatedId, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 55861 | |
| 55862 | if(server->config.pubSubConfig.enableInformationModelMethods) { |
| 55863 | retVal |= UA_Server_addReference(server, sourceId: generatedId, |
| 55864 | refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55865 | targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), true); |
| 55866 | retVal |= UA_Server_addReference(server, sourceId: generatedId, |
| 55867 | refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55868 | targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), true); |
| 55869 | retVal |= UA_Server_addReference(server, sourceId: generatedId, |
| 55870 | refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55871 | targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), true); |
| 55872 | retVal |= UA_Server_addReference(server, sourceId: generatedId, |
| 55873 | refTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55874 | targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), true); |
| 55875 | } |
| 55876 | return retVal; |
| 55877 | } |
| 55878 | |
| 55879 | static UA_StatusCode |
| 55880 | removeDataSetFolderAction(UA_Server *server, |
| 55881 | const UA_NodeId *sessionId, void *sessionHandle, |
| 55882 | const UA_NodeId *methodId, void *methodContext, |
| 55883 | const UA_NodeId *objectId, void *objectContext, |
| 55884 | size_t inputSize, const UA_Variant *input, |
| 55885 | size_t outputSize, UA_Variant *output) { |
| 55886 | UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data); |
| 55887 | return UA_Server_deleteNode(server, nodeId: nodeToRemove, true); |
| 55888 | } |
| 55889 | |
| 55890 | UA_StatusCode |
| 55891 | addPublishedDataItemsRepresentation(UA_Server *server, |
| 55892 | UA_PublishedDataSet *publishedDataSet) { |
| 55893 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 55894 | |
| 55895 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55896 | if(publishedDataSet->config.name.length > 512) |
| 55897 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 55898 | char pdsName[513]; |
| 55899 | memcpy(dest: pdsName, src: publishedDataSet->config.name.data, n: publishedDataSet->config.name.length); |
| 55900 | pdsName[publishedDataSet->config.name.length] = '\0'; |
| 55901 | |
| 55902 | UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; |
| 55903 | object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: pdsName); |
| 55904 | retVal = addNode(server, nodeClass: UA_NODECLASS_OBJECT, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), /* Create a new id */ |
| 55905 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS), |
| 55906 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55907 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: pdsName), |
| 55908 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE), |
| 55909 | attr: &object_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 55910 | NULL, outNewNodeId: &publishedDataSet->identifier); |
| 55911 | UA_CHECK_STATUS(retVal, return retVal); |
| 55912 | |
| 55913 | UA_ValueCallback valueCallback; |
| 55914 | valueCallback.onRead = onRead; |
| 55915 | valueCallback.onWrite = NULL; |
| 55916 | //ToDo: Need to move the browse name from namespaceindex 0 to 1 |
| 55917 | UA_NodeId configurationVersionNode = |
| 55918 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "ConfigurationVersion"), |
| 55919 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 55920 | startingNode: publishedDataSet->identifier); |
| 55921 | if(UA_NodeId_isNull(p: &configurationVersionNode)) |
| 55922 | return UA_STATUSCODE_BADNOTFOUND; |
| 55923 | |
| 55924 | UA_NodePropertyContext *configurationVersionContext = (UA_NodePropertyContext *) |
| 55925 | UA_malloc(size: sizeof(UA_NodePropertyContext)); |
| 55926 | configurationVersionContext->parentNodeId = publishedDataSet->identifier; |
| 55927 | configurationVersionContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE; |
| 55928 | configurationVersionContext->elementClassiefier = |
| 55929 | UA_NS0ID_PUBLISHEDDATAITEMSTYPE_CONFIGURATIONVERSION; |
| 55930 | retVal |= addVariableValueSource(server, valueCallback, node: configurationVersionNode, |
| 55931 | context: configurationVersionContext); |
| 55932 | |
| 55933 | UA_NodeId publishedDataNode = |
| 55934 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PublishedData"), |
| 55935 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 55936 | startingNode: publishedDataSet->identifier); |
| 55937 | if(UA_NodeId_isNull(p: &publishedDataNode)) |
| 55938 | return UA_STATUSCODE_BADNOTFOUND; |
| 55939 | |
| 55940 | UA_NodePropertyContext * publishingIntervalContext = (UA_NodePropertyContext *) |
| 55941 | UA_malloc(size: sizeof(UA_NodePropertyContext)); |
| 55942 | publishingIntervalContext->parentNodeId = publishedDataSet->identifier; |
| 55943 | publishingIntervalContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE; |
| 55944 | publishingIntervalContext->elementClassiefier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE_PUBLISHEDDATA; |
| 55945 | retVal |= addVariableValueSource(server, valueCallback, node: publishedDataNode, |
| 55946 | context: publishingIntervalContext); |
| 55947 | |
| 55948 | UA_NodeId dataSetMetaDataNode = |
| 55949 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetMetaData"), |
| 55950 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 55951 | startingNode: publishedDataSet->identifier); |
| 55952 | if(UA_NodeId_isNull(p: &dataSetMetaDataNode)) |
| 55953 | return UA_STATUSCODE_BADNOTFOUND; |
| 55954 | |
| 55955 | UA_NodePropertyContext *metaDataContext = (UA_NodePropertyContext *) |
| 55956 | UA_malloc(size: sizeof(UA_NodePropertyContext)); |
| 55957 | metaDataContext->parentNodeId = publishedDataSet->identifier; |
| 55958 | metaDataContext->parentClassifier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE; |
| 55959 | metaDataContext->elementClassiefier = UA_NS0ID_PUBLISHEDDATAITEMSTYPE_DATASETMETADATA; |
| 55960 | retVal |= addVariableValueSource(server, valueCallback, |
| 55961 | node: dataSetMetaDataNode, context: metaDataContext); |
| 55962 | |
| 55963 | if(server->config.pubSubConfig.enableInformationModelMethods) { |
| 55964 | retVal |= addRef(server, sourceId: publishedDataSet->identifier, |
| 55965 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55966 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_ADDVARIABLES), true); |
| 55967 | retVal |= addRef(server, sourceId: publishedDataSet->identifier, |
| 55968 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 55969 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_REMOVEVARIABLES), true); |
| 55970 | } |
| 55971 | return retVal; |
| 55972 | } |
| 55973 | |
| 55974 | static UA_StatusCode |
| 55975 | addPublishedDataItemsAction(UA_Server *server, |
| 55976 | const UA_NodeId *sessionId, void *sessionHandle, |
| 55977 | const UA_NodeId *methodId, void *methodContext, |
| 55978 | const UA_NodeId *objectId, void *objectContext, |
| 55979 | size_t inputSize, const UA_Variant *input, |
| 55980 | size_t outputSize, UA_Variant *output){ |
| 55981 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 55982 | size_t fieldNameAliasesSize = input[1].arrayLength; |
| 55983 | UA_String * fieldNameAliases = (UA_String *) input[1].data; |
| 55984 | size_t fieldFlagsSize = input[2].arrayLength; |
| 55985 | UA_DataSetFieldFlags * fieldFlags = (UA_DataSetFieldFlags *) input[2].data; |
| 55986 | size_t variablesToAddSize = input[3].arrayLength; |
| 55987 | UA_PublishedVariableDataType *eoAddVar = |
| 55988 | (UA_PublishedVariableDataType *)input[3].data; |
| 55989 | |
| 55990 | if(fieldNameAliasesSize != fieldFlagsSize || |
| 55991 | fieldFlagsSize != variablesToAddSize) |
| 55992 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 55993 | |
| 55994 | UA_PublishedDataSetConfig publishedDataSetConfig; |
| 55995 | memset(s: &publishedDataSetConfig, c: 0, n: sizeof(publishedDataSetConfig)); |
| 55996 | publishedDataSetConfig.name = *((UA_String *) input[0].data); |
| 55997 | publishedDataSetConfig.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS; |
| 55998 | |
| 55999 | UA_NodeId dataSetItemsNodeId; |
| 56000 | retVal |= UA_Server_addPublishedDataSet(server, publishedDataSetConfig: &publishedDataSetConfig, |
| 56001 | pdsIdentifier: &dataSetItemsNodeId).addResult; |
| 56002 | if(retVal != UA_STATUSCODE_GOOD) { |
| 56003 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 56004 | msg: "addPublishedDataset failed"); |
| 56005 | return retVal; |
| 56006 | } |
| 56007 | |
| 56008 | UA_DataSetFieldConfig dataSetFieldConfig; |
| 56009 | for(size_t j = 0; j < variablesToAddSize; ++j) { |
| 56010 | /* Prepare the config */ |
| 56011 | memset(s: &dataSetFieldConfig, c: 0, n: sizeof(UA_DataSetFieldConfig)); |
| 56012 | dataSetFieldConfig.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE; |
| 56013 | dataSetFieldConfig.field.variable.fieldNameAlias = fieldNameAliases[j]; |
| 56014 | dataSetFieldConfig.field.variable.publishParameters = eoAddVar[j]; |
| 56015 | if(fieldFlags[j] == UA_DATASETFIELDFLAGS_PROMOTEDFIELD) |
| 56016 | dataSetFieldConfig.field.variable.promotedField = true; |
| 56017 | retVal |= UA_Server_addDataSetField(server, publishedDataSet: dataSetItemsNodeId, |
| 56018 | fieldConfig: &dataSetFieldConfig, NULL).result; |
| 56019 | if(retVal != UA_STATUSCODE_GOOD) { |
| 56020 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 56021 | msg: "addDataSetField failed"); |
| 56022 | return retVal; |
| 56023 | } |
| 56024 | } |
| 56025 | |
| 56026 | UA_Variant_setScalarCopy(v: output, p: &dataSetItemsNodeId, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 56027 | return retVal; |
| 56028 | } |
| 56029 | |
| 56030 | static UA_StatusCode |
| 56031 | addVariablesAction(UA_Server *server, |
| 56032 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56033 | const UA_NodeId *methodId, void *methodContext, |
| 56034 | const UA_NodeId *objectId, void *objectContext, |
| 56035 | size_t inputSize, const UA_Variant *input, |
| 56036 | size_t outputSize, UA_Variant *output){ |
| 56037 | return UA_STATUSCODE_GOOD; |
| 56038 | } |
| 56039 | |
| 56040 | static UA_StatusCode |
| 56041 | removeVariablesAction(UA_Server *server, |
| 56042 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56043 | const UA_NodeId *methodId, void *methodContext, |
| 56044 | const UA_NodeId *objectId, void *objectContext, |
| 56045 | size_t inputSize, const UA_Variant *input, |
| 56046 | size_t outputSize, UA_Variant *output){ |
| 56047 | return UA_STATUSCODE_GOOD; |
| 56048 | } |
| 56049 | |
| 56050 | static UA_StatusCode |
| 56051 | removePublishedDataSetAction(UA_Server *server, |
| 56052 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56053 | const UA_NodeId *methodId, void *methodContext, |
| 56054 | const UA_NodeId *objectId, void *objectContext, |
| 56055 | size_t inputSize, const UA_Variant *input, |
| 56056 | size_t outputSize, UA_Variant *output){ |
| 56057 | UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data); |
| 56058 | return UA_Server_removePublishedDataSet(server, pds: nodeToRemove); |
| 56059 | } |
| 56060 | |
| 56061 | /**********************************************/ |
| 56062 | /* StandaloneSubscribedDataSet */ |
| 56063 | /**********************************************/ |
| 56064 | |
| 56065 | UA_StatusCode |
| 56066 | addStandaloneSubscribedDataSetRepresentation(UA_Server *server, |
| 56067 | UA_StandaloneSubscribedDataSet *subscribedDataSet) { |
| 56068 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56069 | |
| 56070 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 56071 | if(subscribedDataSet->config.name.length > 512) |
| 56072 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 56073 | |
| 56074 | UA_STACKARRAY(char, sdsName, sizeof(char) * subscribedDataSet->config.name.length +1); |
| 56075 | memcpy(dest: sdsName, src: subscribedDataSet->config.name.data, n: subscribedDataSet->config.name.length); |
| 56076 | sdsName[subscribedDataSet->config.name.length] = '\0'; |
| 56077 | |
| 56078 | UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; |
| 56079 | object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: sdsName); |
| 56080 | addNode(server, nodeClass: UA_NODECLASS_OBJECT, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), /* Create a new id */ |
| 56081 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_SUBSCRIBEDDATASETS), |
| 56082 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56083 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: sdsName), |
| 56084 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_STANDALONESUBSCRIBEDDATASETTYPE), |
| 56085 | attr: &object_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 56086 | NULL, outNewNodeId: &subscribedDataSet->identifier); |
| 56087 | UA_NodeId sdsObjectNode = findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "SubscribedDataSet"), |
| 56088 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56089 | startingNode: subscribedDataSet->identifier); |
| 56090 | UA_NodeId metaDataId = findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetMetaData"), |
| 56091 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 56092 | startingNode: subscribedDataSet->identifier); |
| 56093 | UA_NodeId connectedId = findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "IsConnected"), |
| 56094 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 56095 | startingNode: subscribedDataSet->identifier); |
| 56096 | |
| 56097 | if(UA_NodeId_equal(p1: &sdsObjectNode, p2: &UA_NODEID_NULL) || |
| 56098 | UA_NodeId_equal(p1: &metaDataId, p2: &UA_NODEID_NULL) || |
| 56099 | UA_NodeId_equal(p1: &connectedId, p2: &UA_NODEID_NULL)) { |
| 56100 | return UA_STATUSCODE_BADNOTFOUND; |
| 56101 | } |
| 56102 | if(subscribedDataSet->config.subscribedDataSetType == UA_PUBSUB_SDS_TARGET){ |
| 56103 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 56104 | UA_NodeId targetVarsId; |
| 56105 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TargetVariables"); |
| 56106 | attr.dataType = UA_TYPES[UA_TYPES_FIELDTARGETDATATYPE].typeId; |
| 56107 | attr.valueRank = UA_VALUERANK_ONE_DIMENSION; |
| 56108 | attr.arrayDimensionsSize = 1; |
| 56109 | UA_UInt32 arrayDimensions[1]; |
| 56110 | arrayDimensions[0] = (UA_UInt32) |
| 56111 | subscribedDataSet->config.subscribedDataSet.target.targetVariablesSize; |
| 56112 | attr.arrayDimensions = arrayDimensions; |
| 56113 | attr.accessLevel = UA_ACCESSLEVELMASK_READ; |
| 56114 | UA_Variant_setArray(v: &attr.value, |
| 56115 | array: subscribedDataSet->config.subscribedDataSet.target.targetVariables, |
| 56116 | arraySize: subscribedDataSet->config.subscribedDataSet.target.targetVariablesSize, |
| 56117 | type: &UA_TYPES[UA_TYPES_FIELDTARGETDATATYPE]); |
| 56118 | ret |= addNode(server, nodeClass: UA_NODECLASS_VARIABLE, requestedNewNodeId: UA_NODEID_NULL, parentNodeId: sdsObjectNode, |
| 56119 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 56120 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "TargetVariables"), |
| 56121 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PROPERTYTYPE), |
| 56122 | attr: &attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES], |
| 56123 | NULL, outNewNodeId: &targetVarsId); |
| 56124 | } |
| 56125 | |
| 56126 | UA_NodePropertyContext *isConnectedNodeContext = (UA_NodePropertyContext *) |
| 56127 | UA_malloc(size: sizeof(UA_NodePropertyContext)); |
| 56128 | isConnectedNodeContext->parentNodeId = subscribedDataSet->identifier; |
| 56129 | isConnectedNodeContext->parentClassifier = UA_NS0ID_STANDALONESUBSCRIBEDDATASETREFDATATYPE; |
| 56130 | isConnectedNodeContext->elementClassiefier = UA_NS0ID_STANDALONESUBSCRIBEDDATASETTYPE_ISCONNECTED; |
| 56131 | |
| 56132 | UA_ValueCallback valueCallback; |
| 56133 | valueCallback.onRead = onRead; |
| 56134 | valueCallback.onWrite = NULL; |
| 56135 | ret |= addVariableValueSource(server, valueCallback, node: connectedId, context: isConnectedNodeContext); |
| 56136 | |
| 56137 | UA_NodePropertyContext *metaDataContext = (UA_NodePropertyContext *) |
| 56138 | UA_malloc(size: sizeof(UA_NodePropertyContext)); |
| 56139 | metaDataContext->parentNodeId = subscribedDataSet->identifier; |
| 56140 | metaDataContext->parentClassifier = UA_NS0ID_STANDALONESUBSCRIBEDDATASETREFDATATYPE; |
| 56141 | metaDataContext->elementClassiefier = UA_NS0ID_STANDALONESUBSCRIBEDDATASETTYPE_DATASETMETADATA; |
| 56142 | ret |= addVariableValueSource(server, valueCallback, node: metaDataId, context: metaDataContext); |
| 56143 | |
| 56144 | return ret; |
| 56145 | } |
| 56146 | |
| 56147 | /**********************************************/ |
| 56148 | /* WriterGroup */ |
| 56149 | /**********************************************/ |
| 56150 | |
| 56151 | static UA_StatusCode |
| 56152 | readContentMask(UA_Server *server, const UA_NodeId *sessionId, |
| 56153 | void *sessionContext, const UA_NodeId *nodeId, |
| 56154 | void *nodeContext, UA_Boolean includeSourceTimeStamp, |
| 56155 | const UA_NumericRange *range, UA_DataValue *value) { |
| 56156 | UA_WriterGroup *writerGroup = (UA_WriterGroup*)nodeContext; |
| 56157 | if((writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED && |
| 56158 | writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) || |
| 56159 | writerGroup->config.messageSettings.content.decoded.type != |
| 56160 | &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]) |
| 56161 | return UA_STATUSCODE_BADINTERNALERROR; |
| 56162 | UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*) |
| 56163 | writerGroup->config.messageSettings.content.decoded.data; |
| 56164 | |
| 56165 | UA_Variant_setScalarCopy(v: &value->value, p: &wgm->networkMessageContentMask, |
| 56166 | type: &UA_TYPES[UA_TYPES_UADPNETWORKMESSAGECONTENTMASK]); |
| 56167 | value->hasValue = true; |
| 56168 | return UA_STATUSCODE_GOOD; |
| 56169 | } |
| 56170 | |
| 56171 | static UA_StatusCode |
| 56172 | writeContentMask(UA_Server *server, const UA_NodeId *sessionId, |
| 56173 | void *sessionContext, const UA_NodeId *nodeId, |
| 56174 | void *nodeContext, const UA_NumericRange *range, |
| 56175 | const UA_DataValue *value) { |
| 56176 | UA_WriterGroup *writerGroup = (UA_WriterGroup*)nodeContext; |
| 56177 | if((writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED && |
| 56178 | writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) || |
| 56179 | writerGroup->config.messageSettings.content.decoded.type != |
| 56180 | &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]) |
| 56181 | return UA_STATUSCODE_BADINTERNALERROR; |
| 56182 | UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*) |
| 56183 | writerGroup->config.messageSettings.content.decoded.data; |
| 56184 | |
| 56185 | if(!value->value.type) |
| 56186 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 56187 | if(value->value.type->typeKind != UA_DATATYPEKIND_ENUM && |
| 56188 | value->value.type->typeKind != UA_DATATYPEKIND_INT32) |
| 56189 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 56190 | |
| 56191 | wgm->networkMessageContentMask = *(UA_UadpNetworkMessageContentMask*)value->value.data; |
| 56192 | return UA_STATUSCODE_GOOD; |
| 56193 | } |
| 56194 | |
| 56195 | static UA_StatusCode |
| 56196 | readGroupVersion(UA_Server *server, const UA_NodeId *sessionId, |
| 56197 | void *sessionContext, const UA_NodeId *nodeId, |
| 56198 | void *nodeContext, UA_Boolean includeSourceTimeStamp, |
| 56199 | const UA_NumericRange *range, UA_DataValue *value) { |
| 56200 | UA_WriterGroup *writerGroup = (UA_WriterGroup*)nodeContext; |
| 56201 | if((writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED && |
| 56202 | writerGroup->config.messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) || |
| 56203 | writerGroup->config.messageSettings.content.decoded.type != |
| 56204 | &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]) |
| 56205 | return UA_STATUSCODE_BADINTERNALERROR; |
| 56206 | UA_UadpWriterGroupMessageDataType *wgm = (UA_UadpWriterGroupMessageDataType*) |
| 56207 | writerGroup->config.messageSettings.content.decoded.data; |
| 56208 | |
| 56209 | UA_Variant_setScalarCopy(v: &value->value, p: &wgm->groupVersion, |
| 56210 | type: &UA_TYPES[UA_DATATYPEKIND_UINT32]); |
| 56211 | value->hasValue = true; |
| 56212 | return UA_STATUSCODE_GOOD; |
| 56213 | } |
| 56214 | |
| 56215 | UA_StatusCode |
| 56216 | addWriterGroupRepresentation(UA_Server *server, UA_WriterGroup *writerGroup) { |
| 56217 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56218 | |
| 56219 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 56220 | if(writerGroup->config.name.length > 512) |
| 56221 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 56222 | char wgName[513]; |
| 56223 | memcpy(dest: wgName, src: writerGroup->config.name.data, n: writerGroup->config.name.length); |
| 56224 | wgName[writerGroup->config.name.length] = '\0'; |
| 56225 | |
| 56226 | UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; |
| 56227 | object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: wgName); |
| 56228 | retVal = addNode(server, nodeClass: UA_NODECLASS_OBJECT, |
| 56229 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), /* create a new id */ |
| 56230 | parentNodeId: writerGroup->linkedConnection->identifier, |
| 56231 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56232 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: wgName), |
| 56233 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_WRITERGROUPTYPE), |
| 56234 | attr: &object_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 56235 | NULL, outNewNodeId: &writerGroup->identifier); |
| 56236 | |
| 56237 | UA_NodeId keepAliveNode = |
| 56238 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "KeepAliveTime"), |
| 56239 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 56240 | startingNode: writerGroup->identifier); |
| 56241 | UA_NodeId publishingIntervalNode = |
| 56242 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PublishingInterval"), |
| 56243 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 56244 | startingNode: writerGroup->identifier); |
| 56245 | if(UA_NodeId_isNull(p: &keepAliveNode) || |
| 56246 | UA_NodeId_isNull(p: &publishingIntervalNode)) |
| 56247 | return UA_STATUSCODE_BADNOTFOUND; |
| 56248 | |
| 56249 | UA_NodePropertyContext * publishingIntervalContext = (UA_NodePropertyContext *) |
| 56250 | UA_malloc(size: sizeof(UA_NodePropertyContext)); |
| 56251 | publishingIntervalContext->parentNodeId = writerGroup->identifier; |
| 56252 | publishingIntervalContext->parentClassifier = UA_NS0ID_WRITERGROUPTYPE; |
| 56253 | publishingIntervalContext->elementClassiefier = UA_NS0ID_WRITERGROUPTYPE_PUBLISHINGINTERVAL; |
| 56254 | UA_ValueCallback valueCallback; |
| 56255 | valueCallback.onRead = onRead; |
| 56256 | valueCallback.onWrite = onWrite; |
| 56257 | retVal |= addVariableValueSource(server, valueCallback, |
| 56258 | node: publishingIntervalNode, context: publishingIntervalContext); |
| 56259 | writeAccessLevelAttribute(server, nodeId: publishingIntervalNode, |
| 56260 | UA_ACCESSLEVELMASK_READ ^ UA_ACCESSLEVELMASK_WRITE); |
| 56261 | |
| 56262 | UA_NodeId priorityNode = |
| 56263 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "Priority"), |
| 56264 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 56265 | startingNode: writerGroup->identifier); |
| 56266 | UA_NodeId writerGroupIdNode = |
| 56267 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "WriterGroupId"), |
| 56268 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 56269 | startingNode: writerGroup->identifier); |
| 56270 | |
| 56271 | UA_Variant value; |
| 56272 | UA_Variant_init(p: &value); |
| 56273 | UA_Variant_setScalar(v: &value, p: &writerGroup->config.publishingInterval, type: &UA_TYPES[UA_TYPES_DURATION]); |
| 56274 | writeValueAttribute(server, nodeId: publishingIntervalNode, value: &value); |
| 56275 | UA_Variant_setScalar(v: &value, p: &writerGroup->config.keepAliveTime, type: &UA_TYPES[UA_TYPES_DURATION]); |
| 56276 | writeValueAttribute(server, nodeId: keepAliveNode, value: &value); |
| 56277 | UA_Variant_setScalar(v: &value, p: &writerGroup->config.priority, type: &UA_TYPES[UA_TYPES_BYTE]); |
| 56278 | writeValueAttribute(server, nodeId: priorityNode, value: &value); |
| 56279 | UA_Variant_setScalar(v: &value, p: &writerGroup->config.writerGroupId, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 56280 | writeValueAttribute(server, nodeId: writerGroupIdNode, value: &value); |
| 56281 | |
| 56282 | object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MessageSettings"); |
| 56283 | retVal |= addNode(server, nodeClass: UA_NODECLASS_OBJECT, |
| 56284 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), |
| 56285 | parentNodeId: writerGroup->identifier, |
| 56286 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56287 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "MessageSettings"), |
| 56288 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_UADPWRITERGROUPMESSAGETYPE), |
| 56289 | attr: &object_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 56290 | NULL, NULL); |
| 56291 | |
| 56292 | /* Find the variable with the content mask */ |
| 56293 | |
| 56294 | UA_NodeId messageSettingsId = |
| 56295 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "MessageSettings"), |
| 56296 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56297 | startingNode: writerGroup->identifier); |
| 56298 | UA_NodeId contentMaskId = |
| 56299 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "NetworkMessageContentMask"), |
| 56300 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: messageSettingsId); |
| 56301 | if(!UA_NodeId_isNull(p: &contentMaskId)) { |
| 56302 | /* Set the callback */ |
| 56303 | UA_DataSource ds; |
| 56304 | ds.read = readContentMask; |
| 56305 | ds.write = writeContentMask; |
| 56306 | setVariableNode_dataSource(server, nodeId: contentMaskId, dataSource: ds); |
| 56307 | setNodeContext(server, nodeId: contentMaskId, nodeContext: writerGroup); |
| 56308 | |
| 56309 | /* Make writable */ |
| 56310 | writeAccessLevelAttribute(server, nodeId: contentMaskId, |
| 56311 | UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_READ); |
| 56312 | |
| 56313 | } |
| 56314 | UA_NodeId groupVersionId = |
| 56315 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "GroupVersion"), |
| 56316 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: messageSettingsId); |
| 56317 | if(!UA_NodeId_isNull(p: &groupVersionId)) { |
| 56318 | /* Set the callback */ |
| 56319 | UA_DataSource ds; |
| 56320 | ds.read = readGroupVersion; |
| 56321 | ds.write = NULL; |
| 56322 | setVariableNode_dataSource(server, nodeId: groupVersionId, dataSource: ds); |
| 56323 | setNodeContext(server, nodeId: groupVersionId, nodeContext: writerGroup); |
| 56324 | |
| 56325 | /* Read only */ |
| 56326 | writeAccessLevelAttribute(server, nodeId: groupVersionId, |
| 56327 | UA_ACCESSLEVELMASK_READ); |
| 56328 | |
| 56329 | } |
| 56330 | |
| 56331 | /* Add reference to methods */ |
| 56332 | if(server->config.pubSubConfig.enableInformationModelMethods) { |
| 56333 | retVal |= addRef(server, sourceId: writerGroup->identifier, |
| 56334 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56335 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_WRITERGROUPTYPE_ADDDATASETWRITER), true); |
| 56336 | retVal |= addRef(server, sourceId: writerGroup->identifier, |
| 56337 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56338 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_WRITERGROUPTYPE_REMOVEDATASETWRITER), true); |
| 56339 | } |
| 56340 | return retVal; |
| 56341 | } |
| 56342 | |
| 56343 | static UA_StatusCode |
| 56344 | addWriterGroupAction(UA_Server *server, |
| 56345 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56346 | const UA_NodeId *methodId, void *methodContext, |
| 56347 | const UA_NodeId *objectId, void *objectContext, |
| 56348 | size_t inputSize, const UA_Variant *input, |
| 56349 | size_t outputSize, UA_Variant *output){ |
| 56350 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56351 | |
| 56352 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 56353 | UA_WriterGroupDataType *writerGroup = ((UA_WriterGroupDataType *) input[0].data); |
| 56354 | UA_NodeId writerGroupId; |
| 56355 | retVal |= addWriterGroupConfig(server, connectionId: *objectId, writerGroup, writerGroupId: &writerGroupId); |
| 56356 | if(retVal != UA_STATUSCODE_GOOD) { |
| 56357 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, msg: "addWriterGroup failed"); |
| 56358 | return retVal; |
| 56359 | } |
| 56360 | // TODO: Need to handle the UA_Server_setWriterGroupOperational based on the |
| 56361 | // status variable in information model |
| 56362 | |
| 56363 | UA_Variant_setScalarCopy(v: output, p: &writerGroupId, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 56364 | return retVal; |
| 56365 | } |
| 56366 | |
| 56367 | static UA_StatusCode |
| 56368 | removeGroupAction(UA_Server *server, |
| 56369 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56370 | const UA_NodeId *methodId, void *methodContext, |
| 56371 | const UA_NodeId *objectId, void *objectContext, |
| 56372 | size_t inputSize, const UA_Variant *input, |
| 56373 | size_t outputSize, UA_Variant *output){ |
| 56374 | UA_NodeId nodeToRemove = *((UA_NodeId *)input->data); |
| 56375 | if(UA_WriterGroup_findWGbyId(server, identifier: nodeToRemove)) { |
| 56376 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: nodeToRemove); |
| 56377 | if(wg->configurationFrozen) |
| 56378 | UA_Server_unfreezeWriterGroupConfiguration(server, writerGroup: nodeToRemove); |
| 56379 | return UA_Server_removeWriterGroup(server, writerGroup: nodeToRemove); |
| 56380 | } else { |
| 56381 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, identifier: nodeToRemove); |
| 56382 | if(rg->configurationFrozen) |
| 56383 | UA_Server_unfreezeReaderGroupConfiguration(server, readerGroupId: nodeToRemove); |
| 56384 | return UA_Server_removeReaderGroup(server, groupIdentifier: nodeToRemove); |
| 56385 | } |
| 56386 | } |
| 56387 | |
| 56388 | /**********************************************/ |
| 56389 | /* ReserveIds */ |
| 56390 | /**********************************************/ |
| 56391 | |
| 56392 | static UA_StatusCode |
| 56393 | addReserveIdsLocked(UA_Server *server, |
| 56394 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56395 | const UA_NodeId *methodId, void *methodContext, |
| 56396 | const UA_NodeId *objectId, void *objectContext, |
| 56397 | size_t inputSize, const UA_Variant *input, |
| 56398 | size_t outputSize, UA_Variant *output){ |
| 56399 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56400 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 56401 | UA_String transportProfileUri = *((UA_String *)input[0].data); |
| 56402 | UA_UInt16 numRegWriterGroupIds = *((UA_UInt16 *)input[1].data); |
| 56403 | UA_UInt16 numRegDataSetWriterIds = *((UA_UInt16 *)input[2].data); |
| 56404 | |
| 56405 | UA_UInt16 *writerGroupIds; |
| 56406 | UA_UInt16 *dataSetWriterIds; |
| 56407 | |
| 56408 | retVal |= UA_PubSubManager_reserveIds(server, sessionId: *sessionId, numRegWriterGroupIds, |
| 56409 | numRegDataSetWriterIds, transportProfileUri, |
| 56410 | writerGroupIds: &writerGroupIds, dataSetWriterIds: &dataSetWriterIds); |
| 56411 | if(retVal != UA_STATUSCODE_GOOD) { |
| 56412 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, msg: "addReserveIds failed"); |
| 56413 | return retVal; |
| 56414 | } |
| 56415 | |
| 56416 | /* Check the transportProfileUri */ |
| 56417 | UA_String profile_1 = UA_STRING(chars: "http://opcfoundation.org/UA-Profile/Transport/pubsub-mqtt-uadp"); |
| 56418 | UA_String profile_2 = UA_STRING(chars: "http://opcfoundation.org/UA-Profile/Transport/pubsub-mqtt-json"); |
| 56419 | |
| 56420 | if(UA_String_equal(p1: &transportProfileUri, p2: &profile_1) || |
| 56421 | UA_String_equal(p1: &transportProfileUri, p2: &profile_2)) { |
| 56422 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, msg: "ApplicationUri: %.*s", |
| 56423 | (int)server->config.applicationDescription.applicationUri.length, |
| 56424 | server->config.applicationDescription.applicationUri.data); |
| 56425 | retVal |= UA_Variant_setScalarCopy(v: &output[0], |
| 56426 | p: &server->config.applicationDescription.applicationUri, |
| 56427 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 56428 | } else { |
| 56429 | retVal |= UA_Variant_setScalarCopy(v: &output[0], |
| 56430 | p: &server->pubSubManager.defaultPublisherId, |
| 56431 | type: &UA_TYPES[UA_TYPES_UINT64]); |
| 56432 | } |
| 56433 | |
| 56434 | UA_Variant_setArray(v: &output[1], array: writerGroupIds, |
| 56435 | arraySize: numRegWriterGroupIds, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 56436 | UA_Variant_setArray(v: &output[2], array: dataSetWriterIds, |
| 56437 | arraySize: numRegDataSetWriterIds, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 56438 | |
| 56439 | return retVal; |
| 56440 | } |
| 56441 | |
| 56442 | static UA_StatusCode |
| 56443 | addReserveIdsAction(UA_Server *server, |
| 56444 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56445 | const UA_NodeId *methodId, void *methodContext, |
| 56446 | const UA_NodeId *objectId, void *objectContext, |
| 56447 | size_t inputSize, const UA_Variant *input, |
| 56448 | size_t outputSize, UA_Variant *output) { |
| 56449 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56450 | return addReserveIdsLocked(server, sessionId, sessionHandle, |
| 56451 | methodId, methodContext, objectId, objectContext, |
| 56452 | inputSize, input, outputSize, output); |
| 56453 | } |
| 56454 | |
| 56455 | /**********************************************/ |
| 56456 | /* ReaderGroup */ |
| 56457 | /**********************************************/ |
| 56458 | |
| 56459 | UA_StatusCode |
| 56460 | addReaderGroupRepresentation(UA_Server *server, UA_ReaderGroup *readerGroup) { |
| 56461 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56462 | if(readerGroup->config.name.length > 512) |
| 56463 | return UA_STATUSCODE_BADCONFIGURATIONERROR; |
| 56464 | char rgName[513]; |
| 56465 | memcpy(dest: rgName, src: readerGroup->config.name.data, n: readerGroup->config.name.length); |
| 56466 | rgName[readerGroup->config.name.length] = '\0'; |
| 56467 | |
| 56468 | UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; |
| 56469 | object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: rgName); |
| 56470 | UA_StatusCode retVal = |
| 56471 | addNode(server, nodeClass: UA_NODECLASS_OBJECT, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), /* create an id */ |
| 56472 | parentNodeId: readerGroup->linkedConnection->identifier, |
| 56473 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56474 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: rgName), typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_READERGROUPTYPE), |
| 56475 | attr: &object_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 56476 | NULL, outNewNodeId: &readerGroup->identifier); |
| 56477 | if(server->config.pubSubConfig.enableInformationModelMethods) { |
| 56478 | retVal |= addRef(server, sourceId: readerGroup->identifier, |
| 56479 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56480 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_READERGROUPTYPE_ADDDATASETREADER), true); |
| 56481 | retVal |= addRef(server, sourceId: readerGroup->identifier, |
| 56482 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56483 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_READERGROUPTYPE_REMOVEDATASETREADER), true); |
| 56484 | } |
| 56485 | return retVal; |
| 56486 | } |
| 56487 | |
| 56488 | static UA_StatusCode |
| 56489 | addReaderGroupAction(UA_Server *server, |
| 56490 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56491 | const UA_NodeId *methodId, void *methodContext, |
| 56492 | const UA_NodeId *objectId, void *objectContext, |
| 56493 | size_t inputSize, const UA_Variant *input, |
| 56494 | size_t outputSize, UA_Variant *output) { |
| 56495 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56496 | |
| 56497 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 56498 | UA_ReaderGroupDataType *readerGroup = ((UA_ReaderGroupDataType *) input->data); |
| 56499 | UA_NodeId readerGroupId; |
| 56500 | retVal |= addReaderGroupConfig(server, connectionId: *objectId, readerGroup, readerGroupId: &readerGroupId); |
| 56501 | if(retVal != UA_STATUSCODE_GOOD) { |
| 56502 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, msg: "addReaderGroup failed"); |
| 56503 | return retVal; |
| 56504 | } |
| 56505 | // TODO: Need to handle the UA_Server_setReaderGroupOperational based on the |
| 56506 | // status variable in information model |
| 56507 | |
| 56508 | UA_Variant_setScalarCopy(v: output, p: &readerGroupId, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 56509 | return retVal; |
| 56510 | } |
| 56511 | |
| 56512 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 56513 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 56514 | static UA_Boolean |
| 56515 | isValidParentNode(UA_Server *server, UA_NodeId parentId) { |
| 56516 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56517 | UA_Boolean retval = true; |
| 56518 | const UA_Node *parentNodeType; |
| 56519 | const UA_NodeId parentNodeTypeId = |
| 56520 | UA_NODEID_NUMERIC(0, UA_NS0ID_SECURITYGROUPFOLDERTYPE); |
| 56521 | const UA_Node *parentNode = UA_NODESTORE_GET(server, &parentId); |
| 56522 | |
| 56523 | if(parentNode) { |
| 56524 | parentNodeType = getNodeType(server, &parentNode->head); |
| 56525 | if(parentNodeType) { |
| 56526 | retval = UA_NodeId_equal(&parentNodeType->head.nodeId, &parentNodeTypeId); |
| 56527 | UA_NODESTORE_RELEASE(server, parentNodeType); |
| 56528 | } |
| 56529 | UA_NODESTORE_RELEASE(server, parentNode); |
| 56530 | } |
| 56531 | return retval; |
| 56532 | } |
| 56533 | |
| 56534 | static UA_StatusCode |
| 56535 | updateSecurityGroupProperties(UA_Server *server, UA_NodeId *securityGroupNodeId, |
| 56536 | UA_SecurityGroupConfig *config) { |
| 56537 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56538 | |
| 56539 | UA_StatusCode retval = UA_STATUSCODE_BAD; |
| 56540 | UA_Variant value; |
| 56541 | UA_Variant_init(&value); |
| 56542 | UA_Variant_setScalar(&value, &config->securityGroupName, &UA_TYPES[UA_TYPES_STRING]); |
| 56543 | retval = writeObjectProperty(server, *securityGroupNodeId, |
| 56544 | UA_QUALIFIEDNAME(0, "SecurityGroupId"), value); |
| 56545 | if(retval != UA_STATUSCODE_GOOD) |
| 56546 | return retval; |
| 56547 | |
| 56548 | /*AddValueCallback*/ |
| 56549 | UA_Variant_setScalar(&value, &config->securityPolicyUri, &UA_TYPES[UA_TYPES_STRING]); |
| 56550 | retval = writeObjectProperty(server, *securityGroupNodeId, |
| 56551 | UA_QUALIFIEDNAME(0, "SecurityPolicyUri"), value); |
| 56552 | if(retval != UA_STATUSCODE_GOOD) |
| 56553 | return retval; |
| 56554 | |
| 56555 | UA_Variant_setScalar(&value, &config->keyLifeTime, &UA_TYPES[UA_TYPES_DURATION]); |
| 56556 | retval = writeObjectProperty(server, *securityGroupNodeId, |
| 56557 | UA_QUALIFIEDNAME(0, "KeyLifetime"), value); |
| 56558 | if(retval != UA_STATUSCODE_GOOD) |
| 56559 | return retval; |
| 56560 | |
| 56561 | UA_Variant_setScalar(&value, &config->maxFutureKeyCount, &UA_TYPES[UA_TYPES_UINT32]); |
| 56562 | retval = writeObjectProperty(server, *securityGroupNodeId, |
| 56563 | UA_QUALIFIEDNAME(0, "MaxFutureKeyCount"), value); |
| 56564 | if(retval != UA_STATUSCODE_GOOD) |
| 56565 | return retval; |
| 56566 | |
| 56567 | UA_Variant_setScalar(&value, &config->maxPastKeyCount, &UA_TYPES[UA_TYPES_UINT32]); |
| 56568 | retval = writeObjectProperty(server, *securityGroupNodeId, |
| 56569 | UA_QUALIFIEDNAME(0, "MaxPastKeyCount"), value); |
| 56570 | if(retval != UA_STATUSCODE_GOOD) |
| 56571 | return retval; |
| 56572 | |
| 56573 | return retval; |
| 56574 | } |
| 56575 | |
| 56576 | UA_StatusCode |
| 56577 | addSecurityGroupRepresentation(UA_Server *server, UA_SecurityGroup *securityGroup) { |
| 56578 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56579 | UA_StatusCode retval = UA_STATUSCODE_BAD; |
| 56580 | |
| 56581 | UA_SecurityGroupConfig *securityGroupConfig = &securityGroup->config; |
| 56582 | if(!isValidParentNode(server, securityGroup->securityGroupFolderId)) |
| 56583 | return UA_STATUSCODE_BADPARENTNODEIDINVALID; |
| 56584 | |
| 56585 | if(securityGroupConfig->securityGroupName.length <= 0) |
| 56586 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 56587 | |
| 56588 | UA_QualifiedName browseName; |
| 56589 | UA_QualifiedName_init(&browseName); |
| 56590 | browseName.name = securityGroupConfig->securityGroupName; |
| 56591 | |
| 56592 | UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; |
| 56593 | object_attr.displayName.text = securityGroupConfig->securityGroupName; |
| 56594 | UA_NodeId refType = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT); |
| 56595 | UA_NodeId nodeType = UA_NODEID_NUMERIC(0, UA_NS0ID_SECURITYGROUPTYPE); |
| 56596 | retval = addNode(server, UA_NODECLASS_OBJECT, UA_NODEID_NULL, |
| 56597 | securityGroup->securityGroupFolderId, refType, |
| 56598 | browseName, nodeType, &object_attr, |
| 56599 | &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], NULL, |
| 56600 | &securityGroup->securityGroupNodeId); |
| 56601 | if(retval != UA_STATUSCODE_GOOD) { |
| 56602 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 56603 | "Add SecurityGroup failed with error: %s.", |
| 56604 | UA_StatusCode_name(retval)); |
| 56605 | return retval; |
| 56606 | } |
| 56607 | |
| 56608 | retval = updateSecurityGroupProperties(server, |
| 56609 | &securityGroup->securityGroupNodeId, |
| 56610 | securityGroupConfig); |
| 56611 | if(retval != UA_STATUSCODE_GOOD) { |
| 56612 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 56613 | "Add SecurityGroup failed with error: %s.", |
| 56614 | UA_StatusCode_name(retval)); |
| 56615 | deleteNode(server, securityGroup->securityGroupNodeId, true); |
| 56616 | } |
| 56617 | return retval; |
| 56618 | } |
| 56619 | |
| 56620 | #endif /* UA_ENABLE_PUBSUB_INFORMATIONMODEL*/ |
| 56621 | #endif /* UA_ENABLE_PUBSUB_SKS */ |
| 56622 | |
| 56623 | /**********************************************/ |
| 56624 | /* DataSetWriter */ |
| 56625 | /**********************************************/ |
| 56626 | |
| 56627 | UA_StatusCode |
| 56628 | addDataSetWriterRepresentation(UA_Server *server, UA_DataSetWriter *dataSetWriter) { |
| 56629 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56630 | |
| 56631 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 56632 | if(dataSetWriter->config.name.length > 512) |
| 56633 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 56634 | |
| 56635 | char dswName[513]; |
| 56636 | memcpy(dest: dswName, src: dataSetWriter->config.name.data, n: dataSetWriter->config.name.length); |
| 56637 | dswName[dataSetWriter->config.name.length] = '\0'; |
| 56638 | |
| 56639 | UA_ObjectAttributes object_attr = UA_ObjectAttributes_default; |
| 56640 | object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: dswName); |
| 56641 | retVal = addNode(server, nodeClass: UA_NODECLASS_OBJECT, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), /* create an id */ |
| 56642 | parentNodeId: dataSetWriter->linkedWriterGroup, |
| 56643 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASDATASETWRITER), |
| 56644 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: dswName), |
| 56645 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETWRITERTYPE), |
| 56646 | attr: &object_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 56647 | NULL, outNewNodeId: &dataSetWriter->identifier); |
| 56648 | //if connected dataset is null this means it's configured for heartbeats |
| 56649 | if(!UA_NodeId_isNull(p: &dataSetWriter->connectedDataSet)) { |
| 56650 | retVal |= addRef(server, sourceId: dataSetWriter->connectedDataSet, |
| 56651 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETTOWRITER), |
| 56652 | targetId: dataSetWriter->identifier, true); |
| 56653 | } |
| 56654 | |
| 56655 | UA_NodeId dataSetWriterIdNode = |
| 56656 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetWriterId"), |
| 56657 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 56658 | startingNode: dataSetWriter->identifier); |
| 56659 | UA_NodeId keyFrameNode = |
| 56660 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "KeyFrameCount"), |
| 56661 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 56662 | startingNode: dataSetWriter->identifier); |
| 56663 | UA_NodeId dataSetFieldContentMaskNode = |
| 56664 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetFieldContentMask"), |
| 56665 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 56666 | startingNode: dataSetWriter->identifier); |
| 56667 | |
| 56668 | UA_NodePropertyContext *dataSetWriterIdContext = (UA_NodePropertyContext *) |
| 56669 | UA_malloc(size: sizeof(UA_NodePropertyContext)); |
| 56670 | dataSetWriterIdContext->parentNodeId = dataSetWriter->identifier; |
| 56671 | dataSetWriterIdContext->parentClassifier = UA_NS0ID_DATASETWRITERTYPE; |
| 56672 | dataSetWriterIdContext->elementClassiefier = UA_NS0ID_DATASETWRITERTYPE_DATASETWRITERID; |
| 56673 | UA_ValueCallback valueCallback; |
| 56674 | valueCallback.onRead = onRead; |
| 56675 | valueCallback.onWrite = NULL; |
| 56676 | retVal |= addVariableValueSource(server, valueCallback, |
| 56677 | node: dataSetWriterIdNode, context: dataSetWriterIdContext); |
| 56678 | |
| 56679 | UA_Variant value; |
| 56680 | UA_Variant_init(p: &value); |
| 56681 | UA_Variant_setScalar(v: &value, p: &dataSetWriter->config.dataSetWriterId, |
| 56682 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 56683 | writeValueAttribute(server, nodeId: dataSetWriterIdNode, value: &value); |
| 56684 | |
| 56685 | UA_Variant_setScalar(v: &value, p: &dataSetWriter->config.keyFrameCount, |
| 56686 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 56687 | writeValueAttribute(server, nodeId: keyFrameNode, value: &value); |
| 56688 | |
| 56689 | UA_Variant_setScalar(v: &value, p: &dataSetWriter->config.dataSetFieldContentMask, |
| 56690 | type: &UA_TYPES[UA_TYPES_DATASETFIELDCONTENTMASK]); |
| 56691 | writeValueAttribute(server, nodeId: dataSetFieldContentMaskNode, value: &value); |
| 56692 | |
| 56693 | object_attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MessageSettings"); |
| 56694 | retVal |= addNode(server, nodeClass: UA_NODECLASS_OBJECT, requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: 1, identifier: 0), |
| 56695 | parentNodeId: dataSetWriter->identifier, |
| 56696 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 56697 | browseName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "MessageSettings"), |
| 56698 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_UADPDATASETWRITERMESSAGETYPE), |
| 56699 | attr: &object_attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 56700 | NULL, NULL); |
| 56701 | |
| 56702 | return retVal; |
| 56703 | } |
| 56704 | |
| 56705 | static UA_StatusCode |
| 56706 | addDataSetWriterLocked(UA_Server *server, |
| 56707 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56708 | const UA_NodeId *methodId, void *methodContext, |
| 56709 | const UA_NodeId *objectId, void *objectContext, |
| 56710 | size_t inputSize, const UA_Variant *input, |
| 56711 | size_t outputSize, UA_Variant *output) { |
| 56712 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56713 | |
| 56714 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 56715 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, identifier: *objectId); |
| 56716 | if(!wg) { |
| 56717 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 56718 | msg: "Not a WriterGroup"); |
| 56719 | return UA_STATUSCODE_BAD; |
| 56720 | } |
| 56721 | if(wg->configurationFrozen) { |
| 56722 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 56723 | msg: "addDataSetWriter cannot be done because writergroup config frozen"); |
| 56724 | return UA_STATUSCODE_BAD; |
| 56725 | } |
| 56726 | |
| 56727 | UA_NodeId dataSetWriterId; |
| 56728 | UA_DataSetWriterDataType *dataSetWriterData = (UA_DataSetWriterDataType *)input->data; |
| 56729 | retVal |= addDataSetWriterConfig(server, writerGroupId: objectId, dataSetWriter: dataSetWriterData, dataSetWriterId: &dataSetWriterId); |
| 56730 | if(retVal != UA_STATUSCODE_GOOD) { |
| 56731 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 56732 | msg: "addDataSetWriter failed"); |
| 56733 | return retVal; |
| 56734 | } |
| 56735 | |
| 56736 | UA_Variant_setScalarCopy(v: output, p: &dataSetWriterId, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 56737 | return UA_STATUSCODE_GOOD; |
| 56738 | } |
| 56739 | |
| 56740 | static UA_StatusCode |
| 56741 | addDataSetWriterAction(UA_Server *server, |
| 56742 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56743 | const UA_NodeId *methodId, void *methodContext, |
| 56744 | const UA_NodeId *objectId, void *objectContext, |
| 56745 | size_t inputSize, const UA_Variant *input, |
| 56746 | size_t outputSize, UA_Variant *output) { |
| 56747 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56748 | return addDataSetWriterLocked(server, sessionId, sessionHandle, |
| 56749 | methodId, methodContext, objectId, objectContext, |
| 56750 | inputSize, input, outputSize, output); |
| 56751 | } |
| 56752 | |
| 56753 | static UA_StatusCode |
| 56754 | removeDataSetWriterAction(UA_Server *server, |
| 56755 | const UA_NodeId *sessionId, void *sessionHandle, |
| 56756 | const UA_NodeId *methodId, void *methodContext, |
| 56757 | const UA_NodeId *objectId, void *objectContext, |
| 56758 | size_t inputSize, const UA_Variant *input, |
| 56759 | size_t outputSize, UA_Variant *output){ |
| 56760 | UA_NodeId nodeToRemove = *((UA_NodeId *) input[0].data); |
| 56761 | return UA_Server_removeDataSetWriter(server, dsw: nodeToRemove); |
| 56762 | } |
| 56763 | |
| 56764 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 56765 | /** |
| 56766 | * @note The user credentials and permissions are checked in the AccessControl plugin |
| 56767 | * before this callback is executed. |
| 56768 | */ |
| 56769 | static UA_StatusCode |
| 56770 | setSecurityKeysLocked(UA_Server *server, const UA_NodeId *sessionId, void *sessionHandle, |
| 56771 | const UA_NodeId *methodId, void *methodContext, |
| 56772 | const UA_NodeId *objectId, void *objectContext, size_t inputSize, |
| 56773 | const UA_Variant *input, size_t outputSize, UA_Variant *output) { |
| 56774 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56775 | |
| 56776 | /*Check whether the channel is encrypted according to specification*/ |
| 56777 | session_list_entry *session_entry; |
| 56778 | LIST_FOREACH(session_entry, &server->sessions, pointers) { |
| 56779 | if(UA_NodeId_equal(&session_entry->session.sessionId, sessionId)) { |
| 56780 | if(session_entry->session.header.channel->securityMode != |
| 56781 | UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 56782 | return UA_STATUSCODE_BADSECURITYMODEINSUFFICIENT; |
| 56783 | } |
| 56784 | } |
| 56785 | |
| 56786 | if(!server || !input) |
| 56787 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 56788 | |
| 56789 | if(inputSize < 7) |
| 56790 | return UA_STATUSCODE_BADARGUMENTSMISSING; |
| 56791 | if(inputSize > 7 || outputSize > 0) |
| 56792 | return UA_STATUSCODE_BADTOOMANYARGUMENTS; |
| 56793 | |
| 56794 | /*check for types*/ |
| 56795 | if(!UA_Variant_hasScalarType(&input[0], &UA_TYPES[UA_TYPES_STRING]) || /*SecurityGroupId*/ |
| 56796 | !UA_Variant_hasScalarType(&input[1], &UA_TYPES[UA_TYPES_STRING]) || /*SecurityPolicyUri*/ |
| 56797 | !UA_Variant_hasScalarType(&input[2], &UA_TYPES[UA_TYPES_INTEGERID]) || /*CurrentTokenId*/ |
| 56798 | !UA_Variant_hasScalarType(&input[3], &UA_TYPES[UA_TYPES_BYTESTRING]) || /*CurrentKey*/ |
| 56799 | !UA_Variant_hasArrayType(&input[4], &UA_TYPES[UA_TYPES_BYTESTRING]) || /*FutureKeys*/ |
| 56800 | (!UA_Variant_hasScalarType(&input[5], &UA_TYPES[UA_TYPES_DURATION]) && |
| 56801 | !UA_Variant_hasScalarType(&input[5], &UA_TYPES[UA_TYPES_DOUBLE])) || /*TimeToNextKey*/ |
| 56802 | (!UA_Variant_hasScalarType(&input[6], &UA_TYPES[UA_TYPES_DURATION]) && |
| 56803 | !UA_Variant_hasScalarType(&input[6], &UA_TYPES[UA_TYPES_DOUBLE]))) /*TimeToNextKey*/ |
| 56804 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 56805 | |
| 56806 | UA_StatusCode retval = UA_STATUSCODE_BAD; |
| 56807 | UA_Duration callbackTime; |
| 56808 | UA_String *securityGroupId = (UA_String *)input[0].data; |
| 56809 | UA_String *securityPolicyUri = (UA_String *)input[1].data; |
| 56810 | UA_UInt32 currentKeyId = *(UA_UInt32 *)input[2].data; |
| 56811 | UA_ByteString *currentKey = (UA_ByteString *)input[3].data; |
| 56812 | UA_ByteString *futureKeys = (UA_ByteString *)input[4].data; |
| 56813 | size_t futureKeySize = input[4].arrayLength; |
| 56814 | UA_Duration msTimeToNextKey = *(UA_Duration *)input[5].data; |
| 56815 | UA_Duration msKeyLifeTime = *(UA_Duration *)input[6].data; |
| 56816 | |
| 56817 | UA_PubSubKeyStorage *ks = |
| 56818 | UA_PubSubKeyStorage_findKeyStorage(server, *securityGroupId); |
| 56819 | if(!ks) |
| 56820 | return UA_STATUSCODE_BADNOTFOUND; |
| 56821 | |
| 56822 | if(!UA_String_equal(securityPolicyUri, &ks->policy->policyUri)) |
| 56823 | return UA_STATUSCODE_BADSECURITYPOLICYREJECTED; |
| 56824 | |
| 56825 | if(ks->keyListSize == 0) { |
| 56826 | retval = UA_PubSubKeyStorage_storeSecurityKeys(server, ks, currentKeyId, |
| 56827 | currentKey, futureKeys, futureKeySize, |
| 56828 | msKeyLifeTime); |
| 56829 | if(retval != UA_STATUSCODE_GOOD) |
| 56830 | return retval; |
| 56831 | } else { |
| 56832 | retval = UA_PubSubKeyStorage_update(server, ks, currentKey, currentKeyId, |
| 56833 | futureKeySize, futureKeys, msKeyLifeTime); |
| 56834 | if(retval != UA_STATUSCODE_GOOD) |
| 56835 | return retval; |
| 56836 | } |
| 56837 | |
| 56838 | retval = UA_PubSubKeyStorage_activateKeyToChannelContext(server, UA_NODEID_NULL, |
| 56839 | ks->securityGroupID); |
| 56840 | if(retval != UA_STATUSCODE_GOOD) { |
| 56841 | UA_LOG_INFO( |
| 56842 | server->config.logging, UA_LOGCATEGORY_SERVER, |
| 56843 | "Failed to import Symmetric Keys into PubSub Channel Context with %s \n", |
| 56844 | UA_StatusCode_name(retval)); |
| 56845 | return retval; |
| 56846 | } |
| 56847 | |
| 56848 | callbackTime = msKeyLifeTime; |
| 56849 | if(msTimeToNextKey > 0) |
| 56850 | callbackTime = msTimeToNextKey; |
| 56851 | |
| 56852 | /*move to setSecurityKeysAction*/ |
| 56853 | retval = UA_PubSubKeyStorage_addKeyRolloverCallback( |
| 56854 | server, ks, (UA_ServerCallback)UA_PubSubKeyStorage_keyRolloverCallback, callbackTime, |
| 56855 | &ks->callBackId); |
| 56856 | return retval; |
| 56857 | } |
| 56858 | |
| 56859 | static UA_StatusCode |
| 56860 | setSecurityKeysAction(UA_Server *server, const UA_NodeId *sessionId, void *sessionHandle, |
| 56861 | const UA_NodeId *methodId, void *methodContext, |
| 56862 | const UA_NodeId *objectId, void *objectContext, size_t inputSize, |
| 56863 | const UA_Variant *input, size_t outputSize, UA_Variant *output) { |
| 56864 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56865 | return setSecurityKeysLocked(server, sessionId, sessionHandle, |
| 56866 | methodId, methodContext, |
| 56867 | objectId, objectContext, inputSize, |
| 56868 | input, outputSize, output); |
| 56869 | } |
| 56870 | |
| 56871 | static UA_StatusCode |
| 56872 | getSecurityKeysLocked(UA_Server *server, const UA_NodeId *sessionId, void *sessionHandle, |
| 56873 | const UA_NodeId *methodId, void *methodContext, |
| 56874 | const UA_NodeId *objectId, void *objectContext, size_t inputSize, |
| 56875 | const UA_Variant *input, size_t outputSize, UA_Variant *output) { |
| 56876 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 56877 | |
| 56878 | /*Check whether the channel is encrypted according to specification*/ |
| 56879 | session_list_entry *session_entry; |
| 56880 | LIST_FOREACH(session_entry, &server->sessions, pointers) { |
| 56881 | if(UA_NodeId_equal(&session_entry->session.sessionId, sessionId)) { |
| 56882 | if(session_entry->session.header.channel->securityMode != |
| 56883 | UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 56884 | return UA_STATUSCODE_BADSECURITYMODEINSUFFICIENT; |
| 56885 | } |
| 56886 | } |
| 56887 | |
| 56888 | if(!server || !input) |
| 56889 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 56890 | |
| 56891 | if(inputSize < 3 || outputSize < 5) |
| 56892 | return UA_STATUSCODE_BADARGUMENTSMISSING; |
| 56893 | if(inputSize > 3 || outputSize > 5) |
| 56894 | return UA_STATUSCODE_BADTOOMANYARGUMENTS; |
| 56895 | |
| 56896 | /*check for types*/ |
| 56897 | if(!UA_Variant_hasScalarType(&input[0], |
| 56898 | &UA_TYPES[UA_TYPES_STRING]) || /*SecurityGroupId*/ |
| 56899 | !UA_Variant_hasScalarType(&input[1], |
| 56900 | &UA_TYPES[UA_TYPES_INTEGERID]) || /*StartingTokenId*/ |
| 56901 | !UA_Variant_hasScalarType(&input[2], |
| 56902 | &UA_TYPES[UA_TYPES_UINT32])) /*RequestedKeyCount*/ |
| 56903 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 56904 | |
| 56905 | UA_StatusCode retval = UA_STATUSCODE_BAD; |
| 56906 | UA_UInt32 currentKeyCount = 1; |
| 56907 | /* input */ |
| 56908 | UA_String *securityGroupId = (UA_String *)input[0].data; |
| 56909 | UA_UInt32 startingTokenId = *(UA_UInt32 *)input[1].data; |
| 56910 | UA_UInt32 requestedKeyCount = *(UA_UInt32 *)input[2].data; |
| 56911 | |
| 56912 | UA_PubSubKeyStorage *ks = |
| 56913 | UA_PubSubKeyStorage_findKeyStorage(server, *securityGroupId); |
| 56914 | if(!ks) |
| 56915 | return UA_STATUSCODE_BADNOTFOUND; |
| 56916 | |
| 56917 | UA_Boolean executable = false; |
| 56918 | UA_SecurityGroup *sg = UA_SecurityGroup_findSGbyName(server, *securityGroupId); |
| 56919 | void *sgNodeCtx; |
| 56920 | getNodeContext(server, sg->securityGroupNodeId, (void **)&sgNodeCtx); |
| 56921 | executable = server->config.accessControl.getUserExecutableOnObject( |
| 56922 | server, &server->config.accessControl, sessionId, sessionHandle, methodId, |
| 56923 | methodContext, &sg->securityGroupNodeId, sgNodeCtx); |
| 56924 | |
| 56925 | if(!executable) |
| 56926 | return UA_STATUSCODE_BADUSERACCESSDENIED; |
| 56927 | |
| 56928 | /* If the caller requests a number larger than the Security Key Service permits, then |
| 56929 | * the SKS shall return the maximum it allows.*/ |
| 56930 | if(requestedKeyCount > sg->config.maxFutureKeyCount) |
| 56931 | requestedKeyCount =(UA_UInt32) sg->keyStorage->keyListSize; |
| 56932 | else |
| 56933 | requestedKeyCount = requestedKeyCount + currentKeyCount; /* Add Current keyCount */ |
| 56934 | |
| 56935 | /*The current token is requested by passing 0.*/ |
| 56936 | UA_PubSubKeyListItem *startingItem = NULL; |
| 56937 | if(startingTokenId == 0) { |
| 56938 | /* currentItem is always set by the server when a security group is added */ |
| 56939 | UA_assert(sg->keyStorage->currentItem != NULL); |
| 56940 | startingItem = sg->keyStorage->currentItem; |
| 56941 | } else { |
| 56942 | retval = UA_PubSubKeyStorage_getKeyByKeyID( |
| 56943 | startingTokenId, sg->keyStorage, &startingItem); |
| 56944 | /*If the StartingTokenId is unknown, the oldest (firstItem) available tokens are |
| 56945 | * returned. */ |
| 56946 | if(retval == UA_STATUSCODE_BADNOTFOUND) |
| 56947 | startingItem = TAILQ_FIRST(&sg->keyStorage->keyList); |
| 56948 | } |
| 56949 | |
| 56950 | /*SecurityPolicyUri*/ |
| 56951 | retval = UA_Variant_setScalarCopy(&output[0], &(sg->keyStorage->policy->policyUri), |
| 56952 | &UA_TYPES[UA_TYPES_STRING]); |
| 56953 | if(retval != UA_STATUSCODE_GOOD) |
| 56954 | return retval; |
| 56955 | |
| 56956 | /*FirstTokenId*/ |
| 56957 | retval = UA_Variant_setScalarCopy(&output[1], &startingItem->keyID, |
| 56958 | &UA_TYPES[UA_TYPES_INTEGERID]); |
| 56959 | if(retval != UA_STATUSCODE_GOOD) |
| 56960 | return retval; |
| 56961 | |
| 56962 | /*TimeToNextKey*/ |
| 56963 | UA_DateTime baseTime = sg->baseTime; |
| 56964 | UA_DateTime currentTime = UA_DateTime_nowMonotonic(); |
| 56965 | UA_Duration interval = sg->config.keyLifeTime; |
| 56966 | UA_Duration timeToNextKey = |
| 56967 | (UA_Duration)((currentTime - baseTime) / UA_DATETIME_MSEC); |
| 56968 | timeToNextKey = interval - timeToNextKey; |
| 56969 | retval = UA_Variant_setScalarCopy(&output[3], &timeToNextKey, |
| 56970 | &UA_TYPES[UA_TYPES_DURATION]); |
| 56971 | if(retval != UA_STATUSCODE_GOOD) |
| 56972 | return retval; |
| 56973 | |
| 56974 | /*KeyLifeTime*/ |
| 56975 | retval = UA_Variant_setScalarCopy(&output[4], &sg->config.keyLifeTime, |
| 56976 | &UA_TYPES[UA_TYPES_DURATION]); |
| 56977 | if(retval != UA_STATUSCODE_GOOD) |
| 56978 | return retval; |
| 56979 | |
| 56980 | /*Keys*/ |
| 56981 | UA_PubSubKeyListItem *iterator = startingItem; |
| 56982 | output[2].data = (UA_ByteString *)UA_calloc(requestedKeyCount, startingItem->key.length); |
| 56983 | if(!output[2].data) |
| 56984 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 56985 | |
| 56986 | UA_ByteString *requestedKeys = (UA_ByteString *)output[2].data; |
| 56987 | UA_UInt32 retkeyCount = 0; |
| 56988 | for(size_t i = 0; i < requestedKeyCount; i++) { |
| 56989 | UA_ByteString_copy(&iterator->key, &requestedKeys[i]); |
| 56990 | ++retkeyCount; |
| 56991 | iterator = TAILQ_NEXT(iterator, keyListEntry); |
| 56992 | if(!iterator) { |
| 56993 | requestedKeyCount = retkeyCount; |
| 56994 | break; |
| 56995 | } |
| 56996 | } |
| 56997 | |
| 56998 | UA_Variant_setArray(&output[2], requestedKeys, requestedKeyCount, &UA_TYPES[UA_TYPES_BYTESTRING]); |
| 56999 | return retval; |
| 57000 | } |
| 57001 | |
| 57002 | static UA_StatusCode |
| 57003 | getSecurityKeysAction(UA_Server *server, const UA_NodeId *sessionId, void *sessionHandle, |
| 57004 | const UA_NodeId *methodId, void *methodContext, |
| 57005 | const UA_NodeId *objectId, void *objectContext, size_t inputSize, |
| 57006 | const UA_Variant *input, size_t outputSize, UA_Variant *output) { |
| 57007 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57008 | return getSecurityKeysLocked(server, sessionId, sessionHandle, |
| 57009 | methodId, methodContext, |
| 57010 | objectId, objectContext, inputSize, |
| 57011 | input, outputSize, output); |
| 57012 | } |
| 57013 | #endif |
| 57014 | |
| 57015 | /**********************************************/ |
| 57016 | /* Destructors */ |
| 57017 | /**********************************************/ |
| 57018 | |
| 57019 | static void |
| 57020 | connectionTypeDestructor(UA_Server *server, |
| 57021 | const UA_NodeId *sessionId, void *sessionContext, |
| 57022 | const UA_NodeId *typeId, void *typeContext, |
| 57023 | const UA_NodeId *nodeId, void **nodeContext) { |
| 57024 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57025 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 57026 | msg: "Connection destructor called!"); |
| 57027 | UA_NodeId publisherIdNode = |
| 57028 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PublisherId"), |
| 57029 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: *nodeId); |
| 57030 | UA_NodePropertyContext *ctx; |
| 57031 | getNodeContext(server, nodeId: publisherIdNode, nodeContext: (void **)&ctx); |
| 57032 | if(!UA_NodeId_isNull(p: &publisherIdNode)) |
| 57033 | UA_free(ptr: ctx); |
| 57034 | } |
| 57035 | |
| 57036 | static void |
| 57037 | writerGroupTypeDestructor(UA_Server *server, |
| 57038 | const UA_NodeId *sessionId, void *sessionContext, |
| 57039 | const UA_NodeId *typeId, void *typeContext, |
| 57040 | const UA_NodeId *nodeId, void **nodeContext) { |
| 57041 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57042 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 57043 | msg: "WriterGroup destructor called!"); |
| 57044 | UA_NodeId intervalNode = |
| 57045 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PublishingInterval"), |
| 57046 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: *nodeId); |
| 57047 | UA_NodePropertyContext *ctx; |
| 57048 | getNodeContext(server, nodeId: intervalNode, nodeContext: (void **)&ctx); |
| 57049 | if(!UA_NodeId_isNull(p: &intervalNode)) |
| 57050 | UA_free(ptr: ctx); |
| 57051 | } |
| 57052 | |
| 57053 | static void |
| 57054 | readerGroupTypeDestructor(UA_Server *server, |
| 57055 | const UA_NodeId *sessionId, void *sessionContext, |
| 57056 | const UA_NodeId *typeId, void *typeContext, |
| 57057 | const UA_NodeId *nodeId, void **nodeContext) { |
| 57058 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 57059 | msg: "ReaderGroup destructor called!"); |
| 57060 | } |
| 57061 | |
| 57062 | static void |
| 57063 | dataSetWriterTypeDestructor(UA_Server *server, |
| 57064 | const UA_NodeId *sessionId, void *sessionContext, |
| 57065 | const UA_NodeId *typeId, void *typeContext, |
| 57066 | const UA_NodeId *nodeId, void **nodeContext) { |
| 57067 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57068 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 57069 | msg: "DataSetWriter destructor called!"); |
| 57070 | UA_NodeId dataSetWriterIdNode = |
| 57071 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetWriterId"), |
| 57072 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: *nodeId); |
| 57073 | UA_NodePropertyContext *ctx; |
| 57074 | getNodeContext(server, nodeId: dataSetWriterIdNode, nodeContext: (void **)&ctx); |
| 57075 | if(!UA_NodeId_isNull(p: &dataSetWriterIdNode)) |
| 57076 | UA_free(ptr: ctx); |
| 57077 | } |
| 57078 | |
| 57079 | static void |
| 57080 | dataSetReaderTypeDestructor(UA_Server *server, |
| 57081 | const UA_NodeId *sessionId, void *sessionContext, |
| 57082 | const UA_NodeId *typeId, void *typeContext, |
| 57083 | const UA_NodeId *nodeId, void **nodeContext) { |
| 57084 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57085 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 57086 | msg: "DataSetReader destructor called!"); |
| 57087 | UA_NodeId publisherIdNode = |
| 57088 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PublisherId"), |
| 57089 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: *nodeId); |
| 57090 | UA_NodePropertyContext *ctx; |
| 57091 | getNodeContext(server, nodeId: publisherIdNode, nodeContext: (void **)&ctx); |
| 57092 | if(!UA_NodeId_isNull(p: &publisherIdNode)) |
| 57093 | UA_free(ptr: ctx); |
| 57094 | } |
| 57095 | |
| 57096 | static void |
| 57097 | publishedDataItemsTypeDestructor(UA_Server *server, |
| 57098 | const UA_NodeId *sessionId, void *sessionContext, |
| 57099 | const UA_NodeId *typeId, void *typeContext, |
| 57100 | const UA_NodeId *nodeId, void **nodeContext) { |
| 57101 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57102 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 57103 | msg: "PublishedDataItems destructor called!"); |
| 57104 | void *childContext; |
| 57105 | UA_NodeId node = findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "PublishedData"), |
| 57106 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: *nodeId); |
| 57107 | getNodeContext(server, nodeId: node, nodeContext: (void**)&childContext); |
| 57108 | if(!UA_NodeId_isNull(p: &node)) |
| 57109 | UA_free(ptr: childContext); |
| 57110 | |
| 57111 | node = findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "ConfigurationVersion"), |
| 57112 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 57113 | startingNode: *nodeId); |
| 57114 | getNodeContext(server, nodeId: node, nodeContext: (void**)&childContext); |
| 57115 | if(!UA_NodeId_isNull(p: &node)) |
| 57116 | UA_free(ptr: childContext); |
| 57117 | |
| 57118 | node = findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetMetaData"), |
| 57119 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: *nodeId); |
| 57120 | getNodeContext(server, nodeId: node, nodeContext: (void**)&childContext); |
| 57121 | if(!UA_NodeId_isNull(p: &node)) |
| 57122 | UA_free(ptr: childContext); |
| 57123 | } |
| 57124 | |
| 57125 | static void |
| 57126 | standaloneSubscribedDataSetTypeDestructor(UA_Server *server, |
| 57127 | const UA_NodeId *sessionId, void *sessionContext, |
| 57128 | const UA_NodeId *typeId, void *typeContext, |
| 57129 | const UA_NodeId *nodeId, void **nodeContext) { |
| 57130 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57131 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 57132 | msg: "Standalone SubscribedDataSet destructor called!"); |
| 57133 | void *childContext; |
| 57134 | UA_NodeId node = |
| 57135 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetMetaData"), |
| 57136 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: *nodeId); |
| 57137 | getNodeContext(server, nodeId: node, nodeContext: (void**)&childContext); |
| 57138 | if(!UA_NodeId_equal(p1: &UA_NODEID_NULL , p2: &node)) |
| 57139 | UA_free(ptr: childContext); |
| 57140 | node = findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "IsConnected"), |
| 57141 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 57142 | startingNode: *nodeId); |
| 57143 | getNodeContext(server, nodeId: node, nodeContext: (void**)&childContext); |
| 57144 | if(!UA_NodeId_equal(p1: &UA_NODEID_NULL , p2: &node)) |
| 57145 | UA_free(ptr: childContext); |
| 57146 | } |
| 57147 | |
| 57148 | /*************************************/ |
| 57149 | /* PubSub configurator */ |
| 57150 | /*************************************/ |
| 57151 | |
| 57152 | #ifdef UA_ENABLE_PUBSUB_FILE_CONFIG |
| 57153 | |
| 57154 | /* Callback function that will be executed when the method "PubSub configurator |
| 57155 | * (replace config)" is called. */ |
| 57156 | static UA_StatusCode |
| 57157 | UA_loadPubSubConfigMethodCallback(UA_Server *server, |
| 57158 | const UA_NodeId *sessionId, void *sessionHandle, |
| 57159 | const UA_NodeId *methodId, void *methodContext, |
| 57160 | const UA_NodeId *objectId, void *objectContext, |
| 57161 | size_t inputSize, const UA_Variant *input, |
| 57162 | size_t outputSize, UA_Variant *output) { |
| 57163 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57164 | if(inputSize == 1) { |
| 57165 | UA_ByteString *inputStr = (UA_ByteString*)input->data; |
| 57166 | UA_StatusCode res = UA_PubSubManager_loadPubSubConfigFromByteString(server, *inputStr); |
| 57167 | return res; |
| 57168 | } else if(inputSize > 1) { |
| 57169 | return UA_STATUSCODE_BADTOOMANYARGUMENTS; |
| 57170 | } else { |
| 57171 | return UA_STATUSCODE_BADARGUMENTSMISSING; |
| 57172 | } |
| 57173 | } |
| 57174 | |
| 57175 | /* Callback function that will be executed when the method "PubSub configurator |
| 57176 | * (delete config)" is called. */ |
| 57177 | static UA_StatusCode |
| 57178 | UA_deletePubSubConfigMethodCallback(UA_Server *server, |
| 57179 | const UA_NodeId *sessionId, void *sessionHandle, |
| 57180 | const UA_NodeId *methodId, void *methodContext, |
| 57181 | const UA_NodeId *objectId, void *objectContext, |
| 57182 | size_t inputSize, const UA_Variant *input, |
| 57183 | size_t outputSize, UA_Variant *output) { |
| 57184 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57185 | UA_PubSubManager_delete(server, &server->pubSubManager); |
| 57186 | return UA_STATUSCODE_GOOD; |
| 57187 | } |
| 57188 | |
| 57189 | #endif |
| 57190 | |
| 57191 | UA_StatusCode |
| 57192 | initPubSubNS0(UA_Server *server) { |
| 57193 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57194 | |
| 57195 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 57196 | UA_String profileArray[1]; |
| 57197 | profileArray[0] = UA_STRING(chars: "http://opcfoundation.org/UA-Profile/Transport/pubsub-udp-uadp"); |
| 57198 | |
| 57199 | retVal |= writePubSubNs0VariableArray(server, |
| 57200 | id: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_SUPPORTEDTRANSPORTPROFILES), |
| 57201 | v: profileArray, length: 1, type: &UA_TYPES[UA_TYPES_STRING]); |
| 57202 | |
| 57203 | if(server->config.pubSubConfig.enableInformationModelMethods) { |
| 57204 | /* Add missing references */ |
| 57205 | retVal |= addRef(server, sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS), |
| 57206 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 57207 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), true); |
| 57208 | retVal |= addRef(server, sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS), |
| 57209 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 57210 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), true); |
| 57211 | retVal |= addRef(server, sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS), |
| 57212 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 57213 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), true); |
| 57214 | retVal |= addRef(server, sourceId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBLISHEDDATASETS), |
| 57215 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), |
| 57216 | targetId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), true); |
| 57217 | |
| 57218 | /* Set method callbacks */ |
| 57219 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_ADDCONNECTION), methodCallback: addPubSubConnectionAction); |
| 57220 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_REMOVECONNECTION), methodCallback: removeConnectionAction); |
| 57221 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_ADDDATASETFOLDER), methodCallback: addDataSetFolderAction); |
| 57222 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEDATASETFOLDER), methodCallback: removeDataSetFolderAction); |
| 57223 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_ADDPUBLISHEDDATAITEMS), methodCallback: addPublishedDataItemsAction); |
| 57224 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETFOLDERTYPE_REMOVEPUBLISHEDDATASET), methodCallback: removePublishedDataSetAction); |
| 57225 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_ADDVARIABLES), methodCallback: addVariablesAction); |
| 57226 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE_REMOVEVARIABLES), methodCallback: removeVariablesAction); |
| 57227 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDWRITERGROUP), methodCallback: addWriterGroupAction); |
| 57228 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBSUBCONNECTIONTYPE_ADDREADERGROUP), methodCallback: addReaderGroupAction); |
| 57229 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBSUBCONNECTIONTYPE_REMOVEGROUP), methodCallback: removeGroupAction); |
| 57230 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_WRITERGROUPTYPE_ADDDATASETWRITER), methodCallback: addDataSetWriterAction); |
| 57231 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_WRITERGROUPTYPE_REMOVEDATASETWRITER), methodCallback: removeDataSetWriterAction); |
| 57232 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_READERGROUPTYPE_ADDDATASETREADER), methodCallback: addDataSetReaderAction); |
| 57233 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_READERGROUPTYPE_REMOVEDATASETREADER), methodCallback: removeDataSetReaderAction); |
| 57234 | retVal |= setMethodNode_callback(server, methodNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_PUBSUBCONFIGURATION_RESERVEIDS), methodCallback: addReserveIdsAction); |
| 57235 | #ifdef UA_ENABLE_PUBSUB_SKS |
| 57236 | retVal |= setMethodNode_callback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_SETSECURITYKEYS), setSecurityKeysAction); |
| 57237 | retVal |= setMethodNode_callback(server, UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_GETSECURITYKEYS), getSecurityKeysAction); |
| 57238 | #endif |
| 57239 | |
| 57240 | #ifdef UA_ENABLE_PUBSUB_FILE_CONFIG |
| 57241 | /* Adds method node to server. This method is used to load binary files for |
| 57242 | * PubSub configuration and delete / replace old PubSub configurations. */ |
| 57243 | UA_Argument inputArgument; |
| 57244 | UA_Argument_init(&inputArgument); |
| 57245 | inputArgument.description = UA_LOCALIZEDTEXT("", "PubSub config binfile"); |
| 57246 | inputArgument.name = UA_STRING("BinFile"); |
| 57247 | inputArgument.dataType = UA_TYPES[UA_TYPES_BYTESTRING].typeId; |
| 57248 | inputArgument.valueRank = UA_VALUERANK_SCALAR; |
| 57249 | |
| 57250 | UA_MethodAttributes configAttr = UA_MethodAttributes_default; |
| 57251 | configAttr.description = UA_LOCALIZEDTEXT("", "Load binary configuration file"); |
| 57252 | configAttr.displayName = UA_LOCALIZEDTEXT("", "LoadPubSubConfigurationFile"); |
| 57253 | configAttr.executable = true; |
| 57254 | configAttr.userExecutable = true; |
| 57255 | retVal |= addMethodNode(server, UA_NODEID_NULL, |
| 57256 | UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE), |
| 57257 | UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT), |
| 57258 | UA_QUALIFIEDNAME(1, "PubSub configuration"), |
| 57259 | &configAttr, UA_loadPubSubConfigMethodCallback, |
| 57260 | 1, &inputArgument, UA_NODEID_NULL, NULL, |
| 57261 | 0, NULL, UA_NODEID_NULL, NULL, |
| 57262 | NULL, NULL); |
| 57263 | |
| 57264 | /* Adds method node to server. This method is used to delete the current |
| 57265 | * PubSub configuration. */ |
| 57266 | configAttr.description = UA_LOCALIZEDTEXT("", "Delete current PubSub configuration"); |
| 57267 | configAttr.displayName = UA_LOCALIZEDTEXT("", "DeletePubSubConfiguration"); |
| 57268 | configAttr.executable = true; |
| 57269 | configAttr.userExecutable = true; |
| 57270 | retVal |= addMethodNode(server, UA_NODEID_NULL, |
| 57271 | UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE), |
| 57272 | UA_NODEID_NUMERIC(0, UA_NS0ID_HASORDEREDCOMPONENT), |
| 57273 | UA_QUALIFIEDNAME(1, "Delete PubSub config"), |
| 57274 | &configAttr, UA_deletePubSubConfigMethodCallback, |
| 57275 | 0, NULL, UA_NODEID_NULL, NULL, |
| 57276 | 0, NULL, UA_NODEID_NULL, NULL, |
| 57277 | NULL, NULL); |
| 57278 | #endif |
| 57279 | } else { |
| 57280 | /* Remove methods */ |
| 57281 | retVal |= deleteReference(server, sourceNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE), |
| 57282 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), true, |
| 57283 | targetNodeId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_ADDCONNECTION), |
| 57284 | false); |
| 57285 | retVal |= deleteReference(server, sourceNodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE), |
| 57286 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), true, |
| 57287 | targetNodeId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHSUBSCRIBE_REMOVECONNECTION), |
| 57288 | false); |
| 57289 | } |
| 57290 | |
| 57291 | /* Set the object-type destructors */ |
| 57292 | UA_NodeTypeLifecycle lifeCycle; |
| 57293 | lifeCycle.constructor = NULL; |
| 57294 | |
| 57295 | lifeCycle.destructor = connectionTypeDestructor; |
| 57296 | retVal |= setNodeTypeLifecycle(server, |
| 57297 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBSUBCONNECTIONTYPE), |
| 57298 | lifecycle: lifeCycle); |
| 57299 | |
| 57300 | lifeCycle.destructor = writerGroupTypeDestructor; |
| 57301 | retVal |= setNodeTypeLifecycle(server, |
| 57302 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_WRITERGROUPTYPE), |
| 57303 | lifecycle: lifeCycle); |
| 57304 | |
| 57305 | lifeCycle.destructor = readerGroupTypeDestructor; |
| 57306 | retVal |= setNodeTypeLifecycle(server, |
| 57307 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_READERGROUPTYPE), |
| 57308 | lifecycle: lifeCycle); |
| 57309 | |
| 57310 | lifeCycle.destructor = dataSetWriterTypeDestructor; |
| 57311 | retVal |= setNodeTypeLifecycle(server, |
| 57312 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETWRITERTYPE), |
| 57313 | lifecycle: lifeCycle); |
| 57314 | |
| 57315 | lifeCycle.destructor = publishedDataItemsTypeDestructor; |
| 57316 | retVal |= setNodeTypeLifecycle(server, |
| 57317 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_PUBLISHEDDATAITEMSTYPE), |
| 57318 | lifecycle: lifeCycle); |
| 57319 | |
| 57320 | lifeCycle.destructor = dataSetReaderTypeDestructor; |
| 57321 | retVal |= setNodeTypeLifecycle(server, |
| 57322 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_DATASETREADERTYPE), |
| 57323 | lifecycle: lifeCycle); |
| 57324 | |
| 57325 | lifeCycle.destructor = standaloneSubscribedDataSetTypeDestructor; |
| 57326 | retVal |= setNodeTypeLifecycle(server, |
| 57327 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_STANDALONESUBSCRIBEDDATASETTYPE), |
| 57328 | lifecycle: lifeCycle); |
| 57329 | |
| 57330 | return retVal; |
| 57331 | } |
| 57332 | |
| 57333 | UA_StatusCode |
| 57334 | connectDataSetReaderToDataSet(UA_Server *server, UA_NodeId dsrId, UA_NodeId standaloneSdsId) { |
| 57335 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57336 | |
| 57337 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 57338 | |
| 57339 | UA_NodeId dataSetMetaDataOnDsrId = |
| 57340 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetMetaData"), |
| 57341 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: dsrId); |
| 57342 | UA_NodeId subscribedDataSetOnDsrId = |
| 57343 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "SubscribedDataSet"), |
| 57344 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), startingNode: dsrId); |
| 57345 | UA_NodeId dataSetMetaDataOnSdsId = |
| 57346 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "DataSetMetaData"), |
| 57347 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), startingNode: standaloneSdsId); |
| 57348 | UA_NodeId subscribedDataSetOnSdsId = |
| 57349 | findSingleChildNode(server, targetName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "SubscribedDataSet"), |
| 57350 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASCOMPONENT), startingNode: standaloneSdsId); |
| 57351 | |
| 57352 | if(UA_NodeId_isNull(p: &dataSetMetaDataOnDsrId) || |
| 57353 | UA_NodeId_isNull(p: &subscribedDataSetOnDsrId) || |
| 57354 | UA_NodeId_isNull(p: &dataSetMetaDataOnSdsId) || |
| 57355 | UA_NodeId_isNull(p: &subscribedDataSetOnSdsId)) |
| 57356 | return UA_STATUSCODE_BADNOTFOUND; |
| 57357 | |
| 57358 | UA_NODESTORE_REMOVE(server, &dataSetMetaDataOnDsrId); |
| 57359 | UA_NODESTORE_REMOVE(server, &subscribedDataSetOnDsrId); |
| 57360 | |
| 57361 | retVal |= addRef(server, sourceId: dsrId, referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 57362 | targetId: UA_NODEID_NUMERIC(nsIndex: dataSetMetaDataOnSdsId.namespaceIndex, |
| 57363 | identifier: dataSetMetaDataOnSdsId.identifier.numeric), true); |
| 57364 | retVal |= addRef(server, sourceId: dsrId, referenceTypeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HASPROPERTY), |
| 57365 | targetId: UA_NODEID_NUMERIC(nsIndex: subscribedDataSetOnSdsId.namespaceIndex, |
| 57366 | identifier: subscribedDataSetOnSdsId.identifier.numeric), true); |
| 57367 | |
| 57368 | return retVal; |
| 57369 | } |
| 57370 | |
| 57371 | #endif /* UA_ENABLE_PUBSUB_INFORMATIONMODEL */ |
| 57372 | |
| 57373 | /**** amalgamated original file "/src/pubsub/ua_pubsub_keystorage.c" ****/ |
| 57374 | |
| 57375 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 57376 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 57377 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 57378 | * |
| 57379 | * Copyright (c) 2019 ifak e.V. Magdeburg (Holger Zipper) |
| 57380 | * Copyright (c) 2022 Linutronix GmbH (Author: Muddasir Shakil) |
| 57381 | */ |
| 57382 | |
| 57383 | |
| 57384 | #ifdef UA_ENABLE_PUBSUB_SKS /* conditional compilation */ |
| 57385 | |
| 57386 | #define UA_REQ_CURRENT_TOKEN 0 |
| 57387 | |
| 57388 | |
| 57389 | UA_PubSubKeyStorage * |
| 57390 | UA_PubSubKeyStorage_findKeyStorage(UA_Server *server, UA_String securityGroupId) { |
| 57391 | if(!server || UA_String_isEmpty(&securityGroupId)) |
| 57392 | return NULL; |
| 57393 | |
| 57394 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57395 | |
| 57396 | UA_PubSubKeyStorage *outKeyStorage; |
| 57397 | LIST_FOREACH(outKeyStorage, &server->pubSubManager.pubSubKeyList, keyStorageList) { |
| 57398 | if(UA_String_equal(&outKeyStorage->securityGroupID, &securityGroupId)) |
| 57399 | return outKeyStorage; |
| 57400 | } |
| 57401 | return NULL; |
| 57402 | } |
| 57403 | |
| 57404 | UA_PubSubSecurityPolicy * |
| 57405 | findPubSubSecurityPolicy(UA_Server *server, const UA_String *securityPolicyUri) { |
| 57406 | if(!server || !securityPolicyUri) |
| 57407 | return NULL; |
| 57408 | |
| 57409 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57410 | |
| 57411 | UA_ServerConfig *config = &server->config; |
| 57412 | for(size_t i = 0; i < config->pubSubConfig.securityPoliciesSize; i++) { |
| 57413 | if(UA_String_equal(securityPolicyUri, |
| 57414 | &config->pubSubConfig.securityPolicies[i].policyUri)) |
| 57415 | return &config->pubSubConfig.securityPolicies[i]; |
| 57416 | } |
| 57417 | return NULL; |
| 57418 | } |
| 57419 | |
| 57420 | static void |
| 57421 | UA_PubSubKeyStorage_clearKeyList(UA_PubSubKeyStorage *keyStorage) { |
| 57422 | if(TAILQ_EMPTY(&keyStorage->keyList)) |
| 57423 | return; |
| 57424 | |
| 57425 | UA_PubSubKeyListItem *item, *item_tmp; |
| 57426 | TAILQ_FOREACH_SAFE(item, &keyStorage->keyList, keyListEntry, item_tmp) { |
| 57427 | TAILQ_REMOVE(&keyStorage->keyList, item, keyListEntry); |
| 57428 | UA_ByteString_clear(&item->key); |
| 57429 | UA_free(item); |
| 57430 | } |
| 57431 | keyStorage->keyListSize = 0; |
| 57432 | } |
| 57433 | |
| 57434 | void |
| 57435 | UA_PubSubKeyStorage_delete(UA_Server *server, UA_PubSubKeyStorage *keyStorage) { |
| 57436 | UA_assert(keyStorage != NULL); |
| 57437 | UA_assert(server != NULL); |
| 57438 | |
| 57439 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57440 | |
| 57441 | /* Remove callback */ |
| 57442 | if(!keyStorage->callBackId != 0) { |
| 57443 | removeCallback(server, keyStorage->callBackId); |
| 57444 | keyStorage->callBackId = 0; |
| 57445 | } |
| 57446 | |
| 57447 | UA_PubSubKeyStorage_clearKeyList(keyStorage); |
| 57448 | UA_String_clear(&keyStorage->securityGroupID); |
| 57449 | UA_ClientConfig_clear(&keyStorage->sksConfig.clientConfig); |
| 57450 | UA_free(keyStorage); |
| 57451 | } |
| 57452 | |
| 57453 | UA_StatusCode |
| 57454 | UA_PubSubKeyStorage_init(UA_Server *server, UA_PubSubKeyStorage *keyStorage, |
| 57455 | const UA_String *securityGroupId, |
| 57456 | UA_PubSubSecurityPolicy *policy, |
| 57457 | UA_UInt32 maxPastKeyCount, UA_UInt32 maxFutureKeyCount) { |
| 57458 | UA_StatusCode res = UA_String_copy(securityGroupId, &keyStorage->securityGroupID); |
| 57459 | if(res != UA_STATUSCODE_GOOD) |
| 57460 | return res; |
| 57461 | |
| 57462 | UA_UInt32 currentkeyCount = 1; |
| 57463 | keyStorage->maxPastKeyCount = maxPastKeyCount; |
| 57464 | keyStorage->maxFutureKeyCount = maxFutureKeyCount; |
| 57465 | keyStorage->maxKeyListSize = maxPastKeyCount + currentkeyCount + maxFutureKeyCount; |
| 57466 | keyStorage->policy = policy; |
| 57467 | |
| 57468 | /* Add this keystorage to the server keystoragelist */ |
| 57469 | LIST_INSERT_HEAD(&server->pubSubManager.pubSubKeyList, keyStorage, keyStorageList); |
| 57470 | |
| 57471 | return UA_STATUSCODE_GOOD; |
| 57472 | } |
| 57473 | |
| 57474 | UA_StatusCode |
| 57475 | UA_PubSubKeyStorage_storeSecurityKeys(UA_Server *server, UA_PubSubKeyStorage *keyStorage, |
| 57476 | UA_UInt32 currentTokenId, const UA_ByteString *currentKey, |
| 57477 | UA_ByteString *futureKeys, size_t futureKeyCount, |
| 57478 | UA_Duration msKeyLifeTime) { |
| 57479 | UA_assert(server); |
| 57480 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57481 | |
| 57482 | UA_StatusCode retval = UA_STATUSCODE_BAD; |
| 57483 | |
| 57484 | if(futureKeyCount > 0 && !futureKeys) { |
| 57485 | retval = UA_STATUSCODE_BADARGUMENTSMISSING; |
| 57486 | goto error; |
| 57487 | } |
| 57488 | |
| 57489 | size_t keyNumber = futureKeyCount; |
| 57490 | |
| 57491 | if(currentKey && keyStorage->keyListSize == 0) { |
| 57492 | |
| 57493 | keyStorage->keyListSize++; |
| 57494 | UA_PubSubKeyListItem *keyItem = |
| 57495 | (UA_PubSubKeyListItem *)UA_calloc(1, sizeof(UA_PubSubKeyListItem)); |
| 57496 | if(!keyItem) |
| 57497 | goto error; |
| 57498 | retval = UA_ByteString_copy(currentKey, &keyItem->key); |
| 57499 | if(UA_StatusCode_isBad(retval)) |
| 57500 | goto error; |
| 57501 | |
| 57502 | keyItem->keyID = currentTokenId; |
| 57503 | |
| 57504 | TAILQ_INIT(&keyStorage->keyList); |
| 57505 | TAILQ_INSERT_HEAD(&keyStorage->keyList, keyItem, keyListEntry); |
| 57506 | } |
| 57507 | |
| 57508 | UA_PubSubKeyListItem *keyListIterator = TAILQ_FIRST(&keyStorage->keyList); |
| 57509 | UA_UInt32 startingTokenID = currentTokenId + 1; |
| 57510 | for(size_t i = 0; i < keyNumber; ++i) { |
| 57511 | retval = UA_PubSubKeyStorage_getKeyByKeyID( |
| 57512 | startingTokenID, keyStorage, &keyListIterator); |
| 57513 | /*Skipping key with matching KeyID in existing list*/ |
| 57514 | if(retval == UA_STATUSCODE_BADNOTFOUND) { |
| 57515 | keyListIterator = UA_PubSubKeyStorage_push(keyStorage, &futureKeys[i], startingTokenID); |
| 57516 | if(!keyListIterator) |
| 57517 | goto error; |
| 57518 | |
| 57519 | keyStorage->keyListSize++; |
| 57520 | } |
| 57521 | if(startingTokenID == UA_UINT32_MAX) |
| 57522 | startingTokenID = 1; |
| 57523 | else |
| 57524 | ++startingTokenID; |
| 57525 | } |
| 57526 | |
| 57527 | /*update keystorage references*/ |
| 57528 | retval = UA_PubSubKeyStorage_getKeyByKeyID(currentTokenId, keyStorage, &keyStorage->currentItem); |
| 57529 | if (retval != UA_STATUSCODE_GOOD && !keyStorage->currentItem) |
| 57530 | goto error; |
| 57531 | |
| 57532 | keyStorage->keyLifeTime = msKeyLifeTime; |
| 57533 | |
| 57534 | return retval; |
| 57535 | error: |
| 57536 | if(keyStorage) { |
| 57537 | UA_PubSubKeyStorage_clearKeyList(keyStorage); |
| 57538 | } |
| 57539 | return retval; |
| 57540 | } |
| 57541 | |
| 57542 | UA_StatusCode |
| 57543 | UA_PubSubKeyStorage_getKeyByKeyID(const UA_UInt32 keyId, UA_PubSubKeyStorage *keyStorage, |
| 57544 | UA_PubSubKeyListItem **keyItem) { |
| 57545 | |
| 57546 | if(!keyStorage) |
| 57547 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 57548 | |
| 57549 | UA_PubSubKeyListItem *item; |
| 57550 | TAILQ_FOREACH(item, &keyStorage->keyList, keyListEntry){ |
| 57551 | if(item->keyID == keyId) { |
| 57552 | *keyItem = item; |
| 57553 | return UA_STATUSCODE_GOOD; |
| 57554 | } |
| 57555 | } |
| 57556 | return UA_STATUSCODE_BADNOTFOUND; |
| 57557 | } |
| 57558 | |
| 57559 | UA_PubSubKeyListItem * |
| 57560 | UA_PubSubKeyStorage_push(UA_PubSubKeyStorage *keyStorage, const UA_ByteString *key, |
| 57561 | UA_UInt32 keyID) { |
| 57562 | UA_PubSubKeyListItem *newItem = (UA_PubSubKeyListItem *)malloc(sizeof(UA_PubSubKeyListItem)); |
| 57563 | if (!newItem) |
| 57564 | return NULL; |
| 57565 | |
| 57566 | newItem->keyID = keyID; |
| 57567 | UA_ByteString_copy(key, &newItem->key); |
| 57568 | TAILQ_INSERT_TAIL(&keyStorage->keyList, newItem, keyListEntry); |
| 57569 | |
| 57570 | return TAILQ_LAST(&keyStorage->keyList, keyListItems); |
| 57571 | } |
| 57572 | |
| 57573 | UA_StatusCode |
| 57574 | UA_PubSubKeyStorage_addKeyRolloverCallback(UA_Server *server, |
| 57575 | UA_PubSubKeyStorage *keyStorage, |
| 57576 | UA_ServerCallback callback, |
| 57577 | UA_Duration timeToNextMs, |
| 57578 | UA_UInt64 *callbackID) { |
| 57579 | if(!server || !keyStorage || !callback || timeToNextMs <= 0) |
| 57580 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 57581 | |
| 57582 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57583 | |
| 57584 | UA_EventLoop *el = server->config.eventLoop; |
| 57585 | if(*callbackID != 0) |
| 57586 | el->removeCyclicCallback(el, *callbackID); |
| 57587 | |
| 57588 | UA_DateTime dateTimeToNextKey = UA_DateTime_nowMonotonic() + |
| 57589 | (UA_DateTime)(UA_DATETIME_MSEC * timeToNextMs); |
| 57590 | return el->addTimedCallback(el, (UA_Callback)callback, server, keyStorage, |
| 57591 | dateTimeToNextKey, callbackID); |
| 57592 | } |
| 57593 | |
| 57594 | static UA_StatusCode |
| 57595 | splitCurrentKeyMaterial(UA_PubSubKeyStorage *keyStorage, UA_ByteString *signingKey, |
| 57596 | UA_ByteString *encryptingKey, UA_ByteString *keyNonce) { |
| 57597 | if(!keyStorage) |
| 57598 | return UA_STATUSCODE_BADNOTFOUND; |
| 57599 | |
| 57600 | if(!keyStorage->policy) |
| 57601 | return UA_STATUSCODE_BADINTERNALERROR; |
| 57602 | |
| 57603 | UA_PubSubSecurityPolicy *policy = keyStorage->policy; |
| 57604 | |
| 57605 | UA_ByteString key = keyStorage->currentItem->key; |
| 57606 | |
| 57607 | /*Check the main key length is the same according to policy*/ |
| 57608 | if(key.length != policy->symmetricModule.secureChannelNonceLength) |
| 57609 | return UA_STATUSCODE_BADINTERNALERROR; |
| 57610 | |
| 57611 | /*Get Key Length according to policy*/ |
| 57612 | size_t signingkeyLength = |
| 57613 | policy->symmetricModule.cryptoModule.signatureAlgorithm.getLocalKeyLength(NULL); |
| 57614 | size_t encryptkeyLength = |
| 57615 | policy->symmetricModule.cryptoModule.encryptionAlgorithm.getLocalKeyLength(NULL); |
| 57616 | /*Rest of the part is the keyNonce*/ |
| 57617 | size_t keyNonceLength = key.length - signingkeyLength - encryptkeyLength; |
| 57618 | |
| 57619 | /*DivideKeys in origin ByteString*/ |
| 57620 | signingKey->data = key.data; |
| 57621 | signingKey->length = signingkeyLength; |
| 57622 | |
| 57623 | encryptingKey->data = key.data + signingkeyLength; |
| 57624 | encryptingKey->length = encryptkeyLength; |
| 57625 | |
| 57626 | keyNonce->data = key.data + signingkeyLength + encryptkeyLength; |
| 57627 | keyNonce->length = keyNonceLength; |
| 57628 | |
| 57629 | return UA_STATUSCODE_GOOD; |
| 57630 | } |
| 57631 | |
| 57632 | static UA_StatusCode |
| 57633 | setPubSubGroupEncryptingKey(UA_Server *server, UA_NodeId PubSubGroupId, UA_UInt32 securityTokenId, |
| 57634 | UA_ByteString signingKey, UA_ByteString encryptingKey, |
| 57635 | UA_ByteString keyNonce) { |
| 57636 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57637 | UA_StatusCode retval = |
| 57638 | setWriterGroupEncryptionKeys(server, PubSubGroupId, securityTokenId, |
| 57639 | signingKey, encryptingKey, keyNonce); |
| 57640 | if(retval == UA_STATUSCODE_BADNOTFOUND) |
| 57641 | retval = setReaderGroupEncryptionKeys(server, PubSubGroupId, securityTokenId, |
| 57642 | signingKey, encryptingKey, keyNonce); |
| 57643 | return retval; |
| 57644 | } |
| 57645 | |
| 57646 | static UA_StatusCode |
| 57647 | setPubSubGroupEncryptingKeyForMatchingSecurityGroupId(UA_Server *server, |
| 57648 | UA_String securityGroupId, |
| 57649 | UA_UInt32 securityTokenId, |
| 57650 | UA_ByteString signingKey, |
| 57651 | UA_ByteString encryptingKey, |
| 57652 | UA_ByteString keyNonce) { |
| 57653 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57654 | UA_StatusCode retval = UA_STATUSCODE_BAD; |
| 57655 | UA_PubSubConnection *tmpPubSubConnections; |
| 57656 | |
| 57657 | /* Key storage is the same for all reader / writer groups, channel context isn't |
| 57658 | * => Update channelcontext in all Writergroups / ReaderGroups which have the same |
| 57659 | * securityGroupId*/ |
| 57660 | TAILQ_FOREACH(tmpPubSubConnections, &server->pubSubManager.connections, listEntry) { |
| 57661 | /* For each writerGroup in server with matching SecurityGroupId */ |
| 57662 | UA_WriterGroup *tmpWriterGroup; |
| 57663 | LIST_FOREACH(tmpWriterGroup, &tmpPubSubConnections->writerGroups, listEntry) { |
| 57664 | if(UA_String_equal(&tmpWriterGroup->config.securityGroupId, &securityGroupId)) { |
| 57665 | retval = setWriterGroupEncryptionKeys(server, tmpWriterGroup->identifier, |
| 57666 | securityTokenId, signingKey, |
| 57667 | encryptingKey, keyNonce); |
| 57668 | if(retval != UA_STATUSCODE_GOOD) |
| 57669 | return retval; |
| 57670 | } |
| 57671 | } |
| 57672 | |
| 57673 | /* For each readerGroup in server with matching SecurityGroupId */ |
| 57674 | UA_ReaderGroup *tmpReaderGroup; |
| 57675 | LIST_FOREACH(tmpReaderGroup, &tmpPubSubConnections->readerGroups, listEntry) { |
| 57676 | if(UA_String_equal(&tmpReaderGroup->config.securityGroupId, &securityGroupId)) { |
| 57677 | retval = setReaderGroupEncryptionKeys(server, tmpReaderGroup->identifier, |
| 57678 | securityTokenId, signingKey, |
| 57679 | encryptingKey, keyNonce); |
| 57680 | if(retval != UA_STATUSCODE_GOOD) |
| 57681 | return retval; |
| 57682 | } |
| 57683 | } |
| 57684 | } |
| 57685 | return retval; |
| 57686 | } |
| 57687 | |
| 57688 | UA_StatusCode |
| 57689 | UA_PubSubKeyStorage_activateKeyToChannelContext(UA_Server *server, UA_NodeId pubSubGroupId, |
| 57690 | UA_String securityGroupId) { |
| 57691 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57692 | if(securityGroupId.data == NULL) |
| 57693 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 57694 | |
| 57695 | UA_PubSubKeyStorage *keyStorage = |
| 57696 | UA_PubSubKeyStorage_findKeyStorage(server, securityGroupId); |
| 57697 | if(!keyStorage) |
| 57698 | return UA_STATUSCODE_BADNOTFOUND; |
| 57699 | |
| 57700 | if(!keyStorage->policy && !(keyStorage->keyListSize > 0)) |
| 57701 | return UA_STATUSCODE_BADINTERNALERROR; |
| 57702 | |
| 57703 | UA_UInt32 securityTokenId = keyStorage->currentItem->keyID; |
| 57704 | |
| 57705 | /*DivideKeys in origin ByteString*/ |
| 57706 | UA_ByteString signingKey; |
| 57707 | UA_ByteString encryptKey; |
| 57708 | UA_ByteString keyNonce; |
| 57709 | UA_StatusCode retval = splitCurrentKeyMaterial(keyStorage, &signingKey, |
| 57710 | &encryptKey, &keyNonce); |
| 57711 | if(retval != UA_STATUSCODE_GOOD) |
| 57712 | return retval; |
| 57713 | |
| 57714 | if(!UA_NodeId_isNull(&pubSubGroupId)) |
| 57715 | retval = setPubSubGroupEncryptingKey(server, pubSubGroupId, securityTokenId, |
| 57716 | signingKey, encryptKey, keyNonce); |
| 57717 | else |
| 57718 | retval = setPubSubGroupEncryptingKeyForMatchingSecurityGroupId( |
| 57719 | server, securityGroupId, securityTokenId, signingKey, encryptKey, keyNonce); |
| 57720 | |
| 57721 | if(retval != UA_STATUSCODE_GOOD) |
| 57722 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 57723 | "Failed to set Encrypting keys with Error: %s", |
| 57724 | UA_StatusCode_name(retval)); |
| 57725 | |
| 57726 | return retval; |
| 57727 | } |
| 57728 | |
| 57729 | static void |
| 57730 | nextGetSecuritykeysCallback(UA_Server *server, UA_PubSubKeyStorage *keyStorage) { |
| 57731 | UA_StatusCode retval = UA_STATUSCODE_BAD; |
| 57732 | if(!keyStorage) { |
| 57733 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 57734 | "GetSecurityKeysCall Failed with error: KeyStorage does not exist " |
| 57735 | "in the server"); |
| 57736 | return; |
| 57737 | } |
| 57738 | retval = getSecurityKeysAndStoreFetchedKeys(server, keyStorage); |
| 57739 | if(retval != UA_STATUSCODE_GOOD) |
| 57740 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 57741 | "GetSecurityKeysCall Failed with error: %s ", |
| 57742 | UA_StatusCode_name(retval)); |
| 57743 | } |
| 57744 | |
| 57745 | void |
| 57746 | UA_PubSubKeyStorage_keyRolloverCallback(UA_Server *server, UA_PubSubKeyStorage *keyStorage) { |
| 57747 | /* Callbacks from the EventLoop are initially unlocked */ |
| 57748 | lockServer(server); |
| 57749 | UA_StatusCode retval = |
| 57750 | UA_PubSubKeyStorage_addKeyRolloverCallback(server, keyStorage, |
| 57751 | (UA_ServerCallback)UA_PubSubKeyStorage_keyRolloverCallback, |
| 57752 | keyStorage->keyLifeTime, &keyStorage->callBackId); |
| 57753 | if(retval != UA_STATUSCODE_GOOD) { |
| 57754 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 57755 | "Failed to update keys for security group id '%.*s'. Reason: '%s'.", |
| 57756 | (int)keyStorage->securityGroupID.length, |
| 57757 | keyStorage->securityGroupID.data, UA_StatusCode_name(retval)); |
| 57758 | } |
| 57759 | |
| 57760 | if(keyStorage->currentItem != TAILQ_LAST(&keyStorage->keyList, keyListItems)) { |
| 57761 | keyStorage->currentItem = TAILQ_NEXT(keyStorage->currentItem, keyListEntry); |
| 57762 | keyStorage->currentTokenId = keyStorage->currentItem->keyID; |
| 57763 | retval = UA_PubSubKeyStorage_activateKeyToChannelContext(server, UA_NODEID_NULL, |
| 57764 | keyStorage->securityGroupID); |
| 57765 | if(retval != UA_STATUSCODE_GOOD) { |
| 57766 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 57767 | "Failed to update keys for security group id '%.*s'. Reason: '%s'.", |
| 57768 | (int)keyStorage->securityGroupID.length, keyStorage->securityGroupID.data, |
| 57769 | UA_StatusCode_name(retval)); |
| 57770 | } |
| 57771 | } else if(keyStorage->sksConfig.endpointUrl && keyStorage->sksConfig.reqId == 0) { |
| 57772 | UA_DateTime now = UA_DateTime_nowMonotonic(); |
| 57773 | /*Publishers using a central SKS shall call GetSecurityKeys at a period of half the KeyLifetime */ |
| 57774 | UA_Duration msTimeToNextGetSecurityKeys = keyStorage->keyLifeTime / 2; |
| 57775 | UA_DateTime dateTimeToNextGetSecurityKeys = |
| 57776 | now + (UA_DateTime)(UA_DATETIME_MSEC * msTimeToNextGetSecurityKeys); |
| 57777 | retval = server->config.eventLoop->addTimedCallback( |
| 57778 | server->config.eventLoop, (UA_Callback)nextGetSecuritykeysCallback, server, |
| 57779 | keyStorage, dateTimeToNextGetSecurityKeys, NULL); |
| 57780 | } |
| 57781 | unlockServer(server); |
| 57782 | } |
| 57783 | |
| 57784 | UA_StatusCode |
| 57785 | UA_PubSubKeyStorage_update(UA_Server *server, UA_PubSubKeyStorage *keyStorage, |
| 57786 | const UA_ByteString *currentKey, UA_UInt32 currentKeyID, |
| 57787 | const size_t futureKeySize, UA_ByteString *futureKeys, |
| 57788 | UA_Duration msKeyLifeTime) { |
| 57789 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57790 | if(!keyStorage) |
| 57791 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 57792 | |
| 57793 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 57794 | UA_PubSubKeyListItem *keyListIterator = NULL; |
| 57795 | |
| 57796 | if(currentKeyID != 0){ |
| 57797 | /* If currentKeyId is known then update keystorage currentItem */ |
| 57798 | retval = UA_PubSubKeyStorage_getKeyByKeyID(currentKeyID, keyStorage, |
| 57799 | &keyListIterator); |
| 57800 | if(retval == UA_STATUSCODE_GOOD && keyListIterator) { |
| 57801 | keyStorage->currentItem = keyListIterator; |
| 57802 | /* Add new keys at the end of KeyList */ |
| 57803 | retval = UA_PubSubKeyStorage_storeSecurityKeys(server, keyStorage, currentKeyID, |
| 57804 | NULL, futureKeys, futureKeySize, |
| 57805 | msKeyLifeTime); |
| 57806 | if(retval != UA_STATUSCODE_GOOD) |
| 57807 | return retval; |
| 57808 | } else if(retval == UA_STATUSCODE_BADNOTFOUND) { |
| 57809 | /* If the CurrentTokenId is unknown, the existing list shall be |
| 57810 | * discarded and replaced by the fetched list */ |
| 57811 | UA_PubSubKeyStorage_clearKeyList(keyStorage); |
| 57812 | retval = UA_PubSubKeyStorage_storeSecurityKeys(server, keyStorage, |
| 57813 | currentKeyID, currentKey, futureKeys, |
| 57814 | futureKeySize, msKeyLifeTime); |
| 57815 | if(retval != UA_STATUSCODE_GOOD) |
| 57816 | return retval; |
| 57817 | } |
| 57818 | } |
| 57819 | return retval; |
| 57820 | } |
| 57821 | |
| 57822 | void |
| 57823 | UA_PubSubKeyStorage_detachKeyStorage(UA_Server *server, UA_PubSubKeyStorage *keyStorage) { |
| 57824 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 57825 | |
| 57826 | keyStorage->referenceCount--; |
| 57827 | if(keyStorage->referenceCount == 0) { |
| 57828 | LIST_REMOVE(keyStorage, keyStorageList); |
| 57829 | UA_PubSubKeyStorage_delete(server, keyStorage); |
| 57830 | } |
| 57831 | } |
| 57832 | |
| 57833 | /** |
| 57834 | * @brief It holds the information required in the async callback to |
| 57835 | * GetSecurityKeys method Call. |
| 57836 | */ |
| 57837 | typedef struct { |
| 57838 | UA_Server *server; |
| 57839 | UA_PubSubKeyStorage *ks; |
| 57840 | UA_UInt32 startingTokenId; |
| 57841 | UA_UInt32 requestedKeyCount; |
| 57842 | UA_DelayedCallback dc; |
| 57843 | } sksClientContext; |
| 57844 | |
| 57845 | static void sksClientCleanupCb(void *client, void *context); |
| 57846 | |
| 57847 | static void |
| 57848 | addDelayedSksClientCleanupCb(UA_Client *client, sksClientContext *context) { |
| 57849 | /* Register at most once */ |
| 57850 | if(context->dc.application != NULL) |
| 57851 | return; |
| 57852 | context->dc.application = client; |
| 57853 | context->dc.callback = sksClientCleanupCb; |
| 57854 | context->dc.context = context; |
| 57855 | client->config.eventLoop->addDelayedCallback(client->config.eventLoop, &context->dc); |
| 57856 | } |
| 57857 | |
| 57858 | static void |
| 57859 | sksClientCleanupCb(void *client, void *context) { |
| 57860 | UA_Client *sksClient = (UA_Client *)client; |
| 57861 | sksClientContext *ctx = (sksClientContext*)context; |
| 57862 | |
| 57863 | /* we do not want to call state change Callback when cleaning up */ |
| 57864 | sksClient->config.stateCallback = NULL; |
| 57865 | |
| 57866 | if(sksClient->sessionState > UA_SESSIONSTATE_CLOSED && |
| 57867 | sksClient->channel.state < UA_SECURECHANNELSTATE_CLOSED) { |
| 57868 | sksClient->config.eventLoop-> |
| 57869 | addDelayedCallback(sksClient->config.eventLoop, &ctx->dc); |
| 57870 | UA_Client_disconnectAsync(sksClient); |
| 57871 | return; |
| 57872 | } |
| 57873 | |
| 57874 | if(sksClient->channel.state == UA_SECURECHANNELSTATE_CLOSED) { |
| 57875 | /* We cannot make deep copy of the following pointers because these have |
| 57876 | * internal structures, therefore we do not free them here. These will |
| 57877 | * be freed in UA_PubSubKeyStorage_delete. */ |
| 57878 | sksClient->config.securityPolicies = NULL; |
| 57879 | sksClient->config.securityPoliciesSize = 0; |
| 57880 | sksClient->config.authSecurityPolicies = NULL; |
| 57881 | sksClient->config.authSecurityPoliciesSize = 0; |
| 57882 | sksClient->config.certificateVerification.context = NULL; |
| 57883 | sksClient->config.logging = NULL; |
| 57884 | sksClient->config.clientContext = NULL; |
| 57885 | UA_Client_delete(sksClient); |
| 57886 | UA_free(context); |
| 57887 | } else { |
| 57888 | sksClient->config.eventLoop-> |
| 57889 | addDelayedCallback(sksClient->config.eventLoop, &ctx->dc); |
| 57890 | } |
| 57891 | } |
| 57892 | |
| 57893 | static void |
| 57894 | storeFetchedKeys(UA_Client *client, void *userdata, UA_UInt32 requestId, |
| 57895 | UA_CallResponse *response) { |
| 57896 | |
| 57897 | sksClientContext *ctx = (sksClientContext *)userdata; |
| 57898 | UA_PubSubKeyStorage *ks = ctx->ks; |
| 57899 | UA_Server *server = ctx->server; |
| 57900 | UA_StatusCode retval = response->responseHeader.serviceResult; |
| 57901 | |
| 57902 | lockServer(server); |
| 57903 | /* check if the call to getSecurityKeys was a success */ |
| 57904 | if(response->resultsSize != 0) |
| 57905 | retval = response->results->statusCode; |
| 57906 | if(retval != UA_STATUSCODE_GOOD) { |
| 57907 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 57908 | "SKS Client: Failed to call GetSecurityKeys on SKS server with error: %s ", |
| 57909 | UA_StatusCode_name(retval)); |
| 57910 | goto cleanup; |
| 57911 | } |
| 57912 | |
| 57913 | UA_String *securityPolicyUri = (UA_String *)response->results->outputArguments[0].data; |
| 57914 | UA_UInt32 firstTokenId = *(UA_UInt32 *)response->results->outputArguments[1].data; |
| 57915 | UA_ByteString *keys = (UA_ByteString *)response->results->outputArguments[2].data; |
| 57916 | UA_ByteString *currentKey = &keys[0]; |
| 57917 | UA_UInt32 currentKeyCount = 1; |
| 57918 | UA_ByteString *futureKeys = &keys[currentKeyCount]; |
| 57919 | size_t futureKeySize = response->results->outputArguments[2].arrayLength - currentKeyCount; |
| 57920 | UA_Duration msKeyLifeTime = *(UA_Duration *)response->results->outputArguments[4].data; |
| 57921 | |
| 57922 | if(!UA_String_equal(securityPolicyUri, &ks->policy->policyUri)) { |
| 57923 | retval = UA_STATUSCODE_BADSECURITYPOLICYREJECTED; |
| 57924 | goto cleanup; |
| 57925 | } |
| 57926 | |
| 57927 | if(ks->keyListSize == 0) { |
| 57928 | retval = UA_PubSubKeyStorage_storeSecurityKeys(server, ks, firstTokenId, |
| 57929 | currentKey, futureKeys, |
| 57930 | futureKeySize, msKeyLifeTime); |
| 57931 | if(retval != UA_STATUSCODE_GOOD) |
| 57932 | goto cleanup; |
| 57933 | } else { |
| 57934 | retval = UA_PubSubKeyStorage_update(server, ks, currentKey, firstTokenId, |
| 57935 | futureKeySize, futureKeys, msKeyLifeTime); |
| 57936 | if(retval != UA_STATUSCODE_GOOD) |
| 57937 | goto cleanup; |
| 57938 | } |
| 57939 | |
| 57940 | /** |
| 57941 | * After a new batch of keys is fetched from SKS server, the key storage is updated |
| 57942 | * with new keys and new keylifetime. Also the remaining time for current |
| 57943 | * keyRollover is also returned. When setting a new keyRollover callback, the |
| 57944 | * previous callback must be removed so that the keyRollover does not happen twice |
| 57945 | */ |
| 57946 | if(ks->callBackId != 0) { |
| 57947 | server->config.eventLoop->removeCyclicCallback(server->config.eventLoop, |
| 57948 | ks->callBackId); |
| 57949 | ks->callBackId = 0; |
| 57950 | } |
| 57951 | |
| 57952 | UA_Duration msTimeToNextKey = |
| 57953 | *(UA_Duration *)response->results->outputArguments[3].data; |
| 57954 | if(!(msTimeToNextKey > 0)) |
| 57955 | msTimeToNextKey = ks->keyLifeTime; |
| 57956 | retval = UA_PubSubKeyStorage_addKeyRolloverCallback( |
| 57957 | server, ks, (UA_ServerCallback)UA_PubSubKeyStorage_keyRolloverCallback, |
| 57958 | msTimeToNextKey, &ks->callBackId); |
| 57959 | |
| 57960 | cleanup: |
| 57961 | if(retval != UA_STATUSCODE_GOOD) { |
| 57962 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 57963 | "Failed to store the fetched keys from SKS server with error: %s", |
| 57964 | UA_StatusCode_name(retval)); |
| 57965 | } |
| 57966 | /* call user callback to notify about the status */ |
| 57967 | if(ks->sksConfig.userNotifyCallback) |
| 57968 | ks->sksConfig.userNotifyCallback(server, retval, ks->sksConfig.context); |
| 57969 | ks->sksConfig.reqId = 0; |
| 57970 | UA_Client_disconnectAsync(client); |
| 57971 | addDelayedSksClientCleanupCb(client, ctx); |
| 57972 | |
| 57973 | unlockServer(server); |
| 57974 | } |
| 57975 | |
| 57976 | static UA_StatusCode |
| 57977 | callGetSecurityKeysMethod(UA_Client *client) { |
| 57978 | |
| 57979 | sksClientContext *ctx = (sksClientContext *)client->config.clientContext; |
| 57980 | |
| 57981 | UA_Variant inputArguments[3]; |
| 57982 | UA_Variant_setScalar(&inputArguments[0], &ctx->ks->securityGroupID, |
| 57983 | &UA_TYPES[UA_TYPES_STRING]); |
| 57984 | UA_Variant_setScalar(&inputArguments[1], &ctx->startingTokenId, |
| 57985 | &UA_TYPES[UA_TYPES_UINT32]); |
| 57986 | UA_Variant_setScalar(&inputArguments[2], &ctx->requestedKeyCount, |
| 57987 | &UA_TYPES[UA_TYPES_UINT32]); |
| 57988 | |
| 57989 | UA_NodeId objectId = UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE); |
| 57990 | UA_NodeId methodId = UA_NODEID_NUMERIC(0, UA_NS0ID_PUBLISHSUBSCRIBE_GETSECURITYKEYS); |
| 57991 | size_t inputArgumentsSize = 3; |
| 57992 | |
| 57993 | UA_StatusCode retval = UA_Client_call_async(client, objectId, methodId, inputArgumentsSize, |
| 57994 | inputArguments, storeFetchedKeys, (void *)ctx, &ctx->ks->sksConfig.reqId); |
| 57995 | return retval; |
| 57996 | } |
| 57997 | |
| 57998 | static void |
| 57999 | onConnect(UA_Client *client, UA_SecureChannelState channelState, |
| 58000 | UA_SessionState sessionState, UA_StatusCode connectStatus) { |
| 58001 | UA_Boolean triggerSKSCleanup = false; |
| 58002 | if(connectStatus != UA_STATUSCODE_GOOD && |
| 58003 | connectStatus != UA_STATUSCODE_BADNOTCONNECTED && |
| 58004 | sessionState != UA_SESSIONSTATE_ACTIVATED) { |
| 58005 | UA_LOG_ERROR(client->config.logging, UA_LOGCATEGORY_CLIENT, |
| 58006 | "SKS Client: Failed to connect SKS server with error: %s ", |
| 58007 | UA_StatusCode_name(connectStatus)); |
| 58008 | triggerSKSCleanup = true; |
| 58009 | } |
| 58010 | if(connectStatus == UA_STATUSCODE_GOOD && sessionState == UA_SESSIONSTATE_ACTIVATED) { |
| 58011 | connectStatus = callGetSecurityKeysMethod(client); |
| 58012 | if(connectStatus != UA_STATUSCODE_GOOD) { |
| 58013 | UA_LOG_ERROR(client->config.logging, UA_LOGCATEGORY_SERVER, |
| 58014 | "SKS Client: Failed to call GetSecurityKeys on SKS server with " |
| 58015 | "error: %s ", |
| 58016 | UA_StatusCode_name(connectStatus)); |
| 58017 | triggerSKSCleanup = true; |
| 58018 | } |
| 58019 | } |
| 58020 | if(triggerSKSCleanup) { |
| 58021 | /* call user callback to notify about the status */ |
| 58022 | sksClientContext *ctx = (sksClientContext *)client->config.clientContext; |
| 58023 | UA_PubSubKeyStorage *ks = ctx->ks; |
| 58024 | if(ks->sksConfig.userNotifyCallback) |
| 58025 | ks->sksConfig.userNotifyCallback(ctx->server, connectStatus, |
| 58026 | ks->sksConfig.context); |
| 58027 | UA_Client_disconnectAsync(client); |
| 58028 | addDelayedSksClientCleanupCb(client, ctx); |
| 58029 | } |
| 58030 | } |
| 58031 | |
| 58032 | static void |
| 58033 | setServerEventloopOnSksClient(UA_ClientConfig *cc, UA_EventLoop *externalEventloop) { |
| 58034 | UA_assert(externalEventloop != NULL); |
| 58035 | cc->eventLoop = externalEventloop; |
| 58036 | cc->externalEventLoop = true; |
| 58037 | } |
| 58038 | |
| 58039 | UA_StatusCode |
| 58040 | getSecurityKeysAndStoreFetchedKeys(UA_Server *server, UA_PubSubKeyStorage *keyStorage) { |
| 58041 | UA_StatusCode retval = UA_STATUSCODE_BAD; |
| 58042 | UA_UInt32 startingTokenId = UA_REQ_CURRENT_TOKEN; |
| 58043 | UA_UInt32 requestKeyCount = UA_UINT32_MAX; |
| 58044 | |
| 58045 | if(keyStorage->sksConfig.reqId != 0) { |
| 58046 | UA_LOG_INFO(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58047 | "SKS Client: SKS Pull request in process "); |
| 58048 | return UA_STATUSCODE_GOOD; |
| 58049 | } |
| 58050 | |
| 58051 | UA_ClientConfig cc; |
| 58052 | memset(&cc, 0, sizeof(UA_ClientConfig)); |
| 58053 | |
| 58054 | /* over write the client config with user specified SKS config */ |
| 58055 | retval = UA_ClientConfig_copy(&keyStorage->sksConfig.clientConfig, &cc); |
| 58056 | if(retval != UA_STATUSCODE_GOOD) |
| 58057 | return retval; |
| 58058 | |
| 58059 | setServerEventloopOnSksClient(&cc, server->config.eventLoop); |
| 58060 | |
| 58061 | /* this is cleanedup in sksClientCleanupCb */ |
| 58062 | sksClientContext *ctx = (sksClientContext *)UA_calloc(1, sizeof(sksClientContext)); |
| 58063 | if(!ctx) |
| 58064 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 58065 | ctx->ks = keyStorage; |
| 58066 | ctx->server = server; |
| 58067 | ctx->startingTokenId = startingTokenId; |
| 58068 | ctx->requestedKeyCount = requestKeyCount; |
| 58069 | cc.clientContext = ctx; |
| 58070 | |
| 58071 | UA_Client *client = UA_Client_newWithConfig(&cc); |
| 58072 | if(!client) |
| 58073 | return retval; |
| 58074 | /* connect to sks server */ |
| 58075 | retval = UA_Client_connectAsync(client, keyStorage->sksConfig.endpointUrl); |
| 58076 | if(retval != UA_STATUSCODE_GOOD) { |
| 58077 | UA_LOG_ERROR(client->config.logging, UA_LOGCATEGORY_CLIENT, |
| 58078 | "Failed to connect SKS server with error: %s ", |
| 58079 | UA_StatusCode_name(retval)); |
| 58080 | /* Make sure the client channel state is closed and not fresh, otherwise, eventloop will |
| 58081 | keep waiting for the client status to go from Fresh to closed in UA_Client_delete*/ |
| 58082 | client->channel.state = UA_SECURECHANNELSTATE_CLOSED; |
| 58083 | /* this client instance will be cleared in the next event loop iteration */ |
| 58084 | addDelayedSksClientCleanupCb(client, ctx); |
| 58085 | return retval; |
| 58086 | } |
| 58087 | |
| 58088 | /* add user specified callback, if the client is properly configured. */ |
| 58089 | client->config.stateCallback = onConnect; |
| 58090 | |
| 58091 | return retval; |
| 58092 | } |
| 58093 | |
| 58094 | UA_StatusCode |
| 58095 | UA_Server_setSksClient(UA_Server *server, UA_String securityGroupId, |
| 58096 | UA_ClientConfig *clientConfig, const char *endpointUrl, |
| 58097 | UA_Server_sksPullRequestCallback callback, void *context) { |
| 58098 | if(!server || !clientConfig || !endpointUrl) |
| 58099 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 58100 | |
| 58101 | UA_StatusCode retval = UA_STATUSCODE_BADNOTFOUND; |
| 58102 | lockServer(server); |
| 58103 | UA_PubSubKeyStorage *ks = UA_PubSubKeyStorage_findKeyStorage(server, securityGroupId); |
| 58104 | if(!ks) { |
| 58105 | unlockServer(server); |
| 58106 | return retval; |
| 58107 | } |
| 58108 | |
| 58109 | UA_ClientConfig_copy(clientConfig, &ks->sksConfig.clientConfig); |
| 58110 | /*Clear the content of original config, so that no body can access the original config */ |
| 58111 | clientConfig->authSecurityPolicies = NULL; |
| 58112 | clientConfig->certificateVerification.context = NULL; |
| 58113 | clientConfig->eventLoop = NULL; |
| 58114 | clientConfig->logging = NULL; |
| 58115 | clientConfig->securityPolicies = NULL; |
| 58116 | UA_ClientConfig_clear(clientConfig); |
| 58117 | |
| 58118 | ks->sksConfig.endpointUrl = endpointUrl; |
| 58119 | ks->sksConfig.userNotifyCallback = callback; |
| 58120 | ks->sksConfig.context = context; |
| 58121 | /* if keys are not previously fetched, then first call GetSecurityKeys*/ |
| 58122 | if(ks->keyListSize == 0) { |
| 58123 | retval = getSecurityKeysAndStoreFetchedKeys(server, ks); |
| 58124 | } |
| 58125 | unlockServer(server); |
| 58126 | return retval; |
| 58127 | } |
| 58128 | |
| 58129 | #endif |
| 58130 | |
| 58131 | /**** amalgamated original file "/src/pubsub/ua_pubsub_securitygroup.c" ****/ |
| 58132 | |
| 58133 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 58134 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 58135 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 58136 | * |
| 58137 | * Copyright (c) 2019 ifak e.V. Magdeburg (Holger Zipper) |
| 58138 | * Copyright (c) 2022 Linutronix GmbH (Author: Muddasir Shakil) |
| 58139 | */ |
| 58140 | |
| 58141 | |
| 58142 | |
| 58143 | #ifdef UA_ENABLE_PUBSUB_SKS /* conditional compilation */ |
| 58144 | |
| 58145 | |
| 58146 | #define UA_PUBSUB_KEYMATERIAL_NONCELENGTH 32 |
| 58147 | |
| 58148 | UA_SecurityGroup * |
| 58149 | UA_SecurityGroup_findSGbyName(UA_Server *server, UA_String securityGroupName) { |
| 58150 | UA_SecurityGroup *tmpSG; |
| 58151 | TAILQ_FOREACH(tmpSG, &server->pubSubManager.securityGroups, listEntry) { |
| 58152 | if(UA_String_equal(&securityGroupName, &tmpSG->config.securityGroupName)) |
| 58153 | return tmpSG; |
| 58154 | } |
| 58155 | return NULL; |
| 58156 | } |
| 58157 | |
| 58158 | UA_StatusCode |
| 58159 | UA_SecurityGroupConfig_copy(const UA_SecurityGroupConfig *src, |
| 58160 | UA_SecurityGroupConfig *dst) { |
| 58161 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 58162 | |
| 58163 | memcpy(dst, src, sizeof(UA_SecurityGroupConfig)); |
| 58164 | if(UA_String_copy(&src->securityGroupName, &dst->securityGroupName) != |
| 58165 | UA_STATUSCODE_GOOD) |
| 58166 | return UA_STATUSCODE_BAD; |
| 58167 | |
| 58168 | if(UA_String_copy(&src->securityPolicyUri, &dst->securityPolicyUri) != |
| 58169 | UA_STATUSCODE_GOOD) |
| 58170 | return UA_STATUSCODE_BAD; |
| 58171 | return retval; |
| 58172 | } |
| 58173 | |
| 58174 | static UA_StatusCode |
| 58175 | generateKeyData(const UA_PubSubSecurityPolicy *policy, UA_ByteString *key) { |
| 58176 | if(!key || !policy) |
| 58177 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 58178 | |
| 58179 | UA_StatusCode retVal; |
| 58180 | |
| 58181 | /* Can't not found in specification for pubsub key generation, so use the idea of |
| 58182 | * securechannel, see specification 1.0.3 6.7.5 Deriving keys for more details |
| 58183 | In pubsub we do get have OpenSecureChannel request, so we cannot have Client or Server Nonce*/ |
| 58184 | UA_Byte secretBytes[UA_PUBSUB_KEYMATERIAL_NONCELENGTH]; |
| 58185 | UA_ByteString secret; |
| 58186 | secret.length = UA_PUBSUB_KEYMATERIAL_NONCELENGTH; |
| 58187 | secret.data = secretBytes; |
| 58188 | |
| 58189 | UA_Byte seedBytes[UA_PUBSUB_KEYMATERIAL_NONCELENGTH]; |
| 58190 | UA_ByteString seed; |
| 58191 | seed.data = seedBytes; |
| 58192 | seed.length = UA_PUBSUB_KEYMATERIAL_NONCELENGTH; |
| 58193 | memset(seed.data, 0, seed.length); |
| 58194 | retVal = policy->symmetricModule.generateNonce(policy->policyContext, &secret); |
| 58195 | retVal |= policy->symmetricModule.generateNonce(policy->policyContext, &seed); |
| 58196 | if(retVal != UA_STATUSCODE_GOOD) |
| 58197 | return retVal; |
| 58198 | |
| 58199 | retVal = policy->symmetricModule.generateKey(policy->policyContext, &secret, &seed, key); |
| 58200 | return retVal; |
| 58201 | } |
| 58202 | |
| 58203 | static void |
| 58204 | updateSKSKeyStorage(UA_Server *server, UA_SecurityGroup *securityGroup){ |
| 58205 | |
| 58206 | if(!securityGroup) { |
| 58207 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_PUBSUB, |
| 58208 | "UpdateSKSKeyStorage callback failed with Error: %s ", |
| 58209 | UA_StatusCode_name(UA_STATUSCODE_BADINVALIDARGUMENT)); |
| 58210 | return; |
| 58211 | } |
| 58212 | |
| 58213 | UA_PubSubKeyStorage *keyStorage = securityGroup->keyStorage; |
| 58214 | |
| 58215 | UA_StatusCode retval = UA_STATUSCODE_BAD; |
| 58216 | UA_ByteString newKey; |
| 58217 | size_t keyLength = keyStorage->policy->symmetricModule.secureChannelNonceLength; |
| 58218 | |
| 58219 | retval = UA_ByteString_allocBuffer(&newKey, keyLength); |
| 58220 | if(retval != UA_STATUSCODE_GOOD) { |
| 58221 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_PUBSUB, |
| 58222 | "UpdateSKSKeyStorage callback failed to allocate memory for new key with Error: %s ", |
| 58223 | UA_StatusCode_name(retval)); |
| 58224 | return; |
| 58225 | } |
| 58226 | |
| 58227 | generateKeyData(keyStorage->policy, &newKey); |
| 58228 | UA_UInt32 newKeyID = TAILQ_LAST(&keyStorage->keyList, keyListItems)->keyID; |
| 58229 | |
| 58230 | if(newKeyID >= UA_UINT32_MAX) |
| 58231 | newKeyID = 1; |
| 58232 | else |
| 58233 | ++newKeyID; |
| 58234 | |
| 58235 | if(keyStorage->keyListSize >= keyStorage->maxKeyListSize) { |
| 58236 | /* reusing the preallocated memory of the oldest key for the new key material */ |
| 58237 | UA_PubSubKeyListItem *oldestKey = TAILQ_FIRST(&keyStorage->keyList); |
| 58238 | TAILQ_REMOVE(&keyStorage->keyList, oldestKey, keyListEntry); |
| 58239 | TAILQ_INSERT_TAIL(&keyStorage->keyList, oldestKey, keyListEntry); |
| 58240 | UA_ByteString_clear(&oldestKey->key); |
| 58241 | oldestKey->keyID = newKeyID; |
| 58242 | UA_ByteString_copy(&newKey, &oldestKey->key); |
| 58243 | } else { |
| 58244 | UA_PubSubKeyListItem *newItem = |
| 58245 | UA_PubSubKeyStorage_push(keyStorage, &newKey, newKeyID); |
| 58246 | if(!newItem) { |
| 58247 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_PUBSUB, |
| 58248 | "UpdateSKSKeyStorage callback failed to add new key to the " |
| 58249 | "sks keystorage for the SecurityGroup %.*s", |
| 58250 | (int)securityGroup->securityGroupId.length, |
| 58251 | securityGroup->securityGroupId.data); |
| 58252 | UA_Byte_delete(newKey.data); |
| 58253 | return; |
| 58254 | } |
| 58255 | keyStorage->keyListSize++; |
| 58256 | } |
| 58257 | |
| 58258 | UA_PubSubKeyListItem *nextCurrentItem = TAILQ_NEXT(keyStorage->currentItem, keyListEntry); |
| 58259 | if(nextCurrentItem) |
| 58260 | keyStorage->currentItem = nextCurrentItem; |
| 58261 | |
| 58262 | securityGroup->baseTime = UA_DateTime_nowMonotonic(); |
| 58263 | |
| 58264 | /* We allocated memory for data with allocBuffer so now we free it */ |
| 58265 | UA_ByteString_clear(&newKey); |
| 58266 | } |
| 58267 | |
| 58268 | static UA_StatusCode |
| 58269 | initializeKeyStorageWithKeys(UA_Server *server, UA_SecurityGroup *securityGroup) { |
| 58270 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 58271 | |
| 58272 | UA_PubSubSecurityPolicy *policy = |
| 58273 | findPubSubSecurityPolicy(server, &securityGroup->config.securityPolicyUri); |
| 58274 | if(!policy) |
| 58275 | return UA_STATUSCODE_BADSECURITYPOLICYREJECTED; |
| 58276 | |
| 58277 | UA_PubSubKeyStorage *ks = (UA_PubSubKeyStorage *) |
| 58278 | UA_calloc(1, sizeof(UA_PubSubKeyStorage)); |
| 58279 | if(!ks) |
| 58280 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 58281 | |
| 58282 | UA_StatusCode retval = |
| 58283 | UA_PubSubKeyStorage_init(server, ks, &securityGroup->securityGroupId, |
| 58284 | policy, securityGroup->config.maxPastKeyCount, |
| 58285 | securityGroup->config.maxFutureKeyCount); |
| 58286 | if(retval != UA_STATUSCODE_GOOD) { |
| 58287 | UA_free(ks); |
| 58288 | return retval; |
| 58289 | } |
| 58290 | |
| 58291 | ks->referenceCount++; |
| 58292 | securityGroup->keyStorage = ks; |
| 58293 | |
| 58294 | UA_ByteString currentKey; |
| 58295 | size_t keyLength = ks->policy->symmetricModule.secureChannelNonceLength; |
| 58296 | retval = UA_ByteString_allocBuffer(¤tKey, keyLength); |
| 58297 | retval = generateKeyData(ks->policy, ¤tKey); |
| 58298 | |
| 58299 | UA_ByteString *futurekeys = (UA_ByteString *)UA_calloc(securityGroup->config.maxFutureKeyCount, sizeof(UA_ByteString)); |
| 58300 | for(size_t i = 0; i < securityGroup->config.maxFutureKeyCount; i++) { |
| 58301 | retval = UA_ByteString_allocBuffer(&futurekeys[i], keyLength); |
| 58302 | retval = generateKeyData(ks->policy, &futurekeys[i]); |
| 58303 | } |
| 58304 | |
| 58305 | UA_UInt32 startingKeyId = 1; |
| 58306 | retval = UA_PubSubKeyStorage_storeSecurityKeys(server, securityGroup->keyStorage, |
| 58307 | startingKeyId, ¤tKey, futurekeys, |
| 58308 | securityGroup->config.maxFutureKeyCount, |
| 58309 | securityGroup->config.keyLifeTime); |
| 58310 | if(retval != UA_STATUSCODE_GOOD) |
| 58311 | goto cleanup; |
| 58312 | |
| 58313 | securityGroup->baseTime = UA_DateTime_nowMonotonic(); |
| 58314 | retval = addRepeatedCallback(server, (UA_ServerCallback)updateSKSKeyStorage, |
| 58315 | securityGroup, securityGroup->config.keyLifeTime, |
| 58316 | &securityGroup->callbackId); |
| 58317 | |
| 58318 | cleanup: |
| 58319 | UA_Array_delete(futurekeys, securityGroup->config.maxFutureKeyCount, |
| 58320 | &UA_TYPES[UA_TYPES_BYTESTRING]); |
| 58321 | UA_ByteString_clear(¤tKey); |
| 58322 | if(retval != UA_STATUSCODE_GOOD) |
| 58323 | UA_PubSubKeyStorage_delete(server, ks); |
| 58324 | return retval; |
| 58325 | } |
| 58326 | |
| 58327 | static UA_StatusCode |
| 58328 | addSecurityGroup(UA_Server *server, UA_NodeId securityGroupFolderNodeId, |
| 58329 | const UA_SecurityGroupConfig *securityGroupConfig, |
| 58330 | UA_NodeId *securityGroupNodeId) { |
| 58331 | if(!securityGroupConfig) |
| 58332 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 58333 | |
| 58334 | /*check minimal config parameters*/ |
| 58335 | if(!securityGroupConfig->keyLifeTime || |
| 58336 | UA_String_isEmpty(&securityGroupConfig->securityGroupName) || |
| 58337 | UA_String_isEmpty(&securityGroupConfig->securityPolicyUri)) |
| 58338 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 58339 | |
| 58340 | if(UA_SecurityGroup_findSGbyName(server, securityGroupConfig->securityGroupName)) |
| 58341 | return UA_STATUSCODE_BADNODEIDEXISTS; |
| 58342 | |
| 58343 | UA_PubSubSecurityPolicy *policy = |
| 58344 | findPubSubSecurityPolicy(server, &securityGroupConfig->securityPolicyUri); |
| 58345 | if(!policy) |
| 58346 | return UA_STATUSCODE_BADSECURITYPOLICYREJECTED; |
| 58347 | |
| 58348 | if(securityGroupConfig->securityGroupName.length > 512) |
| 58349 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 58350 | |
| 58351 | UA_StatusCode retval = UA_STATUSCODE_BAD; |
| 58352 | |
| 58353 | UA_SecurityGroup *newSecurityGroup = |
| 58354 | (UA_SecurityGroup *)UA_calloc(1, sizeof(UA_SecurityGroup)); |
| 58355 | if(!newSecurityGroup) |
| 58356 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 58357 | |
| 58358 | memset(newSecurityGroup, 0, sizeof(UA_SecurityGroup)); |
| 58359 | UA_SecurityGroupConfig_copy(securityGroupConfig, &newSecurityGroup->config); |
| 58360 | |
| 58361 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 58362 | retval = UA_NodeId_copy(&securityGroupFolderNodeId, |
| 58363 | &newSecurityGroup->securityGroupFolderId); |
| 58364 | if(retval != UA_STATUSCODE_GOOD) { |
| 58365 | UA_SecurityGroup_delete(newSecurityGroup); |
| 58366 | return retval; |
| 58367 | } |
| 58368 | #endif |
| 58369 | |
| 58370 | retval = UA_String_copy(&securityGroupConfig->securityGroupName, |
| 58371 | &newSecurityGroup->securityGroupId); |
| 58372 | if(retval != UA_STATUSCODE_GOOD) { |
| 58373 | UA_SecurityGroup_delete(newSecurityGroup); |
| 58374 | return retval; |
| 58375 | } |
| 58376 | |
| 58377 | retval = initializeKeyStorageWithKeys(server, newSecurityGroup); |
| 58378 | if(retval != UA_STATUSCODE_GOOD) { |
| 58379 | UA_SecurityGroup_delete(newSecurityGroup); |
| 58380 | return retval; |
| 58381 | } |
| 58382 | |
| 58383 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 58384 | retval = addSecurityGroupRepresentation(server, newSecurityGroup); |
| 58385 | if(retval != UA_STATUSCODE_GOOD) { |
| 58386 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58387 | "Add SecurityGroup failed with error: %s.", |
| 58388 | UA_StatusCode_name(retval)); |
| 58389 | UA_SecurityGroup_delete(newSecurityGroup); |
| 58390 | return retval; |
| 58391 | } |
| 58392 | #else |
| 58393 | UA_PubSubManager_generateUniqueNodeId(&server->pubSubManager, |
| 58394 | &newSecurityGroup->securityGroupNodeId); |
| 58395 | #endif |
| 58396 | if(securityGroupNodeId) |
| 58397 | UA_NodeId_copy(&newSecurityGroup->securityGroupNodeId, securityGroupNodeId); |
| 58398 | |
| 58399 | TAILQ_INSERT_TAIL(&server->pubSubManager.securityGroups, newSecurityGroup, listEntry); |
| 58400 | |
| 58401 | server->pubSubManager.securityGroupsSize++; |
| 58402 | return retval; |
| 58403 | } |
| 58404 | |
| 58405 | UA_StatusCode |
| 58406 | UA_Server_addSecurityGroup(UA_Server *server, UA_NodeId securityGroupFolderNodeId, |
| 58407 | const UA_SecurityGroupConfig *securityGroupConfig, |
| 58408 | UA_NodeId *securityGroupNodeId) { |
| 58409 | lockServer(server); |
| 58410 | UA_StatusCode retval = addSecurityGroup(server, securityGroupFolderNodeId, |
| 58411 | securityGroupConfig, securityGroupNodeId); |
| 58412 | unlockServer(server); |
| 58413 | return retval; |
| 58414 | } |
| 58415 | |
| 58416 | UA_SecurityGroup * |
| 58417 | UA_SecurityGroup_findSGbyId(UA_Server *server, UA_NodeId identifier) { |
| 58418 | UA_SecurityGroup *tmpSG; |
| 58419 | TAILQ_FOREACH(tmpSG, &server->pubSubManager.securityGroups, listEntry) { |
| 58420 | if(UA_NodeId_equal(&identifier, &tmpSG->securityGroupNodeId)) |
| 58421 | return tmpSG; |
| 58422 | } |
| 58423 | return NULL; |
| 58424 | } |
| 58425 | |
| 58426 | static void |
| 58427 | UA_SecurityGroupConfig_clear(UA_SecurityGroupConfig *config) { |
| 58428 | config->keyLifeTime = 0; |
| 58429 | config->maxFutureKeyCount = 0; |
| 58430 | UA_String_clear(&config->securityGroupName); |
| 58431 | UA_String_clear(&config->securityPolicyUri); |
| 58432 | } |
| 58433 | |
| 58434 | static void |
| 58435 | UA_SecurityGroup_clear(UA_SecurityGroup *securityGroup) { |
| 58436 | UA_SecurityGroupConfig_clear(&securityGroup->config); |
| 58437 | UA_String_clear(&securityGroup->securityGroupId); |
| 58438 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 58439 | UA_NodeId_clear(&securityGroup->securityGroupFolderId); |
| 58440 | #endif |
| 58441 | UA_NodeId_clear(&securityGroup->securityGroupNodeId); |
| 58442 | } |
| 58443 | |
| 58444 | void |
| 58445 | UA_SecurityGroup_delete(UA_SecurityGroup *securityGroup) { |
| 58446 | UA_SecurityGroup_clear(securityGroup); |
| 58447 | UA_free(securityGroup); |
| 58448 | } |
| 58449 | |
| 58450 | void |
| 58451 | removeSecurityGroup(UA_Server *server, UA_SecurityGroup *securityGroup) { |
| 58452 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 58453 | deleteNode(server, securityGroup->securityGroupNodeId, true); |
| 58454 | #endif |
| 58455 | |
| 58456 | /* Unlink from the server */ |
| 58457 | TAILQ_REMOVE(&server->pubSubManager.securityGroups, securityGroup, listEntry); |
| 58458 | server->pubSubManager.securityGroupsSize--; |
| 58459 | if(securityGroup->callbackId > 0) |
| 58460 | removeCallback(server, securityGroup->callbackId); |
| 58461 | |
| 58462 | if(securityGroup->keyStorage) { |
| 58463 | UA_PubSubKeyStorage_detachKeyStorage(server, securityGroup->keyStorage); |
| 58464 | securityGroup->keyStorage = NULL; |
| 58465 | } |
| 58466 | |
| 58467 | UA_SecurityGroup_delete(securityGroup); |
| 58468 | } |
| 58469 | |
| 58470 | UA_StatusCode |
| 58471 | UA_Server_removeSecurityGroup(UA_Server *server, const UA_NodeId securityGroup) { |
| 58472 | lockServer(server); |
| 58473 | UA_SecurityGroup *sg = UA_SecurityGroup_findSGbyId(server, securityGroup); |
| 58474 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 58475 | if(sg) { |
| 58476 | removeSecurityGroup(server, sg); |
| 58477 | } else { |
| 58478 | res = UA_STATUSCODE_BADBOUNDNOTFOUND; |
| 58479 | } |
| 58480 | unlockServer(server); |
| 58481 | return res; |
| 58482 | } |
| 58483 | |
| 58484 | #endif |
| 58485 | |
| 58486 | /**** amalgamated original file "/src/pubsub/ua_pubsub_config.c" ****/ |
| 58487 | |
| 58488 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 58489 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 58490 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 58491 | * |
| 58492 | * Copyright (c) 2020 Yannick Wallerer, Siemens AG |
| 58493 | * Copyright (c) 2020 Thomas Fischer, Siemens AG |
| 58494 | */ |
| 58495 | |
| 58496 | |
| 58497 | #if defined(UA_ENABLE_PUBSUB) && defined(UA_ENABLE_PUBSUB_FILE_CONFIG) |
| 58498 | |
| 58499 | static UA_StatusCode |
| 58500 | createPubSubConnection(UA_Server *server, |
| 58501 | const UA_PubSubConnectionDataType *connection, |
| 58502 | UA_UInt32 pdsCount, UA_NodeId *pdsIdent); |
| 58503 | |
| 58504 | static UA_StatusCode |
| 58505 | createWriterGroup(UA_Server *server, |
| 58506 | const UA_WriterGroupDataType *writerGroupParameters, |
| 58507 | UA_NodeId connectionIdent, UA_UInt32 pdsCount, |
| 58508 | const UA_NodeId *pdsIdent); |
| 58509 | |
| 58510 | static UA_StatusCode |
| 58511 | createDataSetWriter(UA_Server *server, |
| 58512 | const UA_DataSetWriterDataType *dataSetWriterParameters, |
| 58513 | UA_NodeId writerGroupIdent, UA_UInt32 pdsCount, |
| 58514 | const UA_NodeId *pdsIdent); |
| 58515 | |
| 58516 | static UA_StatusCode |
| 58517 | createReaderGroup(UA_Server *server, |
| 58518 | const UA_ReaderGroupDataType *readerGroupParameters, |
| 58519 | UA_NodeId connectionIdent); |
| 58520 | |
| 58521 | static UA_StatusCode |
| 58522 | createDataSetReader(UA_Server *server, |
| 58523 | const UA_DataSetReaderDataType *dataSetReaderParameters, |
| 58524 | UA_NodeId readerGroupIdent); |
| 58525 | |
| 58526 | static UA_StatusCode |
| 58527 | createPublishedDataSet(UA_Server *server, |
| 58528 | const UA_PublishedDataSetDataType *publishedDataSetParameters, |
| 58529 | UA_NodeId *publishedDataSetIdent); |
| 58530 | |
| 58531 | static UA_StatusCode |
| 58532 | createDataSetFields(UA_Server *server, |
| 58533 | const UA_NodeId *publishedDataSetIdent, |
| 58534 | const UA_PublishedDataSetDataType *publishedDataSetParameters); |
| 58535 | |
| 58536 | static UA_StatusCode |
| 58537 | generatePubSubConfigurationDataType(UA_Server *server, |
| 58538 | UA_PubSubConfigurationDataType *pubSubConfiguration); |
| 58539 | |
| 58540 | /* Gets PubSub Configuration from an ExtensionObject */ |
| 58541 | static UA_StatusCode |
| 58542 | extractPubSubConfigFromExtensionObject(UA_Server *server, |
| 58543 | const UA_ExtensionObject *src, |
| 58544 | UA_PubSubConfigurationDataType **dst) { |
| 58545 | if(src->encoding != UA_EXTENSIONOBJECT_DECODED || |
| 58546 | src->content.decoded.type != &UA_TYPES[UA_TYPES_UABINARYFILEDATATYPE]) { |
| 58547 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58548 | "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] " |
| 58549 | "Reading extensionObject failed"); |
| 58550 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 58551 | } |
| 58552 | |
| 58553 | UA_UABinaryFileDataType *binFile = (UA_UABinaryFileDataType*)src->content.decoded.data; |
| 58554 | |
| 58555 | if(binFile->body.arrayLength != 0 || binFile->body.arrayDimensionsSize != 0) { |
| 58556 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58557 | "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] " |
| 58558 | "Loading multiple configurations is not supported"); |
| 58559 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 58560 | } |
| 58561 | |
| 58562 | if(binFile->body.type != &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONDATATYPE]) { |
| 58563 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58564 | "[UA_PubSubManager_extractPubSubConfigFromDecodedObject] " |
| 58565 | "Invalid datatype encoded in the binary file"); |
| 58566 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 58567 | } |
| 58568 | |
| 58569 | *dst = (UA_PubSubConfigurationDataType*)binFile->body.data; |
| 58570 | return UA_STATUSCODE_GOOD; |
| 58571 | } |
| 58572 | |
| 58573 | /* Configures a PubSub Server with given PubSubConfigurationDataType object */ |
| 58574 | static UA_StatusCode |
| 58575 | updatePubSubConfig(UA_Server *server, |
| 58576 | const UA_PubSubConfigurationDataType *configurationParameters) { |
| 58577 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 58578 | |
| 58579 | if(configurationParameters == NULL) { |
| 58580 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58581 | "[UA_PubSubManager_updatePubSubConfig] Invalid argument"); |
| 58582 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 58583 | } |
| 58584 | |
| 58585 | UA_PubSubManager_delete(server, &server->pubSubManager); |
| 58586 | |
| 58587 | /* Configuration of Published DataSets: */ |
| 58588 | UA_UInt32 pdsCount = (UA_UInt32)configurationParameters->publishedDataSetsSize; |
| 58589 | UA_NodeId *publishedDataSetIdent = (UA_NodeId*)UA_calloc(pdsCount, sizeof(UA_NodeId)); |
| 58590 | if(!publishedDataSetIdent) |
| 58591 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 58592 | |
| 58593 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 58594 | |
| 58595 | for(UA_UInt32 i = 0; i < pdsCount; i++) { |
| 58596 | res = createPublishedDataSet(server, |
| 58597 | &configurationParameters->publishedDataSets[i], |
| 58598 | &publishedDataSetIdent[i]); |
| 58599 | if(res != UA_STATUSCODE_GOOD) { |
| 58600 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58601 | "[UA_PubSubManager_updatePubSubConfig] PDS creation failed"); |
| 58602 | UA_free(publishedDataSetIdent); |
| 58603 | return res; |
| 58604 | } |
| 58605 | } |
| 58606 | |
| 58607 | /* Configuration of PubSub Connections: */ |
| 58608 | if(configurationParameters->connectionsSize < 1) { |
| 58609 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58610 | "[UA_PubSubManager_updatePubSubConfig] no connection in " |
| 58611 | "UA_PubSubConfigurationDataType"); |
| 58612 | UA_free(publishedDataSetIdent); |
| 58613 | return UA_STATUSCODE_GOOD; |
| 58614 | } |
| 58615 | |
| 58616 | for(size_t i = 0; i < configurationParameters->connectionsSize; i++) { |
| 58617 | res = createPubSubConnection(server, |
| 58618 | &configurationParameters->connections[i], |
| 58619 | pdsCount, publishedDataSetIdent); |
| 58620 | if(res != UA_STATUSCODE_GOOD) |
| 58621 | break; |
| 58622 | } |
| 58623 | |
| 58624 | UA_free(publishedDataSetIdent); |
| 58625 | |
| 58626 | return res; |
| 58627 | } |
| 58628 | |
| 58629 | /* Function called by UA_PubSubManager_createPubSubConnection to set the |
| 58630 | * PublisherId of a certain connection. */ |
| 58631 | static UA_StatusCode |
| 58632 | setConnectionPublisherId(UA_Server *server, |
| 58633 | const UA_PubSubConnectionDataType *src, |
| 58634 | UA_PubSubConnectionConfig *dst) { |
| 58635 | if(src->publisherId.type == &UA_TYPES[UA_TYPES_STRING]) { |
| 58636 | dst->publisherIdType = UA_PUBLISHERIDTYPE_STRING; |
| 58637 | dst->publisherId.string = *(UA_String*)src->publisherId.data; |
| 58638 | } else if(src->publisherId.type == &UA_TYPES[UA_TYPES_BYTE]) { |
| 58639 | dst->publisherIdType = UA_PUBLISHERIDTYPE_BYTE; |
| 58640 | dst->publisherId.byte = *((UA_Byte*)src->publisherId.data); |
| 58641 | } else if(src->publisherId.type == &UA_TYPES[UA_TYPES_UINT16]) { |
| 58642 | dst->publisherIdType = UA_PUBLISHERIDTYPE_UINT16; |
| 58643 | dst->publisherId.uint16 = *((UA_UInt16*)src->publisherId.data); |
| 58644 | } else if(src->publisherId.type == &UA_TYPES[UA_TYPES_UINT32]) { |
| 58645 | dst->publisherIdType = UA_PUBLISHERIDTYPE_UINT32; |
| 58646 | dst->publisherId.uint32 = *(UA_UInt32*)src->publisherId.data; |
| 58647 | } else if(src->publisherId.type == &UA_TYPES[UA_TYPES_UINT64]) { |
| 58648 | dst->publisherIdType = UA_PUBLISHERIDTYPE_UINT64; |
| 58649 | dst->publisherId.uint64 = *(UA_UInt64*)src->publisherId.data; |
| 58650 | } else { |
| 58651 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58652 | "[UA_PubSubManager_setConnectionPublisherId] PublisherId is not valid."); |
| 58653 | return UA_STATUSCODE_BADINTERNALERROR; |
| 58654 | } |
| 58655 | return UA_STATUSCODE_GOOD; |
| 58656 | } |
| 58657 | |
| 58658 | /* Function called by UA_PubSubManager_createPubSubConnection to create all WriterGroups |
| 58659 | * and ReaderGroups that belong to a certain connection. */ |
| 58660 | static UA_StatusCode |
| 58661 | createComponentsForConnection(UA_Server *server, |
| 58662 | const UA_PubSubConnectionDataType *connParams, |
| 58663 | UA_NodeId connectionIdent, UA_UInt32 pdsCount, |
| 58664 | const UA_NodeId *pdsIdent) { |
| 58665 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 58666 | |
| 58667 | /* WriterGroups configuration */ |
| 58668 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 58669 | for(size_t i = 0; i < connParams->writerGroupsSize; i++) { |
| 58670 | res = createWriterGroup(server, &connParams->writerGroups[i], |
| 58671 | connectionIdent, pdsCount, pdsIdent); |
| 58672 | if(res != UA_STATUSCODE_GOOD) { |
| 58673 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58674 | "[UA_PubSubManager_createComponentsForConnection] " |
| 58675 | "Error occured during %d. WriterGroup Creation", (UA_UInt32)i+1); |
| 58676 | return res; |
| 58677 | } |
| 58678 | } |
| 58679 | |
| 58680 | /* ReaderGroups configuration */ |
| 58681 | for(size_t j = 0; j < connParams->readerGroupsSize; j++) { |
| 58682 | res = createReaderGroup(server, &connParams->readerGroups[j], connectionIdent); |
| 58683 | if(res != UA_STATUSCODE_GOOD) { |
| 58684 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58685 | "[UA_PubSubManager_createComponentsForConnection] " |
| 58686 | "Error occured during %d. ReaderGroup Creation", (UA_UInt32)j+1); |
| 58687 | return res; |
| 58688 | } |
| 58689 | } |
| 58690 | |
| 58691 | return res; |
| 58692 | } |
| 58693 | |
| 58694 | /* Creates PubSubConnection configuration from PubSubConnectionDataType object |
| 58695 | * |
| 58696 | * @param server Server object that shall be configured |
| 58697 | * @param connParams PubSub connection configuration |
| 58698 | * @param pdsCount Number of published DataSets |
| 58699 | * @param pdsIdent Array of NodeIds of the published DataSets */ |
| 58700 | static UA_StatusCode |
| 58701 | createPubSubConnection(UA_Server *server, const UA_PubSubConnectionDataType *connParams, |
| 58702 | UA_UInt32 pdsCount, UA_NodeId *pdsIdent) { |
| 58703 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 58704 | |
| 58705 | UA_PubSubConnectionConfig config; |
| 58706 | memset(&config, 0, sizeof(UA_PubSubConnectionConfig)); |
| 58707 | |
| 58708 | config.name = connParams->name; |
| 58709 | config.enabled = connParams->enabled; |
| 58710 | config.transportProfileUri = connParams->transportProfileUri; |
| 58711 | config.connectionProperties.map = connParams->connectionProperties; |
| 58712 | config.connectionProperties.mapSize = connParams->connectionPropertiesSize; |
| 58713 | |
| 58714 | UA_StatusCode res = setConnectionPublisherId(server, connParams, &config); |
| 58715 | if(res != UA_STATUSCODE_GOOD) { |
| 58716 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58717 | "[UA_PubSubManager_createPubSubConnection] " |
| 58718 | "Setting PublisherId failed"); |
| 58719 | return res; |
| 58720 | } |
| 58721 | |
| 58722 | if(connParams->address.encoding == UA_EXTENSIONOBJECT_DECODED) { |
| 58723 | UA_Variant_setScalar(&(config.address), |
| 58724 | connParams->address.content.decoded.data, |
| 58725 | connParams->address.content.decoded.type); |
| 58726 | } else { |
| 58727 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58728 | "[UA_PubSubManager_createPubSubConnection] " |
| 58729 | "Reading connection address failed"); |
| 58730 | return UA_STATUSCODE_BADINTERNALERROR; |
| 58731 | } |
| 58732 | |
| 58733 | if(connParams->transportSettings.encoding == UA_EXTENSIONOBJECT_DECODED) { |
| 58734 | UA_Variant_setScalar(&(config.connectionTransportSettings), |
| 58735 | connParams->transportSettings.content.decoded.data, |
| 58736 | connParams->transportSettings.content.decoded.type); |
| 58737 | } else { |
| 58738 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58739 | "[UA_PubSubManager_createPubSubConnection] " |
| 58740 | "TransportSettings can not be read"); |
| 58741 | } |
| 58742 | |
| 58743 | /* Load connection config into server: */ |
| 58744 | UA_NodeId connectionIdent; |
| 58745 | res = UA_PubSubConnection_create(server, &config, &connectionIdent); |
| 58746 | if(res == UA_STATUSCODE_GOOD) { |
| 58747 | /* Configuration of all Components that belong to this connection: */ |
| 58748 | res = createComponentsForConnection(server, connParams, connectionIdent, |
| 58749 | pdsCount, pdsIdent); |
| 58750 | } else { |
| 58751 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58752 | "[UA_PubSubManager_createPubSubConnection] " |
| 58753 | "Connection creation failed"); |
| 58754 | } |
| 58755 | |
| 58756 | return res; |
| 58757 | } |
| 58758 | |
| 58759 | /* Function called by UA_PubSubManager_createWriterGroup to configure the messageSettings |
| 58760 | * of a writerGroup */ |
| 58761 | static UA_StatusCode |
| 58762 | setWriterGroupEncodingType(UA_Server *server, |
| 58763 | const UA_WriterGroupDataType *writerGroupParameters, |
| 58764 | UA_WriterGroupConfig *config) { |
| 58765 | if(writerGroupParameters->messageSettings.encoding != UA_EXTENSIONOBJECT_DECODED) { |
| 58766 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58767 | "[UA_PubSubManager_setWriterGroupEncodingType] " |
| 58768 | "getting message type information failed"); |
| 58769 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 58770 | } |
| 58771 | |
| 58772 | if(writerGroupParameters->messageSettings.content.decoded.type == |
| 58773 | &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE]) { |
| 58774 | config->encodingMimeType = UA_PUBSUB_ENCODING_UADP; |
| 58775 | } else if(writerGroupParameters->messageSettings.content.decoded.type == |
| 58776 | &UA_TYPES[UA_TYPES_JSONWRITERGROUPMESSAGEDATATYPE]) { |
| 58777 | #ifdef UA_ENABLE_JSON_ENCODING |
| 58778 | config->encodingMimeType = UA_PUBSUB_ENCODING_JSON; |
| 58779 | #else |
| 58780 | UA_LOG_ERROR(psm->logging, UA_LOGCATEGORY_PUBSUB, |
| 58781 | "[UA_PubSubManager_setWriterGroupEncodingType] " |
| 58782 | "encoding type: JSON (not implemented!)"); |
| 58783 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 58784 | #endif |
| 58785 | } else { |
| 58786 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58787 | "[UA_PubSubManager_setWriterGroupEncodingType] " |
| 58788 | "invalid message encoding type"); |
| 58789 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 58790 | } |
| 58791 | |
| 58792 | return UA_STATUSCODE_GOOD; |
| 58793 | } |
| 58794 | |
| 58795 | /* WriterGroup configuration from WriterGroup object |
| 58796 | * |
| 58797 | * @param server Server object that shall be configured |
| 58798 | * @param writerGroupParameters WriterGroup configuration |
| 58799 | * @param connectionIdent NodeId of the PubSub connection, the WriterGroup belongs to |
| 58800 | * @param pdsCount Number of published DataSets |
| 58801 | * @param pdsIdent Array of NodeIds of the published DataSets */ |
| 58802 | static UA_StatusCode |
| 58803 | createWriterGroup(UA_Server *server, |
| 58804 | const UA_WriterGroupDataType *writerGroupParameters, |
| 58805 | UA_NodeId connectionIdent, UA_UInt32 pdsCount, |
| 58806 | const UA_NodeId *pdsIdent) { |
| 58807 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 58808 | |
| 58809 | UA_WriterGroupConfig config; |
| 58810 | memset(&config, 0, sizeof(UA_WriterGroupConfig)); |
| 58811 | config.name = writerGroupParameters->name; |
| 58812 | config.enabled = writerGroupParameters->enabled; |
| 58813 | config.writerGroupId = writerGroupParameters->writerGroupId; |
| 58814 | config.publishingInterval = writerGroupParameters->publishingInterval; |
| 58815 | config.keepAliveTime = writerGroupParameters->keepAliveTime; |
| 58816 | config.priority = writerGroupParameters->priority; |
| 58817 | config.securityMode = writerGroupParameters->securityMode; |
| 58818 | config.transportSettings = writerGroupParameters->transportSettings; |
| 58819 | config.messageSettings = writerGroupParameters->messageSettings; |
| 58820 | config.groupProperties.mapSize = writerGroupParameters->groupPropertiesSize; |
| 58821 | config.groupProperties.map = writerGroupParameters->groupProperties; |
| 58822 | config.maxEncapsulatedDataSetMessageCount = 255; /* non std parameter */ |
| 58823 | |
| 58824 | UA_StatusCode res = setWriterGroupEncodingType(server, writerGroupParameters, &config); |
| 58825 | if(res != UA_STATUSCODE_GOOD) { |
| 58826 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58827 | "[UA_PubSubManager_createWriterGroup] " |
| 58828 | "Setting message settings failed"); |
| 58829 | return res; |
| 58830 | } |
| 58831 | |
| 58832 | /* Load config into server: */ |
| 58833 | UA_NodeId writerGroupIdent; |
| 58834 | res = UA_WriterGroup_create(server, connectionIdent, &config, &writerGroupIdent); |
| 58835 | UA_WriterGroup *wg = UA_WriterGroup_findWGbyId(server, writerGroupIdent); |
| 58836 | if(wg) |
| 58837 | UA_WriterGroup_setPubSubState(server, wg, UA_PUBSUBSTATE_OPERATIONAL, UA_STATUSCODE_GOOD); |
| 58838 | if(res != UA_STATUSCODE_GOOD) { |
| 58839 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58840 | "[UA_PubSubManager_createWriterGroup] " |
| 58841 | "Adding WriterGroup to server failed: 0x%x", res); |
| 58842 | return res; |
| 58843 | } |
| 58844 | |
| 58845 | /* Configuration of all DataSetWriters that belong to this WriterGroup */ |
| 58846 | for(size_t dsw = 0; dsw < writerGroupParameters->dataSetWritersSize; dsw++) { |
| 58847 | res = createDataSetWriter(server, &writerGroupParameters->dataSetWriters[dsw], |
| 58848 | writerGroupIdent, pdsCount, pdsIdent); |
| 58849 | if(res != UA_STATUSCODE_GOOD) { |
| 58850 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58851 | "[UA_PubSubManager_createWriterGroup] " |
| 58852 | "DataSetWriter Creation failed."); |
| 58853 | break; |
| 58854 | } |
| 58855 | } |
| 58856 | return res; |
| 58857 | } |
| 58858 | |
| 58859 | /* Function called by UA_PubSubManager_createDataSetWriter. It searches for a |
| 58860 | * PublishedDataSet that is referenced by the DataSetWriter. If a related PDS is found, |
| 58861 | * the DSWriter will be added to the server, otherwise, no DSWriter will be added. |
| 58862 | * |
| 58863 | * @param server UA_Server object that shall be configured |
| 58864 | * @param writerGroupIdent NodeId of writerGroup, the DataSetWriter belongs to |
| 58865 | * @param dsWriterConfig WriterGroup configuration |
| 58866 | * @param pdsCount Number of published DataSets |
| 58867 | * @param pdsIdent Array of NodeIds of the published DataSets */ |
| 58868 | static UA_StatusCode |
| 58869 | addDataSetWriterWithPdsReference(UA_Server *server, UA_NodeId writerGroupIdent, |
| 58870 | const UA_DataSetWriterConfig *dsWriterConfig, |
| 58871 | UA_UInt32 pdsCount, const UA_NodeId *pdsIdent) { |
| 58872 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 58873 | |
| 58874 | UA_NodeId dataSetWriterIdent; |
| 58875 | UA_PublishedDataSetConfig pdsConfig; |
| 58876 | UA_Boolean pdsFound = false; |
| 58877 | |
| 58878 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 58879 | for(size_t pds = 0; pds < pdsCount && res == UA_STATUSCODE_GOOD; pds++) { |
| 58880 | res = getPublishedDataSetConfig(server, pdsIdent[pds], &pdsConfig); |
| 58881 | /* members of pdsConfig must be deleted manually */ |
| 58882 | if(res != UA_STATUSCODE_GOOD) { |
| 58883 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58884 | "[UA_PubSubManager_addDataSetWriterWithPdsReference] " |
| 58885 | "Getting pdsConfig from NodeId failed."); |
| 58886 | return res; |
| 58887 | } |
| 58888 | |
| 58889 | if(dsWriterConfig->dataSetName.length == pdsConfig.name.length && |
| 58890 | 0 == strncmp((const char *)dsWriterConfig->dataSetName.data, |
| 58891 | (const char *)pdsConfig.name.data, |
| 58892 | dsWriterConfig->dataSetName.length)) { |
| 58893 | /* DSWriter will only be created, if a matching PDS is found: */ |
| 58894 | res = UA_DataSetWriter_create(server, writerGroupIdent, pdsIdent[pds], |
| 58895 | dsWriterConfig, &dataSetWriterIdent); |
| 58896 | if(res != UA_STATUSCODE_GOOD) { |
| 58897 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58898 | "[UA_PubSubManager_addDataSetWriterWithPdsReference] " |
| 58899 | "Adding DataSetWriter failed"); |
| 58900 | } else { |
| 58901 | pdsFound = true; |
| 58902 | } |
| 58903 | |
| 58904 | UA_PublishedDataSetConfig_clear(&pdsConfig); |
| 58905 | if(pdsFound) |
| 58906 | break; /* break loop if corresponding publishedDataSet was found */ |
| 58907 | } |
| 58908 | } |
| 58909 | |
| 58910 | if(!pdsFound) { |
| 58911 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58912 | "[UA_PubSubManager_addDataSetWriterWithPdsReference] " |
| 58913 | "No matching DataSet found; no DataSetWriter created"); |
| 58914 | } |
| 58915 | |
| 58916 | return res; |
| 58917 | } |
| 58918 | |
| 58919 | /* Creates DataSetWriter configuration from DataSetWriter object |
| 58920 | * |
| 58921 | * @param server UA_Server object that shall be configured |
| 58922 | * @param dataSetWriterParameters DataSetWriter Configuration |
| 58923 | * @param writerGroupIdent NodeId of writerGroup, the DataSetWriter belongs to |
| 58924 | * @param pdsCount Number of published DataSets |
| 58925 | * @param pdsIdent Array of NodeIds of the published DataSets */ |
| 58926 | static UA_StatusCode |
| 58927 | createDataSetWriter(UA_Server *server, |
| 58928 | const UA_DataSetWriterDataType *dataSetWriterParameters, |
| 58929 | UA_NodeId writerGroupIdent, UA_UInt32 pdsCount, |
| 58930 | const UA_NodeId *pdsIdent) { |
| 58931 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 58932 | |
| 58933 | UA_DataSetWriterConfig config; |
| 58934 | memset(&config, 0, sizeof(UA_DataSetWriterConfig)); |
| 58935 | config.name = dataSetWriterParameters->name; |
| 58936 | config.dataSetWriterId = dataSetWriterParameters->dataSetWriterId; |
| 58937 | config.keyFrameCount = dataSetWriterParameters->keyFrameCount; |
| 58938 | config.dataSetFieldContentMask = dataSetWriterParameters->dataSetFieldContentMask; |
| 58939 | config.messageSettings = dataSetWriterParameters->messageSettings; |
| 58940 | config.dataSetName = dataSetWriterParameters->dataSetName; |
| 58941 | config.dataSetWriterProperties.mapSize = dataSetWriterParameters->dataSetWriterPropertiesSize; |
| 58942 | config.dataSetWriterProperties.map = dataSetWriterParameters->dataSetWriterProperties; |
| 58943 | |
| 58944 | UA_StatusCode res = addDataSetWriterWithPdsReference(server, writerGroupIdent, |
| 58945 | &config, pdsCount, pdsIdent); |
| 58946 | if(res != UA_STATUSCODE_GOOD) { |
| 58947 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58948 | "[UA_PubSubManager_createDataSetWriter] " |
| 58949 | "Referencing related PDS failed"); |
| 58950 | } |
| 58951 | |
| 58952 | return res; |
| 58953 | } |
| 58954 | |
| 58955 | /* Creates ReaderGroup configuration from ReaderGroup object |
| 58956 | * |
| 58957 | * @param server UA_Server object that shall be configured |
| 58958 | * @param readerGroupParameters ReaderGroup configuration |
| 58959 | * @param connectionIdent NodeId of the PubSub connection, the ReaderGroup belongs to */ |
| 58960 | static UA_StatusCode |
| 58961 | createReaderGroup(UA_Server *server, |
| 58962 | const UA_ReaderGroupDataType *readerGroupParameters, |
| 58963 | UA_NodeId connectionIdent) { |
| 58964 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 58965 | |
| 58966 | UA_ReaderGroupConfig config; |
| 58967 | memset(&config, 0, sizeof(UA_ReaderGroupConfig)); |
| 58968 | |
| 58969 | config.name = readerGroupParameters->name; |
| 58970 | config.securityMode = readerGroupParameters->securityMode; |
| 58971 | |
| 58972 | UA_NodeId readerGroupIdent; |
| 58973 | UA_StatusCode res = |
| 58974 | UA_ReaderGroup_create(server, connectionIdent, &config, &readerGroupIdent); |
| 58975 | if(res != UA_STATUSCODE_GOOD) { |
| 58976 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58977 | "[UA_PubSubManager_createReaderGroup] Adding ReaderGroup " |
| 58978 | "to server failed: 0x%x", res); |
| 58979 | return res; |
| 58980 | } |
| 58981 | |
| 58982 | UA_LOG_INFO(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58983 | "[UA_PubSubManager_createReaderGroup] ReaderGroup successfully added."); |
| 58984 | for(UA_UInt32 i = 0; i < readerGroupParameters->dataSetReadersSize; i++) { |
| 58985 | res = createDataSetReader(server, &readerGroupParameters->dataSetReaders[i], |
| 58986 | readerGroupIdent); |
| 58987 | if(res != UA_STATUSCODE_GOOD) { |
| 58988 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 58989 | "[UA_PubSubManager_createReaderGroup] Creating DataSetReader failed"); |
| 58990 | break; |
| 58991 | } |
| 58992 | } |
| 58993 | |
| 58994 | UA_ReaderGroup *rg = UA_ReaderGroup_findRGbyId(server, readerGroupIdent); |
| 58995 | if(res == UA_STATUSCODE_GOOD && rg) |
| 58996 | UA_ReaderGroup_setPubSubState(server, rg, UA_PUBSUBSTATE_OPERATIONAL, |
| 58997 | UA_STATUSCODE_GOOD); |
| 58998 | |
| 58999 | return res; |
| 59000 | } |
| 59001 | |
| 59002 | /* Creates TargetVariables or SubscribedDataSetMirror for a given DataSetReader |
| 59003 | * |
| 59004 | * @param server UA_Server object that shall be configured |
| 59005 | * @param dsReaderIdent NodeId of the DataSetReader the SubscribedDataSet belongs to |
| 59006 | * @param dataSetReaderParameters Configuration Parameters of the DataSetReader */ |
| 59007 | static UA_StatusCode |
| 59008 | addSubscribedDataSet(UA_Server *server, const UA_NodeId dsReaderIdent, |
| 59009 | const UA_ExtensionObject *subscribedDataSet) { |
| 59010 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 59011 | |
| 59012 | if(subscribedDataSet->content.decoded.type == |
| 59013 | &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]) { |
| 59014 | UA_TargetVariablesDataType *tmpTargetVars = (UA_TargetVariablesDataType*) |
| 59015 | subscribedDataSet->content.decoded.data; |
| 59016 | UA_FieldTargetVariable *targetVars = (UA_FieldTargetVariable *) |
| 59017 | UA_calloc(tmpTargetVars->targetVariablesSize, sizeof(UA_FieldTargetVariable)); |
| 59018 | |
| 59019 | for(size_t index = 0; index < tmpTargetVars->targetVariablesSize; index++) { |
| 59020 | UA_FieldTargetDataType_copy(&tmpTargetVars->targetVariables[index], |
| 59021 | &targetVars[index].targetVariable); |
| 59022 | } |
| 59023 | |
| 59024 | UA_StatusCode res = UA_STATUSCODE_BADINTERNALERROR; |
| 59025 | UA_DataSetReader *dsr = UA_ReaderGroup_findDSRbyId(server, dsReaderIdent); |
| 59026 | if(dsr) |
| 59027 | res = DataSetReader_createTargetVariables(server, dsr, |
| 59028 | tmpTargetVars->targetVariablesSize, |
| 59029 | targetVars); |
| 59030 | if(res != UA_STATUSCODE_GOOD) { |
| 59031 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59032 | "[UA_PubSubManager_addSubscribedDataSet] " |
| 59033 | "create TargetVariables failed"); |
| 59034 | } |
| 59035 | |
| 59036 | for(size_t index = 0; index < tmpTargetVars->targetVariablesSize; index++) { |
| 59037 | UA_FieldTargetDataType_clear(&targetVars[index].targetVariable); |
| 59038 | } |
| 59039 | |
| 59040 | UA_free(targetVars); |
| 59041 | return res; |
| 59042 | } |
| 59043 | |
| 59044 | if(subscribedDataSet->content.decoded.type == |
| 59045 | &UA_TYPES[UA_TYPES_SUBSCRIBEDDATASETMIRRORDATATYPE]) { |
| 59046 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59047 | "[UA_PubSubManager_addSubscribedDataSet] " |
| 59048 | "DataSetMirror is currently not supported"); |
| 59049 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 59050 | } |
| 59051 | |
| 59052 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59053 | "[UA_PubSubManager_addSubscribedDataSet] " |
| 59054 | "Invalid Type of SubscribedDataSet"); |
| 59055 | return UA_STATUSCODE_BADINTERNALERROR; |
| 59056 | } |
| 59057 | |
| 59058 | /* Creates DataSetReader configuration from DataSetReader object |
| 59059 | * |
| 59060 | * @param server UA_Server object that shall be configured |
| 59061 | * @param dataSetReaderParameters DataSetReader configuration |
| 59062 | * @param writerGroupIdent NodeId of readerGroupParameters, the DataSetReader belongs to */ |
| 59063 | static UA_StatusCode |
| 59064 | createDataSetReader(UA_Server *server, const UA_DataSetReaderDataType *dsrParams, |
| 59065 | UA_NodeId readerGroupIdent) { |
| 59066 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 59067 | |
| 59068 | UA_DataSetReaderConfig config; |
| 59069 | memset(&config, 0, sizeof(UA_DataSetReaderConfig)); |
| 59070 | |
| 59071 | config.name = dsrParams->name; |
| 59072 | config.publisherId = dsrParams->publisherId; |
| 59073 | config.writerGroupId = dsrParams->writerGroupId; |
| 59074 | config.dataSetWriterId = dsrParams->dataSetWriterId; |
| 59075 | config.dataSetMetaData = dsrParams->dataSetMetaData; |
| 59076 | config.dataSetFieldContentMask = dsrParams->dataSetFieldContentMask; |
| 59077 | config.messageReceiveTimeout = dsrParams->messageReceiveTimeout; |
| 59078 | config.messageSettings = dsrParams->messageSettings; |
| 59079 | |
| 59080 | UA_NodeId dsReaderIdent; |
| 59081 | UA_StatusCode res = UA_DataSetReader_create(server, readerGroupIdent, |
| 59082 | &config, &dsReaderIdent); |
| 59083 | if(res == UA_STATUSCODE_GOOD) |
| 59084 | res = addSubscribedDataSet(server, dsReaderIdent, |
| 59085 | &dsrParams->subscribedDataSet); |
| 59086 | if(res != UA_STATUSCODE_GOOD) { |
| 59087 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59088 | "[UA_PubSubManager_createDataSetReader] " |
| 59089 | "create subscribedDataSet failed"); |
| 59090 | } |
| 59091 | |
| 59092 | return res; |
| 59093 | } |
| 59094 | |
| 59095 | /* Determines whether PublishedDataSet is of type PublishedItems or PublishedEvents. |
| 59096 | * (PublishedEvents are currently not supported!) |
| 59097 | * |
| 59098 | * @param publishedDataSetParameters PublishedDataSet parameters |
| 59099 | * @param config PublishedDataSet configuration object */ |
| 59100 | static UA_StatusCode |
| 59101 | setPublishedDataSetType(UA_Server *server, |
| 59102 | const UA_PublishedDataSetDataType *pdsParams, |
| 59103 | UA_PublishedDataSetConfig *config) { |
| 59104 | if(pdsParams->dataSetSource.encoding != UA_EXTENSIONOBJECT_DECODED) |
| 59105 | return UA_STATUSCODE_BADINTERNALERROR; |
| 59106 | |
| 59107 | const UA_DataType *sourceType = pdsParams->dataSetSource.content.decoded.type; |
| 59108 | if(sourceType == &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE]) { |
| 59109 | config->publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDITEMS; |
| 59110 | return UA_STATUSCODE_GOOD; |
| 59111 | } else if(sourceType == &UA_TYPES[UA_TYPES_PUBLISHEDEVENTSDATATYPE]) { |
| 59112 | /* config.publishedDataSetType = UA_PUBSUB_DATASET_PUBLISHEDEVENTS; */ |
| 59113 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59114 | "[UA_PubSubManager_setPublishedDataSetType] Published events not supported."); |
| 59115 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 59116 | } |
| 59117 | |
| 59118 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59119 | "[UA_PubSubManager_setPublishedDataSetType] Invalid DataSetSourceDataType."); |
| 59120 | return UA_STATUSCODE_BADINTERNALERROR; |
| 59121 | } |
| 59122 | |
| 59123 | /* Creates PublishedDataSetConfig object from PublishedDataSet object |
| 59124 | * |
| 59125 | * @param server UA_Server object that shall be configured |
| 59126 | * @param pdsParams publishedDataSet configuration |
| 59127 | * @param pdsIdent NodeId of the publishedDataSet */ |
| 59128 | static UA_StatusCode |
| 59129 | createPublishedDataSet(UA_Server *server, |
| 59130 | const UA_PublishedDataSetDataType *pdsParams, |
| 59131 | UA_NodeId *pdsIdent) { |
| 59132 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 59133 | |
| 59134 | UA_PublishedDataSetConfig config; |
| 59135 | memset(&config, 0, sizeof(UA_PublishedDataSetConfig)); |
| 59136 | |
| 59137 | config.name = pdsParams->name; |
| 59138 | UA_StatusCode res = setPublishedDataSetType(server, pdsParams, &config); |
| 59139 | if(res != UA_STATUSCODE_GOOD) |
| 59140 | return res; |
| 59141 | |
| 59142 | res = UA_PublishedDataSet_create(server, &config, pdsIdent).addResult; |
| 59143 | if(res != UA_STATUSCODE_GOOD) { |
| 59144 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59145 | "[UA_PubSubManager_createPublishedDataSet] " |
| 59146 | "Adding PublishedDataSet failed."); |
| 59147 | return res; |
| 59148 | } |
| 59149 | |
| 59150 | /* DataSetField configuration for this publishedDataSet: */ |
| 59151 | res = createDataSetFields(server, pdsIdent, pdsParams); |
| 59152 | if(res != UA_STATUSCODE_GOOD) { |
| 59153 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59154 | "[UA_PubSubManager_createPublishedDataSet] " |
| 59155 | "Creating DataSetFieldConfig failed."); |
| 59156 | } |
| 59157 | |
| 59158 | return res; |
| 59159 | } |
| 59160 | |
| 59161 | /* Adds DataSetField Variables bound to a certain PublishedDataSet. This method does NOT |
| 59162 | * check, whether the PublishedDataSet actually contains Variables instead of Events! |
| 59163 | * |
| 59164 | * @param server UA_Server object that shall be configured |
| 59165 | * @param pdsIdent NodeId of the publishedDataSet, the DataSetField belongs to |
| 59166 | * @param publishedDataSetParameters publishedDataSet configuration */ |
| 59167 | static UA_StatusCode |
| 59168 | addDataSetFieldVariables(UA_Server *server, const UA_NodeId *pdsIdent, |
| 59169 | const UA_PublishedDataSetDataType *pdsParams) { |
| 59170 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 59171 | |
| 59172 | UA_PublishedDataItemsDataType *pdItems = (UA_PublishedDataItemsDataType *) |
| 59173 | pdsParams->dataSetSource.content.decoded.data; |
| 59174 | if(pdItems->publishedDataSize != pdsParams->dataSetMetaData.fieldsSize) |
| 59175 | return UA_STATUSCODE_BADINTERNALERROR; |
| 59176 | |
| 59177 | for(size_t i = 0; i < pdItems->publishedDataSize; i++) { |
| 59178 | UA_DataSetFieldConfig fc; |
| 59179 | memset(&fc, 0, sizeof(UA_DataSetFieldConfig)); |
| 59180 | fc.dataSetFieldType = UA_PUBSUB_DATASETFIELD_VARIABLE; |
| 59181 | fc.field.variable.configurationVersion = |
| 59182 | pdsParams->dataSetMetaData.configurationVersion; |
| 59183 | fc.field.variable.fieldNameAlias = pdsParams->dataSetMetaData.fields[i].name; |
| 59184 | fc.field.variable.promotedField = pdsParams->dataSetMetaData. |
| 59185 | fields[i].fieldFlags & 0x0001; |
| 59186 | fc.field.variable.publishParameters = pdItems->publishedData[i]; |
| 59187 | |
| 59188 | UA_NodeId fieldIdent; |
| 59189 | UA_StatusCode res = UA_DataSetField_create(server, *pdsIdent, &fc, &fieldIdent).result; |
| 59190 | if(res != UA_STATUSCODE_GOOD) { |
| 59191 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59192 | "[UA_PubSubManager_addDataSetFieldVariables] " |
| 59193 | "Adding DataSetField Variable failed."); |
| 59194 | return res; |
| 59195 | } |
| 59196 | } |
| 59197 | |
| 59198 | return UA_STATUSCODE_GOOD; |
| 59199 | } |
| 59200 | |
| 59201 | /* Checks if PublishedDataSet contains event or variable fields and calls the |
| 59202 | * corresponding method to add these fields to the server. |
| 59203 | * |
| 59204 | * @param server UA_Server object that shall be configured |
| 59205 | * @param pdsIdent NodeId of the publishedDataSet, the DataSetFields belongs to |
| 59206 | * @param pdsParams publishedDataSet configuration */ |
| 59207 | static UA_StatusCode |
| 59208 | createDataSetFields(UA_Server *server, const UA_NodeId *pdsIdent, |
| 59209 | const UA_PublishedDataSetDataType *pdsParams) { |
| 59210 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 59211 | |
| 59212 | if(pdsParams->dataSetSource.encoding != UA_EXTENSIONOBJECT_DECODED) |
| 59213 | return UA_STATUSCODE_BADINTERNALERROR; |
| 59214 | |
| 59215 | if(pdsParams->dataSetSource.content.decoded.type == |
| 59216 | &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE]) |
| 59217 | return addDataSetFieldVariables(server, pdsIdent, pdsParams); |
| 59218 | |
| 59219 | /* TODO: Implement Routine for adding Event DataSetFields */ |
| 59220 | if(pdsParams->dataSetSource.content.decoded.type == |
| 59221 | &UA_TYPES[UA_TYPES_PUBLISHEDEVENTSDATATYPE]) { |
| 59222 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59223 | "[UA_PubSubManager_createDataSetFields] " |
| 59224 | "Published events not supported."); |
| 59225 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 59226 | } |
| 59227 | |
| 59228 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59229 | "[UA_PubSubManager_createDataSetFields] " |
| 59230 | "Invalid DataSetSourceDataType."); |
| 59231 | return UA_STATUSCODE_BADINTERNALERROR; |
| 59232 | } |
| 59233 | |
| 59234 | UA_StatusCode |
| 59235 | UA_PubSubManager_loadPubSubConfigFromByteString(UA_Server *server, |
| 59236 | const UA_ByteString buffer) { |
| 59237 | size_t offset = 0; |
| 59238 | UA_ExtensionObject decodedFile; |
| 59239 | UA_StatusCode res; |
| 59240 | |
| 59241 | if(server == NULL) { |
| 59242 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59243 | "[UA_PubSubManager_loadPubSubConfigFromByteString] Invalid argument"); |
| 59244 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 59245 | } |
| 59246 | |
| 59247 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 59248 | |
| 59249 | res = UA_ExtensionObject_decodeBinary(&buffer, &offset, &decodedFile); |
| 59250 | if(res != UA_STATUSCODE_GOOD) { |
| 59251 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59252 | "[UA_decodeBinFile] decoding UA_Binary failed"); |
| 59253 | goto cleanup; |
| 59254 | } |
| 59255 | |
| 59256 | UA_PubSubConfigurationDataType *pubSubConfig = NULL; |
| 59257 | res = extractPubSubConfigFromExtensionObject(server, &decodedFile, &pubSubConfig); |
| 59258 | if(res != UA_STATUSCODE_GOOD) { |
| 59259 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59260 | "[UA_PubSubManager_loadPubSubConfigFromByteString] " |
| 59261 | "Extracting PubSub Configuration failed"); |
| 59262 | goto cleanup; |
| 59263 | } |
| 59264 | |
| 59265 | res = updatePubSubConfig(server, pubSubConfig); |
| 59266 | if(res != UA_STATUSCODE_GOOD) { |
| 59267 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59268 | "[UA_PubSubManager_loadPubSubConfigFromByteString] " |
| 59269 | "Loading PubSub configuration into server failed"); |
| 59270 | goto cleanup; |
| 59271 | } |
| 59272 | |
| 59273 | cleanup: |
| 59274 | UA_ExtensionObject_clear(&decodedFile); |
| 59275 | return res; |
| 59276 | } |
| 59277 | |
| 59278 | /* Encodes a PubSubConfigurationDataType object as ByteString using the UA Binary Data |
| 59279 | * Encoding */ |
| 59280 | static UA_StatusCode |
| 59281 | encodePubSubConfiguration(UA_Server *server, |
| 59282 | UA_PubSubConfigurationDataType *configurationParameters, |
| 59283 | UA_ByteString *buffer) { |
| 59284 | UA_UABinaryFileDataType binFile; |
| 59285 | memset(&binFile, 0, sizeof(UA_UABinaryFileDataType)); |
| 59286 | /*Perhaps, additional initializations of binFile are necessary here.*/ |
| 59287 | |
| 59288 | UA_Variant_setScalar(&binFile.body, configurationParameters, |
| 59289 | &UA_TYPES[UA_TYPES_PUBSUBCONFIGURATIONDATATYPE]); |
| 59290 | |
| 59291 | UA_ExtensionObject container; |
| 59292 | memset(&container, 0, sizeof(UA_ExtensionObject)); |
| 59293 | container.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 59294 | container.content.decoded.type = &UA_TYPES[UA_TYPES_UABINARYFILEDATATYPE]; |
| 59295 | container.content.decoded.data = &binFile; |
| 59296 | |
| 59297 | size_t fileSize = UA_ExtensionObject_calcSizeBinary(&container); |
| 59298 | buffer->data = (UA_Byte*)UA_calloc(fileSize, sizeof(UA_Byte)); |
| 59299 | if(buffer->data == NULL) { |
| 59300 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59301 | "[UA_PubSubManager_encodePubSubConfiguration] Allocating buffer failed"); |
| 59302 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59303 | } |
| 59304 | |
| 59305 | buffer->length = fileSize; |
| 59306 | |
| 59307 | UA_Byte *bufferPos = buffer->data; |
| 59308 | UA_StatusCode res = |
| 59309 | UA_ExtensionObject_encodeBinary(&container, &bufferPos, bufferPos + fileSize); |
| 59310 | if(res != UA_STATUSCODE_GOOD) { |
| 59311 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59312 | "[UA_PubSubManager_encodePubSubConfiguration] Encoding failed"); |
| 59313 | } |
| 59314 | return res; |
| 59315 | } |
| 59316 | |
| 59317 | static UA_StatusCode |
| 59318 | generatePublishedDataSetDataType(UA_Server* server, |
| 59319 | const UA_PublishedDataSet *src, |
| 59320 | UA_PublishedDataSetDataType *dst) { |
| 59321 | if(src->config.publishedDataSetType != UA_PUBSUB_DATASET_PUBLISHEDITEMS) |
| 59322 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 59323 | |
| 59324 | memset(dst, 0, sizeof(UA_PublishedDataSetDataType)); |
| 59325 | |
| 59326 | UA_PublishedDataItemsDataType *tmp = UA_PublishedDataItemsDataType_new(); |
| 59327 | UA_String_copy(&src->config.name, &dst->name); |
| 59328 | dst->dataSetMetaData.fieldsSize = src->fieldSize; |
| 59329 | |
| 59330 | size_t index = 0; |
| 59331 | tmp->publishedDataSize = src->fieldSize; |
| 59332 | tmp->publishedData = (UA_PublishedVariableDataType*) |
| 59333 | UA_Array_new(tmp->publishedDataSize, &UA_TYPES[UA_TYPES_PUBLISHEDVARIABLEDATATYPE]); |
| 59334 | if(tmp->publishedData == NULL) { |
| 59335 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, "Allocation memory failed"); |
| 59336 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59337 | } |
| 59338 | |
| 59339 | dst->dataSetMetaData.fields = (UA_FieldMetaData*) |
| 59340 | UA_Array_new(dst->dataSetMetaData.fieldsSize, &UA_TYPES[UA_TYPES_FIELDMETADATA]); |
| 59341 | if(dst->dataSetMetaData.fields == NULL) { |
| 59342 | UA_free(tmp->publishedData); |
| 59343 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, "Allocation memory failed"); |
| 59344 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59345 | } |
| 59346 | |
| 59347 | UA_DataSetField *dsf, *dsf_tmp = NULL; |
| 59348 | TAILQ_FOREACH_SAFE(dsf ,&src->fields, listEntry, dsf_tmp) { |
| 59349 | UA_String_copy(&dsf->config.field.variable.fieldNameAlias, |
| 59350 | &dst->dataSetMetaData.fields[index].name); |
| 59351 | UA_PublishedVariableDataType_copy(&dsf->config.field.variable.publishParameters, |
| 59352 | &tmp->publishedData[index]); |
| 59353 | UA_ConfigurationVersionDataType_copy(&dsf->config.field.variable.configurationVersion, |
| 59354 | &dst->dataSetMetaData.configurationVersion); |
| 59355 | dst->dataSetMetaData.fields[index].fieldFlags = |
| 59356 | dsf->config.field.variable.promotedField; |
| 59357 | index++; |
| 59358 | } |
| 59359 | UA_ExtensionObject_setValue(&dst->dataSetSource, tmp, |
| 59360 | &UA_TYPES[UA_TYPES_PUBLISHEDDATAITEMSDATATYPE]); |
| 59361 | |
| 59362 | return UA_STATUSCODE_GOOD; |
| 59363 | } |
| 59364 | |
| 59365 | static UA_StatusCode |
| 59366 | generateDataSetWriterDataType(const UA_DataSetWriter *src, |
| 59367 | UA_DataSetWriterDataType *dst) { |
| 59368 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 59369 | memset(dst, 0, sizeof(UA_DataSetWriterDataType)); |
| 59370 | res |= UA_String_copy(&src->config.name, &dst->name); |
| 59371 | dst->dataSetWriterId = src->config.dataSetWriterId; |
| 59372 | dst->keyFrameCount = src->config.keyFrameCount; |
| 59373 | dst->dataSetFieldContentMask = src->config.dataSetFieldContentMask; |
| 59374 | res |= UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings); |
| 59375 | res |= UA_String_copy(&src->config.dataSetName, &dst->dataSetName); |
| 59376 | if(res != UA_STATUSCODE_GOOD) { |
| 59377 | UA_DataSetWriterDataType_clear(dst); |
| 59378 | return res; |
| 59379 | } |
| 59380 | |
| 59381 | res = UA_Array_copy(src->config.dataSetWriterProperties.map, |
| 59382 | src->config.dataSetWriterProperties.mapSize, |
| 59383 | (void**)&dst->dataSetWriterProperties, |
| 59384 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR]); |
| 59385 | if(res == UA_STATUSCODE_GOOD) |
| 59386 | dst->dataSetWriterPropertiesSize = src->config.dataSetWriterProperties.mapSize; |
| 59387 | else |
| 59388 | UA_DataSetWriterDataType_clear(dst); |
| 59389 | |
| 59390 | return res; |
| 59391 | } |
| 59392 | |
| 59393 | static UA_StatusCode |
| 59394 | generateWriterGroupDataType(const UA_WriterGroup *src, |
| 59395 | UA_WriterGroupDataType *dst) { |
| 59396 | memset(dst, 0, sizeof(UA_WriterGroupDataType)); |
| 59397 | |
| 59398 | UA_String_copy(&src->config.name, &dst->name); |
| 59399 | dst->enabled = src->config.enabled; |
| 59400 | dst->writerGroupId = src->config.writerGroupId; |
| 59401 | dst->publishingInterval = src->config.publishingInterval; |
| 59402 | dst->keepAliveTime = src->config.keepAliveTime; |
| 59403 | dst->priority = src->config.priority; |
| 59404 | dst->securityMode = src->config.securityMode; |
| 59405 | |
| 59406 | UA_ExtensionObject_copy(&src->config.transportSettings, &dst->transportSettings); |
| 59407 | UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings); |
| 59408 | |
| 59409 | UA_StatusCode res = |
| 59410 | UA_Array_copy(src->config.groupProperties.map, |
| 59411 | src->config.groupProperties.mapSize, |
| 59412 | (void**)&dst->groupProperties, |
| 59413 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR]); |
| 59414 | if(res != UA_STATUSCODE_GOOD) { |
| 59415 | UA_WriterGroupDataType_clear(dst); |
| 59416 | return res; |
| 59417 | } |
| 59418 | dst->groupPropertiesSize = src->config.groupProperties.mapSize, |
| 59419 | |
| 59420 | dst->dataSetWriters = (UA_DataSetWriterDataType*) |
| 59421 | UA_calloc(src->writersCount, sizeof(UA_DataSetWriterDataType)); |
| 59422 | if(!dst->dataSetWriters) { |
| 59423 | UA_WriterGroupDataType_clear(dst); |
| 59424 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59425 | } |
| 59426 | |
| 59427 | dst->dataSetWritersSize = src->writersCount; |
| 59428 | |
| 59429 | UA_DataSetWriter *dsw; |
| 59430 | size_t dsWriterIndex = 0; |
| 59431 | LIST_FOREACH(dsw, &src->writers, listEntry) { |
| 59432 | res |= generateDataSetWriterDataType(dsw, &dst->dataSetWriters[dsWriterIndex]); |
| 59433 | dsWriterIndex++; |
| 59434 | } |
| 59435 | if(res != UA_STATUSCODE_GOOD) |
| 59436 | UA_WriterGroupDataType_clear(dst); |
| 59437 | return res; |
| 59438 | } |
| 59439 | |
| 59440 | static UA_StatusCode |
| 59441 | generateDataSetReaderDataType(const UA_DataSetReader *src, |
| 59442 | UA_DataSetReaderDataType *dst) { |
| 59443 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 59444 | memset(dst, 0, sizeof(UA_DataSetReaderDataType)); |
| 59445 | dst->writerGroupId = src->config.writerGroupId; |
| 59446 | dst->dataSetWriterId = src->config.dataSetWriterId; |
| 59447 | dst->dataSetFieldContentMask = src->config.dataSetFieldContentMask; |
| 59448 | dst->messageReceiveTimeout = src->config.messageReceiveTimeout; |
| 59449 | res |= UA_String_copy(&src->config.name, &dst->name); |
| 59450 | res |= UA_Variant_copy(&src->config.publisherId, &dst->publisherId); |
| 59451 | res |= UA_DataSetMetaDataType_copy(&src->config.dataSetMetaData, |
| 59452 | &dst->dataSetMetaData); |
| 59453 | res |= UA_ExtensionObject_copy(&src->config.messageSettings, &dst->messageSettings); |
| 59454 | |
| 59455 | UA_TargetVariablesDataType *tmpTarget = UA_TargetVariablesDataType_new(); |
| 59456 | if(!tmpTarget) |
| 59457 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59458 | UA_ExtensionObject_setValue(&dst->subscribedDataSet, tmpTarget, |
| 59459 | &UA_TYPES[UA_TYPES_TARGETVARIABLESDATATYPE]); |
| 59460 | |
| 59461 | const UA_TargetVariables *targets = |
| 59462 | &src->config.subscribedDataSet.subscribedDataSetTarget; |
| 59463 | tmpTarget->targetVariables = (UA_FieldTargetDataType *) |
| 59464 | UA_calloc(targets->targetVariablesSize, sizeof(UA_FieldTargetDataType)); |
| 59465 | if(!tmpTarget->targetVariables) |
| 59466 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59467 | tmpTarget->targetVariablesSize = targets->targetVariablesSize; |
| 59468 | |
| 59469 | for(size_t i = 0; i < tmpTarget->targetVariablesSize; i++) { |
| 59470 | res |= UA_FieldTargetDataType_copy(&targets->targetVariables[i].targetVariable, |
| 59471 | &tmpTarget->targetVariables[i]); |
| 59472 | } |
| 59473 | |
| 59474 | return res; |
| 59475 | } |
| 59476 | |
| 59477 | static UA_StatusCode |
| 59478 | generateReaderGroupDataType(const UA_ReaderGroup *src, |
| 59479 | UA_ReaderGroupDataType *dst) { |
| 59480 | memset(dst, 0, sizeof(UA_ReaderGroupDataType)); |
| 59481 | |
| 59482 | UA_String_copy(&src->config.name, &dst->name); |
| 59483 | dst->dataSetReaders = (UA_DataSetReaderDataType*) |
| 59484 | UA_calloc(src->readersCount, sizeof(UA_DataSetReaderDataType)); |
| 59485 | if(dst->dataSetReaders == NULL) |
| 59486 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59487 | dst->dataSetReadersSize = src->readersCount; |
| 59488 | |
| 59489 | size_t i = 0; |
| 59490 | UA_DataSetReader *dsr, *dsr_tmp = NULL; |
| 59491 | LIST_FOREACH_SAFE(dsr, &src->readers, listEntry, dsr_tmp) { |
| 59492 | UA_StatusCode res = |
| 59493 | generateDataSetReaderDataType(dsr, &dst->dataSetReaders[i]); |
| 59494 | if(res != UA_STATUSCODE_GOOD) |
| 59495 | return res; |
| 59496 | i++; |
| 59497 | } |
| 59498 | |
| 59499 | return UA_STATUSCODE_GOOD; |
| 59500 | } |
| 59501 | |
| 59502 | /* Generates a PubSubConnectionDataType object from a PubSubConnection. */ |
| 59503 | static UA_StatusCode |
| 59504 | generatePubSubConnectionDataType(UA_Server* server, |
| 59505 | const UA_PubSubConnection *src, |
| 59506 | UA_PubSubConnectionDataType *dst) { |
| 59507 | const UA_DataType *publisherIdType; |
| 59508 | memset(dst, 0, sizeof(UA_PubSubConnectionDataType)); |
| 59509 | |
| 59510 | UA_String_copy(&src->config.name, &dst->name); |
| 59511 | UA_String_copy(&src->config.transportProfileUri, &dst->transportProfileUri); |
| 59512 | dst->enabled = src->config.enabled; |
| 59513 | |
| 59514 | UA_StatusCode res = |
| 59515 | UA_Array_copy(src->config.connectionProperties.map, |
| 59516 | src->config.connectionProperties.mapSize, |
| 59517 | (void**)&dst->connectionProperties, |
| 59518 | &UA_TYPES[UA_TYPES_KEYVALUEPAIR]); |
| 59519 | if(res != UA_STATUSCODE_GOOD) { |
| 59520 | UA_PubSubConnectionDataType_clear(dst); |
| 59521 | return res; |
| 59522 | } |
| 59523 | dst->connectionPropertiesSize = src->config.connectionProperties.mapSize; |
| 59524 | |
| 59525 | switch (src->config.publisherIdType) { |
| 59526 | case UA_PUBLISHERIDTYPE_BYTE: |
| 59527 | publisherIdType = &UA_TYPES[UA_TYPES_BYTE]; |
| 59528 | break; |
| 59529 | case UA_PUBLISHERIDTYPE_UINT16: |
| 59530 | publisherIdType = &UA_TYPES[UA_TYPES_UINT16]; |
| 59531 | break; |
| 59532 | case UA_PUBLISHERIDTYPE_UINT32: |
| 59533 | publisherIdType = &UA_TYPES[UA_TYPES_UINT32]; |
| 59534 | break; |
| 59535 | case UA_PUBLISHERIDTYPE_UINT64: |
| 59536 | publisherIdType = &UA_TYPES[UA_TYPES_UINT64]; |
| 59537 | break; |
| 59538 | case UA_PUBLISHERIDTYPE_STRING: |
| 59539 | publisherIdType = &UA_TYPES[UA_TYPES_STRING]; |
| 59540 | break; |
| 59541 | default: |
| 59542 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59543 | "generatePubSubConnectionDataType(): publisher Id type is not supported"); |
| 59544 | return UA_STATUSCODE_BADINTERNALERROR; |
| 59545 | break; |
| 59546 | } |
| 59547 | UA_Variant_setScalarCopy(&dst->publisherId, |
| 59548 | &src->config.publisherId, |
| 59549 | publisherIdType); |
| 59550 | |
| 59551 | /* Possibly, array size and dimensions of src->config->address and |
| 59552 | * src->config->connectionTransportSettings should be checked beforehand. */ |
| 59553 | dst->address.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 59554 | dst->address.content.decoded.type = src->config.address.type; |
| 59555 | res = UA_Array_copy(src->config.address.data, 1, |
| 59556 | &dst->address.content.decoded.data, |
| 59557 | src->config.address.type); |
| 59558 | if(res != UA_STATUSCODE_GOOD) { |
| 59559 | UA_PubSubConnectionDataType_clear(dst); |
| 59560 | return res; |
| 59561 | } |
| 59562 | |
| 59563 | if(src->config.connectionTransportSettings.data) { |
| 59564 | dst->transportSettings.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 59565 | dst->transportSettings.content.decoded.type = |
| 59566 | src->config.connectionTransportSettings.type; |
| 59567 | res = UA_Array_copy(src->config.connectionTransportSettings.data, 1, |
| 59568 | &dst->transportSettings.content.decoded.data, |
| 59569 | src->config.connectionTransportSettings.type); |
| 59570 | |
| 59571 | if(res != UA_STATUSCODE_GOOD) { |
| 59572 | UA_PubSubConnectionDataType_clear(dst); |
| 59573 | return res; |
| 59574 | } |
| 59575 | } |
| 59576 | |
| 59577 | dst->writerGroups = (UA_WriterGroupDataType*) |
| 59578 | UA_calloc(src->writerGroupsSize, sizeof(UA_WriterGroupDataType)); |
| 59579 | if(!dst->writerGroups) { |
| 59580 | UA_PubSubConnectionDataType_clear(dst); |
| 59581 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59582 | } |
| 59583 | |
| 59584 | dst->writerGroupsSize = src->writerGroupsSize; |
| 59585 | UA_WriterGroup *wg, *wg_tmp = NULL; |
| 59586 | size_t wgIndex = 0; |
| 59587 | LIST_FOREACH_SAFE(wg, &src->writerGroups, listEntry, wg_tmp) { |
| 59588 | res = generateWriterGroupDataType(wg, &dst->writerGroups[wgIndex]); |
| 59589 | if(res != UA_STATUSCODE_GOOD) { |
| 59590 | UA_PubSubConnectionDataType_clear(dst); |
| 59591 | return res; |
| 59592 | } |
| 59593 | wgIndex++; |
| 59594 | } |
| 59595 | |
| 59596 | dst->readerGroups = (UA_ReaderGroupDataType*) |
| 59597 | UA_calloc(src->readerGroupsSize, sizeof(UA_ReaderGroupDataType)); |
| 59598 | if(dst->readerGroups == NULL) { |
| 59599 | UA_PubSubConnectionDataType_clear(dst); |
| 59600 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59601 | } |
| 59602 | |
| 59603 | dst->readerGroupsSize = src->readerGroupsSize; |
| 59604 | UA_ReaderGroup *rg = NULL; |
| 59605 | size_t rgIndex = 0; |
| 59606 | LIST_FOREACH(rg, &src->readerGroups, listEntry) { |
| 59607 | res = generateReaderGroupDataType(rg, &dst->readerGroups[rgIndex]); |
| 59608 | if(res != UA_STATUSCODE_GOOD) { |
| 59609 | UA_PubSubConnectionDataType_clear(dst); |
| 59610 | return res; |
| 59611 | } |
| 59612 | rgIndex++; |
| 59613 | } |
| 59614 | |
| 59615 | return UA_STATUSCODE_GOOD; |
| 59616 | } |
| 59617 | |
| 59618 | static UA_StatusCode |
| 59619 | generatePubSubConfigurationDataType(UA_Server* server, |
| 59620 | UA_PubSubConfigurationDataType *configDT) { |
| 59621 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 59622 | |
| 59623 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 59624 | const UA_PubSubManager *manager = &server->pubSubManager; |
| 59625 | memset(configDT, 0, sizeof(UA_PubSubConfigurationDataType)); |
| 59626 | |
| 59627 | configDT->publishedDataSets = (UA_PublishedDataSetDataType*) |
| 59628 | UA_calloc(manager->publishedDataSetsSize, |
| 59629 | sizeof(UA_PublishedDataSetDataType)); |
| 59630 | if(configDT->publishedDataSets == NULL) |
| 59631 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59632 | configDT->publishedDataSetsSize = manager->publishedDataSetsSize; |
| 59633 | |
| 59634 | UA_PublishedDataSet *pds; |
| 59635 | UA_UInt32 pdsIndex = 0; |
| 59636 | TAILQ_FOREACH(pds, &manager->publishedDataSets, listEntry) { |
| 59637 | UA_PublishedDataSetDataType *dst = &configDT->publishedDataSets[pdsIndex]; |
| 59638 | res = generatePublishedDataSetDataType(server, pds, dst); |
| 59639 | if(res != UA_STATUSCODE_GOOD) { |
| 59640 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59641 | "[UA_PubSubManager_generatePubSubConfigurationDataType] " |
| 59642 | "retrieving PublishedDataSet configuration failed"); |
| 59643 | return res; |
| 59644 | } |
| 59645 | pdsIndex++; |
| 59646 | } |
| 59647 | |
| 59648 | configDT->connections = (UA_PubSubConnectionDataType*) |
| 59649 | UA_calloc(manager->connectionsSize, sizeof(UA_PubSubConnectionDataType)); |
| 59650 | if(configDT->connections == NULL) |
| 59651 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 59652 | configDT->connectionsSize = manager->connectionsSize; |
| 59653 | |
| 59654 | UA_UInt32 connectionIndex = 0; |
| 59655 | UA_PubSubConnection *connection; |
| 59656 | TAILQ_FOREACH(connection, &manager->connections, listEntry) { |
| 59657 | UA_PubSubConnectionDataType *cdt = &configDT->connections[connectionIndex]; |
| 59658 | res = generatePubSubConnectionDataType(server, connection, cdt); |
| 59659 | if(res != UA_STATUSCODE_GOOD) { |
| 59660 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59661 | "[UA_PubSubManager_generatePubSubConfigurationDataType] " |
| 59662 | "retrieving PubSubConnection configuration failed"); |
| 59663 | return res; |
| 59664 | } |
| 59665 | connectionIndex++; |
| 59666 | } |
| 59667 | |
| 59668 | return UA_STATUSCODE_GOOD; |
| 59669 | } |
| 59670 | |
| 59671 | UA_StatusCode |
| 59672 | UA_PubSubManager_getEncodedPubSubConfiguration(UA_Server *server, |
| 59673 | UA_ByteString *buffer) { |
| 59674 | UA_PubSubConfigurationDataType config; |
| 59675 | memset(&config, 0, sizeof(UA_PubSubConfigurationDataType)); |
| 59676 | |
| 59677 | if(server == NULL) { |
| 59678 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59679 | "[UA_PubSubManager_getEncodedPubSubConfiguration] Invalid argument"); |
| 59680 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 59681 | } |
| 59682 | |
| 59683 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 59684 | |
| 59685 | UA_StatusCode res = generatePubSubConfigurationDataType(server, &config); |
| 59686 | if(res != UA_STATUSCODE_GOOD) { |
| 59687 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59688 | "retrieving PubSub configuration from server failed"); |
| 59689 | goto cleanup; |
| 59690 | } |
| 59691 | |
| 59692 | res = encodePubSubConfiguration(server, &config, buffer); |
| 59693 | if(res != UA_STATUSCODE_GOOD) { |
| 59694 | UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59695 | "encoding PubSub configuration failed"); |
| 59696 | goto cleanup; |
| 59697 | } |
| 59698 | |
| 59699 | UA_LOG_INFO(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 59700 | "Saving PubSub config was successful"); |
| 59701 | |
| 59702 | cleanup: |
| 59703 | UA_PubSubConfigurationDataType_clear(&config); |
| 59704 | return res; |
| 59705 | } |
| 59706 | |
| 59707 | #endif /* UA_ENABLE_PUBSUB && UA_ENABLE_PUBSUB_FILE_CONFIG */ |
| 59708 | |
| 59709 | /**** amalgamated original file "/src/client/ua_client.c" ****/ |
| 59710 | |
| 59711 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 59712 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 59713 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 59714 | * |
| 59715 | * Copyright 2015-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 59716 | * Copyright 2015-2016 (c) Sten Grüner |
| 59717 | * Copyright 2015-2016 (c) Chris Iatrou |
| 59718 | * Copyright 2015 (c) hfaham |
| 59719 | * Copyright 2015-2017 (c) Florian Palm |
| 59720 | * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA |
| 59721 | * Copyright 2015 (c) Holger Jeromin |
| 59722 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 59723 | * Copyright 2016 (c) TorbenD |
| 59724 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 59725 | * Copyright 2016 (c) Lykurg |
| 59726 | * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB |
| 59727 | * Copyright 2018 (c) Kalycito Infotech Private Limited |
| 59728 | * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart |
| 59729 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes) |
| 59730 | * Copyright 2022 (c) Linutronix GmbH (Author: Muddasir Shakil) |
| 59731 | */ |
| 59732 | |
| 59733 | |
| 59734 | |
| 59735 | static void |
| 59736 | clientHouseKeeping(UA_Client *client, void *_); |
| 59737 | |
| 59738 | /********************/ |
| 59739 | /* Client Lifecycle */ |
| 59740 | /********************/ |
| 59741 | |
| 59742 | UA_StatusCode |
| 59743 | UA_ClientConfig_copy(UA_ClientConfig const *src, UA_ClientConfig *dst){ |
| 59744 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 59745 | |
| 59746 | retval = UA_ApplicationDescription_copy(src: &src->clientDescription, dst: &dst->clientDescription); |
| 59747 | if(retval != UA_STATUSCODE_GOOD) |
| 59748 | goto cleanup; |
| 59749 | |
| 59750 | retval = UA_ExtensionObject_copy(src: &src->userIdentityToken, dst: &dst->userIdentityToken); |
| 59751 | if(retval != UA_STATUSCODE_GOOD) |
| 59752 | goto cleanup; |
| 59753 | |
| 59754 | retval = UA_String_copy(src: &src->securityPolicyUri, dst: &dst->securityPolicyUri); |
| 59755 | if(retval != UA_STATUSCODE_GOOD) |
| 59756 | goto cleanup; |
| 59757 | |
| 59758 | retval = UA_EndpointDescription_copy(src: &src->endpoint, dst: &dst->endpoint); |
| 59759 | if(retval != UA_STATUSCODE_GOOD) |
| 59760 | goto cleanup; |
| 59761 | |
| 59762 | retval = UA_UserTokenPolicy_copy(src: &src->userTokenPolicy, dst: &dst->userTokenPolicy); |
| 59763 | if(retval != UA_STATUSCODE_GOOD) |
| 59764 | goto cleanup; |
| 59765 | |
| 59766 | retval = UA_Array_copy(src: src->sessionLocaleIds, size: src->sessionLocaleIdsSize, |
| 59767 | dst: (void **)&dst->sessionLocaleIds, type: &UA_TYPES[UA_TYPES_LOCALEID]); |
| 59768 | if(retval != UA_STATUSCODE_GOOD) |
| 59769 | goto cleanup; |
| 59770 | |
| 59771 | dst->sessionLocaleIdsSize = src->sessionLocaleIdsSize; |
| 59772 | dst->connectivityCheckInterval = src->connectivityCheckInterval; |
| 59773 | dst->certificateVerification = src->certificateVerification; |
| 59774 | dst->clientContext = src->clientContext; |
| 59775 | dst->customDataTypes = src->customDataTypes; |
| 59776 | dst->eventLoop = src->eventLoop; |
| 59777 | dst->externalEventLoop = src->externalEventLoop; |
| 59778 | dst->inactivityCallback = src->inactivityCallback; |
| 59779 | dst->localConnectionConfig = src->localConnectionConfig; |
| 59780 | dst->logging = src->logging; |
| 59781 | if(src->certificateVerification.logging == NULL) |
| 59782 | dst->certificateVerification.logging = dst->logging; |
| 59783 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 59784 | dst->outStandingPublishRequests = src->outStandingPublishRequests; |
| 59785 | #endif |
| 59786 | dst->requestedSessionTimeout = src->requestedSessionTimeout; |
| 59787 | dst->secureChannelLifeTime = src->secureChannelLifeTime; |
| 59788 | dst->securityMode = src->securityMode; |
| 59789 | dst->stateCallback = src->stateCallback; |
| 59790 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 59791 | dst->subscriptionInactivityCallback = src->subscriptionInactivityCallback; |
| 59792 | #endif |
| 59793 | dst->timeout = src->timeout; |
| 59794 | dst->userTokenPolicy = src->userTokenPolicy; |
| 59795 | dst->securityPolicies = src->securityPolicies; |
| 59796 | dst->securityPoliciesSize = src->securityPoliciesSize; |
| 59797 | dst->authSecurityPolicies = src->authSecurityPolicies; |
| 59798 | dst->authSecurityPoliciesSize = src->authSecurityPoliciesSize; |
| 59799 | |
| 59800 | cleanup: |
| 59801 | if(retval != UA_STATUSCODE_GOOD) { |
| 59802 | /* _clear will free the plugins in dst that are a shallow copy from src. */ |
| 59803 | dst->authSecurityPolicies = NULL; |
| 59804 | dst->certificateVerification.context = NULL; |
| 59805 | dst->eventLoop = NULL; |
| 59806 | dst->logging = NULL; |
| 59807 | dst->securityPolicies = NULL; |
| 59808 | UA_ClientConfig_clear(config: dst); |
| 59809 | } |
| 59810 | return retval; |
| 59811 | } |
| 59812 | |
| 59813 | UA_Client * |
| 59814 | UA_Client_newWithConfig(const UA_ClientConfig *config) { |
| 59815 | if(!config) |
| 59816 | return NULL; |
| 59817 | UA_Client *client = (UA_Client*)UA_malloc(size: sizeof(UA_Client)); |
| 59818 | if(!client) |
| 59819 | return NULL; |
| 59820 | memset(s: client, c: 0, n: sizeof(UA_Client)); |
| 59821 | client->config = *config; |
| 59822 | |
| 59823 | UA_SecureChannel_init(channel: &client->channel); |
| 59824 | client->channel.config = client->config.localConnectionConfig; |
| 59825 | client->connectStatus = UA_STATUSCODE_GOOD; |
| 59826 | |
| 59827 | #if UA_MULTITHREADING >= 100 |
| 59828 | UA_LOCK_INIT(&client->clientMutex); |
| 59829 | #endif |
| 59830 | |
| 59831 | return client; |
| 59832 | } |
| 59833 | |
| 59834 | void |
| 59835 | UA_ClientConfig_clear(UA_ClientConfig *config) { |
| 59836 | UA_ApplicationDescription_clear(p: &config->clientDescription); |
| 59837 | UA_String_clear(p: &config->endpointUrl); |
| 59838 | UA_ExtensionObject_clear(p: &config->userIdentityToken); |
| 59839 | |
| 59840 | /* Delete the SecurityPolicies for Authentication */ |
| 59841 | if(config->authSecurityPolicies != 0) { |
| 59842 | for(size_t i = 0; i < config->authSecurityPoliciesSize; i++) |
| 59843 | config->authSecurityPolicies[i].clear(&config->authSecurityPolicies[i]); |
| 59844 | UA_free(ptr: config->authSecurityPolicies); |
| 59845 | config->authSecurityPolicies = 0; |
| 59846 | } |
| 59847 | UA_String_clear(p: &config->securityPolicyUri); |
| 59848 | UA_String_clear(p: &config->authSecurityPolicyUri); |
| 59849 | |
| 59850 | UA_EndpointDescription_clear(p: &config->endpoint); |
| 59851 | UA_UserTokenPolicy_clear(p: &config->userTokenPolicy); |
| 59852 | |
| 59853 | UA_String_clear(p: &config->applicationUri); |
| 59854 | |
| 59855 | if(config->certificateVerification.clear) |
| 59856 | config->certificateVerification.clear(&config->certificateVerification); |
| 59857 | |
| 59858 | /* Delete the SecurityPolicies */ |
| 59859 | if(config->securityPolicies != 0) { |
| 59860 | for(size_t i = 0; i < config->securityPoliciesSize; i++) |
| 59861 | config->securityPolicies[i].clear(&config->securityPolicies[i]); |
| 59862 | UA_free(ptr: config->securityPolicies); |
| 59863 | config->securityPolicies = 0; |
| 59864 | } |
| 59865 | |
| 59866 | /* Stop and delete the EventLoop */ |
| 59867 | UA_EventLoop *el = config->eventLoop; |
| 59868 | if(el && !config->externalEventLoop) { |
| 59869 | if(el->state != UA_EVENTLOOPSTATE_FRESH && |
| 59870 | el->state != UA_EVENTLOOPSTATE_STOPPED) { |
| 59871 | el->stop(el); |
| 59872 | while(el->state != UA_EVENTLOOPSTATE_STOPPED) { |
| 59873 | el->run(el, 100); |
| 59874 | } |
| 59875 | } |
| 59876 | el->free(el); |
| 59877 | config->eventLoop = NULL; |
| 59878 | } |
| 59879 | |
| 59880 | /* Logging */ |
| 59881 | if(config->logging != NULL && config->logging->clear != NULL) |
| 59882 | config->logging->clear(config->logging); |
| 59883 | config->logging = NULL; |
| 59884 | |
| 59885 | UA_String_clear(p: &config->sessionName); |
| 59886 | if(config->sessionLocaleIdsSize > 0 && config->sessionLocaleIds) { |
| 59887 | UA_Array_delete(p: config->sessionLocaleIds, |
| 59888 | size: config->sessionLocaleIdsSize, type: &UA_TYPES[UA_TYPES_LOCALEID]); |
| 59889 | } |
| 59890 | config->sessionLocaleIds = NULL; |
| 59891 | config->sessionLocaleIdsSize = 0; |
| 59892 | |
| 59893 | /* Custom Data Types */ |
| 59894 | UA_cleanupDataTypeWithCustom(customTypes: config->customDataTypes); |
| 59895 | |
| 59896 | #ifdef UA_ENABLE_ENCRYPTION |
| 59897 | config->privateKeyPasswordCallback = NULL; |
| 59898 | #endif |
| 59899 | } |
| 59900 | |
| 59901 | void |
| 59902 | UA_ClientConfig_delete(UA_ClientConfig *config){ |
| 59903 | UA_assert(config != NULL); |
| 59904 | UA_ClientConfig_clear(config); |
| 59905 | UA_free(ptr: config); |
| 59906 | } |
| 59907 | |
| 59908 | static void |
| 59909 | UA_Client_clear(UA_Client *client) { |
| 59910 | /* Prevent new async service calls in UA_Client_AsyncService_removeAll */ |
| 59911 | UA_SessionState oldState = client->sessionState; |
| 59912 | client->sessionState = UA_SESSIONSTATE_CLOSING; |
| 59913 | |
| 59914 | /* Delete the async service calls with BADHSUTDOWN */ |
| 59915 | __Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSHUTDOWN); |
| 59916 | |
| 59917 | /* Reset to the old state to properly close the session */ |
| 59918 | client->sessionState = oldState; |
| 59919 | |
| 59920 | UA_Client_disconnect(client); |
| 59921 | UA_String_clear(p: &client->discoveryUrl); |
| 59922 | UA_EndpointDescription_clear(p: &client->endpoint); |
| 59923 | |
| 59924 | UA_String_clear(p: &client->serverSessionNonce); |
| 59925 | UA_String_clear(p: &client->clientSessionNonce); |
| 59926 | |
| 59927 | /* Delete the subscriptions */ |
| 59928 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 59929 | __Client_Subscriptions_clean(client); |
| 59930 | #endif |
| 59931 | |
| 59932 | /* Remove the internal regular callback */ |
| 59933 | UA_Client_removeCallback(client, callbackId: client->houseKeepingCallbackId); |
| 59934 | client->houseKeepingCallbackId = 0; |
| 59935 | |
| 59936 | UA_SecureChannel_clear(channel: &client->channel); |
| 59937 | |
| 59938 | #if UA_MULTITHREADING >= 100 |
| 59939 | UA_LOCK_DESTROY(&client->clientMutex); |
| 59940 | #endif |
| 59941 | } |
| 59942 | |
| 59943 | void |
| 59944 | UA_Client_delete(UA_Client* client) { |
| 59945 | UA_Client_disconnect(client); |
| 59946 | UA_Client_clear(client); |
| 59947 | UA_ClientConfig_clear(config: &client->config); |
| 59948 | UA_free(ptr: client); |
| 59949 | } |
| 59950 | |
| 59951 | void |
| 59952 | UA_Client_getState(UA_Client *client, UA_SecureChannelState *channelState, |
| 59953 | UA_SessionState *sessionState, UA_StatusCode *connectStatus) { |
| 59954 | lockClient(client); |
| 59955 | if(channelState) |
| 59956 | *channelState = client->channel.state; |
| 59957 | if(sessionState) |
| 59958 | *sessionState = client->sessionState; |
| 59959 | if(connectStatus) |
| 59960 | *connectStatus = client->connectStatus; |
| 59961 | unlockClient(client); |
| 59962 | } |
| 59963 | |
| 59964 | UA_ClientConfig * |
| 59965 | UA_Client_getConfig(UA_Client *client) { |
| 59966 | if(!client) |
| 59967 | return NULL; |
| 59968 | return &client->config; |
| 59969 | } |
| 59970 | |
| 59971 | #if UA_LOGLEVEL <= 300 |
| 59972 | static const char *channelStateTexts[14] = { |
| 59973 | "Fresh", "ReverseListening", "Connecting", "Connected", "ReverseConnected", "RHESent", "HELSent", "HELReceived", "ACKSent", |
| 59974 | "AckReceived", "OPNSent", "Open", "Closing", "Closed"}; |
| 59975 | static const char *sessionStateTexts[6] = |
| 59976 | {"Closed", "CreateRequested", "Created", |
| 59977 | "ActivateRequested", "Activated", "Closing"}; |
| 59978 | #endif |
| 59979 | |
| 59980 | void |
| 59981 | notifyClientState(UA_Client *client) { |
| 59982 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 59983 | |
| 59984 | if(client->connectStatus == client->oldConnectStatus && |
| 59985 | client->channel.state == client->oldChannelState && |
| 59986 | client->sessionState == client->oldSessionState) |
| 59987 | return; |
| 59988 | |
| 59989 | #if UA_LOGLEVEL <= 300 |
| 59990 | UA_Boolean info = (client->connectStatus != UA_STATUSCODE_GOOD); |
| 59991 | if(client->oldChannelState != client->channel.state) |
| 59992 | info |= (client->channel.state == UA_SECURECHANNELSTATE_OPEN || |
| 59993 | client->channel.state == UA_SECURECHANNELSTATE_CLOSED); |
| 59994 | if(client->oldSessionState != client->sessionState) |
| 59995 | info |= (client->sessionState == UA_SESSIONSTATE_CREATED || |
| 59996 | client->sessionState == UA_SESSIONSTATE_ACTIVATED || |
| 59997 | client->sessionState == UA_SESSIONSTATE_CLOSED); |
| 59998 | |
| 59999 | const char *channelStateText = channelStateTexts[client->channel.state]; |
| 60000 | const char *sessionStateText = sessionStateTexts[client->sessionState]; |
| 60001 | const char *connectStatusText = UA_StatusCode_name(code: client->connectStatus); |
| 60002 | |
| 60003 | if(info) |
| 60004 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60005 | msg: "Client Status: ChannelState: %s, SessionState: %s, ConnectStatus: %s", |
| 60006 | channelStateText, sessionStateText, connectStatusText); |
| 60007 | else |
| 60008 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60009 | msg: "Client Status: ChannelState: %s, SessionState: %s, ConnectStatus: %s", |
| 60010 | channelStateText, sessionStateText, connectStatusText); |
| 60011 | #endif |
| 60012 | |
| 60013 | client->oldConnectStatus = client->connectStatus; |
| 60014 | client->oldChannelState = client->channel.state; |
| 60015 | client->oldSessionState = client->sessionState; |
| 60016 | |
| 60017 | if(client->config.stateCallback) |
| 60018 | client->config.stateCallback(client, client->channel.state, |
| 60019 | client->sessionState, client->connectStatus); |
| 60020 | } |
| 60021 | |
| 60022 | /****************/ |
| 60023 | /* Raw Services */ |
| 60024 | /****************/ |
| 60025 | |
| 60026 | /* For both synchronous and asynchronous service calls */ |
| 60027 | static UA_StatusCode |
| 60028 | sendRequest(UA_Client *client, const void *request, |
| 60029 | const UA_DataType *requestType, UA_UInt32 *requestId) { |
| 60030 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 60031 | |
| 60032 | /* Renew SecureChannel if necessary */ |
| 60033 | __Client_renewSecureChannel(client); |
| 60034 | if(client->connectStatus != UA_STATUSCODE_GOOD) |
| 60035 | return client->connectStatus; |
| 60036 | |
| 60037 | /* Adjusting the request header. The const attribute is violated, but we |
| 60038 | * reset to the original state before returning. Use the AuthenticationToken |
| 60039 | * only once the session is active (or to activate / close it). */ |
| 60040 | UA_RequestHeader *rr = (UA_RequestHeader*)(uintptr_t)request; |
| 60041 | UA_NodeId oldToken = rr->authenticationToken; /* Put back in place later */ |
| 60042 | if(client->sessionState == UA_SESSIONSTATE_ACTIVATED || |
| 60043 | requestType == &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST] || |
| 60044 | requestType == &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST]) |
| 60045 | rr->authenticationToken = client->authenticationToken; |
| 60046 | rr->timestamp = UA_DateTime_now(); |
| 60047 | |
| 60048 | /* Create a unique handle >100,000 if not manually defined. The handle is |
| 60049 | * not necessarily unique when manually defined and used to cancel async |
| 60050 | * service requests. */ |
| 60051 | if(rr->requestHandle == 0) { |
| 60052 | if(UA_UNLIKELY(client->requestHandle < 100000)) |
| 60053 | client->requestHandle = 100000; |
| 60054 | rr->requestHandle = ++client->requestHandle; |
| 60055 | } |
| 60056 | |
| 60057 | /* Set the timeout hint if not manually defined */ |
| 60058 | if(rr->timeoutHint == 0) |
| 60059 | rr->timeoutHint = client->config.timeout; |
| 60060 | |
| 60061 | /* Generate the request id */ |
| 60062 | UA_UInt32 rqId = ++client->requestId; |
| 60063 | |
| 60064 | #ifdef UA_ENABLE_TYPEDESCRIPTION |
| 60065 | UA_LOG_DEBUG_CHANNEL(client->config.logging, &client->channel, |
| 60066 | "Sending request with RequestId %u of type %s", |
| 60067 | (unsigned)rqId, requestType->typeName); |
| 60068 | #else |
| 60069 | UA_LOG_DEBUG_CHANNEL(client->config.logging, &client->channel, |
| 60070 | "Sending request with RequestId %u of type %"PRIu32, |
| 60071 | (unsigned)rqId, requestType->binaryEncodingId.identifier.numeric); |
| 60072 | #endif |
| 60073 | |
| 60074 | /* Send the message */ |
| 60075 | UA_StatusCode retval = |
| 60076 | UA_SecureChannel_sendSymmetricMessage(channel: &client->channel, requestId: rqId, |
| 60077 | messageType: UA_MESSAGETYPE_MSG, payload: rr, payloadType: requestType); |
| 60078 | |
| 60079 | rr->authenticationToken = oldToken; /* Set back to the original token */ |
| 60080 | |
| 60081 | /* Sending failed. The SecureChannel cannot recover from that. Call |
| 60082 | * closeSecureChannel to a) close from our end and b) set the session to |
| 60083 | * non-activated. */ |
| 60084 | if(retval != UA_STATUSCODE_GOOD) |
| 60085 | closeSecureChannel(client); |
| 60086 | |
| 60087 | /* Return the request id */ |
| 60088 | *requestId = rqId; |
| 60089 | return retval; |
| 60090 | } |
| 60091 | |
| 60092 | static const UA_NodeId |
| 60093 | serviceFaultId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_SERVICEFAULT_ENCODING_DEFAULTBINARY}}; |
| 60094 | |
| 60095 | /* Look for the async callback in the linked list, execute and delete it */ |
| 60096 | static UA_StatusCode |
| 60097 | processMSGResponse(UA_Client *client, UA_UInt32 requestId, |
| 60098 | const UA_ByteString *msg) { |
| 60099 | /* Find the callback */ |
| 60100 | AsyncServiceCall *ac; |
| 60101 | LIST_FOREACH(ac, &client->asyncServiceCalls, pointers) { |
| 60102 | if(ac->requestId == requestId) |
| 60103 | break; |
| 60104 | } |
| 60105 | |
| 60106 | /* Part 6, 6.7.6: After the security validation is complete the receiver |
| 60107 | * shall verify the RequestId and the SequenceNumber. If these checks fail a |
| 60108 | * Bad_SecurityChecksFailed error is reported. The RequestId only needs to |
| 60109 | * be verified by the Client since only the Client knows if it is valid or |
| 60110 | * not.*/ |
| 60111 | if(!ac) { |
| 60112 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60113 | msg: "Request with unknown RequestId %u", requestId); |
| 60114 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 60115 | } |
| 60116 | |
| 60117 | UA_Response asyncResponse; |
| 60118 | UA_Response *response = (ac->syncResponse) ? ac->syncResponse : &asyncResponse; |
| 60119 | const UA_DataType *responseType = ac->responseType; |
| 60120 | |
| 60121 | /* Dequeue ac. We might disconnect the client (remove all ac) in the callback. */ |
| 60122 | LIST_REMOVE(ac, pointers); |
| 60123 | |
| 60124 | /* Decode the response type */ |
| 60125 | size_t offset = 0; |
| 60126 | UA_NodeId responseTypeId; |
| 60127 | UA_StatusCode retval = UA_NodeId_decodeBinary(src: msg, offset: &offset, dst: &responseTypeId); |
| 60128 | if(retval != UA_STATUSCODE_GOOD) |
| 60129 | goto process; |
| 60130 | |
| 60131 | /* Verify the type of the response */ |
| 60132 | if(!UA_NodeId_equal(p1: &responseTypeId, p2: &ac->responseType->binaryEncodingId)) { |
| 60133 | /* Initialize before switching the responseType to ServiceFault. |
| 60134 | * Otherwise the decoding will leave fields from the original response |
| 60135 | * type uninitialized. */ |
| 60136 | UA_init(p: response, type: ac->responseType); |
| 60137 | if(UA_NodeId_equal(p1: &responseTypeId, p2: &serviceFaultId)) { |
| 60138 | /* Decode as a ServiceFault, i.e. only the response header */ |
| 60139 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60140 | msg: "Received a ServiceFault response"); |
| 60141 | responseType = &UA_TYPES[UA_TYPES_SERVICEFAULT]; |
| 60142 | } else { |
| 60143 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60144 | msg: "Service response type does not match"); |
| 60145 | retval = UA_STATUSCODE_BADCOMMUNICATIONERROR; |
| 60146 | goto process; /* Do not decode */ |
| 60147 | } |
| 60148 | } |
| 60149 | |
| 60150 | /* Decode the response */ |
| 60151 | #ifdef UA_ENABLE_TYPEDESCRIPTION |
| 60152 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60153 | msg: "Decode a message of type %s", responseType->typeName); |
| 60154 | #else |
| 60155 | UA_LOG_DEBUG(client->config.logging, UA_LOGCATEGORY_CLIENT, |
| 60156 | "Decode a message of type %"PRIu32, |
| 60157 | responseTypeId.identifier.numeric); |
| 60158 | #endif |
| 60159 | retval = UA_decodeBinaryInternal(src: msg, offset: &offset, dst: response, type: responseType, |
| 60160 | customTypes: client->config.customDataTypes); |
| 60161 | |
| 60162 | process: |
| 60163 | /* Process the received MSG response */ |
| 60164 | if(retval != UA_STATUSCODE_GOOD) { |
| 60165 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60166 | msg: "Could not decode the response with RequestId %u with status %s", |
| 60167 | (unsigned)requestId, UA_StatusCode_name(code: retval)); |
| 60168 | response->responseHeader.serviceResult = retval; |
| 60169 | } |
| 60170 | |
| 60171 | /* The Session closed. The current response is processed with the return code. |
| 60172 | * The next request first recreates a session. */ |
| 60173 | if(responseType != &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE] && |
| 60174 | (response->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONIDINVALID || |
| 60175 | response->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONCLOSED)) { |
| 60176 | /* Clean up the session information and reset the state */ |
| 60177 | cleanupSession(client); |
| 60178 | |
| 60179 | if(client->config.noNewSession) { |
| 60180 | /* Configuration option to not create a new Session. Disconnect the |
| 60181 | * client. */ |
| 60182 | client->connectStatus = response->responseHeader.serviceResult; |
| 60183 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60184 | msg: "Session cannot be activated with StatusCode %s. " |
| 60185 | "The client is configured not to create a new Session.", |
| 60186 | UA_StatusCode_name(code: client->connectStatus)); |
| 60187 | closeSecureChannel(client); |
| 60188 | } else { |
| 60189 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60190 | msg: "Session no longer valid. A new Session is created for the next " |
| 60191 | "Service request but we do not re-send the current request."); |
| 60192 | } |
| 60193 | } |
| 60194 | |
| 60195 | /* Call the async callback. This is the only thread with access to ac. So we |
| 60196 | * can just unlock for the callback into userland. */ |
| 60197 | if(ac->callback) |
| 60198 | ac->callback(client, ac->userdata, requestId, response); |
| 60199 | |
| 60200 | /* Clean up */ |
| 60201 | UA_NodeId_clear(p: &responseTypeId); |
| 60202 | if(!ac->syncResponse) { |
| 60203 | UA_clear(p: response, type: ac->responseType); |
| 60204 | UA_free(ptr: ac); |
| 60205 | } else { |
| 60206 | /* Return a special status code after processing a synchronous message. |
| 60207 | * This makes the client return control immediately. */ |
| 60208 | ac->syncResponse = NULL; /* Indicate that response was received */ |
| 60209 | if(retval == UA_STATUSCODE_GOOD) |
| 60210 | retval = UA_STATUSCODE_GOODCOMPLETESASYNCHRONOUSLY; |
| 60211 | } |
| 60212 | return retval; |
| 60213 | } |
| 60214 | |
| 60215 | UA_StatusCode |
| 60216 | processServiceResponse(UA_Client *client, UA_SecureChannel *channel, |
| 60217 | UA_MessageType messageType, UA_UInt32 requestId, |
| 60218 | UA_ByteString *message) { |
| 60219 | if(!UA_SecureChannel_isConnected(channel)) { |
| 60220 | if(messageType == UA_MESSAGETYPE_MSG) { |
| 60221 | UA_LOG_DEBUG_CHANNEL(client->config.logging, channel, "Discard MSG message " |
| 60222 | "with RequestId %u as the SecureChannel is not connected", |
| 60223 | requestId); |
| 60224 | } else { |
| 60225 | UA_LOG_DEBUG_CHANNEL(client->config.logging, channel, "Discard message " |
| 60226 | "as the SecureChannel is not connected"); |
| 60227 | } |
| 60228 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 60229 | } |
| 60230 | |
| 60231 | switch(messageType) { |
| 60232 | case UA_MESSAGETYPE_RHE: |
| 60233 | UA_LOG_DEBUG_CHANNEL(client->config.logging, channel, "Process RHE message"); |
| 60234 | processRHEMessage(client, chunk: message); |
| 60235 | return UA_STATUSCODE_GOOD; |
| 60236 | case UA_MESSAGETYPE_ACK: |
| 60237 | UA_LOG_DEBUG_CHANNEL(client->config.logging, channel, "Process ACK message"); |
| 60238 | processACKResponse(client, chunk: message); |
| 60239 | return UA_STATUSCODE_GOOD; |
| 60240 | case UA_MESSAGETYPE_OPN: |
| 60241 | UA_LOG_DEBUG_CHANNEL(client->config.logging, channel, "Process OPN message"); |
| 60242 | processOPNResponse(client, message); |
| 60243 | return UA_STATUSCODE_GOOD; |
| 60244 | case UA_MESSAGETYPE_ERR: |
| 60245 | UA_LOG_DEBUG_CHANNEL(client->config.logging, channel, "Process ERR message"); |
| 60246 | processERRResponse(client, chunk: message); |
| 60247 | return UA_STATUSCODE_GOOD; |
| 60248 | case UA_MESSAGETYPE_MSG: |
| 60249 | UA_LOG_DEBUG_CHANNEL(client->config.logging, channel, "Process MSG message " |
| 60250 | "with RequestId %u", requestId); |
| 60251 | return processMSGResponse(client, requestId, msg: message); |
| 60252 | default: |
| 60253 | UA_LOG_TRACE_CHANNEL(client->config.logging, channel, |
| 60254 | "Invalid message type"); |
| 60255 | channel->state = UA_SECURECHANNELSTATE_CLOSING; |
| 60256 | return UA_STATUSCODE_BADTCPMESSAGETYPEINVALID; |
| 60257 | } |
| 60258 | } |
| 60259 | |
| 60260 | void |
| 60261 | __Client_Service(UA_Client *client, const void *request, |
| 60262 | const UA_DataType *requestType, void *response, |
| 60263 | const UA_DataType *responseType) { |
| 60264 | UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response; |
| 60265 | |
| 60266 | /* Initialize. Response is valied in case of aborting. */ |
| 60267 | UA_init(p: response, type: responseType); |
| 60268 | |
| 60269 | /* Verify that the EventLoop is running */ |
| 60270 | UA_EventLoop *el = client->config.eventLoop; |
| 60271 | if(!el || el->state != UA_EVENTLOOPSTATE_STARTED) { |
| 60272 | respHeader->serviceResult = UA_STATUSCODE_BADINTERNALERROR; |
| 60273 | return; |
| 60274 | } |
| 60275 | |
| 60276 | /* Check that the SecureChannel is open and also a Session active (if we |
| 60277 | * want a Session). Otherwise reopen. */ |
| 60278 | if(!isFullyConnected(client)) { |
| 60279 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60280 | msg: "Re-establish the connction for the synchronous service call"); |
| 60281 | connectSync(client); |
| 60282 | if(client->connectStatus != UA_STATUSCODE_GOOD) { |
| 60283 | respHeader->serviceResult = client->connectStatus; |
| 60284 | return; |
| 60285 | } |
| 60286 | } |
| 60287 | |
| 60288 | /* Store the channelId to detect if the channel was changed by a |
| 60289 | * reconnection within the EventLoop run method. */ |
| 60290 | UA_UInt32 channelId = client->channel.securityToken.channelId; |
| 60291 | |
| 60292 | /* Send the request */ |
| 60293 | UA_UInt32 requestId = 0; |
| 60294 | UA_StatusCode retval = sendRequest(client, request, requestType, requestId: &requestId); |
| 60295 | if(retval != UA_STATUSCODE_GOOD) { |
| 60296 | /* If sending failed, the status is set to closing. The SecureChannel is |
| 60297 | * the actually closed in the next iteration of the EventLoop. */ |
| 60298 | UA_assert(client->channel.state == UA_SECURECHANNELSTATE_CLOSING || |
| 60299 | client->channel.state == UA_SECURECHANNELSTATE_CLOSED); |
| 60300 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60301 | msg: "Sending the request failed with status %s", |
| 60302 | UA_StatusCode_name(code: retval)); |
| 60303 | notifyClientState(client); |
| 60304 | respHeader->serviceResult = retval; |
| 60305 | return; |
| 60306 | } |
| 60307 | |
| 60308 | /* Temporarily insert an AsyncServiceCall */ |
| 60309 | const UA_RequestHeader *rh = (const UA_RequestHeader*)request; |
| 60310 | AsyncServiceCall ac; |
| 60311 | ac.callback = NULL; |
| 60312 | ac.userdata = NULL; |
| 60313 | ac.responseType = responseType; |
| 60314 | ac.syncResponse = (UA_Response*)response; |
| 60315 | ac.requestId = requestId; |
| 60316 | ac.start = UA_DateTime_nowMonotonic(); /* Start timeout after sending */ |
| 60317 | ac.timeout = rh->timeoutHint; |
| 60318 | ac.requestHandle = rh->requestHandle; |
| 60319 | if(ac.timeout == 0) |
| 60320 | ac.timeout = UA_UINT32_MAX; /* 0 -> unlimited */ |
| 60321 | |
| 60322 | LIST_INSERT_HEAD(&client->asyncServiceCalls, &ac, pointers); |
| 60323 | |
| 60324 | /* Time until which the request has to be answered */ |
| 60325 | UA_DateTime maxDate = ac.start + ((UA_DateTime)ac.timeout * UA_DATETIME_MSEC); |
| 60326 | |
| 60327 | /* Run the EventLoop until the request was processed, the request has timed |
| 60328 | * out or the client connection fails */ |
| 60329 | UA_UInt32 timeout_remaining = ac.timeout; |
| 60330 | while(true) { |
| 60331 | /* Unlock before dropping into the EventLoop. The client lock is |
| 60332 | * re-taken in the network callback if an event occurs. */ |
| 60333 | retval = el->run(el, timeout_remaining); |
| 60334 | |
| 60335 | /* Was the response received? In that case we can directly return. The |
| 60336 | * ac was already removed from the internal linked list. */ |
| 60337 | if(ac.syncResponse == NULL) |
| 60338 | return; |
| 60339 | |
| 60340 | /* Check the status. Do not try to resend if the connection breaks. |
| 60341 | * Leave this to the application-level user. For example, we do not want |
| 60342 | * to call a method twice is the connection broke after sending the |
| 60343 | * request. */ |
| 60344 | if(retval != UA_STATUSCODE_GOOD) |
| 60345 | break; |
| 60346 | |
| 60347 | /* The connection was lost */ |
| 60348 | retval = client->connectStatus; |
| 60349 | if(retval != UA_STATUSCODE_GOOD) |
| 60350 | break; |
| 60351 | |
| 60352 | /* The channel is no longer the same or was closed */ |
| 60353 | if(channelId != client->channel.securityToken.channelId) { |
| 60354 | retval = UA_STATUSCODE_BADSECURECHANNELCLOSED; |
| 60355 | break; |
| 60356 | } |
| 60357 | |
| 60358 | /* Update the remaining timeout or break */ |
| 60359 | UA_DateTime now = UA_DateTime_nowMonotonic(); |
| 60360 | if(now > maxDate) { |
| 60361 | retval = UA_STATUSCODE_BADTIMEOUT; |
| 60362 | break; |
| 60363 | } |
| 60364 | timeout_remaining = (UA_UInt32)((maxDate - now) / UA_DATETIME_MSEC); |
| 60365 | } |
| 60366 | |
| 60367 | /* Detach from the internal async service list */ |
| 60368 | LIST_REMOVE(&ac, pointers); |
| 60369 | |
| 60370 | /* Return the status code */ |
| 60371 | respHeader->serviceResult = retval; |
| 60372 | } |
| 60373 | |
| 60374 | void |
| 60375 | __UA_Client_Service(UA_Client *client, const void *request, |
| 60376 | const UA_DataType *requestType, void *response, |
| 60377 | const UA_DataType *responseType) { |
| 60378 | lockClient(client); |
| 60379 | __Client_Service(client, request, requestType, response, responseType); |
| 60380 | unlockClient(client); |
| 60381 | } |
| 60382 | |
| 60383 | /***********************************/ |
| 60384 | /* Handling of Async Service Calls */ |
| 60385 | /***********************************/ |
| 60386 | |
| 60387 | static void |
| 60388 | __Client_AsyncService_cancel(UA_Client *client, AsyncServiceCall *ac, |
| 60389 | UA_StatusCode statusCode) { |
| 60390 | /* Set the status for the synchronous service call. Don't free the ac. */ |
| 60391 | if(ac->syncResponse) { |
| 60392 | ac->syncResponse->responseHeader.serviceResult = statusCode; |
| 60393 | ac->syncResponse = NULL; /* Indicate the async service call was processed */ |
| 60394 | return; |
| 60395 | } |
| 60396 | |
| 60397 | if(ac->callback) { |
| 60398 | /* Create an empty response with the statuscode and call the callback */ |
| 60399 | UA_Response response; |
| 60400 | UA_init(p: &response, type: ac->responseType); |
| 60401 | response.responseHeader.serviceResult = statusCode; |
| 60402 | ac->callback(client, ac->userdata, ac->requestId, &response); |
| 60403 | |
| 60404 | /* Clean up the response. The user callback might move data into it. For |
| 60405 | * whatever reasons. */ |
| 60406 | UA_clear(p: &response, type: ac->responseType); |
| 60407 | } |
| 60408 | |
| 60409 | UA_free(ptr: ac); |
| 60410 | } |
| 60411 | |
| 60412 | void |
| 60413 | __Client_AsyncService_removeAll(UA_Client *client, UA_StatusCode statusCode) { |
| 60414 | /* Make this function reentrant. One of the async callbacks could indirectly |
| 60415 | * operate on the list. Moving all elements to a local list before iterating |
| 60416 | * that. */ |
| 60417 | UA_AsyncServiceList asyncServiceCalls = client->asyncServiceCalls; |
| 60418 | LIST_INIT(&client->asyncServiceCalls); |
| 60419 | if(asyncServiceCalls.lh_first) |
| 60420 | asyncServiceCalls.lh_first->pointers.le_prev = &asyncServiceCalls.lh_first; |
| 60421 | |
| 60422 | /* Cancel and remove the elements from the local list */ |
| 60423 | AsyncServiceCall *ac, *ac_tmp; |
| 60424 | LIST_FOREACH_SAFE(ac, &asyncServiceCalls, pointers, ac_tmp) { |
| 60425 | LIST_REMOVE(ac, pointers); |
| 60426 | __Client_AsyncService_cancel(client, ac, statusCode); |
| 60427 | } |
| 60428 | } |
| 60429 | |
| 60430 | UA_StatusCode |
| 60431 | UA_Client_modifyAsyncCallback(UA_Client *client, UA_UInt32 requestId, |
| 60432 | void *userdata, UA_ClientAsyncServiceCallback callback) { |
| 60433 | lockClient(client); |
| 60434 | AsyncServiceCall *ac; |
| 60435 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 60436 | LIST_FOREACH(ac, &client->asyncServiceCalls, pointers) { |
| 60437 | if(ac->requestId == requestId) { |
| 60438 | ac->callback = callback; |
| 60439 | ac->userdata = userdata; |
| 60440 | res = UA_STATUSCODE_GOOD; |
| 60441 | break; |
| 60442 | } |
| 60443 | } |
| 60444 | unlockClient(client); |
| 60445 | return res; |
| 60446 | } |
| 60447 | |
| 60448 | UA_StatusCode |
| 60449 | __Client_AsyncService(UA_Client *client, const void *request, |
| 60450 | const UA_DataType *requestType, |
| 60451 | UA_ClientAsyncServiceCallback callback, |
| 60452 | const UA_DataType *responseType, |
| 60453 | void *userdata, UA_UInt32 *requestId) { |
| 60454 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 60455 | |
| 60456 | /* Is the SecureChannel connected? */ |
| 60457 | if(client->channel.state != UA_SECURECHANNELSTATE_OPEN) { |
| 60458 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60459 | msg: "SecureChannel must be connected to send request"); |
| 60460 | return UA_STATUSCODE_BADSERVERNOTCONNECTED; |
| 60461 | } |
| 60462 | |
| 60463 | /* Prepare the entry for the linked list */ |
| 60464 | AsyncServiceCall *ac = (AsyncServiceCall*)UA_malloc(size: sizeof(AsyncServiceCall)); |
| 60465 | if(!ac) |
| 60466 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 60467 | |
| 60468 | /* Call the service and set the requestId */ |
| 60469 | UA_StatusCode retval = sendRequest(client, request, requestType, requestId: &ac->requestId); |
| 60470 | if(retval != UA_STATUSCODE_GOOD) { |
| 60471 | /* If sending failed, the status is set to closing. The SecureChannel is |
| 60472 | * the actually closed in the next iteration of the EventLoop. */ |
| 60473 | UA_assert(client->channel.state == UA_SECURECHANNELSTATE_CLOSING || |
| 60474 | client->channel.state == UA_SECURECHANNELSTATE_CLOSED); |
| 60475 | UA_free(ptr: ac); |
| 60476 | notifyClientState(client); |
| 60477 | return retval; |
| 60478 | } |
| 60479 | |
| 60480 | /* Set up the AsyncServiceCall for processing the response */ |
| 60481 | const UA_RequestHeader *rh = (const UA_RequestHeader*)request; |
| 60482 | ac->callback = callback; |
| 60483 | ac->responseType = responseType; |
| 60484 | ac->userdata = userdata; |
| 60485 | ac->syncResponse = NULL; |
| 60486 | ac->start = UA_DateTime_nowMonotonic(); |
| 60487 | ac->timeout = rh->timeoutHint; |
| 60488 | ac->requestHandle = rh->requestHandle; |
| 60489 | if(ac->timeout == 0) |
| 60490 | ac->timeout = UA_UINT32_MAX; /* 0 -> unlimited */ |
| 60491 | |
| 60492 | LIST_INSERT_HEAD(&client->asyncServiceCalls, ac, pointers); |
| 60493 | |
| 60494 | /* Return the generated request id */ |
| 60495 | if(requestId) |
| 60496 | *requestId = ac->requestId; |
| 60497 | |
| 60498 | /* Notify the userland if a change happened */ |
| 60499 | notifyClientState(client); |
| 60500 | |
| 60501 | return UA_STATUSCODE_GOOD; |
| 60502 | } |
| 60503 | |
| 60504 | UA_StatusCode |
| 60505 | __UA_Client_AsyncService(UA_Client *client, const void *request, |
| 60506 | const UA_DataType *requestType, |
| 60507 | UA_ClientAsyncServiceCallback callback, |
| 60508 | const UA_DataType *responseType, |
| 60509 | void *userdata, UA_UInt32 *requestId) { |
| 60510 | lockClient(client); |
| 60511 | UA_StatusCode res = |
| 60512 | __Client_AsyncService(client, request, requestType, callback, responseType, |
| 60513 | userdata, requestId); |
| 60514 | unlockClient(client); |
| 60515 | return res; |
| 60516 | } |
| 60517 | |
| 60518 | static UA_StatusCode |
| 60519 | cancelByRequestHandle(UA_Client *client, UA_UInt32 requestHandle, UA_UInt32 *cancelCount) { |
| 60520 | UA_CancelRequest creq; |
| 60521 | UA_CancelRequest_init(p: &creq); |
| 60522 | creq.requestHandle = requestHandle; |
| 60523 | UA_CancelResponse cresp; |
| 60524 | UA_CancelResponse_init(p: &cresp); |
| 60525 | __Client_Service(client, request: &creq, requestType: &UA_TYPES[UA_TYPES_CANCELREQUEST], |
| 60526 | response: &cresp, responseType: &UA_TYPES[UA_TYPES_CANCELRESPONSE]); |
| 60527 | if(cancelCount) |
| 60528 | *cancelCount = cresp.cancelCount; |
| 60529 | UA_StatusCode res = cresp.responseHeader.serviceResult; |
| 60530 | UA_CancelResponse_clear(p: &cresp); |
| 60531 | return res; |
| 60532 | } |
| 60533 | |
| 60534 | UA_StatusCode |
| 60535 | UA_Client_cancelByRequestHandle(UA_Client *client, UA_UInt32 requestHandle, |
| 60536 | UA_UInt32 *cancelCount) { |
| 60537 | lockClient(client); |
| 60538 | UA_StatusCode res = cancelByRequestHandle(client, requestHandle, cancelCount); |
| 60539 | unlockClient(client); |
| 60540 | return res; |
| 60541 | } |
| 60542 | |
| 60543 | UA_StatusCode |
| 60544 | UA_Client_cancelByRequestId(UA_Client *client, UA_UInt32 requestId, |
| 60545 | UA_UInt32 *cancelCount) { |
| 60546 | lockClient(client); |
| 60547 | UA_StatusCode res = UA_STATUSCODE_BADNOTFOUND; |
| 60548 | AsyncServiceCall *ac; |
| 60549 | LIST_FOREACH(ac, &client->asyncServiceCalls, pointers) { |
| 60550 | if(ac->requestId != requestId) |
| 60551 | continue; |
| 60552 | res = cancelByRequestHandle(client, requestHandle: ac->requestHandle, cancelCount); |
| 60553 | break; |
| 60554 | } |
| 60555 | unlockClient(client); |
| 60556 | return res; |
| 60557 | } |
| 60558 | |
| 60559 | /*******************/ |
| 60560 | /* Timed Callbacks */ |
| 60561 | /*******************/ |
| 60562 | |
| 60563 | UA_StatusCode |
| 60564 | UA_Client_addTimedCallback(UA_Client *client, UA_ClientCallback callback, |
| 60565 | void *data, UA_DateTime date, UA_UInt64 *callbackId) { |
| 60566 | if(!client->config.eventLoop) |
| 60567 | return UA_STATUSCODE_BADINTERNALERROR; |
| 60568 | lockClient(client); |
| 60569 | UA_StatusCode res = client->config.eventLoop-> |
| 60570 | addTimedCallback(client->config.eventLoop, (UA_Callback)callback, |
| 60571 | client, data, date, callbackId); |
| 60572 | unlockClient(client); |
| 60573 | return res; |
| 60574 | } |
| 60575 | |
| 60576 | UA_StatusCode |
| 60577 | UA_Client_addRepeatedCallback(UA_Client *client, UA_ClientCallback callback, |
| 60578 | void *data, UA_Double interval_ms, UA_UInt64 *callbackId) { |
| 60579 | if(!client->config.eventLoop) |
| 60580 | return UA_STATUSCODE_BADINTERNALERROR; |
| 60581 | lockClient(client); |
| 60582 | UA_StatusCode res = client->config.eventLoop-> |
| 60583 | addCyclicCallback(client->config.eventLoop, (UA_Callback)callback, |
| 60584 | client, data, interval_ms, NULL, |
| 60585 | UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, callbackId); |
| 60586 | unlockClient(client); |
| 60587 | return res; |
| 60588 | } |
| 60589 | |
| 60590 | UA_StatusCode |
| 60591 | UA_Client_changeRepeatedCallbackInterval(UA_Client *client, UA_UInt64 callbackId, |
| 60592 | UA_Double interval_ms) { |
| 60593 | if(!client->config.eventLoop) |
| 60594 | return UA_STATUSCODE_BADINTERNALERROR; |
| 60595 | lockClient(client); |
| 60596 | UA_StatusCode res = client->config.eventLoop-> |
| 60597 | modifyCyclicCallback(client->config.eventLoop, callbackId, interval_ms, |
| 60598 | NULL, UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME); |
| 60599 | unlockClient(client); |
| 60600 | return res; |
| 60601 | } |
| 60602 | |
| 60603 | void |
| 60604 | UA_Client_removeCallback(UA_Client *client, UA_UInt64 callbackId) { |
| 60605 | if(!client->config.eventLoop) |
| 60606 | return; |
| 60607 | lockClient(client); |
| 60608 | client->config.eventLoop-> |
| 60609 | removeCyclicCallback(client->config.eventLoop, callbackId); |
| 60610 | unlockClient(client); |
| 60611 | } |
| 60612 | |
| 60613 | /**********************/ |
| 60614 | /* Housekeeping Tasks */ |
| 60615 | /**********************/ |
| 60616 | |
| 60617 | static void |
| 60618 | asyncServiceTimeoutCheck(UA_Client *client) { |
| 60619 | /* Make this function reentrant. One of the async callbacks could indirectly |
| 60620 | * operate on the list. Moving all elements to a local list before iterating |
| 60621 | * that. */ |
| 60622 | UA_AsyncServiceList asyncServiceCalls; |
| 60623 | AsyncServiceCall *ac, *ac_tmp; |
| 60624 | UA_DateTime now = UA_DateTime_nowMonotonic(); |
| 60625 | LIST_INIT(&asyncServiceCalls); |
| 60626 | LIST_FOREACH_SAFE(ac, &client->asyncServiceCalls, pointers, ac_tmp) { |
| 60627 | if(!ac->timeout) |
| 60628 | continue; |
| 60629 | if(ac->start + (UA_DateTime)(ac->timeout * UA_DATETIME_MSEC) <= now) { |
| 60630 | LIST_REMOVE(ac, pointers); |
| 60631 | LIST_INSERT_HEAD(&asyncServiceCalls, ac, pointers); |
| 60632 | } |
| 60633 | } |
| 60634 | |
| 60635 | /* Cancel and remove the elements from the local list */ |
| 60636 | LIST_FOREACH_SAFE(ac, &asyncServiceCalls, pointers, ac_tmp) { |
| 60637 | LIST_REMOVE(ac, pointers); |
| 60638 | __Client_AsyncService_cancel(client, ac, UA_STATUSCODE_BADTIMEOUT); |
| 60639 | } |
| 60640 | } |
| 60641 | |
| 60642 | static void |
| 60643 | backgroundConnectivityCallback(UA_Client *client, void *userdata, |
| 60644 | UA_UInt32 requestId, const UA_ReadResponse *response) { |
| 60645 | lockClient(client); |
| 60646 | if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTIMEOUT) { |
| 60647 | if(client->config.inactivityCallback) |
| 60648 | client->config.inactivityCallback(client); |
| 60649 | } |
| 60650 | client->pendingConnectivityCheck = false; |
| 60651 | client->lastConnectivityCheck = UA_DateTime_nowMonotonic(); |
| 60652 | unlockClient(client); |
| 60653 | } |
| 60654 | |
| 60655 | static void |
| 60656 | __Client_backgroundConnectivity(UA_Client *client) { |
| 60657 | if(!client->config.connectivityCheckInterval) |
| 60658 | return; |
| 60659 | |
| 60660 | if(client->pendingConnectivityCheck) |
| 60661 | return; |
| 60662 | |
| 60663 | UA_DateTime now = UA_DateTime_nowMonotonic(); |
| 60664 | UA_DateTime nextDate = client->lastConnectivityCheck + |
| 60665 | (UA_DateTime)(client->config.connectivityCheckInterval * UA_DATETIME_MSEC); |
| 60666 | if(now <= nextDate) |
| 60667 | return; |
| 60668 | |
| 60669 | /* Prepare the request */ |
| 60670 | UA_ReadValueId rvid; |
| 60671 | UA_ReadValueId_init(p: &rvid); |
| 60672 | rvid.attributeId = UA_ATTRIBUTEID_VALUE; |
| 60673 | rvid.nodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_STATE); |
| 60674 | UA_ReadRequest request; |
| 60675 | UA_ReadRequest_init(p: &request); |
| 60676 | request.nodesToRead = &rvid; |
| 60677 | request.nodesToReadSize = 1; |
| 60678 | UA_StatusCode retval = |
| 60679 | __Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_READREQUEST], |
| 60680 | callback: (UA_ClientAsyncServiceCallback)backgroundConnectivityCallback, |
| 60681 | responseType: &UA_TYPES[UA_TYPES_READRESPONSE], NULL, NULL); |
| 60682 | if(retval == UA_STATUSCODE_GOOD) |
| 60683 | client->pendingConnectivityCheck = true; |
| 60684 | } |
| 60685 | |
| 60686 | /* Regular housekeeping activities in the client -- called via a cyclic callback */ |
| 60687 | static void |
| 60688 | clientHouseKeeping(UA_Client *client, void *_) { |
| 60689 | lockClient(client); |
| 60690 | |
| 60691 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60692 | msg: "Internally check the the client state and " |
| 60693 | "required activities"); |
| 60694 | |
| 60695 | /* Renew Secure Channel */ |
| 60696 | __Client_renewSecureChannel(client); |
| 60697 | |
| 60698 | /* Send read requests from time to time to test the connectivity */ |
| 60699 | __Client_backgroundConnectivity(client); |
| 60700 | |
| 60701 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 60702 | /* Feed the server PublishRequests for the Subscriptions */ |
| 60703 | __Client_Subscriptions_backgroundPublish(client); |
| 60704 | |
| 60705 | /* Check for inactive Subscriptions */ |
| 60706 | __Client_Subscriptions_backgroundPublishInactivityCheck(client); |
| 60707 | #endif |
| 60708 | |
| 60709 | /* Did async services time out? Process callbacks with an error code */ |
| 60710 | asyncServiceTimeoutCheck(client); |
| 60711 | |
| 60712 | /* Log and notify user if the client state has changed */ |
| 60713 | notifyClientState(client); |
| 60714 | |
| 60715 | unlockClient(client); |
| 60716 | } |
| 60717 | |
| 60718 | UA_StatusCode |
| 60719 | __UA_Client_startup(UA_Client *client) { |
| 60720 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 60721 | |
| 60722 | UA_EventLoop *el = client->config.eventLoop; |
| 60723 | UA_CHECK_ERROR(el != NULL, |
| 60724 | return UA_STATUSCODE_BADINTERNALERROR, |
| 60725 | client->config.logging, UA_LOGCATEGORY_CLIENT, |
| 60726 | "No EventLoop configured"); |
| 60727 | |
| 60728 | /* Set up the repeated timer callback for checking the internal state. Like |
| 60729 | * in the public API UA_Client_addRepeatedCallback, but without locking the |
| 60730 | * mutex again */ |
| 60731 | UA_StatusCode rv = UA_STATUSCODE_GOOD; |
| 60732 | if(!client->houseKeepingCallbackId) { |
| 60733 | rv = el->addCyclicCallback(el, (UA_Callback)clientHouseKeeping, |
| 60734 | client, NULL, 1000.0, NULL, |
| 60735 | UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, |
| 60736 | &client->houseKeepingCallbackId); |
| 60737 | UA_CHECK_STATUS(rv, return rv); |
| 60738 | } |
| 60739 | |
| 60740 | /* Start the EventLoop? */ |
| 60741 | if(el->state == UA_EVENTLOOPSTATE_FRESH) { |
| 60742 | rv = el->start(el); |
| 60743 | UA_CHECK_STATUS(rv, return rv); |
| 60744 | } |
| 60745 | |
| 60746 | return UA_STATUSCODE_GOOD; |
| 60747 | } |
| 60748 | |
| 60749 | UA_StatusCode |
| 60750 | UA_Client_run_iterate(UA_Client *client, UA_UInt32 timeout) { |
| 60751 | /* Make sure the EventLoop has been started */ |
| 60752 | lockClient(client); |
| 60753 | UA_StatusCode rv = __UA_Client_startup(client); |
| 60754 | unlockClient(client); |
| 60755 | UA_CHECK_STATUS(rv, return rv); |
| 60756 | |
| 60757 | /* All timers and network events are triggered in the EventLoop. Release the |
| 60758 | * client lock before. The callbacks from the EventLoop take the lock |
| 60759 | * again. */ |
| 60760 | UA_EventLoop *el = client->config.eventLoop; |
| 60761 | rv = el->run(el, timeout); |
| 60762 | UA_CHECK_STATUS(rv, return rv); |
| 60763 | return client->connectStatus; |
| 60764 | } |
| 60765 | |
| 60766 | const UA_DataType * |
| 60767 | UA_Client_findDataType(UA_Client *client, const UA_NodeId *typeId) { |
| 60768 | return UA_findDataTypeWithCustom(typeId, customTypes: client->config.customDataTypes); |
| 60769 | } |
| 60770 | |
| 60771 | /*************************/ |
| 60772 | /* Connection Attributes */ |
| 60773 | /*************************/ |
| 60774 | |
| 60775 | #define UA_CONNECTIONATTRIBUTESSIZE 3 |
| 60776 | static const UA_QualifiedName connectionAttributes[UA_CONNECTIONATTRIBUTESSIZE] = { |
| 60777 | {0, UA_STRING_STATIC("serverDescription")}, |
| 60778 | {0, UA_STRING_STATIC("securityPolicyUri")}, |
| 60779 | {0, UA_STRING_STATIC("securityMode")} |
| 60780 | }; |
| 60781 | |
| 60782 | static UA_StatusCode |
| 60783 | getConnectionttribute(UA_Client *client, const UA_QualifiedName key, |
| 60784 | UA_Variant *outValue, UA_Boolean copy) { |
| 60785 | if(!outValue) |
| 60786 | return UA_STATUSCODE_BADINTERNALERROR; |
| 60787 | |
| 60788 | UA_Variant localAttr; |
| 60789 | |
| 60790 | if(UA_QualifiedName_equal(p1: &key, p2: &connectionAttributes[0])) { |
| 60791 | /* ServerDescription */ |
| 60792 | UA_Variant_setScalar(v: &localAttr, p: &client->endpoint.server, |
| 60793 | type: &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]); |
| 60794 | } else if(UA_QualifiedName_equal(p1: &key, p2: &connectionAttributes[1])) { |
| 60795 | /* SecurityPolicyUri */ |
| 60796 | const UA_SecurityPolicy *sp = client->channel.securityPolicy; |
| 60797 | if(!sp) |
| 60798 | return UA_STATUSCODE_BADNOTCONNECTED; |
| 60799 | UA_Variant_setScalar(v: &localAttr, p: (void*)(uintptr_t)&sp->policyUri, |
| 60800 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 60801 | } else if(UA_QualifiedName_equal(p1: &key, p2: &connectionAttributes[2])) { |
| 60802 | /* SecurityMode */ |
| 60803 | UA_Variant_setScalar(v: &localAttr, p: &client->channel.securityMode, |
| 60804 | type: &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE]); |
| 60805 | } else { |
| 60806 | return UA_STATUSCODE_BADINTERNALERROR; |
| 60807 | } |
| 60808 | |
| 60809 | if(copy) |
| 60810 | return UA_Variant_copy(src: &localAttr, dst: outValue); |
| 60811 | |
| 60812 | localAttr.storageType = UA_VARIANT_DATA_NODELETE; |
| 60813 | *outValue = localAttr; |
| 60814 | return UA_STATUSCODE_GOOD; |
| 60815 | } |
| 60816 | |
| 60817 | UA_StatusCode |
| 60818 | UA_Client_getConnectionAttribute(UA_Client *client, const UA_QualifiedName key, |
| 60819 | UA_Variant *outValue) { |
| 60820 | lockClient(client); |
| 60821 | UA_StatusCode res = getConnectionttribute(client, key, outValue, false); |
| 60822 | unlockClient(client); |
| 60823 | return res; |
| 60824 | } |
| 60825 | |
| 60826 | UA_StatusCode |
| 60827 | UA_Client_getConnectionAttributeCopy(UA_Client *client, const UA_QualifiedName key, |
| 60828 | UA_Variant *outValue) { |
| 60829 | lockClient(client); |
| 60830 | UA_StatusCode res = getConnectionttribute(client, key, outValue, true); |
| 60831 | unlockClient(client); |
| 60832 | return res; |
| 60833 | } |
| 60834 | |
| 60835 | UA_StatusCode |
| 60836 | UA_Client_getConnectionAttribute_scalar(UA_Client *client, |
| 60837 | const UA_QualifiedName key, |
| 60838 | const UA_DataType *type, |
| 60839 | void *outValue) { |
| 60840 | lockClient(client); |
| 60841 | |
| 60842 | UA_Variant attr; |
| 60843 | UA_StatusCode res = getConnectionttribute(client, key, outValue: &attr, false); |
| 60844 | if(res != UA_STATUSCODE_GOOD) { |
| 60845 | unlockClient(client); |
| 60846 | return res; |
| 60847 | } |
| 60848 | |
| 60849 | if(!UA_Variant_hasScalarType(v: &attr, type)) { |
| 60850 | unlockClient(client); |
| 60851 | return UA_STATUSCODE_BADNOTFOUND; |
| 60852 | } |
| 60853 | |
| 60854 | memcpy(dest: outValue, src: attr.data, n: type->memSize); |
| 60855 | |
| 60856 | unlockClient(client); |
| 60857 | return UA_STATUSCODE_GOOD; |
| 60858 | } |
| 60859 | |
| 60860 | void lockClient(UA_Client *client) { |
| 60861 | if(UA_LIKELY(client->config.eventLoop && client->config.eventLoop->lock)) |
| 60862 | client->config.eventLoop->lock(client->config.eventLoop); |
| 60863 | UA_LOCK(&client->clientMutex); |
| 60864 | } |
| 60865 | |
| 60866 | void unlockClient(UA_Client *client) { |
| 60867 | if(UA_LIKELY(client->config.eventLoop && client->config.eventLoop->unlock)) |
| 60868 | client->config.eventLoop->unlock(client->config.eventLoop); |
| 60869 | UA_UNLOCK(&client->clientMutex); |
| 60870 | } |
| 60871 | |
| 60872 | /**** amalgamated original file "/src/client/ua_client_connect.c" ****/ |
| 60873 | |
| 60874 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 60875 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 60876 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 60877 | * |
| 60878 | * Copyright 2017-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 60879 | * Copyright 2017-2019 (c) Fraunhofer IOSB (Author: Mark Giraud) |
| 60880 | */ |
| 60881 | |
| 60882 | |
| 60883 | |
| 60884 | /* Some OPC UA servers only return all Endpoints if the EndpointURL used during |
| 60885 | * the HEL/ACK handshake exactly matches -- including the path following the |
| 60886 | * address and port! Hence for the first connection we only call FindServers and |
| 60887 | * reopen a new TCP connection using then EndpointURL found there. |
| 60888 | * |
| 60889 | * The overall process is this: |
| 60890 | * - Connect with the EndpointURL provided by the user (HEL/ACK) |
| 60891 | * - Call FindServers |
| 60892 | * - If one of the results has an exactly matching EndpointUrl, continue. |
| 60893 | * - Otherwise select a matching server, update the endpointURL member of |
| 60894 | * UA_Client and reconnect. |
| 60895 | * - Call GetEndpoints and select an Endpoint |
| 60896 | * - Open a SecureChannel and Session for that Endpoint |
| 60897 | */ |
| 60898 | |
| 60899 | #define UA_MINMESSAGESIZE 8192 |
| 60900 | #define UA_SESSION_LOCALNONCELENGTH 32 |
| 60901 | #define MAX_DATA_SIZE 4096 |
| 60902 | |
| 60903 | static void initConnect(UA_Client *client); |
| 60904 | static UA_StatusCode createSessionAsync(UA_Client *client); |
| 60905 | static UA_UserTokenPolicy * |
| 60906 | findUserTokenPolicy(UA_Client *client, UA_EndpointDescription *endpoint); |
| 60907 | |
| 60908 | /* Get the EndpointUrl to be used right now. |
| 60909 | * This is adjusted during the discovery process. |
| 60910 | * We fall back if connecting to an EndpointUrl fails. */ |
| 60911 | static UA_String |
| 60912 | getEndpointUrl(UA_Client *client) { |
| 60913 | if(client->endpoint.endpointUrl.length > 0) |
| 60914 | return client->endpoint.endpointUrl; |
| 60915 | if(client->discoveryUrl.length > 0) |
| 60916 | return client->discoveryUrl; |
| 60917 | return client->config.endpointUrl; |
| 60918 | } |
| 60919 | |
| 60920 | /* If an EndpointUrl doesn't work (TCP connection fails), fall back to the |
| 60921 | * initial EndpointUrl */ |
| 60922 | static UA_StatusCode |
| 60923 | fallbackEndpointUrl(UA_Client* client) { |
| 60924 | /* Cannot fallback, the initial EndpointUrl is already in use */ |
| 60925 | UA_String currentUrl = getEndpointUrl(client); |
| 60926 | if(UA_String_equal(p1: ¤tUrl, p2: &client->config.endpointUrl)) { |
| 60927 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60928 | msg: "Could not open a TCP connection to the Endpoint at %.*s", |
| 60929 | (int)client->config.endpointUrl.length, |
| 60930 | client->config.endpointUrl.data); |
| 60931 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 60932 | } |
| 60933 | |
| 60934 | if(client->endpoint.endpointUrl.length > 0) { |
| 60935 | /* Overwrite the EndpointUrl of the Endpoint */ |
| 60936 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60937 | msg: "Could not open a TCP connection to the Endpoint at %.*s. " |
| 60938 | "Overriding the endpoint description with the initial " |
| 60939 | "EndpointUrl at %.*s.", |
| 60940 | (int)client->endpoint.endpointUrl.length, |
| 60941 | client->endpoint.endpointUrl.data, |
| 60942 | (int)client->config.endpointUrl.length, |
| 60943 | client->config.endpointUrl.data); |
| 60944 | UA_String_clear(p: &client->endpoint.endpointUrl); |
| 60945 | return UA_String_copy(src: &client->config.endpointUrl, |
| 60946 | dst: &client->endpoint.endpointUrl); |
| 60947 | } else { |
| 60948 | /* Overwrite the DiscoveryUrl returned by FindServers */ |
| 60949 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 60950 | msg: "The DiscoveryUrl returned by the FindServers service (%.*s) " |
| 60951 | "could not be connected. Continuing with the initial EndpointUrl " |
| 60952 | "%.*s for the GetEndpoints service.", |
| 60953 | (int)client->config.endpointUrl.length, |
| 60954 | client->config.endpointUrl.data, |
| 60955 | (int)client->config.endpointUrl.length, |
| 60956 | client->config.endpointUrl.data); |
| 60957 | UA_String_clear(p: &client->discoveryUrl); |
| 60958 | return UA_String_copy(src: &client->config.endpointUrl, dst: &client->discoveryUrl); |
| 60959 | } |
| 60960 | } |
| 60961 | |
| 60962 | static UA_SecurityPolicy * |
| 60963 | getSecurityPolicy(UA_Client *client, UA_String policyUri) { |
| 60964 | if(policyUri.length == 0) |
| 60965 | policyUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None"); |
| 60966 | for(size_t i = 0; i < client->config.securityPoliciesSize; i++) { |
| 60967 | if(UA_String_equal(p1: &policyUri, p2: &client->config.securityPolicies[i].policyUri)) |
| 60968 | return &client->config.securityPolicies[i]; |
| 60969 | } |
| 60970 | return NULL; |
| 60971 | } |
| 60972 | |
| 60973 | static UA_SecurityPolicy * |
| 60974 | getAuthSecurityPolicy(UA_Client *client, UA_String policyUri) { |
| 60975 | for(size_t i = 0; i < client->config.authSecurityPoliciesSize; i++) { |
| 60976 | if(UA_String_equal(p1: &policyUri, p2: &client->config.authSecurityPolicies[i].policyUri)) |
| 60977 | return &client->config.authSecurityPolicies[i]; |
| 60978 | } |
| 60979 | return NULL; |
| 60980 | } |
| 60981 | |
| 60982 | /* The endpoint is unconfigured if the description is all zeroed-out */ |
| 60983 | static UA_Boolean |
| 60984 | endpointUnconfigured(const UA_EndpointDescription *endpoint) { |
| 60985 | UA_EndpointDescription tmp; |
| 60986 | UA_EndpointDescription_init(p: &tmp); |
| 60987 | return UA_equal(p1: &tmp, p2: endpoint, type: &UA_TYPES[UA_TYPES_ENDPOINTDESCRIPTION]); |
| 60988 | } |
| 60989 | |
| 60990 | UA_Boolean |
| 60991 | isFullyConnected(UA_Client *client) { |
| 60992 | /* No Session, but require one */ |
| 60993 | if(client->sessionState != UA_SESSIONSTATE_ACTIVATED && !client->config.noSession) |
| 60994 | return false; |
| 60995 | |
| 60996 | /* No SecureChannel */ |
| 60997 | if(client->channel.state != UA_SECURECHANNELSTATE_OPEN) |
| 60998 | return false; |
| 60999 | |
| 61000 | /* GetEndpoints handshake ongoing or not yet done */ |
| 61001 | if(client->endpointsHandshake || endpointUnconfigured(endpoint: &client->endpoint)) |
| 61002 | return false; |
| 61003 | |
| 61004 | /* FindServers handshake ongoing or not yet done */ |
| 61005 | if(client->findServersHandshake || client->discoveryUrl.length == 0) |
| 61006 | return false; |
| 61007 | |
| 61008 | return true; |
| 61009 | } |
| 61010 | |
| 61011 | #ifdef UA_ENABLE_ENCRYPTION |
| 61012 | |
| 61013 | /* Function to create a signature using remote certificate and nonce. |
| 61014 | * This uses the SecurityPolicy of the SecureChannel. */ |
| 61015 | static UA_StatusCode |
| 61016 | signClientSignature(UA_Client *client, UA_ActivateSessionRequest *request) { |
| 61017 | UA_SecureChannel *channel = &client->channel; |
| 61018 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 61019 | UA_SignatureData *sd = &request->clientSignature; |
| 61020 | const UA_SecurityPolicySignatureAlgorithm *signAlg = |
| 61021 | &sp->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 61022 | |
| 61023 | /* Copy the signature algorithm identifier */ |
| 61024 | UA_StatusCode retval = UA_String_copy(src: &signAlg->uri, dst: &sd->algorithm); |
| 61025 | if(retval != UA_STATUSCODE_GOOD) |
| 61026 | return retval; |
| 61027 | |
| 61028 | /* Allocate memory for the signature */ |
| 61029 | size_t signatureSize = signAlg->getLocalSignatureSize(channel->channelContext); |
| 61030 | retval = UA_ByteString_allocBuffer(bs: &sd->signature, length: signatureSize); |
| 61031 | if(retval != UA_STATUSCODE_GOOD) |
| 61032 | return retval; |
| 61033 | |
| 61034 | /* Create a temporary buffer */ |
| 61035 | size_t signDataSize = |
| 61036 | channel->remoteCertificate.length + client->serverSessionNonce.length; |
| 61037 | if(signDataSize > MAX_DATA_SIZE) |
| 61038 | return UA_STATUSCODE_BADINTERNALERROR; |
| 61039 | UA_Byte buf[MAX_DATA_SIZE]; |
| 61040 | UA_ByteString signData = {signDataSize, buf}; |
| 61041 | |
| 61042 | /* Sign the ClientSignature */ |
| 61043 | memcpy(dest: buf, src: channel->remoteCertificate.data, n: channel->remoteCertificate.length); |
| 61044 | memcpy(dest: buf + channel->remoteCertificate.length, src: client->serverSessionNonce.data, |
| 61045 | n: client->serverSessionNonce.length); |
| 61046 | return signAlg->sign(channel->channelContext, &signData, &sd->signature); |
| 61047 | } |
| 61048 | |
| 61049 | static UA_StatusCode |
| 61050 | signUserTokenSignature(UA_Client *client, UA_SecurityPolicy *utsp, |
| 61051 | UA_ActivateSessionRequest *request) { |
| 61052 | /* Check the size of the content for signing and create a temporary buffer */ |
| 61053 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 61054 | size_t signDataSize = |
| 61055 | client->channel.remoteCertificate.length + client->serverSessionNonce.length; |
| 61056 | if(signDataSize > MAX_DATA_SIZE) |
| 61057 | return UA_STATUSCODE_BADINTERNALERROR; |
| 61058 | UA_Byte buf[MAX_DATA_SIZE]; |
| 61059 | UA_ByteString signData = {signDataSize, buf}; |
| 61060 | |
| 61061 | /* Copy the algorithm identifier */ |
| 61062 | UA_SecurityPolicySignatureAlgorithm *utpSignAlg = |
| 61063 | &utsp->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 61064 | UA_SignatureData *utsd = &request->userTokenSignature; |
| 61065 | retval = UA_String_copy(src: &utpSignAlg->uri, dst: &utsd->algorithm); |
| 61066 | if(retval != UA_STATUSCODE_GOOD) |
| 61067 | return retval; |
| 61068 | |
| 61069 | /* We need a channel context with the user certificate in order to reuse the |
| 61070 | * code for signing. */ |
| 61071 | void *tmpCtx; |
| 61072 | retval = utsp->channelModule.newContext(utsp, &client->channel.remoteCertificate, &tmpCtx); |
| 61073 | if(retval != UA_STATUSCODE_GOOD) |
| 61074 | return retval; |
| 61075 | |
| 61076 | /* Allocate memory for the signature */ |
| 61077 | retval = UA_ByteString_allocBuffer(bs: &utsd->signature, |
| 61078 | length: utpSignAlg->getLocalSignatureSize(tmpCtx)); |
| 61079 | if(retval != UA_STATUSCODE_GOOD) |
| 61080 | goto cleanup_utp; |
| 61081 | |
| 61082 | /* Create the userTokenSignature */ |
| 61083 | memcpy(dest: buf, src: client->channel.remoteCertificate.data, |
| 61084 | n: client->channel.remoteCertificate.length); |
| 61085 | memcpy(dest: buf + client->channel.remoteCertificate.length, |
| 61086 | src: client->serverSessionNonce.data, n: client->serverSessionNonce.length); |
| 61087 | retval = utpSignAlg->sign(tmpCtx, &signData, &utsd->signature); |
| 61088 | |
| 61089 | /* Clean up */ |
| 61090 | cleanup_utp: |
| 61091 | utsp->channelModule.deleteContext(tmpCtx); |
| 61092 | return retval; |
| 61093 | } |
| 61094 | |
| 61095 | /* UserName and IssuedIdentity are transferred encrypted. |
| 61096 | * X509 and Anonymous are not. */ |
| 61097 | static UA_StatusCode |
| 61098 | encryptUserIdentityToken(UA_Client *client, UA_SecurityPolicy *utsp, |
| 61099 | UA_ExtensionObject *userIdentityToken) { |
| 61100 | UA_IssuedIdentityToken *iit = NULL; |
| 61101 | UA_UserNameIdentityToken *unit = NULL; |
| 61102 | UA_ByteString *tokenData; |
| 61103 | const UA_DataType *tokenType = userIdentityToken->content.decoded.type; |
| 61104 | if(tokenType == &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN]) { |
| 61105 | iit = (UA_IssuedIdentityToken*)userIdentityToken->content.decoded.data; |
| 61106 | tokenData = &iit->tokenData; |
| 61107 | } else if(tokenType == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) { |
| 61108 | unit = (UA_UserNameIdentityToken*)userIdentityToken->content.decoded.data; |
| 61109 | tokenData = &unit->password; |
| 61110 | } else { |
| 61111 | return UA_STATUSCODE_GOOD; |
| 61112 | } |
| 61113 | |
| 61114 | /* Create a temp channel context */ |
| 61115 | |
| 61116 | void *channelContext; |
| 61117 | UA_StatusCode retval = utsp->channelModule. |
| 61118 | newContext(utsp, &client->endpoint.serverCertificate, &channelContext); |
| 61119 | if(retval != UA_STATUSCODE_GOOD) { |
| 61120 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_NETWORK, |
| 61121 | msg: "Could not instantiate the SecurityPolicy for the UserToken"); |
| 61122 | return UA_STATUSCODE_BADINTERNALERROR; |
| 61123 | } |
| 61124 | |
| 61125 | /* Compute the encrypted length (at least one byte padding) */ |
| 61126 | size_t plainTextBlockSize = utsp->asymmetricModule.cryptoModule. |
| 61127 | encryptionAlgorithm.getRemotePlainTextBlockSize(channelContext); |
| 61128 | size_t encryptedBlockSize = utsp->asymmetricModule.cryptoModule. |
| 61129 | encryptionAlgorithm.getRemoteBlockSize(channelContext); |
| 61130 | UA_UInt32 length = (UA_UInt32)(tokenData->length + client->serverSessionNonce.length); |
| 61131 | UA_UInt32 totalLength = length + 4; /* Including the length field */ |
| 61132 | size_t blocks = totalLength / plainTextBlockSize; |
| 61133 | if(totalLength % plainTextBlockSize != 0) |
| 61134 | blocks++; |
| 61135 | size_t encryptedLength = blocks * encryptedBlockSize; |
| 61136 | |
| 61137 | /* Allocate memory for encryption overhead */ |
| 61138 | UA_ByteString encrypted; |
| 61139 | retval = UA_ByteString_allocBuffer(bs: &encrypted, length: encryptedLength); |
| 61140 | if(retval != UA_STATUSCODE_GOOD) { |
| 61141 | utsp->channelModule.deleteContext(channelContext); |
| 61142 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 61143 | } |
| 61144 | |
| 61145 | UA_Byte *pos = encrypted.data; |
| 61146 | const UA_Byte *end = &encrypted.data[encrypted.length]; |
| 61147 | retval = UA_UInt32_encodeBinary(src: &length, bufPos: &pos, bufEnd: end); |
| 61148 | memcpy(dest: pos, src: tokenData->data, n: tokenData->length); |
| 61149 | memcpy(dest: &pos[tokenData->length], src: client->serverSessionNonce.data, |
| 61150 | n: client->serverSessionNonce.length); |
| 61151 | UA_assert(retval == UA_STATUSCODE_GOOD); |
| 61152 | |
| 61153 | /* Add padding |
| 61154 | * |
| 61155 | * 7.36.2.2 Legacy Encrypted Token Secret Format: A Client should not add any |
| 61156 | * padding after the secret. If a Client adds padding then all bytes shall |
| 61157 | * be zero. A Server shall check for padding added by Clients and ensure |
| 61158 | * that all padding bytes are zeros. */ |
| 61159 | size_t paddedLength = plainTextBlockSize * blocks; |
| 61160 | for(size_t i = totalLength; i < paddedLength; i++) |
| 61161 | encrypted.data[i] = 0; |
| 61162 | encrypted.length = paddedLength; |
| 61163 | |
| 61164 | retval = utsp->asymmetricModule.cryptoModule.encryptionAlgorithm. |
| 61165 | encrypt(channelContext, &encrypted); |
| 61166 | encrypted.length = encryptedLength; |
| 61167 | UA_ByteString_clear(p: tokenData); |
| 61168 | *tokenData = encrypted; |
| 61169 | |
| 61170 | /* Delete the temporary channel context */ |
| 61171 | utsp->channelModule.deleteContext(channelContext); |
| 61172 | |
| 61173 | if(iit) { |
| 61174 | retval |= UA_String_copy(src: &utsp->asymmetricModule.cryptoModule.encryptionAlgorithm.uri, |
| 61175 | dst: &iit->encryptionAlgorithm); |
| 61176 | } else { |
| 61177 | retval |= UA_String_copy(src: &utsp->asymmetricModule.cryptoModule.encryptionAlgorithm.uri, |
| 61178 | dst: &unit->encryptionAlgorithm); |
| 61179 | } |
| 61180 | return retval; |
| 61181 | } |
| 61182 | |
| 61183 | /* Function to verify the signature corresponds to ClientNonce |
| 61184 | * using the local certificate */ |
| 61185 | static UA_StatusCode |
| 61186 | checkCreateSessionSignature(UA_Client *client, const UA_SecureChannel *channel, |
| 61187 | const UA_CreateSessionResponse *response) { |
| 61188 | if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN && |
| 61189 | channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 61190 | return UA_STATUSCODE_GOOD; |
| 61191 | |
| 61192 | if(!channel->securityPolicy) |
| 61193 | return UA_STATUSCODE_BADINTERNALERROR; |
| 61194 | |
| 61195 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 61196 | const UA_ByteString *lc = &sp->localCertificate; |
| 61197 | |
| 61198 | size_t dataToVerifySize = lc->length + client->clientSessionNonce.length; |
| 61199 | UA_ByteString dataToVerify = UA_BYTESTRING_NULL; |
| 61200 | UA_StatusCode retval = UA_ByteString_allocBuffer(bs: &dataToVerify, length: dataToVerifySize); |
| 61201 | if(retval != UA_STATUSCODE_GOOD) |
| 61202 | return retval; |
| 61203 | |
| 61204 | memcpy(dest: dataToVerify.data, src: lc->data, n: lc->length); |
| 61205 | memcpy(dest: dataToVerify.data + lc->length, src: client->clientSessionNonce.data, |
| 61206 | n: client->clientSessionNonce.length); |
| 61207 | |
| 61208 | retval = sp->asymmetricModule.cryptoModule.signatureAlgorithm. |
| 61209 | verify(channel->channelContext, &dataToVerify, |
| 61210 | &response->serverSignature.signature); |
| 61211 | UA_ByteString_clear(p: &dataToVerify); |
| 61212 | return retval; |
| 61213 | } |
| 61214 | |
| 61215 | #endif |
| 61216 | |
| 61217 | /***********************/ |
| 61218 | /* Open the Connection */ |
| 61219 | /***********************/ |
| 61220 | |
| 61221 | void |
| 61222 | processERRResponse(UA_Client *client, const UA_ByteString *chunk) { |
| 61223 | size_t offset = 0; |
| 61224 | UA_TcpErrorMessage errMessage; |
| 61225 | client->connectStatus = |
| 61226 | UA_decodeBinaryInternal(src: chunk, offset: &offset, dst: &errMessage, |
| 61227 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPERRORMESSAGE], NULL); |
| 61228 | if(client->connectStatus != UA_STATUSCODE_GOOD) { |
| 61229 | UA_LOG_ERROR_CHANNEL(client->config.logging, &client->channel, |
| 61230 | "Received an ERR response that could not be decoded " |
| 61231 | "with StatusCode %s", |
| 61232 | UA_StatusCode_name(client->connectStatus)); |
| 61233 | closeSecureChannel(client); |
| 61234 | return; |
| 61235 | } |
| 61236 | |
| 61237 | UA_LOG_ERROR_CHANNEL(client->config.logging, &client->channel, |
| 61238 | "Received an ERR response with StatusCode %s and the following " |
| 61239 | "reason: %.*s", UA_StatusCode_name(errMessage.error), |
| 61240 | (int)errMessage.reason.length, errMessage.reason.data); |
| 61241 | client->connectStatus = errMessage.error; |
| 61242 | closeSecureChannel(client); |
| 61243 | UA_TcpErrorMessage_clear(p: &errMessage); |
| 61244 | } |
| 61245 | |
| 61246 | void |
| 61247 | processACKResponse(UA_Client *client, const UA_ByteString *chunk) { |
| 61248 | UA_SecureChannel *channel = &client->channel; |
| 61249 | if(channel->state != UA_SECURECHANNELSTATE_HEL_SENT) { |
| 61250 | UA_LOG_ERROR_CHANNEL(client->config.logging, channel, |
| 61251 | "SecureChannel not in the HEL-sent state"); |
| 61252 | client->connectStatus = UA_STATUSCODE_BADSECURECHANNELCLOSED; |
| 61253 | closeSecureChannel(client); |
| 61254 | return; |
| 61255 | } |
| 61256 | |
| 61257 | /* Decode the message */ |
| 61258 | size_t offset = 0; |
| 61259 | UA_TcpAcknowledgeMessage ackMessage; |
| 61260 | client->connectStatus = |
| 61261 | UA_decodeBinaryInternal(src: chunk, offset: &offset, dst: &ackMessage, |
| 61262 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPACKNOWLEDGEMESSAGE], NULL); |
| 61263 | if(client->connectStatus != UA_STATUSCODE_GOOD) { |
| 61264 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_NETWORK, |
| 61265 | msg: "Decoding ACK message failed"); |
| 61266 | closeSecureChannel(client); |
| 61267 | return; |
| 61268 | } |
| 61269 | |
| 61270 | client->connectStatus = |
| 61271 | UA_SecureChannel_processHELACK(channel, remoteConfig: &ackMessage); |
| 61272 | if(client->connectStatus != UA_STATUSCODE_GOOD) { |
| 61273 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_NETWORK, |
| 61274 | msg: "Processing the ACK message failed with StatusCode %s", |
| 61275 | UA_StatusCode_name(code: client->connectStatus)); |
| 61276 | closeSecureChannel(client); |
| 61277 | return; |
| 61278 | } |
| 61279 | |
| 61280 | client->channel.state = UA_SECURECHANNELSTATE_ACK_RECEIVED; |
| 61281 | } |
| 61282 | |
| 61283 | static UA_StatusCode |
| 61284 | sendHELMessage(UA_Client *client) { |
| 61285 | UA_ConnectionManager *cm = client->channel.connectionManager; |
| 61286 | if(!UA_SecureChannel_isConnected(channel: &client->channel)) |
| 61287 | return UA_STATUSCODE_BADNOTCONNECTED; |
| 61288 | |
| 61289 | /* Get a buffer */ |
| 61290 | UA_ByteString message; |
| 61291 | UA_StatusCode retval = cm->allocNetworkBuffer(cm, client->channel.connectionId, |
| 61292 | &message, UA_MINMESSAGESIZE); |
| 61293 | if(retval != UA_STATUSCODE_GOOD) |
| 61294 | return retval; |
| 61295 | |
| 61296 | /* Prepare the HEL message and encode at offset 8 */ |
| 61297 | UA_TcpHelloMessage hello; |
| 61298 | hello.protocolVersion = 0; |
| 61299 | hello.receiveBufferSize = client->config.localConnectionConfig.recvBufferSize; |
| 61300 | hello.sendBufferSize = client->config.localConnectionConfig.sendBufferSize; |
| 61301 | hello.maxMessageSize = client->config.localConnectionConfig.localMaxMessageSize; |
| 61302 | hello.maxChunkCount = client->config.localConnectionConfig.localMaxChunkCount; |
| 61303 | hello.endpointUrl = getEndpointUrl(client); |
| 61304 | |
| 61305 | UA_Byte *bufPos = &message.data[8]; /* skip the header */ |
| 61306 | const UA_Byte *bufEnd = &message.data[message.length]; |
| 61307 | client->connectStatus = |
| 61308 | UA_encodeBinaryInternal(src: &hello, type: &UA_TRANSPORT[UA_TRANSPORT_TCPHELLOMESSAGE], |
| 61309 | bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 61310 | |
| 61311 | /* Encode the message header at offset 0 */ |
| 61312 | UA_TcpMessageHeader messageHeader; |
| 61313 | messageHeader.messageTypeAndChunkType = UA_CHUNKTYPE_FINAL + UA_MESSAGETYPE_HEL; |
| 61314 | messageHeader.messageSize = (UA_UInt32) ((uintptr_t)bufPos - (uintptr_t)message.data); |
| 61315 | bufPos = message.data; |
| 61316 | retval = UA_encodeBinaryInternal(src: &messageHeader, |
| 61317 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPMESSAGEHEADER], |
| 61318 | bufPos: &bufPos, bufEnd: &bufEnd, NULL, NULL); |
| 61319 | if(retval != UA_STATUSCODE_GOOD) { |
| 61320 | cm->freeNetworkBuffer(cm, client->channel.connectionId, &message); |
| 61321 | return retval; |
| 61322 | } |
| 61323 | |
| 61324 | /* Send the HEL message */ |
| 61325 | message.length = messageHeader.messageSize; |
| 61326 | retval = cm->sendWithConnection(cm, client->channel.connectionId, |
| 61327 | &UA_KEYVALUEMAP_NULL, &message); |
| 61328 | if(retval != UA_STATUSCODE_GOOD) { |
| 61329 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, msg: "Sending HEL failed"); |
| 61330 | closeSecureChannel(client); |
| 61331 | return retval; |
| 61332 | } |
| 61333 | |
| 61334 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, msg: "Sent HEL message"); |
| 61335 | client->channel.state = UA_SECURECHANNELSTATE_HEL_SENT; |
| 61336 | return UA_STATUSCODE_GOOD; |
| 61337 | } |
| 61338 | |
| 61339 | void processRHEMessage(UA_Client *client, const UA_ByteString *chunk) { |
| 61340 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, msg: "RHE received"); |
| 61341 | |
| 61342 | size_t offset = 0; /* Go to the beginning of the TcpHelloMessage */ |
| 61343 | UA_TcpReverseHelloMessage rheMessage; |
| 61344 | UA_StatusCode retval = |
| 61345 | UA_decodeBinaryInternal(src: chunk, offset: &offset, dst: &rheMessage, |
| 61346 | type: &UA_TRANSPORT[UA_TRANSPORT_TCPREVERSEHELLOMESSAGE], NULL); |
| 61347 | |
| 61348 | if(retval != UA_STATUSCODE_GOOD) { |
| 61349 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_NETWORK, |
| 61350 | msg: "Decoding RHE message failed"); |
| 61351 | closeSecureChannel(client); |
| 61352 | return; |
| 61353 | } |
| 61354 | |
| 61355 | UA_String_clear(p: &client->discoveryUrl); |
| 61356 | UA_String_copy(src: &rheMessage.endpointUrl, dst: &client->discoveryUrl); |
| 61357 | |
| 61358 | UA_TcpReverseHelloMessage_clear(p: &rheMessage); |
| 61359 | |
| 61360 | sendHELMessage(client); |
| 61361 | } |
| 61362 | |
| 61363 | void |
| 61364 | processOPNResponse(UA_Client *client, const UA_ByteString *message) { |
| 61365 | /* Is the content of the expected type? */ |
| 61366 | size_t offset = 0; |
| 61367 | UA_NodeId responseId; |
| 61368 | UA_NodeId expectedId = |
| 61369 | UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_OPENSECURECHANNELRESPONSE_ENCODING_DEFAULTBINARY); |
| 61370 | UA_StatusCode retval = UA_NodeId_decodeBinary(src: message, offset: &offset, dst: &responseId); |
| 61371 | if(retval != UA_STATUSCODE_GOOD) { |
| 61372 | closeSecureChannel(client); |
| 61373 | return; |
| 61374 | } |
| 61375 | |
| 61376 | if(!UA_NodeId_equal(p1: &responseId, p2: &expectedId)) { |
| 61377 | UA_NodeId_clear(p: &responseId); |
| 61378 | closeSecureChannel(client); |
| 61379 | return; |
| 61380 | } |
| 61381 | |
| 61382 | /* Decode the response */ |
| 61383 | UA_OpenSecureChannelResponse response; |
| 61384 | retval = UA_decodeBinaryInternal(src: message, offset: &offset, dst: &response, |
| 61385 | type: &UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE], NULL); |
| 61386 | if(retval != UA_STATUSCODE_GOOD) { |
| 61387 | closeSecureChannel(client); |
| 61388 | return; |
| 61389 | } |
| 61390 | |
| 61391 | /* Check whether the nonce was reused */ |
| 61392 | if(client->channel.securityMode != UA_MESSAGESECURITYMODE_NONE && |
| 61393 | UA_ByteString_equal(p1: &client->channel.remoteNonce, p2: &response.serverNonce)) { |
| 61394 | UA_LOG_ERROR_CHANNEL(client->config.logging, &client->channel, |
| 61395 | "The server reused the last nonce"); |
| 61396 | client->connectStatus = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 61397 | closeSecureChannel(client); |
| 61398 | return; |
| 61399 | } |
| 61400 | |
| 61401 | /* Move the nonce out of the response */ |
| 61402 | UA_ByteString_clear(p: &client->channel.remoteNonce); |
| 61403 | client->channel.remoteNonce = response.serverNonce; |
| 61404 | UA_ByteString_init(p: &response.serverNonce); |
| 61405 | UA_ResponseHeader_clear(p: &response.responseHeader); |
| 61406 | |
| 61407 | /* Replace the token. Keep the current token as the old token. Messages |
| 61408 | * might still arrive for the old token. */ |
| 61409 | client->channel.altSecurityToken = client->channel.securityToken; |
| 61410 | client->channel.securityToken = response.securityToken; |
| 61411 | client->channel.renewState = UA_SECURECHANNELRENEWSTATE_NEWTOKEN_CLIENT; |
| 61412 | |
| 61413 | /* Log a warning if the SecurityToken is not "fresh". Use the normal system |
| 61414 | * clock to do the comparison. */ |
| 61415 | UA_EventLoop *el = client->config.eventLoop; |
| 61416 | UA_DateTime wallClockNow = el->dateTime_now(el); |
| 61417 | if(wallClockNow - client->channel.securityToken.createdAt >= UA_DATETIME_SEC * 10 || |
| 61418 | wallClockNow - client->channel.securityToken.createdAt <= -UA_DATETIME_SEC * 10) |
| 61419 | UA_LOG_WARNING_CHANNEL(client->config.logging, &client->channel, "The \"CreatedAt\" " |
| 61420 | "timestamp of the received ChannelSecurityToken does not match " |
| 61421 | "with the local system clock"); |
| 61422 | |
| 61423 | /* The internal "monotonic" clock is used by the SecureChannel to validate |
| 61424 | * that the SecurityToken is still valid. The monotonic clock is independent |
| 61425 | * from the system clock getting changed or synchronized to a master clock |
| 61426 | * during runtime. */ |
| 61427 | client->channel.securityToken.createdAt = el->dateTime_nowMonotonic(el); |
| 61428 | |
| 61429 | /* Response.securityToken.revisedLifetime is UInt32, we need to cast it to |
| 61430 | * DateTime=Int64. After 75% of the lifetime the renewal takes place as |
| 61431 | * described in standard */ |
| 61432 | client->nextChannelRenewal = client->channel.securityToken.createdAt + |
| 61433 | (UA_DateTime) (response.securityToken.revisedLifetime * |
| 61434 | (UA_Double) UA_DATETIME_MSEC * 0.75); |
| 61435 | |
| 61436 | /* Compute the new local keys. The remote keys are updated when a message |
| 61437 | * with the new SecurityToken is received. */ |
| 61438 | retval = UA_SecureChannel_generateLocalKeys(channel: &client->channel); |
| 61439 | if(retval != UA_STATUSCODE_GOOD) { |
| 61440 | closeSecureChannel(client); |
| 61441 | return; |
| 61442 | } |
| 61443 | |
| 61444 | UA_Float lifetime = (UA_Float)response.securityToken.revisedLifetime / 1000; |
| 61445 | UA_Boolean renew = (client->channel.state == UA_SECURECHANNELSTATE_OPEN); |
| 61446 | if(renew) { |
| 61447 | UA_LOG_INFO_CHANNEL(client->config.logging, &client->channel, "SecureChannel " |
| 61448 | "renewed with a revised lifetime of %.2fs", lifetime); |
| 61449 | } else { |
| 61450 | UA_LOG_INFO_CHANNEL(client->config.logging, &client->channel, |
| 61451 | "SecureChannel opened with SecurityPolicy %.*s " |
| 61452 | "and a revised lifetime of %.2fs", |
| 61453 | (int)client->channel.securityPolicy->policyUri.length, |
| 61454 | client->channel.securityPolicy->policyUri.data, lifetime); |
| 61455 | } |
| 61456 | |
| 61457 | client->channel.state = UA_SECURECHANNELSTATE_OPEN; |
| 61458 | } |
| 61459 | |
| 61460 | /* OPN messges to renew the channel are sent asynchronous */ |
| 61461 | static void |
| 61462 | sendOPNAsync(UA_Client *client, UA_Boolean renew) { |
| 61463 | if(!UA_SecureChannel_isConnected(channel: &client->channel)) { |
| 61464 | client->connectStatus = UA_STATUSCODE_BADINTERNALERROR; |
| 61465 | return; |
| 61466 | } |
| 61467 | |
| 61468 | client->connectStatus = |
| 61469 | UA_SecureChannel_generateLocalNonce(channel: &client->channel); |
| 61470 | if(client->connectStatus != UA_STATUSCODE_GOOD) |
| 61471 | return; |
| 61472 | |
| 61473 | /* Prepare the OpenSecureChannelRequest */ |
| 61474 | UA_OpenSecureChannelRequest opnSecRq; |
| 61475 | UA_OpenSecureChannelRequest_init(p: &opnSecRq); |
| 61476 | opnSecRq.requestHeader.timestamp = UA_DateTime_now(); |
| 61477 | opnSecRq.requestHeader.authenticationToken = client->authenticationToken; |
| 61478 | opnSecRq.securityMode = client->channel.securityMode; |
| 61479 | opnSecRq.clientNonce = client->channel.localNonce; |
| 61480 | opnSecRq.requestedLifetime = client->config.secureChannelLifeTime; |
| 61481 | if(renew) { |
| 61482 | opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_RENEW; |
| 61483 | UA_LOG_DEBUG_CHANNEL(client->config.logging, &client->channel, |
| 61484 | "Requesting to renew the SecureChannel"); |
| 61485 | } else { |
| 61486 | opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE; |
| 61487 | UA_LOG_DEBUG_CHANNEL(client->config.logging, &client->channel, |
| 61488 | "Requesting to open a SecureChannel"); |
| 61489 | } |
| 61490 | |
| 61491 | /* Prepare the entry for the linked list */ |
| 61492 | UA_UInt32 requestId = ++client->requestId; |
| 61493 | |
| 61494 | /* Send the OPN message */ |
| 61495 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 61496 | msg: "Requesting to open a SecureChannel"); |
| 61497 | client->connectStatus = |
| 61498 | UA_SecureChannel_sendAsymmetricOPNMessage(channel: &client->channel, requestId, content: &opnSecRq, |
| 61499 | contentType: &UA_TYPES[UA_TYPES_OPENSECURECHANNELREQUEST]); |
| 61500 | if(client->connectStatus != UA_STATUSCODE_GOOD) { |
| 61501 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 61502 | msg: "Sending OPN message failed with error %s", |
| 61503 | UA_StatusCode_name(code: client->connectStatus)); |
| 61504 | closeSecureChannel(client); |
| 61505 | return; |
| 61506 | } |
| 61507 | |
| 61508 | /* Update the state */ |
| 61509 | client->channel.renewState = UA_SECURECHANNELRENEWSTATE_SENT; |
| 61510 | if(client->channel.state < UA_SECURECHANNELSTATE_OPN_SENT) |
| 61511 | client->channel.state = UA_SECURECHANNELSTATE_OPN_SENT; |
| 61512 | |
| 61513 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 61514 | msg: "OPN message sent"); |
| 61515 | } |
| 61516 | |
| 61517 | UA_StatusCode |
| 61518 | __Client_renewSecureChannel(UA_Client *client) { |
| 61519 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 61520 | |
| 61521 | /* Check if OPN has been sent or the SecureChannel is still valid */ |
| 61522 | if(client->channel.state != UA_SECURECHANNELSTATE_OPEN || |
| 61523 | client->channel.renewState == UA_SECURECHANNELRENEWSTATE_SENT || |
| 61524 | client->nextChannelRenewal > UA_DateTime_nowMonotonic()) |
| 61525 | return UA_STATUSCODE_GOODCALLAGAIN; |
| 61526 | |
| 61527 | sendOPNAsync(client, true); |
| 61528 | |
| 61529 | return client->connectStatus; |
| 61530 | } |
| 61531 | |
| 61532 | UA_StatusCode |
| 61533 | UA_Client_renewSecureChannel(UA_Client *client) { |
| 61534 | lockClient(client); |
| 61535 | UA_StatusCode res = __Client_renewSecureChannel(client); |
| 61536 | unlockClient(client); |
| 61537 | return res; |
| 61538 | } |
| 61539 | |
| 61540 | static void |
| 61541 | responseActivateSession(UA_Client *client, void *userdata, |
| 61542 | UA_UInt32 requestId, void *response) { |
| 61543 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 61544 | |
| 61545 | UA_ActivateSessionResponse *ar = (UA_ActivateSessionResponse*)response; |
| 61546 | if(ar->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 61547 | /* Activating the Session failed */ |
| 61548 | cleanupSession(client); |
| 61549 | |
| 61550 | /* Configuration option to not create a new Session */ |
| 61551 | if(client->config.noNewSession) { |
| 61552 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61553 | msg: "Session cannot be activated with StatusCode %s. " |
| 61554 | "The client is configured not to create a new Session.", |
| 61555 | UA_StatusCode_name(code: ar->responseHeader.serviceResult)); |
| 61556 | client->connectStatus = ar->responseHeader.serviceResult; |
| 61557 | closeSecureChannel(client); |
| 61558 | return; |
| 61559 | } |
| 61560 | |
| 61561 | /* The Session is no longer usable. Create a brand new one. */ |
| 61562 | if(ar->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONIDINVALID || |
| 61563 | ar->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONCLOSED) { |
| 61564 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61565 | msg: "Session to be activated no longer exists. Create a new Session."); |
| 61566 | client->connectStatus = createSessionAsync(client); |
| 61567 | return; |
| 61568 | } |
| 61569 | |
| 61570 | /* Something else is wrong. Maybe the credentials no longer work. Give up. */ |
| 61571 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61572 | msg: "Session cannot be activated with StatusCode %s. " |
| 61573 | "The client cannot recover from this, closing the connection.", |
| 61574 | UA_StatusCode_name(code: ar->responseHeader.serviceResult)); |
| 61575 | client->connectStatus = ar->responseHeader.serviceResult; |
| 61576 | closeSecureChannel(client); |
| 61577 | return; |
| 61578 | } |
| 61579 | |
| 61580 | /* Replace the nonce */ |
| 61581 | UA_ByteString_clear(p: &client->serverSessionNonce); |
| 61582 | client->serverSessionNonce = ar->serverNonce; |
| 61583 | UA_ByteString_init(p: &ar->serverNonce); |
| 61584 | |
| 61585 | client->sessionState = UA_SESSIONSTATE_ACTIVATED; |
| 61586 | notifyClientState(client); |
| 61587 | |
| 61588 | /* Immediately check if publish requests are outstanding - for example when |
| 61589 | * an existing Session has been reattached / activated. */ |
| 61590 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 61591 | __Client_Subscriptions_backgroundPublish(client); |
| 61592 | #endif |
| 61593 | } |
| 61594 | |
| 61595 | static UA_StatusCode |
| 61596 | activateSessionAsync(UA_Client *client) { |
| 61597 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 61598 | |
| 61599 | if(client->sessionState != UA_SESSIONSTATE_CREATED && |
| 61600 | client->sessionState != UA_SESSIONSTATE_ACTIVATED) { |
| 61601 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61602 | msg: "Can not activate session, session neither created nor activated. " |
| 61603 | "Actual state: '%u'", client->sessionState); |
| 61604 | return UA_STATUSCODE_BADSESSIONCLOSED; |
| 61605 | } |
| 61606 | |
| 61607 | const UA_UserTokenPolicy *utp = findUserTokenPolicy(client, endpoint: &client->endpoint); |
| 61608 | if(!utp) { |
| 61609 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_NETWORK, |
| 61610 | msg: "Could not find a matching UserTokenPolicy in the endpoint"); |
| 61611 | return UA_STATUSCODE_BADINTERNALERROR; |
| 61612 | } |
| 61613 | |
| 61614 | /* Initialize the request */ |
| 61615 | UA_ActivateSessionRequest request; |
| 61616 | UA_ActivateSessionRequest_init(p: &request); |
| 61617 | |
| 61618 | /* Set the requested LocaleIds */ |
| 61619 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 61620 | if(client->config.sessionLocaleIdsSize && client->config.sessionLocaleIds) { |
| 61621 | retval = UA_Array_copy(src: client->config.sessionLocaleIds, |
| 61622 | size: client->config.sessionLocaleIdsSize, |
| 61623 | dst: (void **)&request.localeIds, type: &UA_TYPES[UA_TYPES_LOCALEID]); |
| 61624 | if(retval != UA_STATUSCODE_GOOD) |
| 61625 | return retval; |
| 61626 | request.localeIdsSize = client->config.sessionLocaleIdsSize; |
| 61627 | } |
| 61628 | |
| 61629 | /* Set the User Identity Token. If not defined use an anonymous token. Use |
| 61630 | * the PolicyId from the UserTokenPolicy. All token types have the PolicyId |
| 61631 | * string as the first element. */ |
| 61632 | UA_AnonymousIdentityToken anonToken; |
| 61633 | retval = UA_ExtensionObject_copy(src: &client->config.userIdentityToken, |
| 61634 | dst: &request.userIdentityToken); |
| 61635 | if(request.userIdentityToken.encoding != UA_EXTENSIONOBJECT_ENCODED_NOBODY) { |
| 61636 | UA_String *policyId = (UA_String*)request.userIdentityToken.content.decoded.data; |
| 61637 | UA_String_clear(p: policyId); |
| 61638 | retval = UA_String_copy(src: &utp->policyId, dst: policyId); |
| 61639 | } else { |
| 61640 | UA_AnonymousIdentityToken_init(p: &anonToken); |
| 61641 | UA_ExtensionObject_setValueNoDelete(eo: &request.userIdentityToken, p: &anonToken, |
| 61642 | type: &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]); |
| 61643 | anonToken.policyId = utp->policyId; |
| 61644 | } |
| 61645 | if(retval != UA_STATUSCODE_GOOD) |
| 61646 | return retval; |
| 61647 | |
| 61648 | #ifdef UA_ENABLE_ENCRYPTION |
| 61649 | UA_SecurityPolicy *utsp = NULL; |
| 61650 | UA_SecureChannel *channel = &client->channel; |
| 61651 | |
| 61652 | if(request.userIdentityToken.content.decoded.type == |
| 61653 | &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) |
| 61654 | goto utp_done; |
| 61655 | |
| 61656 | /* Does the UserTokenPolicy have encryption? If not specifically defined in |
| 61657 | * the UserTokenPolicy, then the SecurityPolicy of the underlying endpoint |
| 61658 | * (SecureChannel) is used. */ |
| 61659 | UA_String tokenSecurityPolicyUri = (utp->securityPolicyUri.length > 0) ? |
| 61660 | utp->securityPolicyUri : client->endpoint.securityPolicyUri; |
| 61661 | const UA_String none = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None"); |
| 61662 | if(UA_String_equal(p1: &none, p2: &tokenSecurityPolicyUri)) { |
| 61663 | if(UA_String_equal(p1: &none, p2: &client->channel.securityPolicy->policyUri)) { |
| 61664 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61665 | msg: "!!! Warning !!! AuthenticationToken is transmitted " |
| 61666 | "without encryption"); |
| 61667 | } |
| 61668 | goto utp_done; |
| 61669 | } |
| 61670 | |
| 61671 | /* Get the SecurityPolicy for authentication */ |
| 61672 | utsp = getAuthSecurityPolicy(client, policyUri: tokenSecurityPolicyUri); |
| 61673 | if(!utsp) { |
| 61674 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61675 | msg: "UserTokenPolicy %.*s not available for authentication", |
| 61676 | (int)tokenSecurityPolicyUri.length, tokenSecurityPolicyUri.data); |
| 61677 | retval = UA_STATUSCODE_BADSECURITYPOLICYREJECTED; |
| 61678 | goto utp_done; |
| 61679 | } |
| 61680 | |
| 61681 | /* Encrypt the UserIdentityToken */ |
| 61682 | retval = encryptUserIdentityToken(client, utsp, userIdentityToken: &request.userIdentityToken); |
| 61683 | |
| 61684 | /* Create the UserTokenSignature if this is possible for the token. |
| 61685 | * The certificate is already loaded into the utsp. */ |
| 61686 | if(utp->tokenType == UA_USERTOKENTYPE_CERTIFICATE) |
| 61687 | retval |= signUserTokenSignature(client, utsp, request: &request); |
| 61688 | |
| 61689 | utp_done: |
| 61690 | /* Create the client signature with the SecurityPolicy of the SecurteChannel */ |
| 61691 | if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 61692 | channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 61693 | retval |= signClientSignature(client, request: &request); |
| 61694 | #endif |
| 61695 | |
| 61696 | /* Send the request */ |
| 61697 | if(UA_LIKELY(retval == UA_STATUSCODE_GOOD)) |
| 61698 | retval = __Client_AsyncService(client, request: &request, |
| 61699 | requestType: &UA_TYPES[UA_TYPES_ACTIVATESESSIONREQUEST], |
| 61700 | callback: (UA_ClientAsyncServiceCallback)responseActivateSession, |
| 61701 | responseType: &UA_TYPES[UA_TYPES_ACTIVATESESSIONRESPONSE], |
| 61702 | NULL, NULL); |
| 61703 | |
| 61704 | /* On success, advance the session state */ |
| 61705 | if(retval == UA_STATUSCODE_GOOD) |
| 61706 | client->sessionState = UA_SESSIONSTATE_ACTIVATE_REQUESTED; |
| 61707 | else |
| 61708 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61709 | msg: "ActivateSession failed when sending the request with error code %s", |
| 61710 | UA_StatusCode_name(code: retval)); |
| 61711 | |
| 61712 | /* Clean up */ |
| 61713 | UA_ActivateSessionRequest_clear(p: &request); |
| 61714 | return retval; |
| 61715 | } |
| 61716 | |
| 61717 | static const UA_String binaryTransport = |
| 61718 | UA_STRING_STATIC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary"); |
| 61719 | |
| 61720 | /* Find a matching endpoint -- the UserTokenPolicy is matched later */ |
| 61721 | static UA_Boolean |
| 61722 | matchEndpoint(UA_Client *client, const UA_EndpointDescription *endpoint, unsigned i) { |
| 61723 | /* Matching ApplicationUri if defined */ |
| 61724 | if(client->config.applicationUri.length > 0 && |
| 61725 | !UA_String_equal(p1: &client->config.applicationUri, |
| 61726 | p2: &endpoint->server.applicationUri)) { |
| 61727 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61728 | msg: "Rejecting endpoint %u: application uri not match", i); |
| 61729 | return false; |
| 61730 | } |
| 61731 | |
| 61732 | /* Look out for binary transport endpoints. |
| 61733 | * Note: Siemens returns empty ProfileUrl, we will accept it as binary. */ |
| 61734 | if(endpoint->transportProfileUri.length != 0 && |
| 61735 | !UA_String_equal(p1: &endpoint->transportProfileUri, p2: &binaryTransport)) { |
| 61736 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61737 | msg: "Rejecting endpoint %u: transport profile does not match", i); |
| 61738 | return false; |
| 61739 | } |
| 61740 | |
| 61741 | /* Valid SecurityMode? */ |
| 61742 | if(endpoint->securityMode < 1 || endpoint->securityMode > 3) { |
| 61743 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61744 | msg: "Rejecting endpoint %u: invalid security mode", i); |
| 61745 | return false; |
| 61746 | } |
| 61747 | |
| 61748 | /* Selected SecurityMode? */ |
| 61749 | if(client->config.securityMode > 0 && |
| 61750 | client->config.securityMode != endpoint->securityMode) { |
| 61751 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61752 | msg: "Rejecting endpoint %u: security mode does not match", i); |
| 61753 | return false; |
| 61754 | } |
| 61755 | |
| 61756 | /* Matching SecurityPolicy? */ |
| 61757 | if(client->config.securityPolicyUri.length > 0 && |
| 61758 | !UA_String_equal(p1: &client->config.securityPolicyUri, p2: &endpoint->securityPolicyUri)) { |
| 61759 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61760 | msg: "Rejecting endpoint %u: security policy does not match the configuration", i); |
| 61761 | return false; |
| 61762 | } |
| 61763 | |
| 61764 | /* SecurityPolicy available? */ |
| 61765 | if(!getSecurityPolicy(client, policyUri: endpoint->securityPolicyUri)) { |
| 61766 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61767 | msg: "Rejecting endpoint %u: security policy not available", i); |
| 61768 | return false; |
| 61769 | } |
| 61770 | |
| 61771 | return true; |
| 61772 | } |
| 61773 | |
| 61774 | /* Match the policy with the configured user token */ |
| 61775 | static UA_Boolean |
| 61776 | matchUserToken(UA_Client *client, |
| 61777 | const UA_UserTokenPolicy *tokenPolicy) { |
| 61778 | const UA_DataType *tokenType = |
| 61779 | client->config.userIdentityToken.content.decoded.type; |
| 61780 | |
| 61781 | if(tokenPolicy->tokenType == UA_USERTOKENTYPE_ANONYMOUS && |
| 61782 | (tokenType == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN] || !tokenType)) |
| 61783 | return true; |
| 61784 | |
| 61785 | if(tokenPolicy->tokenType == UA_USERTOKENTYPE_USERNAME && |
| 61786 | tokenType == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) |
| 61787 | return true; |
| 61788 | |
| 61789 | if(tokenPolicy->tokenType == UA_USERTOKENTYPE_CERTIFICATE && |
| 61790 | tokenType == &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) |
| 61791 | return true; |
| 61792 | |
| 61793 | if(tokenPolicy->tokenType == UA_USERTOKENTYPE_ISSUEDTOKEN && |
| 61794 | tokenType == &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN]) |
| 61795 | return true; |
| 61796 | |
| 61797 | return false; |
| 61798 | } |
| 61799 | |
| 61800 | /* Returns a matching UserTokenPolicy from the EndpointDescription. If a |
| 61801 | * UserTokenPolicy is configured in the client config, then we need an exact |
| 61802 | * match. */ |
| 61803 | static UA_UserTokenPolicy * |
| 61804 | findUserTokenPolicy(UA_Client *client, UA_EndpointDescription *endpoint) { |
| 61805 | /* Was a UserTokenPolicy configured? Then we need an exact match. */ |
| 61806 | UA_UserTokenPolicy *requiredTokenPolicy = NULL; |
| 61807 | UA_UserTokenPolicy tmp; |
| 61808 | UA_UserTokenPolicy_init(p: &tmp); |
| 61809 | if(!UA_equal(p1: &tmp, p2: &client->config.userTokenPolicy, type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY])) |
| 61810 | requiredTokenPolicy = &client->config.userTokenPolicy; |
| 61811 | |
| 61812 | for(size_t j = 0; j < endpoint->userIdentityTokensSize; ++j) { |
| 61813 | /* Is the SecurityPolicy available? */ |
| 61814 | UA_UserTokenPolicy *tokenPolicy = &endpoint->userIdentityTokens[j]; |
| 61815 | |
| 61816 | UA_String tokenPolicyUri = tokenPolicy->securityPolicyUri; |
| 61817 | if(UA_String_isEmpty(s: &tokenPolicyUri)) |
| 61818 | tokenPolicyUri = endpoint->securityPolicyUri; |
| 61819 | |
| 61820 | /* Ignore missing auth security policy for anonymous tokens */ |
| 61821 | if(client->config.userIdentityToken.content.decoded.type && |
| 61822 | client->config.userIdentityToken.content.decoded.type != |
| 61823 | &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) { |
| 61824 | const UA_String none = UA_STRING_STATIC("http://opcfoundation.org/UA/SecurityPolicy#None"); |
| 61825 | /* activateSessionAsync() handles the None case separately without accessing authSecurityPolicies */ |
| 61826 | if(!UA_String_equal(p1: &none, p2: &tokenPolicyUri) && !getAuthSecurityPolicy(client, policyUri: tokenPolicyUri)) |
| 61827 | continue; |
| 61828 | } |
| 61829 | |
| 61830 | /* Required SecurityPolicyUri in the configuration? */ |
| 61831 | if(!UA_String_isEmpty(s: &client->config.authSecurityPolicyUri) && |
| 61832 | !UA_String_equal(p1: &client->config.authSecurityPolicyUri, |
| 61833 | p2: &tokenPolicyUri)) |
| 61834 | continue; |
| 61835 | |
| 61836 | /* Match (entire) UserTokenPolicy if defined in the configuration? */ |
| 61837 | if(requiredTokenPolicy && |
| 61838 | !UA_equal(p1: requiredTokenPolicy, p2: tokenPolicy, type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY])) |
| 61839 | continue; |
| 61840 | |
| 61841 | /* Match with the configured UserToken */ |
| 61842 | if(!matchUserToken(client, tokenPolicy)) |
| 61843 | continue; |
| 61844 | |
| 61845 | /* Found a match? */ |
| 61846 | return tokenPolicy; |
| 61847 | } |
| 61848 | |
| 61849 | return NULL; |
| 61850 | } |
| 61851 | |
| 61852 | /* Combination of UA_Client_getEndpointsInternal and getEndpoints */ |
| 61853 | static void |
| 61854 | responseGetEndpoints(UA_Client *client, void *userdata, |
| 61855 | UA_UInt32 requestId, void *response) { |
| 61856 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 61857 | |
| 61858 | client->endpointsHandshake = false; |
| 61859 | |
| 61860 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61861 | msg: "Received GetEndpointsResponse"); |
| 61862 | |
| 61863 | UA_GetEndpointsResponse *resp = (UA_GetEndpointsResponse*)response; |
| 61864 | |
| 61865 | /* GetEndpoints not possible. Fail the connection */ |
| 61866 | if(resp->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 61867 | /* Fail the connection attempt if the SecureChannel is still connected. |
| 61868 | * If the SecureChannel is (intentionally or unintentionally) closed, |
| 61869 | * the connectStatus should come from there. */ |
| 61870 | if(UA_SecureChannel_isConnected(channel: &client->channel)) { |
| 61871 | client->connectStatus = resp->responseHeader.serviceResult; |
| 61872 | closeSecureChannel(client); |
| 61873 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61874 | msg: "GetEndpointRequest failed with error code %s", |
| 61875 | UA_StatusCode_name(code: client->connectStatus)); |
| 61876 | } |
| 61877 | |
| 61878 | UA_GetEndpointsResponse_clear(p: resp); |
| 61879 | return; |
| 61880 | } |
| 61881 | |
| 61882 | /* Warn if the Endpoints look incomplete / don't match the EndpointUrl */ |
| 61883 | Client_warnEndpointsResult(client, response: resp, endpointUrl: &client->discoveryUrl); |
| 61884 | |
| 61885 | const size_t notFound = (size_t)-1; |
| 61886 | size_t bestEndpointIndex = notFound; |
| 61887 | UA_Byte bestEndpointLevel = 0; |
| 61888 | |
| 61889 | /* Find a matching combination of Endpoint and UserTokenPolicy */ |
| 61890 | for(size_t i = 0; i < resp->endpointsSize; ++i) { |
| 61891 | UA_EndpointDescription* endpoint = &resp->endpoints[i]; |
| 61892 | |
| 61893 | /* Do we already have a better candidate? */ |
| 61894 | if(endpoint->securityLevel < bestEndpointLevel) |
| 61895 | continue; |
| 61896 | |
| 61897 | /* Does the endpoint match the client configuration? */ |
| 61898 | if(!matchEndpoint(client, endpoint, i: (unsigned)i)) |
| 61899 | continue; |
| 61900 | |
| 61901 | /* Do we want a session? If yes, then the endpoint needs to have a |
| 61902 | * UserTokenPolicy that matches the configuration. */ |
| 61903 | if(!client->config.noSession && !findUserTokenPolicy(client, endpoint)) { |
| 61904 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61905 | msg: "Rejecting endpoint %lu: No matching UserTokenPolicy", |
| 61906 | (long unsigned)i); |
| 61907 | continue; |
| 61908 | } |
| 61909 | |
| 61910 | /* Best endpoint so far */ |
| 61911 | bestEndpointLevel = endpoint->securityLevel; |
| 61912 | bestEndpointIndex = i; |
| 61913 | } |
| 61914 | |
| 61915 | /* No matching endpoint found */ |
| 61916 | if(bestEndpointIndex == notFound) { |
| 61917 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61918 | msg: "No suitable endpoint found"); |
| 61919 | client->connectStatus = UA_STATUSCODE_BADIDENTITYTOKENREJECTED; |
| 61920 | closeSecureChannel(client); |
| 61921 | return; |
| 61922 | } |
| 61923 | |
| 61924 | /* Store the endpoint description in the client. It contains the |
| 61925 | * ApplicationDescription and the UserTokenPolicies. We continue to look up |
| 61926 | * the matching UserTokenPolicy from there. */ |
| 61927 | UA_EndpointDescription_clear(p: &client->endpoint); |
| 61928 | client->endpoint = resp->endpoints[bestEndpointIndex]; |
| 61929 | UA_EndpointDescription_init(p: &resp->endpoints[bestEndpointIndex]); |
| 61930 | |
| 61931 | #if UA_LOGLEVEL <= 300 |
| 61932 | const char *securityModeNames[3] = {"None", "Sign", "SignAndEncrypt"}; |
| 61933 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61934 | msg: "Selected endpoint with EndpointUrl %.*s, SecurityMode " |
| 61935 | "%s and SecurityPolicy %.*s", |
| 61936 | (int)client->endpoint.endpointUrl.length, |
| 61937 | client->endpoint.endpointUrl.data, |
| 61938 | securityModeNames[client->endpoint.securityMode - 1], |
| 61939 | (int)client->endpoint.securityPolicyUri.length, |
| 61940 | client->endpoint.securityPolicyUri.data); |
| 61941 | #endif |
| 61942 | |
| 61943 | /* A different SecurityMode or SecurityPolicy is defined by the Endpoint. |
| 61944 | * Close the SecureChannel and reconnect. */ |
| 61945 | if(client->endpoint.securityMode != client->channel.securityMode || |
| 61946 | !UA_String_equal(p1: &client->endpoint.securityPolicyUri, |
| 61947 | p2: &client->channel.securityPolicy->policyUri)) { |
| 61948 | closeSecureChannel(client); |
| 61949 | return; |
| 61950 | } |
| 61951 | |
| 61952 | /* We were using a distinct discovery URL and we are switching away from it. |
| 61953 | * Close the SecureChannel to reopen with the EndpointUrl. If an endpoint |
| 61954 | * was selected, then we use the endpointUrl for the HEL message. */ |
| 61955 | if(client->discoveryUrl.length > 0 && |
| 61956 | !UA_String_equal(p1: &client->discoveryUrl, p2: &client->endpoint.endpointUrl)) { |
| 61957 | closeSecureChannel(client); |
| 61958 | return; |
| 61959 | } |
| 61960 | |
| 61961 | /* Nothing to do. We have selected an endpoint that we can use to open a |
| 61962 | * Session on the current SecureChannel. */ |
| 61963 | } |
| 61964 | |
| 61965 | static UA_StatusCode |
| 61966 | requestGetEndpoints(UA_Client *client) { |
| 61967 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 61968 | |
| 61969 | UA_GetEndpointsRequest request; |
| 61970 | UA_GetEndpointsRequest_init(p: &request); |
| 61971 | request.endpointUrl = getEndpointUrl(client); |
| 61972 | |
| 61973 | UA_StatusCode retval = |
| 61974 | __Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST], |
| 61975 | callback: (UA_ClientAsyncServiceCallback) responseGetEndpoints, |
| 61976 | responseType: &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE], NULL, NULL); |
| 61977 | if(retval != UA_STATUSCODE_GOOD) { |
| 61978 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61979 | msg: "RequestGetEndpoints failed when sending the request with error code %s", |
| 61980 | UA_StatusCode_name(code: retval)); |
| 61981 | return retval; |
| 61982 | } |
| 61983 | |
| 61984 | client->endpointsHandshake = true; |
| 61985 | return UA_STATUSCODE_GOOD; |
| 61986 | } |
| 61987 | |
| 61988 | static void |
| 61989 | responseFindServers(UA_Client *client, void *userdata, |
| 61990 | UA_UInt32 requestId, void *response) { |
| 61991 | client->findServersHandshake = false; |
| 61992 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 61993 | msg: "Received FindServersResponse"); |
| 61994 | |
| 61995 | /* Error handling. Log the error but continue to connect with the current |
| 61996 | * EndpointURL. */ |
| 61997 | UA_FindServersResponse *fsr = (UA_FindServersResponse*)response; |
| 61998 | if(fsr->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 61999 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62000 | msg: "FindServers failed with error code %s. Continue with the " |
| 62001 | "EndpointURL %.*s.", |
| 62002 | UA_StatusCode_name(code: fsr->responseHeader.serviceResult), |
| 62003 | (int)client->config.endpointUrl.length, |
| 62004 | client->config.endpointUrl.data); |
| 62005 | UA_String_clear(p: &client->discoveryUrl); |
| 62006 | UA_String_copy(src: &client->config.endpointUrl, dst: &client->discoveryUrl); |
| 62007 | return; |
| 62008 | } |
| 62009 | |
| 62010 | /* Check if one of the returned servers matches the EndpointURL already used */ |
| 62011 | for(size_t i = 0; i < fsr->serversSize; i++) { |
| 62012 | UA_ApplicationDescription *server = &fsr->servers[i]; |
| 62013 | |
| 62014 | /* Filter by the ApplicationURI if defined */ |
| 62015 | if(client->config.applicationUri.length > 0 && |
| 62016 | !UA_String_equal(p1: &client->config.applicationUri, p2: &server->applicationUri)) |
| 62017 | continue; |
| 62018 | |
| 62019 | for(size_t j = 0; j < server->discoveryUrlsSize; j++) { |
| 62020 | if(UA_String_equal(p1: &client->config.endpointUrl, p2: &server->discoveryUrls[j])) { |
| 62021 | UA_String_clear(p: &client->discoveryUrl); |
| 62022 | client->discoveryUrl = server->discoveryUrls[j]; |
| 62023 | UA_String_init(p: &server->discoveryUrls[j]); |
| 62024 | return; |
| 62025 | } |
| 62026 | } |
| 62027 | } |
| 62028 | |
| 62029 | /* The current EndpointURL is not usable. Pick the first "opc.tcp" DiscoveryUrl of a |
| 62030 | * returned server. */ |
| 62031 | for(size_t i = 0; i < fsr->serversSize; i++) { |
| 62032 | UA_ApplicationDescription *server = &fsr->servers[i]; |
| 62033 | if(server->applicationType != UA_APPLICATIONTYPE_SERVER && |
| 62034 | server->applicationType != UA_APPLICATIONTYPE_CLIENTANDSERVER && |
| 62035 | server->applicationType != UA_APPLICATIONTYPE_DISCOVERYSERVER) |
| 62036 | continue; |
| 62037 | |
| 62038 | /* Filter by the ApplicationURI if defined */ |
| 62039 | if(client->config.applicationUri.length > 0 && |
| 62040 | !UA_String_equal(p1: &client->config.applicationUri, p2: &server->applicationUri)) |
| 62041 | continue; |
| 62042 | |
| 62043 | for(size_t j = 0; j < server->discoveryUrlsSize; j++) { |
| 62044 | /* Try to parse the DiscoveryUrl. This weeds out http schemas (etc.) |
| 62045 | * and invalid DiscoveryUrls in general. */ |
| 62046 | UA_String hostname, path; |
| 62047 | UA_UInt16 port; |
| 62048 | UA_StatusCode res = |
| 62049 | UA_parseEndpointUrl(endpointUrl: &server->discoveryUrls[j], outHostname: &hostname, outPort: &port, outPath: &path); |
| 62050 | if(res != UA_STATUSCODE_GOOD) |
| 62051 | continue; |
| 62052 | |
| 62053 | /* Use this DiscoveryUrl in the client */ |
| 62054 | UA_String_clear(p: &client->discoveryUrl); |
| 62055 | client->discoveryUrl = server->discoveryUrls[j]; |
| 62056 | UA_String_init(p: &server->discoveryUrls[j]); |
| 62057 | |
| 62058 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62059 | msg: "Use the EndpointURL %.*s returned from FindServers and reconnect", |
| 62060 | (int)client->discoveryUrl.length, client->discoveryUrl.data); |
| 62061 | |
| 62062 | /* Close the SecureChannel to build it up new with the correct |
| 62063 | * EndpointURL in the HEL/ACK handshake. In closeSecureChannel the |
| 62064 | * received client->endpoint is reset also. */ |
| 62065 | closeSecureChannel(client); |
| 62066 | return; |
| 62067 | } |
| 62068 | } |
| 62069 | |
| 62070 | /* Could not find a suitable server. Try to continue with the |
| 62071 | * original EndpointURL. */ |
| 62072 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62073 | msg: "FindServers did not returned a suitable DiscoveryURL. " |
| 62074 | "Continue with the EndpointURL %.*s.", |
| 62075 | (int)client->config.endpointUrl.length, |
| 62076 | client->config.endpointUrl.data); |
| 62077 | UA_String_clear(p: &client->discoveryUrl); |
| 62078 | UA_String_copy(src: &client->config.endpointUrl, dst: &client->discoveryUrl); |
| 62079 | } |
| 62080 | |
| 62081 | static UA_StatusCode |
| 62082 | requestFindServers(UA_Client *client) { |
| 62083 | UA_FindServersRequest request; |
| 62084 | UA_FindServersRequest_init(p: &request); |
| 62085 | request.requestHeader.timestamp = UA_DateTime_now(); |
| 62086 | request.requestHeader.timeoutHint = 10000; |
| 62087 | request.endpointUrl = client->config.endpointUrl; |
| 62088 | UA_StatusCode retval = |
| 62089 | __Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST], |
| 62090 | callback: (UA_ClientAsyncServiceCallback) responseFindServers, |
| 62091 | responseType: &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE], NULL, NULL); |
| 62092 | if(retval != UA_STATUSCODE_GOOD) { |
| 62093 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62094 | msg: "FindServers failed when sending the request with error code %s", |
| 62095 | UA_StatusCode_name(code: retval)); |
| 62096 | return retval; |
| 62097 | } |
| 62098 | |
| 62099 | client->findServersHandshake = true; |
| 62100 | return UA_STATUSCODE_GOOD; |
| 62101 | } |
| 62102 | |
| 62103 | static void |
| 62104 | createSessionCallback(UA_Client *client, void *userdata, |
| 62105 | UA_UInt32 requestId, void *response) { |
| 62106 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 62107 | |
| 62108 | UA_CreateSessionResponse *sessionResponse = (UA_CreateSessionResponse*)response; |
| 62109 | UA_StatusCode res = sessionResponse->responseHeader.serviceResult; |
| 62110 | if(res != UA_STATUSCODE_GOOD) |
| 62111 | goto cleanup; |
| 62112 | |
| 62113 | #ifdef UA_ENABLE_ENCRYPTION |
| 62114 | if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 62115 | client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 62116 | /* Verify the session response was created with the same certificate as |
| 62117 | * the SecureChannel */ |
| 62118 | if(!UA_ByteString_equal(p1: &sessionResponse->serverCertificate, |
| 62119 | p2: &client->channel.remoteCertificate)) { |
| 62120 | res = UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 62121 | goto cleanup; |
| 62122 | } |
| 62123 | |
| 62124 | /* Verify the client signature */ |
| 62125 | res = checkCreateSessionSignature(client, channel: &client->channel, response: sessionResponse); |
| 62126 | if(res != UA_STATUSCODE_GOOD) |
| 62127 | goto cleanup; |
| 62128 | } |
| 62129 | #endif |
| 62130 | |
| 62131 | /* Copy nonce and AuthenticationToken */ |
| 62132 | UA_ByteString_clear(p: &client->serverSessionNonce); |
| 62133 | UA_NodeId_clear(p: &client->authenticationToken); |
| 62134 | res |= UA_ByteString_copy(src: &sessionResponse->serverNonce, |
| 62135 | dst: &client->serverSessionNonce); |
| 62136 | res |= UA_NodeId_copy(src: &sessionResponse->authenticationToken, |
| 62137 | dst: &client->authenticationToken); |
| 62138 | if(res != UA_STATUSCODE_GOOD) |
| 62139 | goto cleanup; |
| 62140 | |
| 62141 | /* Activate the new Session */ |
| 62142 | client->sessionState = UA_SESSIONSTATE_CREATED; |
| 62143 | |
| 62144 | cleanup: |
| 62145 | client->connectStatus = res; |
| 62146 | if(client->connectStatus != UA_STATUSCODE_GOOD) |
| 62147 | client->sessionState = UA_SESSIONSTATE_CLOSED; |
| 62148 | } |
| 62149 | |
| 62150 | static UA_StatusCode |
| 62151 | createSessionAsync(UA_Client *client) { |
| 62152 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 62153 | |
| 62154 | /* Generate the local nonce for the session */ |
| 62155 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 62156 | if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 62157 | client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 62158 | if(client->clientSessionNonce.length != UA_SESSION_LOCALNONCELENGTH) { |
| 62159 | UA_ByteString_clear(p: &client->clientSessionNonce); |
| 62160 | res = UA_ByteString_allocBuffer(bs: &client->clientSessionNonce, |
| 62161 | UA_SESSION_LOCALNONCELENGTH); |
| 62162 | if(res != UA_STATUSCODE_GOOD) |
| 62163 | return res; |
| 62164 | } |
| 62165 | res = client->channel.securityPolicy->symmetricModule. |
| 62166 | generateNonce(client->channel.securityPolicy->policyContext, |
| 62167 | &client->clientSessionNonce); |
| 62168 | if(res != UA_STATUSCODE_GOOD) |
| 62169 | return res; |
| 62170 | } |
| 62171 | |
| 62172 | /* Prepare and send the request */ |
| 62173 | UA_CreateSessionRequest request; |
| 62174 | UA_CreateSessionRequest_init(p: &request); |
| 62175 | request.clientNonce = client->clientSessionNonce; |
| 62176 | request.requestedSessionTimeout = client->config.requestedSessionTimeout; |
| 62177 | request.maxResponseMessageSize = UA_INT32_MAX; |
| 62178 | request.endpointUrl = client->endpoint.endpointUrl; |
| 62179 | request.clientDescription = client->config.clientDescription; |
| 62180 | request.sessionName = client->config.sessionName; |
| 62181 | if(client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGN || |
| 62182 | client->channel.securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) { |
| 62183 | request.clientCertificate = client->channel.securityPolicy->localCertificate; |
| 62184 | } |
| 62185 | |
| 62186 | res = __Client_AsyncService(client, request: &request, |
| 62187 | requestType: &UA_TYPES[UA_TYPES_CREATESESSIONREQUEST], |
| 62188 | callback: (UA_ClientAsyncServiceCallback)createSessionCallback, |
| 62189 | responseType: &UA_TYPES[UA_TYPES_CREATESESSIONRESPONSE], NULL, NULL); |
| 62190 | |
| 62191 | if(res == UA_STATUSCODE_GOOD) |
| 62192 | client->sessionState = UA_SESSIONSTATE_CREATE_REQUESTED; |
| 62193 | else |
| 62194 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62195 | msg: "CreateSession failed when sending the request with " |
| 62196 | "error code %s", UA_StatusCode_name(code: res)); |
| 62197 | |
| 62198 | return res; |
| 62199 | } |
| 62200 | |
| 62201 | static UA_StatusCode |
| 62202 | initSecurityPolicy(UA_Client *client) { |
| 62203 | /* Find the SecurityPolicy */ |
| 62204 | UA_SecurityPolicy *sp = |
| 62205 | getSecurityPolicy(client, policyUri: client->endpoint.securityPolicyUri); |
| 62206 | |
| 62207 | /* Unknown SecurityPolicy -- we would never select such an endpoint */ |
| 62208 | if(!sp) |
| 62209 | return UA_STATUSCODE_BADINTERNALERROR; |
| 62210 | |
| 62211 | /* Already initialized -- check we are using the configured SecurityPolicy */ |
| 62212 | if(client->channel.securityPolicy) |
| 62213 | return (client->channel.securityPolicy == sp) ? |
| 62214 | UA_STATUSCODE_GOOD : UA_STATUSCODE_BADINTERNALERROR; |
| 62215 | |
| 62216 | /* Set the SecurityMode -- none if no endpoint is selected so far */ |
| 62217 | client->channel.securityMode = client->endpoint.securityMode; |
| 62218 | if(client->channel.securityMode == UA_MESSAGESECURITYMODE_INVALID) |
| 62219 | client->channel.securityMode = UA_MESSAGESECURITYMODE_NONE; |
| 62220 | |
| 62221 | /* Instantiate the SecurityPolicy context with the remote certificate */ |
| 62222 | return UA_SecureChannel_setSecurityPolicy(channel: &client->channel, securityPolicy: sp, |
| 62223 | remoteCertificate: &client->endpoint.serverCertificate); |
| 62224 | } |
| 62225 | |
| 62226 | static void |
| 62227 | connectActivity(UA_Client *client) { |
| 62228 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 62229 | UA_LOG_TRACE(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62230 | msg: "Client connect iterate"); |
| 62231 | |
| 62232 | /* Could not connect with an error that canot be recovered from */ |
| 62233 | if(client->connectStatus != UA_STATUSCODE_GOOD) |
| 62234 | return; |
| 62235 | |
| 62236 | /* Already connected */ |
| 62237 | if(client->sessionState == UA_SESSIONSTATE_ACTIVATED) |
| 62238 | return; |
| 62239 | |
| 62240 | /* Switch on the SecureChannel state */ |
| 62241 | switch(client->channel.state) { |
| 62242 | /* Nothing to do if the connection has not opened fully */ |
| 62243 | case UA_SECURECHANNELSTATE_CONNECTING: |
| 62244 | case UA_SECURECHANNELSTATE_REVERSE_CONNECTED: |
| 62245 | case UA_SECURECHANNELSTATE_CLOSING: |
| 62246 | case UA_SECURECHANNELSTATE_HEL_SENT: |
| 62247 | case UA_SECURECHANNELSTATE_OPN_SENT: |
| 62248 | return; |
| 62249 | |
| 62250 | /* Send HEL */ |
| 62251 | case UA_SECURECHANNELSTATE_CONNECTED: |
| 62252 | client->connectStatus = sendHELMessage(client); |
| 62253 | return; |
| 62254 | |
| 62255 | /* ACK receieved. Send OPN. */ |
| 62256 | case UA_SECURECHANNELSTATE_ACK_RECEIVED: |
| 62257 | sendOPNAsync(client, false); /* Send OPN */ |
| 62258 | return; |
| 62259 | |
| 62260 | /* The channel is open -> continue with the Session handling */ |
| 62261 | case UA_SECURECHANNELSTATE_OPEN: |
| 62262 | break; |
| 62263 | |
| 62264 | /* The connection is closed. Reset the SecureChannel and open a new TCP |
| 62265 | * connection */ |
| 62266 | case UA_SECURECHANNELSTATE_CLOSED: |
| 62267 | if(client->config.noReconnect) |
| 62268 | client->connectStatus = UA_STATUSCODE_BADNOTCONNECTED; |
| 62269 | else |
| 62270 | initConnect(client); /* Sets the connectStatus internally */ |
| 62271 | return; |
| 62272 | |
| 62273 | /* These states should never occur for the client */ |
| 62274 | default: |
| 62275 | client->connectStatus = UA_STATUSCODE_BADINTERNALERROR; |
| 62276 | return; |
| 62277 | } |
| 62278 | |
| 62279 | /* <-- The SecureChannel is open --> */ |
| 62280 | |
| 62281 | /* Ongoing handshake -> Waiting for a response */ |
| 62282 | if(client->endpointsHandshake || client->findServersHandshake) |
| 62283 | return; |
| 62284 | |
| 62285 | /* Call FindServers to see if we should reconnect with another EndpointUrl. |
| 62286 | * This needs to be done before GetEndpoints, as the set of returned |
| 62287 | * endpoints may depend on the EndpointUrl used during the initial HEL/ACK |
| 62288 | * handshake. */ |
| 62289 | if(client->discoveryUrl.length == 0) { |
| 62290 | client->connectStatus = requestFindServers(client); |
| 62291 | return; |
| 62292 | } |
| 62293 | |
| 62294 | /* GetEndpoints to identify the remote side and/or reset the SecureChannel |
| 62295 | * with encryption */ |
| 62296 | if(endpointUnconfigured(endpoint: &client->endpoint)) { |
| 62297 | client->connectStatus = requestGetEndpoints(client); |
| 62298 | return; |
| 62299 | } |
| 62300 | |
| 62301 | /* Have the final SecureChannel but no session */ |
| 62302 | if(client->config.noSession) |
| 62303 | return; |
| 62304 | |
| 62305 | /* Create and Activate the Session */ |
| 62306 | switch(client->sessionState) { |
| 62307 | /* Send a CreateSessionRequest */ |
| 62308 | case UA_SESSIONSTATE_CLOSED: |
| 62309 | client->connectStatus = createSessionAsync(client); |
| 62310 | return; |
| 62311 | |
| 62312 | /* Activate the Session */ |
| 62313 | case UA_SESSIONSTATE_CREATED: |
| 62314 | client->connectStatus = activateSessionAsync(client); |
| 62315 | return; |
| 62316 | |
| 62317 | case UA_SESSIONSTATE_CREATE_REQUESTED: |
| 62318 | case UA_SESSIONSTATE_ACTIVATE_REQUESTED: |
| 62319 | case UA_SESSIONSTATE_ACTIVATED: |
| 62320 | case UA_SESSIONSTATE_CLOSING: |
| 62321 | return; /* Nothing to do */ |
| 62322 | |
| 62323 | /* These states should never occur for the client */ |
| 62324 | default: |
| 62325 | client->connectStatus = UA_STATUSCODE_BADINTERNALERROR; |
| 62326 | break; |
| 62327 | } |
| 62328 | } |
| 62329 | |
| 62330 | static UA_StatusCode |
| 62331 | verifyClientSecureChannelHeader(void *application, UA_SecureChannel *channel, |
| 62332 | const UA_AsymmetricAlgorithmSecurityHeader *asymHeader) { |
| 62333 | UA_Client *client = (UA_Client*)application; |
| 62334 | const UA_SecurityPolicy *sp = channel->securityPolicy; |
| 62335 | UA_assert(sp != NULL); |
| 62336 | |
| 62337 | /* Check the SecurityPolicyUri */ |
| 62338 | if(asymHeader->securityPolicyUri.length > 0 && |
| 62339 | !UA_String_equal(p1: &sp->policyUri, p2: &asymHeader->securityPolicyUri)) { |
| 62340 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62341 | msg: "The server uses a different SecurityPolicy from the client"); |
| 62342 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 62343 | } |
| 62344 | |
| 62345 | /* Get the remote certificate. |
| 62346 | * Omit the remainder if an entire certificate chain was sent. */ |
| 62347 | UA_ByteString serverCert = getLeafCertificate(chain: asymHeader->senderCertificate); |
| 62348 | |
| 62349 | /* If encryption is enabled, then a server certificate is defined. |
| 62350 | * Otherwise the creation of the SecureChannel would have failed. */ |
| 62351 | UA_assert(channel->securityMode == UA_MESSAGESECURITYMODE_NONE || |
| 62352 | serverCert.length > 0); |
| 62353 | |
| 62354 | /* If a server certificate is sent in the asymHeader, check that the same |
| 62355 | * certificate was defined for the endpoint */ |
| 62356 | if(serverCert.length > 0 && |
| 62357 | !UA_String_equal(p1: &serverCert, p2: &client->endpoint.serverCertificate)) { |
| 62358 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62359 | msg: "The server certificate is different from the EndpointDescription"); |
| 62360 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 62361 | } |
| 62362 | |
| 62363 | /* Verify the certificate the server assumes on our end */ |
| 62364 | UA_StatusCode res = sp->asymmetricModule. |
| 62365 | compareCertificateThumbprint(sp, &asymHeader->receiverCertificateThumbprint); |
| 62366 | if(res != UA_STATUSCODE_GOOD) { |
| 62367 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62368 | msg: "The server does not use the client certificate " |
| 62369 | "used for the selected SecurityPolicy"); |
| 62370 | return res; |
| 62371 | } |
| 62372 | |
| 62373 | return UA_STATUSCODE_GOOD; |
| 62374 | } |
| 62375 | |
| 62376 | /* The local ApplicationURI has to match the certificates of the |
| 62377 | * SecurityPolicies */ |
| 62378 | static void |
| 62379 | verifyClientApplicationURI(const UA_Client *client) { |
| 62380 | #if defined(UA_ENABLE_ENCRYPTION) && (UA_LOGLEVEL <= 400) |
| 62381 | for(size_t i = 0; i < client->config.securityPoliciesSize; i++) { |
| 62382 | UA_SecurityPolicy *sp = &client->config.securityPolicies[i]; |
| 62383 | if(!sp->localCertificate.data) { |
| 62384 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62385 | msg: "skip verifying ApplicationURI for the SecurityPolicy %.*s", |
| 62386 | (int)sp->policyUri.length, sp->policyUri.data); |
| 62387 | continue; |
| 62388 | } |
| 62389 | |
| 62390 | UA_StatusCode retval = |
| 62391 | client->config.certificateVerification. |
| 62392 | verifyApplicationURI(&client->config.certificateVerification, |
| 62393 | &sp->localCertificate, |
| 62394 | &client->config.clientDescription.applicationUri); |
| 62395 | if(retval != UA_STATUSCODE_GOOD) { |
| 62396 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62397 | msg: "The configured ApplicationURI does not match the URI " |
| 62398 | "specified in the certificate for the SecurityPolicy %.*s", |
| 62399 | (int)sp->policyUri.length, sp->policyUri.data); |
| 62400 | } |
| 62401 | } |
| 62402 | #endif |
| 62403 | } |
| 62404 | |
| 62405 | static void |
| 62406 | delayedNetworkCallback(void *application, void *context); |
| 62407 | |
| 62408 | static void |
| 62409 | __Client_networkCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 62410 | void *application, void **connectionContext, |
| 62411 | UA_ConnectionState state, const UA_KeyValueMap *params, |
| 62412 | UA_ByteString msg) { |
| 62413 | /* Take the client lock */ |
| 62414 | UA_Client *client = (UA_Client*)application; |
| 62415 | lockClient(client); |
| 62416 | |
| 62417 | UA_LOG_TRACE(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, msg: "Client network callback"); |
| 62418 | |
| 62419 | /* A new connection with no context pointer attached */ |
| 62420 | if(!*connectionContext) { |
| 62421 | /* Inconsistent SecureChannel state. Has to be fresh for a new |
| 62422 | * connection. */ |
| 62423 | if(client->channel.state != UA_SECURECHANNELSTATE_CLOSED && |
| 62424 | client->channel.state != UA_SECURECHANNELSTATE_REVERSE_LISTENING) { |
| 62425 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62426 | msg: "Cannot open a connection, the SecureChannel is already used"); |
| 62427 | client->connectStatus = UA_STATUSCODE_BADINTERNALERROR; |
| 62428 | notifyClientState(client); |
| 62429 | unlockClient(client); |
| 62430 | return; |
| 62431 | } |
| 62432 | |
| 62433 | /* Initialize the client connection and attach to the EventLoop connection */ |
| 62434 | client->channel.connectionManager = cm; |
| 62435 | client->channel.connectionId = connectionId; |
| 62436 | *connectionContext = &client->channel; |
| 62437 | } |
| 62438 | |
| 62439 | /* The connection is closing in the EventLoop. This is the last callback |
| 62440 | * from that connection. Clean up the SecureChannel in the client. */ |
| 62441 | if(state == UA_CONNECTIONSTATE_CLOSING) { |
| 62442 | UA_LOG_INFO_CHANNEL(client->config.logging, &client->channel, |
| 62443 | "SecureChannel closed"); |
| 62444 | |
| 62445 | /* Set to closing (could be done already in UA_SecureChannel_shutdown). |
| 62446 | * This impacts the handling of cancelled requests below. */ |
| 62447 | UA_SecureChannelState oldState = client->channel.state; |
| 62448 | client->channel.state = UA_SECURECHANNELSTATE_CLOSING; |
| 62449 | |
| 62450 | /* Set the Session to CREATED if it was ACTIVATED */ |
| 62451 | if(client->sessionState == UA_SESSIONSTATE_ACTIVATED) |
| 62452 | client->sessionState = UA_SESSIONSTATE_CREATED; |
| 62453 | |
| 62454 | /* Delete outstanding async services - the RequestId is no longer valid. Do |
| 62455 | * this after setting the Session state. Otherwise we send out new Publish |
| 62456 | * Requests immediately. */ |
| 62457 | __Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSECURECHANNELCLOSED); |
| 62458 | |
| 62459 | /* Clean up the channel and set the status to CLOSED */ |
| 62460 | UA_SecureChannel_clear(channel: &client->channel); |
| 62461 | |
| 62462 | /* The connection closed before it actually opened. Since we are |
| 62463 | * connecting asynchronously, this happens when the TCP connection |
| 62464 | * fails. Try to fall back on the initial EndpointUrl. */ |
| 62465 | if(oldState == UA_SECURECHANNELSTATE_CONNECTING && |
| 62466 | client->connectStatus == UA_STATUSCODE_GOOD) |
| 62467 | client->connectStatus = fallbackEndpointUrl(client); |
| 62468 | |
| 62469 | /* Try to reconnect */ |
| 62470 | goto continue_connect; |
| 62471 | } |
| 62472 | |
| 62473 | /* Update the SecureChannel state */ |
| 62474 | if(UA_LIKELY(state == UA_CONNECTIONSTATE_ESTABLISHED)) { |
| 62475 | /* The connection is now open on the TCP level. Set the SecureChannel |
| 62476 | * state to reflect this. Otherwise later consistency checks for the |
| 62477 | * received messages fail. */ |
| 62478 | if(client->channel.state < UA_SECURECHANNELSTATE_CONNECTED) |
| 62479 | client->channel.state = UA_SECURECHANNELSTATE_CONNECTED; |
| 62480 | } else /* state == UA_CONNECTIONSTATE_OPENING */ { |
| 62481 | /* The connection was opened on our end only. Waiting for the TCP handshake |
| 62482 | * to complete. */ |
| 62483 | client->channel.state = UA_SECURECHANNELSTATE_CONNECTING; |
| 62484 | } |
| 62485 | |
| 62486 | /* Received a message. Process the message with the SecureChannel. */ |
| 62487 | UA_StatusCode res = UA_SecureChannel_loadBuffer(channel: &client->channel, buffer: msg); |
| 62488 | while(UA_LIKELY(res == UA_STATUSCODE_GOOD)) { |
| 62489 | UA_MessageType messageType; |
| 62490 | UA_UInt32 requestId = 0; |
| 62491 | UA_ByteString payload = UA_BYTESTRING_NULL; |
| 62492 | UA_Boolean copied = false; |
| 62493 | res = UA_SecureChannel_getCompleteMessage(channel: &client->channel, messageType: &messageType, requestId: &requestId, |
| 62494 | payload: &payload, copied: &copied); |
| 62495 | if(res != UA_STATUSCODE_GOOD || payload.length == 0) |
| 62496 | break; |
| 62497 | res = processServiceResponse(client, channel: &client->channel, |
| 62498 | messageType, requestId, message: &payload); |
| 62499 | if(copied) |
| 62500 | UA_ByteString_clear(p: &payload); |
| 62501 | |
| 62502 | /* Abort after synchronous processing of a message. |
| 62503 | * Add a delayed callback to process the remaining buffer ASAP. */ |
| 62504 | if(res == UA_STATUSCODE_GOODCOMPLETESASYNCHRONOUSLY) { |
| 62505 | if(client->channel.unprocessed.length > client->channel.unprocessedOffset && |
| 62506 | client->channel.unprocessedDelayed.callback == NULL) { |
| 62507 | client->channel.unprocessedDelayed.callback = delayedNetworkCallback; |
| 62508 | client->channel.unprocessedDelayed.application = client; |
| 62509 | client->channel.unprocessedDelayed.context = &client->channel; |
| 62510 | UA_EventLoop *el = client->config.eventLoop; |
| 62511 | el->addDelayedCallback(el, &client->channel.unprocessedDelayed); |
| 62512 | } |
| 62513 | res = UA_STATUSCODE_GOOD; |
| 62514 | break; |
| 62515 | } |
| 62516 | } |
| 62517 | res |= UA_SecureChannel_persistBuffer(channel: &client->channel); |
| 62518 | |
| 62519 | if(res != UA_STATUSCODE_GOOD) { |
| 62520 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62521 | msg: "Processing the message returned the error code %s", |
| 62522 | UA_StatusCode_name(code: res)); |
| 62523 | |
| 62524 | /* If processing the buffer fails before the SecureChannel has opened, |
| 62525 | * then the client cannot recover. Set the connectStatus to reflect |
| 62526 | * this. The application is notified when the socket has closed. */ |
| 62527 | if(client->channel.state != UA_SECURECHANNELSTATE_OPEN) |
| 62528 | client->connectStatus = res; |
| 62529 | |
| 62530 | /* Close the SecureChannel, but don't notify the client right away. |
| 62531 | * Return immediately. notifyClientState will be called in the next |
| 62532 | * callback from the ConnectionManager when the connection closes with a |
| 62533 | * StatusCode. |
| 62534 | * |
| 62535 | * If the connectStatus is still good (the SecureChannel was fully |
| 62536 | * opened before), then a reconnect is attempted. */ |
| 62537 | closeSecureChannel(client); |
| 62538 | unlockClient(client); |
| 62539 | return; |
| 62540 | } |
| 62541 | |
| 62542 | continue_connect: |
| 62543 | /* Trigger the next action from our end to fully open up the connection */ |
| 62544 | if(!isFullyConnected(client)) |
| 62545 | connectActivity(client); |
| 62546 | notifyClientState(client); |
| 62547 | unlockClient(client); |
| 62548 | } |
| 62549 | |
| 62550 | static void |
| 62551 | delayedNetworkCallback(void *application, void *context) { |
| 62552 | UA_Client *client = (UA_Client*)application; |
| 62553 | client->channel.unprocessedDelayed.callback = NULL; |
| 62554 | if(client->channel.state >= UA_SECURECHANNELSTATE_CONNECTING) |
| 62555 | __Client_networkCallback(cm: client->channel.connectionManager, |
| 62556 | connectionId: client->channel.connectionId, |
| 62557 | application: client, connectionContext: &context, |
| 62558 | state: UA_CONNECTIONSTATE_ESTABLISHED, |
| 62559 | params: &UA_KEYVALUEMAP_NULL, msg: UA_BYTESTRING_NULL); |
| 62560 | } |
| 62561 | |
| 62562 | /* Initialize a TCP connection. Writes the result to client->connectStatus. */ |
| 62563 | static void |
| 62564 | initConnect(UA_Client *client) { |
| 62565 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 62566 | if(client->channel.state != UA_SECURECHANNELSTATE_CLOSED) { |
| 62567 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62568 | msg: "Client connection already initiated"); |
| 62569 | return; |
| 62570 | } |
| 62571 | |
| 62572 | /* An exact endpoint was configured. Use it. */ |
| 62573 | if(!endpointUnconfigured(endpoint: &client->config.endpoint)) { |
| 62574 | UA_EndpointDescription_clear(p: &client->endpoint); |
| 62575 | client->connectStatus = |
| 62576 | UA_EndpointDescription_copy(src: &client->config.endpoint, dst: &client->endpoint); |
| 62577 | UA_CHECK_STATUS(client->connectStatus, return); |
| 62578 | } |
| 62579 | |
| 62580 | /* Start the EventLoop if not already started */ |
| 62581 | client->connectStatus = __UA_Client_startup(client); |
| 62582 | UA_CHECK_STATUS(client->connectStatus, return); |
| 62583 | |
| 62584 | /* Consistency check the client's own ApplicationURI. |
| 62585 | * Problems are only logged. */ |
| 62586 | verifyClientApplicationURI(client); |
| 62587 | |
| 62588 | /* Initialize the SecureChannel */ |
| 62589 | UA_SecureChannel_clear(channel: &client->channel); |
| 62590 | client->channel.config = client->config.localConnectionConfig; |
| 62591 | client->channel.certificateVerification = &client->config.certificateVerification; |
| 62592 | client->channel.processOPNHeader = verifyClientSecureChannelHeader; |
| 62593 | client->channel.processOPNHeaderApplication = client; |
| 62594 | |
| 62595 | /* Initialize the SecurityPolicy */ |
| 62596 | client->connectStatus = initSecurityPolicy(client); |
| 62597 | if(client->connectStatus != UA_STATUSCODE_GOOD) |
| 62598 | return; |
| 62599 | |
| 62600 | /* Extract hostname and port from the URL */ |
| 62601 | UA_String hostname = UA_STRING_NULL; |
| 62602 | UA_String path = UA_STRING_NULL; |
| 62603 | UA_UInt16 port = 4840; |
| 62604 | |
| 62605 | client->connectStatus = |
| 62606 | UA_parseEndpointUrl(endpointUrl: &client->config.endpointUrl, outHostname: &hostname, outPort: &port, outPath: &path); |
| 62607 | if(client->connectStatus != UA_STATUSCODE_GOOD) { |
| 62608 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_NETWORK, |
| 62609 | msg: "OPC UA URL is invalid: %.*s", |
| 62610 | (int)client->config.endpointUrl.length, |
| 62611 | client->config.endpointUrl.data); |
| 62612 | return; |
| 62613 | } |
| 62614 | |
| 62615 | /* Initialize the TCP connection */ |
| 62616 | UA_String tcpString = UA_STRING(chars: "tcp"); |
| 62617 | for(UA_EventSource *es = client->config.eventLoop->eventSources; |
| 62618 | es != NULL; es = es->next) { |
| 62619 | /* Is this a usable connection manager? */ |
| 62620 | if(es->eventSourceType != UA_EVENTSOURCETYPE_CONNECTIONMANAGER) |
| 62621 | continue; |
| 62622 | UA_ConnectionManager *cm = (UA_ConnectionManager*)es; |
| 62623 | if(!UA_String_equal(p1: &tcpString, p2: &cm->protocol)) |
| 62624 | continue; |
| 62625 | |
| 62626 | /* Set up the parameters */ |
| 62627 | UA_KeyValuePair params[2]; |
| 62628 | params[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "port"); |
| 62629 | UA_Variant_setScalar(v: ¶ms[0].value, p: &port, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 62630 | params[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "address"); |
| 62631 | UA_Variant_setScalar(v: ¶ms[1].value, p: &hostname, type: &UA_TYPES[UA_TYPES_STRING]); |
| 62632 | |
| 62633 | UA_KeyValueMap paramMap; |
| 62634 | paramMap.map = params; |
| 62635 | paramMap.mapSize = 2; |
| 62636 | |
| 62637 | /* Open the client TCP connection */ |
| 62638 | UA_StatusCode res = cm->openConnection(cm, ¶mMap, client, NULL, __Client_networkCallback); |
| 62639 | if(res == UA_STATUSCODE_GOOD) |
| 62640 | break; |
| 62641 | } |
| 62642 | |
| 62643 | /* The channel has not opened */ |
| 62644 | if(client->channel.state == UA_SECURECHANNELSTATE_CLOSED) |
| 62645 | client->connectStatus = UA_STATUSCODE_BADINTERNALERROR; |
| 62646 | |
| 62647 | /* Opening the TCP connection failed */ |
| 62648 | if(client->connectStatus != UA_STATUSCODE_GOOD) { |
| 62649 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62650 | msg: "Could not open a TCP connection to %.*s", |
| 62651 | (int)client->config.endpointUrl.length, |
| 62652 | client->config.endpointUrl.data); |
| 62653 | client->connectStatus = UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 62654 | } |
| 62655 | } |
| 62656 | |
| 62657 | void |
| 62658 | connectSync(UA_Client *client) { |
| 62659 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 62660 | |
| 62661 | /* Initialize the connection */ |
| 62662 | initConnect(client); |
| 62663 | notifyClientState(client); |
| 62664 | if(client->connectStatus != UA_STATUSCODE_GOOD) |
| 62665 | return; |
| 62666 | |
| 62667 | UA_DateTime now = UA_DateTime_nowMonotonic(); |
| 62668 | UA_DateTime maxDate = now + ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC); |
| 62669 | |
| 62670 | /* EventLoop is started. Otherwise initConnect would have failed. */ |
| 62671 | UA_EventLoop *el = client->config.eventLoop; |
| 62672 | UA_assert(el); |
| 62673 | |
| 62674 | /* Run the EventLoop until connected, connect fail or timeout. Write the |
| 62675 | * iterate result to the connectStatus. So we do not attempt to restore a |
| 62676 | * failed connection during the sync connect. */ |
| 62677 | while(client->connectStatus == UA_STATUSCODE_GOOD && |
| 62678 | !isFullyConnected(client)) { |
| 62679 | |
| 62680 | /* Timeout -> abort */ |
| 62681 | now = UA_DateTime_nowMonotonic(); |
| 62682 | if(maxDate < now) { |
| 62683 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62684 | msg: "The connection has timed out before it could be fully opened"); |
| 62685 | client->connectStatus = UA_STATUSCODE_BADTIMEOUT; |
| 62686 | closeSecureChannel(client); |
| 62687 | /* Continue to run. So the SecureChannel is fully closed in the next |
| 62688 | * EventLoop iteration. */ |
| 62689 | } |
| 62690 | |
| 62691 | /* Drop into the EventLoop */ |
| 62692 | UA_StatusCode res = el->run(el, (UA_UInt32)((maxDate - now) / UA_DATETIME_MSEC)); |
| 62693 | if(res != UA_STATUSCODE_GOOD) { |
| 62694 | client->connectStatus = res; |
| 62695 | closeSecureChannel(client); |
| 62696 | } |
| 62697 | |
| 62698 | notifyClientState(client); |
| 62699 | } |
| 62700 | } |
| 62701 | |
| 62702 | UA_StatusCode |
| 62703 | connectInternal(UA_Client *client, UA_Boolean async) { |
| 62704 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 62705 | |
| 62706 | /* Reset the connectStatus. This should be the only place where we can |
| 62707 | * recover from a bad connectStatus. */ |
| 62708 | client->connectStatus = UA_STATUSCODE_GOOD; |
| 62709 | |
| 62710 | if(async) |
| 62711 | initConnect(client); |
| 62712 | else |
| 62713 | connectSync(client); |
| 62714 | notifyClientState(client); |
| 62715 | return client->connectStatus; |
| 62716 | } |
| 62717 | |
| 62718 | UA_StatusCode |
| 62719 | connectSecureChannel(UA_Client *client, const char *endpointUrl) { |
| 62720 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 62721 | |
| 62722 | UA_ClientConfig *cc = UA_Client_getConfig(client); |
| 62723 | cc->noSession = true; |
| 62724 | UA_String_clear(p: &cc->endpointUrl); |
| 62725 | cc->endpointUrl = UA_STRING_ALLOC(endpointUrl); |
| 62726 | return connectInternal(client, false); |
| 62727 | } |
| 62728 | |
| 62729 | UA_StatusCode |
| 62730 | __UA_Client_connect(UA_Client *client, UA_Boolean async) { |
| 62731 | lockClient(client); |
| 62732 | connectInternal(client, async); |
| 62733 | unlockClient(client); |
| 62734 | return client->connectStatus; |
| 62735 | } |
| 62736 | |
| 62737 | static UA_StatusCode |
| 62738 | activateSessionSync(UA_Client *client) { |
| 62739 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 62740 | |
| 62741 | UA_DateTime now = UA_DateTime_nowMonotonic(); |
| 62742 | UA_DateTime maxDate = now + ((UA_DateTime)client->config.timeout * UA_DATETIME_MSEC); |
| 62743 | |
| 62744 | /* Try to activate */ |
| 62745 | UA_StatusCode res = activateSessionAsync(client); |
| 62746 | if(res != UA_STATUSCODE_GOOD) |
| 62747 | return res; |
| 62748 | |
| 62749 | /* EventLoop is started. Otherwise activateSessionAsync would have failed. */ |
| 62750 | UA_EventLoop *el = client->config.eventLoop; |
| 62751 | UA_assert(el); |
| 62752 | while(client->sessionState != UA_SESSIONSTATE_ACTIVATED && |
| 62753 | client->connectStatus == UA_STATUSCODE_GOOD) { |
| 62754 | |
| 62755 | /* Timeout -> abort */ |
| 62756 | now = UA_DateTime_nowMonotonic(); |
| 62757 | if(maxDate < now) { |
| 62758 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62759 | msg: "The connection has timed out before it could be fully opened"); |
| 62760 | client->connectStatus = UA_STATUSCODE_BADTIMEOUT; |
| 62761 | closeSecureChannel(client); |
| 62762 | /* Continue to run. So the SecureChannel is fully closed in the next |
| 62763 | * EventLoop iteration. */ |
| 62764 | } |
| 62765 | |
| 62766 | /* Drop into the EventLoop */ |
| 62767 | res = el->run(el, (UA_UInt32)((maxDate - now) / UA_DATETIME_MSEC)); |
| 62768 | if(res != UA_STATUSCODE_GOOD) { |
| 62769 | client->connectStatus = res; |
| 62770 | closeSecureChannel(client); |
| 62771 | } |
| 62772 | |
| 62773 | notifyClientState(client); |
| 62774 | } |
| 62775 | |
| 62776 | return client->connectStatus; |
| 62777 | } |
| 62778 | |
| 62779 | UA_StatusCode |
| 62780 | UA_Client_activateCurrentSession(UA_Client *client) { |
| 62781 | lockClient(client); |
| 62782 | UA_StatusCode res = activateSessionSync(client); |
| 62783 | notifyClientState(client); |
| 62784 | unlockClient(client); |
| 62785 | return res != UA_STATUSCODE_GOOD ? res : client->connectStatus; |
| 62786 | } |
| 62787 | |
| 62788 | UA_StatusCode |
| 62789 | UA_Client_activateCurrentSessionAsync(UA_Client *client) { |
| 62790 | lockClient(client); |
| 62791 | UA_StatusCode res = activateSessionAsync(client); |
| 62792 | notifyClientState(client); |
| 62793 | unlockClient(client); |
| 62794 | return res != UA_STATUSCODE_GOOD ? res : client->connectStatus; |
| 62795 | } |
| 62796 | |
| 62797 | UA_StatusCode |
| 62798 | UA_Client_getSessionAuthenticationToken(UA_Client *client, UA_NodeId *authenticationToken, |
| 62799 | UA_ByteString *serverNonce) { |
| 62800 | lockClient(client); |
| 62801 | if(client->sessionState != UA_SESSIONSTATE_CREATED && |
| 62802 | client->sessionState != UA_SESSIONSTATE_ACTIVATED) { |
| 62803 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62804 | msg: "There is no current session"); |
| 62805 | unlockClient(client); |
| 62806 | return UA_STATUSCODE_BADSESSIONCLOSED; |
| 62807 | } |
| 62808 | |
| 62809 | UA_StatusCode res = UA_NodeId_copy(src: &client->authenticationToken, dst: authenticationToken); |
| 62810 | res |= UA_ByteString_copy(src: &client->serverSessionNonce, dst: serverNonce); |
| 62811 | unlockClient(client); |
| 62812 | return res; |
| 62813 | } |
| 62814 | |
| 62815 | static UA_StatusCode |
| 62816 | switchSession(UA_Client *client, |
| 62817 | const UA_NodeId authenticationToken, |
| 62818 | const UA_ByteString serverNonce) { |
| 62819 | /* Check that there is no pending session in the client */ |
| 62820 | if(client->sessionState != UA_SESSIONSTATE_CLOSED) { |
| 62821 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62822 | msg: "Cannot activate a session with a different AuthenticationToken " |
| 62823 | "when the client already has a Session."); |
| 62824 | return UA_STATUSCODE_BADINTERNALERROR; |
| 62825 | } |
| 62826 | |
| 62827 | /* Replace token and nonce */ |
| 62828 | UA_NodeId_clear(p: &client->authenticationToken); |
| 62829 | UA_ByteString_clear(p: &client->serverSessionNonce); |
| 62830 | UA_StatusCode res = UA_NodeId_copy(src: &authenticationToken, dst: &client->authenticationToken); |
| 62831 | res |= UA_ByteString_copy(src: &serverNonce, dst: &client->serverSessionNonce); |
| 62832 | if(res != UA_STATUSCODE_GOOD) |
| 62833 | return res; |
| 62834 | |
| 62835 | /* Notify that we have now a created session */ |
| 62836 | client->sessionState = UA_SESSIONSTATE_CREATED; |
| 62837 | notifyClientState(client); |
| 62838 | |
| 62839 | return UA_STATUSCODE_GOOD; |
| 62840 | } |
| 62841 | |
| 62842 | UA_StatusCode |
| 62843 | UA_Client_activateSession(UA_Client *client, |
| 62844 | const UA_NodeId authenticationToken, |
| 62845 | const UA_ByteString serverNonce) { |
| 62846 | lockClient(client); |
| 62847 | UA_StatusCode res = switchSession(client, authenticationToken, serverNonce); |
| 62848 | if(res != UA_STATUSCODE_GOOD) { |
| 62849 | unlockClient(client); |
| 62850 | return res; |
| 62851 | } |
| 62852 | res = activateSessionSync(client); |
| 62853 | notifyClientState(client); |
| 62854 | unlockClient(client); |
| 62855 | return res != UA_STATUSCODE_GOOD ? res : client->connectStatus; |
| 62856 | } |
| 62857 | |
| 62858 | UA_StatusCode |
| 62859 | UA_Client_activateSessionAsync(UA_Client *client, |
| 62860 | const UA_NodeId authenticationToken, |
| 62861 | const UA_ByteString serverNonce) { |
| 62862 | lockClient(client); |
| 62863 | UA_StatusCode res = switchSession(client, authenticationToken, serverNonce); |
| 62864 | if(res != UA_STATUSCODE_GOOD) { |
| 62865 | unlockClient(client); |
| 62866 | return res; |
| 62867 | } |
| 62868 | res = activateSessionAsync(client); |
| 62869 | notifyClientState(client); |
| 62870 | unlockClient(client); |
| 62871 | return res != UA_STATUSCODE_GOOD ? res : client->connectStatus; |
| 62872 | } |
| 62873 | |
| 62874 | static void |
| 62875 | disconnectListenSockets(UA_Client *client) { |
| 62876 | UA_ConnectionManager *cm = client->reverseConnectionCM; |
| 62877 | for(size_t i = 0; i < 16; i++) { |
| 62878 | if(client->reverseConnectionIds[i] != 0) { |
| 62879 | cm->closeConnection(cm, client->reverseConnectionIds[i]); |
| 62880 | } |
| 62881 | } |
| 62882 | } |
| 62883 | |
| 62884 | /* ConnectionContext meaning: |
| 62885 | * - NULL: New listen connection |
| 62886 | * - &client->channel: Established active socket to a server |
| 62887 | * - &client->reverseConnectionIds[*] == connectionId: Established listen socket |
| 62888 | * - &client->reverseConnectionIds[*] != connectionId: New active socket */ |
| 62889 | static void |
| 62890 | __Client_reverseConnectCallback(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 62891 | void *application, void **connectionContext, |
| 62892 | UA_ConnectionState state, const UA_KeyValueMap *params, |
| 62893 | UA_ByteString msg) { |
| 62894 | UA_Client *client = (UA_Client*)application; |
| 62895 | lockClient(client); |
| 62896 | |
| 62897 | if(!*connectionContext) { |
| 62898 | /* Store the new listen connection */ |
| 62899 | size_t i = 0; |
| 62900 | for(; i < 16; i++) { |
| 62901 | if(client->reverseConnectionIds[i] == 0) { |
| 62902 | client->reverseConnectionIds[i] = connectionId; |
| 62903 | client->reverseConnectionCM = cm; |
| 62904 | *connectionContext = &client->reverseConnectionIds[i]; |
| 62905 | if(client->channel.state == UA_SECURECHANNELSTATE_CLOSED) |
| 62906 | client->channel.state = UA_SECURECHANNELSTATE_REVERSE_LISTENING; |
| 62907 | break; |
| 62908 | } |
| 62909 | } |
| 62910 | /* All slots are full, close */ |
| 62911 | if(i == 16) { |
| 62912 | cm->closeConnection(cm, connectionId); |
| 62913 | unlockClient(client); |
| 62914 | return; |
| 62915 | } |
| 62916 | } else if(*connectionContext == &client->channel || |
| 62917 | *(uintptr_t*)*connectionContext != connectionId) { |
| 62918 | /* Active socket */ |
| 62919 | |
| 62920 | /* New active socket */ |
| 62921 | if(*connectionContext != &client->channel) { |
| 62922 | /* The client already has an active connection */ |
| 62923 | if(client->channel.connectionId) { |
| 62924 | cm->closeConnection(cm, connectionId); |
| 62925 | unlockClient(client); |
| 62926 | return; |
| 62927 | } |
| 62928 | |
| 62929 | /* Set the connection the SecureChannel */ |
| 62930 | client->channel.connectionId = connectionId; |
| 62931 | client->channel.connectionManager = cm; |
| 62932 | *connectionContext = &client->channel; |
| 62933 | |
| 62934 | /* Don't keep the listen sockets when an active connection is open */ |
| 62935 | disconnectListenSockets(client); |
| 62936 | |
| 62937 | /* Set the channel state. The notification callback is called within |
| 62938 | * __Client_reverseConnectCallback. */ |
| 62939 | if(client->channel.state == UA_SECURECHANNELSTATE_REVERSE_LISTENING) |
| 62940 | client->channel.state = UA_SECURECHANNELSTATE_REVERSE_CONNECTED; |
| 62941 | } |
| 62942 | |
| 62943 | /* Handle the active connection in the normal network callback */ |
| 62944 | unlockClient(client); |
| 62945 | __Client_networkCallback(cm, connectionId, application, |
| 62946 | connectionContext, state, params, msg); |
| 62947 | return; |
| 62948 | } |
| 62949 | |
| 62950 | /* Close the listen socket. Was this the last one? */ |
| 62951 | if(state == UA_CONNECTIONSTATE_CLOSING) { |
| 62952 | UA_Byte count = 0; |
| 62953 | for(size_t i = 0; i < 16; i++) { |
| 62954 | if(client->reverseConnectionIds[i] == connectionId) |
| 62955 | client->reverseConnectionIds[i] = 0; |
| 62956 | if(client->reverseConnectionIds[i] != 0) |
| 62957 | count++; |
| 62958 | } |
| 62959 | /* The last connection was closed */ |
| 62960 | if(count == 0 && client->channel.connectionId == 0) |
| 62961 | client->channel.state = UA_SECURECHANNELSTATE_CLOSED; |
| 62962 | } |
| 62963 | |
| 62964 | notifyClientState(client); |
| 62965 | unlockClient(client); |
| 62966 | } |
| 62967 | |
| 62968 | UA_StatusCode |
| 62969 | UA_Client_startListeningForReverseConnect(UA_Client *client, |
| 62970 | const UA_String *listenHostnames, |
| 62971 | size_t listenHostnamesLength, |
| 62972 | UA_UInt16 port) { |
| 62973 | lockClient(client); |
| 62974 | |
| 62975 | if(client->channel.state != UA_SECURECHANNELSTATE_CLOSED) { |
| 62976 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 62977 | msg: "Unable to listen for reverse connect while the client " |
| 62978 | "is connected or already listening"); |
| 62979 | unlockClient(client); |
| 62980 | return UA_STATUSCODE_BADINVALIDSTATE; |
| 62981 | } |
| 62982 | |
| 62983 | const UA_String tcpString = UA_STRING_STATIC("tcp"); |
| 62984 | UA_StatusCode res = UA_STATUSCODE_BADINTERNALERROR; |
| 62985 | |
| 62986 | client->connectStatus = UA_STATUSCODE_GOOD; |
| 62987 | client->channel.renewState = UA_SECURECHANNELRENEWSTATE_NORMAL; |
| 62988 | |
| 62989 | UA_SecureChannel_init(channel: &client->channel); |
| 62990 | client->channel.config = client->config.localConnectionConfig; |
| 62991 | client->channel.certificateVerification = &client->config.certificateVerification; |
| 62992 | client->channel.processOPNHeader = verifyClientSecureChannelHeader; |
| 62993 | client->channel.processOPNHeaderApplication = client; |
| 62994 | client->channel.connectionId = 0; |
| 62995 | |
| 62996 | client->connectStatus = initSecurityPolicy(client); |
| 62997 | if(client->connectStatus != UA_STATUSCODE_GOOD) |
| 62998 | return client->connectStatus; |
| 62999 | |
| 63000 | UA_EventLoop *el = client->config.eventLoop; |
| 63001 | if(!el) { |
| 63002 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 63003 | msg: "No EventLoop configured"); |
| 63004 | unlockClient(client); |
| 63005 | return UA_STATUSCODE_BADINTERNALERROR; |
| 63006 | } |
| 63007 | |
| 63008 | if(el->state != UA_EVENTLOOPSTATE_STARTED) { |
| 63009 | res = el->start(el); |
| 63010 | UA_CHECK_STATUS(res, unlockClient(client); return res); |
| 63011 | } |
| 63012 | |
| 63013 | UA_ConnectionManager *cm = NULL; |
| 63014 | for(UA_EventSource *es = el->eventSources; es != NULL; es = es->next) { |
| 63015 | if(es->eventSourceType != UA_EVENTSOURCETYPE_CONNECTIONMANAGER) |
| 63016 | continue; |
| 63017 | cm = (UA_ConnectionManager*)es; |
| 63018 | if(UA_String_equal(p1: &tcpString, p2: &cm->protocol)) |
| 63019 | break; |
| 63020 | cm = NULL; |
| 63021 | } |
| 63022 | |
| 63023 | if(!cm) { |
| 63024 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 63025 | msg: "Could not find a TCP connection manager, unable to " |
| 63026 | "listen for reverse connect"); |
| 63027 | unlockClient(client); |
| 63028 | return UA_STATUSCODE_BADINTERNALERROR; |
| 63029 | } |
| 63030 | |
| 63031 | client->channel.connectionManager = cm; |
| 63032 | |
| 63033 | UA_KeyValuePair params[4]; |
| 63034 | bool booleanTrue = true; |
| 63035 | params[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "port"); |
| 63036 | UA_Variant_setScalar(v: ¶ms[0].value, p: &port, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 63037 | params[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "address"); |
| 63038 | UA_Variant_setArray(v: ¶ms[1].value, array: (void *)(uintptr_t)listenHostnames, |
| 63039 | arraySize: listenHostnamesLength, type: &UA_TYPES[UA_TYPES_STRING]); |
| 63040 | params[2].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "listen"); |
| 63041 | UA_Variant_setScalar(v: ¶ms[2].value, p: &booleanTrue, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 63042 | params[3].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "reuse"); |
| 63043 | UA_Variant_setScalar(v: ¶ms[3].value, p: &booleanTrue, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 63044 | |
| 63045 | UA_KeyValueMap paramMap; |
| 63046 | paramMap.map = params; |
| 63047 | paramMap.mapSize = 4; |
| 63048 | |
| 63049 | res = cm->openConnection(cm, ¶mMap, client, NULL, __Client_reverseConnectCallback); |
| 63050 | |
| 63051 | /* Opening the TCP connection failed */ |
| 63052 | if(res != UA_STATUSCODE_GOOD) { |
| 63053 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 63054 | msg: "Failed to open a listening TCP socket for reverse connect"); |
| 63055 | res = UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 63056 | } |
| 63057 | |
| 63058 | unlockClient(client); |
| 63059 | return res; |
| 63060 | } |
| 63061 | |
| 63062 | /************************/ |
| 63063 | /* Close the Connection */ |
| 63064 | /************************/ |
| 63065 | |
| 63066 | void |
| 63067 | closeSecureChannel(UA_Client *client) { |
| 63068 | /* If we close SecureChannel when the Session is still active, set to |
| 63069 | * created. Otherwise the Session would remain active until the connection |
| 63070 | * callback is called for the closing connection. */ |
| 63071 | if(client->sessionState == UA_SESSIONSTATE_ACTIVATED) |
| 63072 | client->sessionState = UA_SESSIONSTATE_CREATED; |
| 63073 | |
| 63074 | /* Prevent recursion */ |
| 63075 | if(client->channel.state == UA_SECURECHANNELSTATE_CLOSING || |
| 63076 | client->channel.state == UA_SECURECHANNELSTATE_CLOSED) |
| 63077 | return; |
| 63078 | |
| 63079 | UA_LOG_DEBUG_CHANNEL(client->config.logging, &client->channel, |
| 63080 | "Closing the channel"); |
| 63081 | |
| 63082 | disconnectListenSockets(client); |
| 63083 | |
| 63084 | /* Send CLO if the SecureChannel is open */ |
| 63085 | if(client->channel.state == UA_SECURECHANNELSTATE_OPEN) { |
| 63086 | UA_LOG_DEBUG_CHANNEL(client->config.logging, &client->channel, |
| 63087 | "Sending the CLO message"); |
| 63088 | |
| 63089 | /* Manually set up the header (otherwise done in sendRequest) */ |
| 63090 | UA_CloseSecureChannelRequest request; |
| 63091 | UA_CloseSecureChannelRequest_init(p: &request); |
| 63092 | request.requestHeader.requestHandle = ++client->requestHandle; |
| 63093 | request.requestHeader.timestamp = UA_DateTime_now(); |
| 63094 | request.requestHeader.timeoutHint = client->config.timeout; |
| 63095 | request.requestHeader.authenticationToken = client->authenticationToken; |
| 63096 | UA_SecureChannel_sendSymmetricMessage(channel: &client->channel, requestId: ++client->requestId, |
| 63097 | messageType: UA_MESSAGETYPE_CLO, payload: &request, |
| 63098 | payloadType: &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST]); |
| 63099 | } |
| 63100 | |
| 63101 | /* The connection is eventually closed in the next callback from the |
| 63102 | * ConnectionManager with the appropriate status code. Don't set the |
| 63103 | * connection closed right away! */ |
| 63104 | UA_SecureChannel_shutdown(channel: &client->channel, shutdownReason: UA_SHUTDOWNREASON_CLOSE); |
| 63105 | } |
| 63106 | |
| 63107 | static void |
| 63108 | sendCloseSession(UA_Client *client) { |
| 63109 | UA_CloseSessionRequest request; |
| 63110 | UA_CloseSessionRequest_init(p: &request); |
| 63111 | request.deleteSubscriptions = true; |
| 63112 | UA_CloseSessionResponse response; |
| 63113 | __Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST], |
| 63114 | response: &response, responseType: &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE]); |
| 63115 | UA_CloseSessionRequest_clear(p: &request); |
| 63116 | UA_CloseSessionResponse_clear(p: &response); |
| 63117 | |
| 63118 | /* Set after sending the message to prevent immediate reoping during the |
| 63119 | * service call */ |
| 63120 | client->sessionState = UA_SESSIONSTATE_CLOSING; |
| 63121 | } |
| 63122 | |
| 63123 | void |
| 63124 | cleanupSession(UA_Client *client) { |
| 63125 | UA_NodeId_clear(p: &client->authenticationToken); |
| 63126 | client->requestHandle = 0; |
| 63127 | |
| 63128 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 63129 | /* We need to clean up the subscriptions */ |
| 63130 | __Client_Subscriptions_clean(client); |
| 63131 | #endif |
| 63132 | |
| 63133 | /* Delete outstanding async services */ |
| 63134 | __Client_AsyncService_removeAll(client, UA_STATUSCODE_BADSESSIONCLOSED); |
| 63135 | |
| 63136 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 63137 | client->currentlyOutStandingPublishRequests = 0; |
| 63138 | #endif |
| 63139 | |
| 63140 | client->sessionState = UA_SESSIONSTATE_CLOSED; |
| 63141 | } |
| 63142 | |
| 63143 | static void |
| 63144 | disconnectSecureChannel(UA_Client *client, UA_Boolean sync) { |
| 63145 | /* Clean the DiscoveryUrl and endpoint description when the connection is |
| 63146 | * explicitly closed */ |
| 63147 | UA_String_clear(p: &client->discoveryUrl); |
| 63148 | UA_EndpointDescription_clear(p: &client->endpoint); |
| 63149 | |
| 63150 | /* Close the SecureChannel */ |
| 63151 | closeSecureChannel(client); |
| 63152 | |
| 63153 | /* Manually set the status to closed to prevent an automatic reconnection */ |
| 63154 | if(client->connectStatus == UA_STATUSCODE_GOOD) |
| 63155 | client->connectStatus = UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 63156 | |
| 63157 | /* In the synchronous case, loop until the client has actually closed. */ |
| 63158 | UA_EventLoop *el = client->config.eventLoop; |
| 63159 | if(sync && el && |
| 63160 | el->state != UA_EVENTLOOPSTATE_FRESH && |
| 63161 | el->state != UA_EVENTLOOPSTATE_STOPPED) { |
| 63162 | while(client->channel.state != UA_SECURECHANNELSTATE_CLOSED) { |
| 63163 | el->run(el, 100); |
| 63164 | } |
| 63165 | } |
| 63166 | |
| 63167 | notifyClientState(client); |
| 63168 | } |
| 63169 | |
| 63170 | UA_StatusCode |
| 63171 | UA_Client_disconnectSecureChannel(UA_Client *client) { |
| 63172 | lockClient(client); |
| 63173 | disconnectSecureChannel(client, true); |
| 63174 | unlockClient(client); |
| 63175 | return UA_STATUSCODE_GOOD; |
| 63176 | } |
| 63177 | |
| 63178 | UA_StatusCode |
| 63179 | UA_Client_disconnectSecureChannelAsync(UA_Client *client) { |
| 63180 | lockClient(client); |
| 63181 | disconnectSecureChannel(client, false); |
| 63182 | unlockClient(client); |
| 63183 | return UA_STATUSCODE_GOOD; |
| 63184 | } |
| 63185 | |
| 63186 | UA_StatusCode |
| 63187 | UA_Client_disconnect(UA_Client *client) { |
| 63188 | lockClient(client); |
| 63189 | if(client->sessionState == UA_SESSIONSTATE_ACTIVATED) |
| 63190 | sendCloseSession(client); |
| 63191 | cleanupSession(client); |
| 63192 | disconnectSecureChannel(client, true); |
| 63193 | unlockClient(client); |
| 63194 | return UA_STATUSCODE_GOOD; |
| 63195 | } |
| 63196 | |
| 63197 | static void |
| 63198 | closeSessionCallback(UA_Client *client, void *userdata, |
| 63199 | UA_UInt32 requestId, void *response) { |
| 63200 | lockClient(client); |
| 63201 | cleanupSession(client); |
| 63202 | disconnectSecureChannel(client, false); |
| 63203 | notifyClientState(client); |
| 63204 | unlockClient(client); |
| 63205 | } |
| 63206 | |
| 63207 | UA_StatusCode |
| 63208 | UA_Client_disconnectAsync(UA_Client *client) { |
| 63209 | lockClient(client); |
| 63210 | |
| 63211 | if(client->sessionState == UA_SESSIONSTATE_CLOSED || |
| 63212 | client->sessionState == UA_SESSIONSTATE_CLOSING) { |
| 63213 | disconnectSecureChannel(client, false); |
| 63214 | notifyClientState(client); |
| 63215 | unlockClient(client); |
| 63216 | return UA_STATUSCODE_GOOD; |
| 63217 | } |
| 63218 | |
| 63219 | /* Set before sending the message to prevent recursion */ |
| 63220 | client->sessionState = UA_SESSIONSTATE_CLOSING; |
| 63221 | |
| 63222 | UA_CloseSessionRequest request; |
| 63223 | UA_CloseSessionRequest_init(p: &request); |
| 63224 | request.deleteSubscriptions = true; |
| 63225 | UA_StatusCode res = |
| 63226 | __Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_CLOSESESSIONREQUEST], |
| 63227 | callback: (UA_ClientAsyncServiceCallback)closeSessionCallback, |
| 63228 | responseType: &UA_TYPES[UA_TYPES_CLOSESESSIONRESPONSE], NULL, NULL); |
| 63229 | if(res != UA_STATUSCODE_GOOD) { |
| 63230 | /* Sending the close request failed. Continue to close the connection |
| 63231 | * anyway. */ |
| 63232 | cleanupSession(client); |
| 63233 | disconnectSecureChannel(client, false); |
| 63234 | } |
| 63235 | |
| 63236 | notifyClientState(client); |
| 63237 | unlockClient(client); |
| 63238 | return res; |
| 63239 | } |
| 63240 | |
| 63241 | /**** amalgamated original file "/src/client/ua_client_discovery.c" ****/ |
| 63242 | |
| 63243 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 63244 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 63245 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 63246 | * |
| 63247 | * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 63248 | * Copyright 2017 (c) Mark Giraud, Fraunhofer IOSB |
| 63249 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 63250 | */ |
| 63251 | |
| 63252 | |
| 63253 | /* Helper method for additional warnings */ |
| 63254 | void |
| 63255 | Client_warnEndpointsResult(UA_Client *client, |
| 63256 | const UA_GetEndpointsResponse *response, |
| 63257 | const UA_String *endpointUrl) { |
| 63258 | if(response->endpointsSize == 0) { |
| 63259 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 63260 | msg: "The server did not return any endpoints. " |
| 63261 | "Did you use the correct endpointUrl?"); |
| 63262 | return; |
| 63263 | } |
| 63264 | |
| 63265 | if(!UA_String_equal(p1: endpointUrl, p2: &response->endpoints[0].endpointUrl) || |
| 63266 | (response->endpoints[0].server.discoveryUrlsSize > 0 && |
| 63267 | !UA_String_equal(p1: endpointUrl, p2: &response->endpoints[0].server.discoveryUrls[0]))) { |
| 63268 | UA_String *betterUrl = &response->endpoints[0].endpointUrl; |
| 63269 | if(response->endpoints[0].server.discoveryUrlsSize > 0) |
| 63270 | betterUrl = &response->endpoints[0].server.discoveryUrls[0]; |
| 63271 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 63272 | msg: "The server returned Endpoints with a different EndpointUrl %.*s than was " |
| 63273 | "used to initialize the connection: %.*s. Some servers require a complete " |
| 63274 | "match of the EndpointUrl/DiscoveryUrl (including the path) " |
| 63275 | "to return all endpoints.", |
| 63276 | (int)betterUrl->length, betterUrl->data, |
| 63277 | (int)endpointUrl->length, endpointUrl->data); |
| 63278 | } |
| 63279 | } |
| 63280 | |
| 63281 | /* Gets a list of endpoints. Memory is allocated for endpointDescription array */ |
| 63282 | static UA_StatusCode |
| 63283 | getEndpointsInternal(UA_Client *client, const UA_String endpointUrl, |
| 63284 | size_t *endpointDescriptionsSize, |
| 63285 | UA_EndpointDescription **endpointDescriptions) { |
| 63286 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 63287 | |
| 63288 | UA_GetEndpointsRequest request; |
| 63289 | UA_GetEndpointsRequest_init(p: &request); |
| 63290 | request.requestHeader.timestamp = UA_DateTime_now(); |
| 63291 | request.requestHeader.timeoutHint = 10000; |
| 63292 | // assume the endpointurl outlives the service call |
| 63293 | request.endpointUrl = endpointUrl; |
| 63294 | |
| 63295 | UA_GetEndpointsResponse response; |
| 63296 | __Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_GETENDPOINTSREQUEST], |
| 63297 | response: &response, responseType: &UA_TYPES[UA_TYPES_GETENDPOINTSRESPONSE]); |
| 63298 | |
| 63299 | if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 63300 | UA_StatusCode retval = response.responseHeader.serviceResult; |
| 63301 | UA_LOG_ERROR(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 63302 | msg: "GetEndpointRequest failed with error code %s", |
| 63303 | UA_StatusCode_name(code: retval)); |
| 63304 | UA_GetEndpointsResponse_clear(p: &response); |
| 63305 | return retval; |
| 63306 | } |
| 63307 | |
| 63308 | *endpointDescriptions = response.endpoints; |
| 63309 | *endpointDescriptionsSize = response.endpointsSize; |
| 63310 | response.endpoints = NULL; |
| 63311 | response.endpointsSize = 0; |
| 63312 | UA_GetEndpointsResponse_clear(p: &response); |
| 63313 | return UA_STATUSCODE_GOOD; |
| 63314 | } |
| 63315 | |
| 63316 | UA_StatusCode |
| 63317 | UA_Client_getEndpoints(UA_Client *client, const char *serverUrl, |
| 63318 | size_t *endpointDescriptionsSize, |
| 63319 | UA_EndpointDescription** endpointDescriptions) { |
| 63320 | lockClient(client); |
| 63321 | |
| 63322 | UA_Boolean connected = (client->channel.state == UA_SECURECHANNELSTATE_OPEN); |
| 63323 | /* Client is already connected to a different server */ |
| 63324 | if(connected && strncmp(s1: (const char*)client->config.endpoint.endpointUrl.data, s2: serverUrl, |
| 63325 | n: client->config.endpoint.endpointUrl.length) != 0) { |
| 63326 | unlockClient(client); |
| 63327 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 63328 | } |
| 63329 | |
| 63330 | UA_StatusCode retval; |
| 63331 | const UA_String url = UA_STRING(chars: (char*)(uintptr_t)serverUrl); |
| 63332 | if(!connected) { |
| 63333 | retval = connectSecureChannel(client, endpointUrl: serverUrl); |
| 63334 | if(retval != UA_STATUSCODE_GOOD) { |
| 63335 | unlockClient(client); |
| 63336 | return retval; |
| 63337 | } |
| 63338 | } |
| 63339 | retval = getEndpointsInternal(client, endpointUrl: url, endpointDescriptionsSize, |
| 63340 | endpointDescriptions); |
| 63341 | unlockClient(client); |
| 63342 | |
| 63343 | if(!connected) |
| 63344 | UA_Client_disconnect(client); |
| 63345 | return retval; |
| 63346 | } |
| 63347 | |
| 63348 | UA_StatusCode |
| 63349 | UA_Client_findServers(UA_Client *client, const char *serverUrl, |
| 63350 | size_t serverUrisSize, UA_String *serverUris, |
| 63351 | size_t localeIdsSize, UA_String *localeIds, |
| 63352 | size_t *registeredServersSize, |
| 63353 | UA_ApplicationDescription **registeredServers) { |
| 63354 | lockClient(client); |
| 63355 | UA_Boolean connected = (client->channel.state == UA_SECURECHANNELSTATE_OPEN); |
| 63356 | /* Client is already connected to a different server */ |
| 63357 | if(connected && strncmp(s1: (const char*)client->config.endpoint.endpointUrl.data, s2: serverUrl, |
| 63358 | n: client->config.endpoint.endpointUrl.length) != 0) { |
| 63359 | unlockClient(client); |
| 63360 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 63361 | } |
| 63362 | |
| 63363 | UA_StatusCode retval; |
| 63364 | if(!connected) { |
| 63365 | retval = connectSecureChannel(client, endpointUrl: serverUrl); |
| 63366 | if(retval != UA_STATUSCODE_GOOD) { |
| 63367 | unlockClient(client); |
| 63368 | return retval; |
| 63369 | } |
| 63370 | } |
| 63371 | |
| 63372 | /* Prepare the request */ |
| 63373 | UA_FindServersRequest request; |
| 63374 | UA_FindServersRequest_init(p: &request); |
| 63375 | request.serverUrisSize = serverUrisSize; |
| 63376 | request.serverUris = serverUris; |
| 63377 | request.localeIdsSize = localeIdsSize; |
| 63378 | request.localeIds = localeIds; |
| 63379 | |
| 63380 | /* Send the request */ |
| 63381 | UA_FindServersResponse response; |
| 63382 | __Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_FINDSERVERSREQUEST], |
| 63383 | response: &response, responseType: &UA_TYPES[UA_TYPES_FINDSERVERSRESPONSE]); |
| 63384 | |
| 63385 | unlockClient(client); |
| 63386 | |
| 63387 | /* Process the response */ |
| 63388 | retval = response.responseHeader.serviceResult; |
| 63389 | if(retval == UA_STATUSCODE_GOOD) { |
| 63390 | *registeredServersSize = response.serversSize; |
| 63391 | *registeredServers = response.servers; |
| 63392 | response.serversSize = 0; |
| 63393 | response.servers = NULL; |
| 63394 | } else { |
| 63395 | *registeredServersSize = 0; |
| 63396 | *registeredServers = NULL; |
| 63397 | } |
| 63398 | |
| 63399 | /* Clean up */ |
| 63400 | UA_FindServersResponse_clear(p: &response); |
| 63401 | if(!connected) |
| 63402 | UA_Client_disconnect(client); |
| 63403 | return retval; |
| 63404 | } |
| 63405 | |
| 63406 | UA_StatusCode |
| 63407 | UA_Client_findServersOnNetwork(UA_Client *client, const char *serverUrl, |
| 63408 | UA_UInt32 startingRecordId, UA_UInt32 maxRecordsToReturn, |
| 63409 | size_t serverCapabilityFilterSize, UA_String *serverCapabilityFilter, |
| 63410 | size_t *serverOnNetworkSize, UA_ServerOnNetwork **serverOnNetwork) { |
| 63411 | lockClient(client); |
| 63412 | |
| 63413 | UA_Boolean connected = (client->channel.state == UA_SECURECHANNELSTATE_OPEN); |
| 63414 | /* Client is already connected to a different server */ |
| 63415 | if(connected && strncmp(s1: (const char*)client->config.endpoint.endpointUrl.data, s2: serverUrl, |
| 63416 | n: client->config.endpoint.endpointUrl.length) != 0) { |
| 63417 | unlockClient(client); |
| 63418 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 63419 | } |
| 63420 | |
| 63421 | UA_StatusCode retval; |
| 63422 | if(!connected) { |
| 63423 | retval = connectSecureChannel(client, endpointUrl: serverUrl); |
| 63424 | if(retval != UA_STATUSCODE_GOOD) { |
| 63425 | lockClient(client); |
| 63426 | return retval; |
| 63427 | } |
| 63428 | } |
| 63429 | |
| 63430 | /* Prepare the request */ |
| 63431 | UA_FindServersOnNetworkRequest request; |
| 63432 | UA_FindServersOnNetworkRequest_init(p: &request); |
| 63433 | request.startingRecordId = startingRecordId; |
| 63434 | request.maxRecordsToReturn = maxRecordsToReturn; |
| 63435 | request.serverCapabilityFilterSize = serverCapabilityFilterSize; |
| 63436 | request.serverCapabilityFilter = serverCapabilityFilter; |
| 63437 | |
| 63438 | /* Send the request */ |
| 63439 | UA_FindServersOnNetworkResponse response; |
| 63440 | __Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKREQUEST], |
| 63441 | response: &response, responseType: &UA_TYPES[UA_TYPES_FINDSERVERSONNETWORKRESPONSE]); |
| 63442 | |
| 63443 | unlockClient(client); |
| 63444 | |
| 63445 | /* Process the response */ |
| 63446 | retval = response.responseHeader.serviceResult; |
| 63447 | if(retval == UA_STATUSCODE_GOOD) { |
| 63448 | *serverOnNetworkSize = response.serversSize; |
| 63449 | *serverOnNetwork = response.servers; |
| 63450 | response.serversSize = 0; |
| 63451 | response.servers = NULL; |
| 63452 | } else { |
| 63453 | *serverOnNetworkSize = 0; |
| 63454 | *serverOnNetwork = NULL; |
| 63455 | } |
| 63456 | |
| 63457 | /* Clean up */ |
| 63458 | UA_FindServersOnNetworkResponse_clear(p: &response); |
| 63459 | if(!connected) |
| 63460 | UA_Client_disconnect(client); |
| 63461 | return retval; |
| 63462 | } |
| 63463 | |
| 63464 | /**** amalgamated original file "/src/client/ua_client_highlevel.c" ****/ |
| 63465 | |
| 63466 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 63467 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 63468 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 63469 | * |
| 63470 | * Copyright 2015-2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 63471 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 63472 | * Copyright 2017 (c) Florian Palm |
| 63473 | * Copyright 2016 (c) Chris Iatrou |
| 63474 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 63475 | * Copyright 2018 (c) Fabian Arndt |
| 63476 | * Copyright 2018 (c) Peter Rustler, basyskom GmbH |
| 63477 | */ |
| 63478 | |
| 63479 | |
| 63480 | /* The highlevel client API is an "outer onion layer". This file does not |
| 63481 | * include ua_client_internal.h on purpose. */ |
| 63482 | |
| 63483 | UA_StatusCode |
| 63484 | UA_Client_NamespaceGetIndex(UA_Client *client, UA_String *namespaceUri, |
| 63485 | UA_UInt16 *namespaceIndex) { |
| 63486 | UA_ReadRequest request; |
| 63487 | UA_ReadRequest_init(p: &request); |
| 63488 | UA_ReadValueId id; |
| 63489 | UA_ReadValueId_init(p: &id); |
| 63490 | id.attributeId = UA_ATTRIBUTEID_VALUE; |
| 63491 | id.nodeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_NAMESPACEARRAY); |
| 63492 | request.nodesToRead = &id; |
| 63493 | request.nodesToReadSize = 1; |
| 63494 | |
| 63495 | UA_ReadResponse response = UA_Client_Service_read(client, request); |
| 63496 | |
| 63497 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 63498 | if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) |
| 63499 | retval = response.responseHeader.serviceResult; |
| 63500 | else if(response.resultsSize != 1 || !response.results[0].hasValue) |
| 63501 | retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID; |
| 63502 | else if(response.results[0].value.type != &UA_TYPES[UA_TYPES_STRING]) |
| 63503 | retval = UA_STATUSCODE_BADTYPEMISMATCH; |
| 63504 | |
| 63505 | if(retval != UA_STATUSCODE_GOOD) { |
| 63506 | UA_ReadResponse_clear(p: &response); |
| 63507 | return retval; |
| 63508 | } |
| 63509 | |
| 63510 | retval = UA_STATUSCODE_BADNOTFOUND; |
| 63511 | UA_String *ns = (UA_String *)response.results[0].value.data; |
| 63512 | for(size_t i = 0; i < response.results[0].value.arrayLength; ++i) { |
| 63513 | if(UA_String_equal(p1: namespaceUri, p2: &ns[i])) { |
| 63514 | *namespaceIndex = (UA_UInt16)i; |
| 63515 | retval = UA_STATUSCODE_GOOD; |
| 63516 | break; |
| 63517 | } |
| 63518 | } |
| 63519 | |
| 63520 | UA_ReadResponse_clear(p: &response); |
| 63521 | return retval; |
| 63522 | } |
| 63523 | |
| 63524 | UA_StatusCode |
| 63525 | UA_Client_forEachChildNodeCall(UA_Client *client, UA_NodeId parentNodeId, |
| 63526 | UA_NodeIteratorCallback callback, void *handle) { |
| 63527 | UA_BrowseRequest bReq; |
| 63528 | UA_BrowseRequest_init(p: &bReq); |
| 63529 | bReq.requestedMaxReferencesPerNode = 0; |
| 63530 | bReq.nodesToBrowse = UA_BrowseDescription_new(); |
| 63531 | bReq.nodesToBrowseSize = 1; |
| 63532 | UA_NodeId_copy(src: &parentNodeId, dst: &bReq.nodesToBrowse[0].nodeId); |
| 63533 | bReq.nodesToBrowse[0].resultMask = UA_BROWSERESULTMASK_ALL; //return everything |
| 63534 | bReq.nodesToBrowse[0].browseDirection = UA_BROWSEDIRECTION_BOTH; |
| 63535 | |
| 63536 | UA_BrowseResponse bResp = UA_Client_Service_browse(client, request: bReq); |
| 63537 | |
| 63538 | UA_StatusCode retval = bResp.responseHeader.serviceResult; |
| 63539 | if(retval == UA_STATUSCODE_GOOD) { |
| 63540 | for(size_t i = 0; i < bResp.resultsSize; ++i) { |
| 63541 | for(size_t j = 0; j < bResp.results[i].referencesSize; ++j) { |
| 63542 | UA_ReferenceDescription *ref = &bResp.results[i].references[j]; |
| 63543 | retval |= callback(ref->nodeId.nodeId, !ref->isForward, |
| 63544 | ref->referenceTypeId, handle); |
| 63545 | } |
| 63546 | } |
| 63547 | } |
| 63548 | |
| 63549 | UA_BrowseRequest_clear(p: &bReq); |
| 63550 | UA_BrowseResponse_clear(p: &bResp); |
| 63551 | return retval; |
| 63552 | } |
| 63553 | |
| 63554 | /*******************/ |
| 63555 | /* Node Management */ |
| 63556 | /*******************/ |
| 63557 | |
| 63558 | UA_StatusCode |
| 63559 | UA_Client_addReference(UA_Client *client, const UA_NodeId sourceNodeId, |
| 63560 | const UA_NodeId referenceTypeId, UA_Boolean isForward, |
| 63561 | const UA_String targetServerUri, |
| 63562 | const UA_ExpandedNodeId targetNodeId, |
| 63563 | UA_NodeClass targetNodeClass) { |
| 63564 | UA_AddReferencesItem item; |
| 63565 | UA_AddReferencesItem_init(p: &item); |
| 63566 | item.sourceNodeId = sourceNodeId; |
| 63567 | item.referenceTypeId = referenceTypeId; |
| 63568 | item.isForward = isForward; |
| 63569 | item.targetServerUri = targetServerUri; |
| 63570 | item.targetNodeId = targetNodeId; |
| 63571 | item.targetNodeClass = targetNodeClass; |
| 63572 | UA_AddReferencesRequest request; |
| 63573 | UA_AddReferencesRequest_init(p: &request); |
| 63574 | request.referencesToAdd = &item; |
| 63575 | request.referencesToAddSize = 1; |
| 63576 | UA_AddReferencesResponse response = UA_Client_Service_addReferences(client, request); |
| 63577 | UA_StatusCode retval = response.responseHeader.serviceResult; |
| 63578 | if(retval != UA_STATUSCODE_GOOD) { |
| 63579 | UA_AddReferencesResponse_clear(p: &response); |
| 63580 | return retval; |
| 63581 | } |
| 63582 | if(response.resultsSize != 1) { |
| 63583 | UA_AddReferencesResponse_clear(p: &response); |
| 63584 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63585 | } |
| 63586 | retval = response.results[0]; |
| 63587 | UA_AddReferencesResponse_clear(p: &response); |
| 63588 | return retval; |
| 63589 | } |
| 63590 | |
| 63591 | UA_StatusCode |
| 63592 | UA_Client_deleteReference(UA_Client *client, const UA_NodeId sourceNodeId, |
| 63593 | const UA_NodeId referenceTypeId, UA_Boolean isForward, |
| 63594 | const UA_ExpandedNodeId targetNodeId, |
| 63595 | UA_Boolean deleteBidirectional) { |
| 63596 | UA_DeleteReferencesItem item; |
| 63597 | UA_DeleteReferencesItem_init(p: &item); |
| 63598 | item.sourceNodeId = sourceNodeId; |
| 63599 | item.referenceTypeId = referenceTypeId; |
| 63600 | item.isForward = isForward; |
| 63601 | item.targetNodeId = targetNodeId; |
| 63602 | item.deleteBidirectional = deleteBidirectional; |
| 63603 | UA_DeleteReferencesRequest request; |
| 63604 | UA_DeleteReferencesRequest_init(p: &request); |
| 63605 | request.referencesToDelete = &item; |
| 63606 | request.referencesToDeleteSize = 1; |
| 63607 | UA_DeleteReferencesResponse response = UA_Client_Service_deleteReferences(client, request); |
| 63608 | UA_StatusCode retval = response.responseHeader.serviceResult; |
| 63609 | if(retval != UA_STATUSCODE_GOOD) { |
| 63610 | UA_DeleteReferencesResponse_clear(p: &response); |
| 63611 | return retval; |
| 63612 | } |
| 63613 | if(response.resultsSize != 1) { |
| 63614 | UA_DeleteReferencesResponse_clear(p: &response); |
| 63615 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63616 | } |
| 63617 | retval = response.results[0]; |
| 63618 | UA_DeleteReferencesResponse_clear(p: &response); |
| 63619 | return retval; |
| 63620 | } |
| 63621 | |
| 63622 | UA_StatusCode |
| 63623 | UA_Client_deleteNode(UA_Client *client, const UA_NodeId nodeId, |
| 63624 | UA_Boolean deleteTargetReferences) { |
| 63625 | UA_DeleteNodesItem item; |
| 63626 | UA_DeleteNodesItem_init(p: &item); |
| 63627 | item.nodeId = nodeId; |
| 63628 | item.deleteTargetReferences = deleteTargetReferences; |
| 63629 | UA_DeleteNodesRequest request; |
| 63630 | UA_DeleteNodesRequest_init(p: &request); |
| 63631 | request.nodesToDelete = &item; |
| 63632 | request.nodesToDeleteSize = 1; |
| 63633 | UA_DeleteNodesResponse response = UA_Client_Service_deleteNodes(client, request); |
| 63634 | UA_StatusCode retval = response.responseHeader.serviceResult; |
| 63635 | if(retval != UA_STATUSCODE_GOOD) { |
| 63636 | UA_DeleteNodesResponse_clear(p: &response); |
| 63637 | return retval; |
| 63638 | } |
| 63639 | if(response.resultsSize != 1) { |
| 63640 | UA_DeleteNodesResponse_clear(p: &response); |
| 63641 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63642 | } |
| 63643 | retval = response.results[0]; |
| 63644 | UA_DeleteNodesResponse_clear(p: &response); |
| 63645 | return retval; |
| 63646 | } |
| 63647 | |
| 63648 | UA_StatusCode |
| 63649 | __UA_Client_addNode(UA_Client *client, const UA_NodeClass nodeClass, |
| 63650 | const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, |
| 63651 | const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, |
| 63652 | const UA_NodeId typeDefinition, const UA_NodeAttributes *attr, |
| 63653 | const UA_DataType *attributeType, UA_NodeId *outNewNodeId) { |
| 63654 | UA_AddNodesRequest request; |
| 63655 | UA_AddNodesRequest_init(p: &request); |
| 63656 | UA_AddNodesItem item; |
| 63657 | UA_AddNodesItem_init(p: &item); |
| 63658 | item.parentNodeId.nodeId = parentNodeId; |
| 63659 | item.referenceTypeId = referenceTypeId; |
| 63660 | item.requestedNewNodeId.nodeId = requestedNewNodeId; |
| 63661 | item.browseName = browseName; |
| 63662 | item.nodeClass = nodeClass; |
| 63663 | item.typeDefinition.nodeId = typeDefinition; |
| 63664 | item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE; |
| 63665 | item.nodeAttributes.content.decoded.type = attributeType; |
| 63666 | item.nodeAttributes.content.decoded.data = (void*)(uintptr_t)attr; // hack. is not written into. |
| 63667 | request.nodesToAdd = &item; |
| 63668 | request.nodesToAddSize = 1; |
| 63669 | UA_AddNodesResponse response = UA_Client_Service_addNodes(client, request); |
| 63670 | |
| 63671 | UA_StatusCode retval = response.responseHeader.serviceResult; |
| 63672 | if(retval != UA_STATUSCODE_GOOD) { |
| 63673 | UA_AddNodesResponse_clear(p: &response); |
| 63674 | return retval; |
| 63675 | } |
| 63676 | |
| 63677 | if(response.resultsSize != 1) { |
| 63678 | UA_AddNodesResponse_clear(p: &response); |
| 63679 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63680 | } |
| 63681 | |
| 63682 | /* Move the id of the created node */ |
| 63683 | retval = response.results[0].statusCode; |
| 63684 | if(retval == UA_STATUSCODE_GOOD && outNewNodeId) { |
| 63685 | *outNewNodeId = response.results[0].addedNodeId; |
| 63686 | UA_NodeId_init(p: &response.results[0].addedNodeId); |
| 63687 | } |
| 63688 | |
| 63689 | UA_AddNodesResponse_clear(p: &response); |
| 63690 | return retval; |
| 63691 | } |
| 63692 | |
| 63693 | /********/ |
| 63694 | /* Call */ |
| 63695 | /********/ |
| 63696 | |
| 63697 | UA_StatusCode |
| 63698 | UA_Client_call(UA_Client *client, const UA_NodeId objectId, |
| 63699 | const UA_NodeId methodId, size_t inputSize, |
| 63700 | const UA_Variant *input, size_t *outputSize, |
| 63701 | UA_Variant **output) { |
| 63702 | /* Set up the request */ |
| 63703 | UA_CallRequest request; |
| 63704 | UA_CallRequest_init(p: &request); |
| 63705 | UA_CallMethodRequest item; |
| 63706 | UA_CallMethodRequest_init(p: &item); |
| 63707 | item.methodId = methodId; |
| 63708 | item.objectId = objectId; |
| 63709 | item.inputArguments = (UA_Variant *)(void*)(uintptr_t)input; // cast const... |
| 63710 | item.inputArgumentsSize = inputSize; |
| 63711 | request.methodsToCall = &item; |
| 63712 | request.methodsToCallSize = 1; |
| 63713 | |
| 63714 | /* Call the service */ |
| 63715 | UA_CallResponse response = UA_Client_Service_call(client, request); |
| 63716 | UA_StatusCode retval = response.responseHeader.serviceResult; |
| 63717 | if(retval == UA_STATUSCODE_GOOD) { |
| 63718 | if(response.resultsSize == 1) |
| 63719 | retval = response.results[0].statusCode; |
| 63720 | else |
| 63721 | retval = UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63722 | } |
| 63723 | if(UA_StatusCode_isBad(code: retval)) { |
| 63724 | UA_CallResponse_clear(p: &response); |
| 63725 | return retval; |
| 63726 | } |
| 63727 | |
| 63728 | /* Move the output arguments */ |
| 63729 | if(output != NULL && outputSize != NULL) { |
| 63730 | *output = response.results[0].outputArguments; |
| 63731 | *outputSize = response.results[0].outputArgumentsSize; |
| 63732 | response.results[0].outputArguments = NULL; |
| 63733 | response.results[0].outputArgumentsSize = 0; |
| 63734 | } |
| 63735 | UA_CallResponse_clear(p: &response); |
| 63736 | return retval; |
| 63737 | } |
| 63738 | |
| 63739 | /********************/ |
| 63740 | /* Write Attributes */ |
| 63741 | /********************/ |
| 63742 | |
| 63743 | UA_StatusCode |
| 63744 | __UA_Client_writeAttribute(UA_Client *client, const UA_NodeId *nodeId, |
| 63745 | UA_AttributeId attributeId, const void *in, |
| 63746 | const UA_DataType *inDataType) { |
| 63747 | if(!in || !inDataType) |
| 63748 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 63749 | |
| 63750 | UA_WriteValue wValue; |
| 63751 | UA_WriteValue_init(p: &wValue); |
| 63752 | wValue.nodeId = *nodeId; |
| 63753 | wValue.attributeId = attributeId; |
| 63754 | if(attributeId == UA_ATTRIBUTEID_VALUE && |
| 63755 | inDataType == &UA_TYPES[UA_TYPES_VARIANT]) { |
| 63756 | wValue.value.value = *(const UA_Variant*)in; |
| 63757 | wValue.value.hasValue = true; |
| 63758 | } else if(attributeId == UA_ATTRIBUTEID_VALUE && |
| 63759 | inDataType == &UA_TYPES[UA_TYPES_DATAVALUE]) { |
| 63760 | wValue.value = *(const UA_DataValue*)in; |
| 63761 | } else { |
| 63762 | /* Hack to get rid of the const annotation. |
| 63763 | * The value is never written into. */ |
| 63764 | UA_Variant_setScalar(v: &wValue.value.value, p: (void*)(uintptr_t)in, type: inDataType); |
| 63765 | wValue.value.hasValue = true; |
| 63766 | } |
| 63767 | UA_WriteRequest wReq; |
| 63768 | UA_WriteRequest_init(p: &wReq); |
| 63769 | wReq.nodesToWrite = &wValue; |
| 63770 | wReq.nodesToWriteSize = 1; |
| 63771 | |
| 63772 | UA_WriteResponse wResp = UA_Client_Service_write(client, request: wReq); |
| 63773 | |
| 63774 | UA_StatusCode retval = wResp.responseHeader.serviceResult; |
| 63775 | if(retval == UA_STATUSCODE_GOOD) { |
| 63776 | if(wResp.resultsSize == 1) |
| 63777 | retval = wResp.results[0]; |
| 63778 | else |
| 63779 | retval = UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63780 | } |
| 63781 | |
| 63782 | UA_WriteResponse_clear(p: &wResp); |
| 63783 | return retval; |
| 63784 | } |
| 63785 | |
| 63786 | UA_StatusCode |
| 63787 | UA_Client_writeArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId, |
| 63788 | size_t newArrayDimensionsSize, |
| 63789 | const UA_UInt32 *newArrayDimensions) { |
| 63790 | if(!newArrayDimensions) |
| 63791 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 63792 | |
| 63793 | UA_WriteValue wValue; |
| 63794 | UA_WriteValue_init(p: &wValue); |
| 63795 | wValue.nodeId = nodeId; |
| 63796 | wValue.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS; |
| 63797 | UA_Variant_setArray(v: &wValue.value.value, array: (void*)(uintptr_t)newArrayDimensions, |
| 63798 | arraySize: newArrayDimensionsSize, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 63799 | wValue.value.hasValue = true; |
| 63800 | UA_WriteRequest wReq; |
| 63801 | UA_WriteRequest_init(p: &wReq); |
| 63802 | wReq.nodesToWrite = &wValue; |
| 63803 | wReq.nodesToWriteSize = 1; |
| 63804 | |
| 63805 | UA_WriteResponse wResp = UA_Client_Service_write(client, request: wReq); |
| 63806 | |
| 63807 | UA_StatusCode retval = wResp.responseHeader.serviceResult; |
| 63808 | if(retval == UA_STATUSCODE_GOOD) { |
| 63809 | if(wResp.resultsSize == 1) |
| 63810 | retval = wResp.results[0]; |
| 63811 | else |
| 63812 | retval = UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63813 | } |
| 63814 | UA_WriteResponse_clear(p: &wResp); |
| 63815 | return retval; |
| 63816 | } |
| 63817 | |
| 63818 | /*******************/ |
| 63819 | /* Read Attributes */ |
| 63820 | /*******************/ |
| 63821 | |
| 63822 | UA_StatusCode |
| 63823 | __UA_Client_readAttribute(UA_Client *client, const UA_NodeId *nodeId, |
| 63824 | UA_AttributeId attributeId, void *out, |
| 63825 | const UA_DataType *outDataType) { |
| 63826 | UA_ReadValueId item; |
| 63827 | UA_ReadValueId_init(p: &item); |
| 63828 | item.nodeId = *nodeId; |
| 63829 | item.attributeId = attributeId; |
| 63830 | UA_ReadRequest request; |
| 63831 | UA_ReadRequest_init(p: &request); |
| 63832 | request.nodesToRead = &item; |
| 63833 | request.nodesToReadSize = 1; |
| 63834 | UA_ReadResponse response = UA_Client_Service_read(client, request); |
| 63835 | UA_StatusCode retval = response.responseHeader.serviceResult; |
| 63836 | if(retval == UA_STATUSCODE_GOOD) { |
| 63837 | if(response.resultsSize == 1) |
| 63838 | retval = response.results[0].status; |
| 63839 | else |
| 63840 | retval = UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63841 | } |
| 63842 | if(!UA_StatusCode_isEqualTop(s1: retval,UA_STATUSCODE_GOOD)) { |
| 63843 | UA_ReadResponse_clear(p: &response); |
| 63844 | return retval; |
| 63845 | } |
| 63846 | |
| 63847 | /* Set the StatusCode */ |
| 63848 | UA_DataValue *res = response.results; |
| 63849 | if(res->hasStatus) |
| 63850 | retval = res->status; |
| 63851 | |
| 63852 | /* Return early of no value is given */ |
| 63853 | if(!res->hasValue) { |
| 63854 | retval = UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63855 | UA_ReadResponse_clear(p: &response); |
| 63856 | return retval; |
| 63857 | } |
| 63858 | |
| 63859 | /* Copy value into out */ |
| 63860 | if(attributeId == UA_ATTRIBUTEID_VALUE) { |
| 63861 | memcpy(dest: out, src: &res->value, n: sizeof(UA_Variant)); |
| 63862 | UA_Variant_init(p: &res->value); |
| 63863 | } else if(attributeId == UA_ATTRIBUTEID_NODECLASS) { |
| 63864 | memcpy(dest: out, src: (UA_NodeClass*)res->value.data, n: sizeof(UA_NodeClass)); |
| 63865 | } else if(UA_Variant_isScalar(v: &res->value) && |
| 63866 | res->value.type == outDataType) { |
| 63867 | memcpy(dest: out, src: res->value.data, n: res->value.type->memSize); |
| 63868 | UA_free(ptr: res->value.data); |
| 63869 | res->value.data = NULL; |
| 63870 | } else { |
| 63871 | retval = UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63872 | } |
| 63873 | |
| 63874 | UA_ReadResponse_clear(p: &response); |
| 63875 | return retval; |
| 63876 | } |
| 63877 | |
| 63878 | static UA_StatusCode |
| 63879 | processReadArrayDimensionsResult(UA_ReadResponse *response, |
| 63880 | UA_UInt32 **outArrayDimensions, |
| 63881 | size_t *outArrayDimensionsSize) { |
| 63882 | UA_StatusCode retval = response->responseHeader.serviceResult; |
| 63883 | if(retval != UA_STATUSCODE_GOOD) |
| 63884 | return retval; |
| 63885 | |
| 63886 | if(response->resultsSize != 1) |
| 63887 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63888 | |
| 63889 | retval = response->results[0].status; |
| 63890 | if(!UA_StatusCode_isEqualTop(s1: retval,UA_STATUSCODE_GOOD)) |
| 63891 | return retval; |
| 63892 | |
| 63893 | UA_DataValue *res = &response->results[0]; |
| 63894 | if(!res->hasValue || |
| 63895 | UA_Variant_isScalar(v: &res->value) || |
| 63896 | res->value.type != &UA_TYPES[UA_TYPES_UINT32]) |
| 63897 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63898 | |
| 63899 | /* Move results */ |
| 63900 | *outArrayDimensions = (UA_UInt32*)res->value.data; |
| 63901 | *outArrayDimensionsSize = res->value.arrayLength; |
| 63902 | res->value.data = NULL; |
| 63903 | res->value.arrayLength = 0; |
| 63904 | return UA_STATUSCODE_GOOD; |
| 63905 | } |
| 63906 | |
| 63907 | UA_StatusCode |
| 63908 | UA_Client_readArrayDimensionsAttribute(UA_Client *client, const UA_NodeId nodeId, |
| 63909 | size_t *outArrayDimensionsSize, |
| 63910 | UA_UInt32 **outArrayDimensions) { |
| 63911 | UA_ReadValueId item; |
| 63912 | UA_ReadValueId_init(p: &item); |
| 63913 | item.nodeId = nodeId; |
| 63914 | item.attributeId = UA_ATTRIBUTEID_ARRAYDIMENSIONS; |
| 63915 | UA_ReadRequest request; |
| 63916 | UA_ReadRequest_init(p: &request); |
| 63917 | request.nodesToRead = &item; |
| 63918 | request.nodesToReadSize = 1; |
| 63919 | |
| 63920 | UA_ReadResponse response = UA_Client_Service_read(client, request); |
| 63921 | UA_StatusCode retval = processReadArrayDimensionsResult(response: &response, outArrayDimensions, |
| 63922 | outArrayDimensionsSize); |
| 63923 | UA_ReadResponse_clear(p: &response); |
| 63924 | return retval; |
| 63925 | } |
| 63926 | |
| 63927 | /*********************/ |
| 63928 | /* Historical Access */ |
| 63929 | /*********************/ |
| 63930 | |
| 63931 | static UA_HistoryReadResponse |
| 63932 | __UA_Client_HistoryRead(UA_Client *client, const UA_NodeId *nodeId, |
| 63933 | UA_ExtensionObject* details, UA_String indexRange, |
| 63934 | UA_TimestampsToReturn timestampsToReturn, |
| 63935 | UA_ByteString continuationPoint, UA_Boolean releaseConti) { |
| 63936 | |
| 63937 | UA_HistoryReadValueId item; |
| 63938 | UA_HistoryReadValueId_init(p: &item); |
| 63939 | |
| 63940 | item.nodeId = *nodeId; |
| 63941 | item.indexRange = indexRange; |
| 63942 | item.continuationPoint = continuationPoint; |
| 63943 | item.dataEncoding = UA_QUALIFIEDNAME(nsIndex: 0, chars: ""); |
| 63944 | |
| 63945 | UA_HistoryReadRequest request; |
| 63946 | UA_HistoryReadRequest_init(p: &request); |
| 63947 | |
| 63948 | request.nodesToRead = &item; |
| 63949 | request.nodesToReadSize = 1; |
| 63950 | request.timestampsToReturn = timestampsToReturn; // Defaults to Source |
| 63951 | request.releaseContinuationPoints = releaseConti; // No values are returned, if true |
| 63952 | |
| 63953 | /* Build ReadDetails */ |
| 63954 | request.historyReadDetails = *details; |
| 63955 | |
| 63956 | return UA_Client_Service_historyRead(client, request); |
| 63957 | } |
| 63958 | |
| 63959 | static UA_StatusCode |
| 63960 | __UA_Client_HistoryRead_service(UA_Client *client, const UA_NodeId *nodeId, |
| 63961 | const UA_HistoricalIteratorCallback callback, |
| 63962 | UA_ExtensionObject *details, UA_String indexRange, |
| 63963 | UA_TimestampsToReturn timestampsToReturn, |
| 63964 | void *callbackContext) { |
| 63965 | |
| 63966 | UA_ByteString continuationPoint = UA_BYTESTRING_NULL; |
| 63967 | UA_Boolean continuationAvail = false; |
| 63968 | UA_Boolean fetchMore = false; |
| 63969 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 63970 | |
| 63971 | do { |
| 63972 | /* We release the continuation point, if no more data is requested by the user */ |
| 63973 | UA_Boolean cleanup = !fetchMore && continuationAvail; |
| 63974 | UA_HistoryReadResponse response = |
| 63975 | __UA_Client_HistoryRead(client, nodeId, details, indexRange, timestampsToReturn, continuationPoint, releaseConti: cleanup); |
| 63976 | |
| 63977 | if(cleanup) { |
| 63978 | retval = response.responseHeader.serviceResult; |
| 63979 | cleanup: UA_HistoryReadResponse_clear(p: &response); |
| 63980 | UA_ByteString_clear(p: &continuationPoint); |
| 63981 | return retval; |
| 63982 | } |
| 63983 | |
| 63984 | retval = response.responseHeader.serviceResult; |
| 63985 | if(retval == UA_STATUSCODE_GOOD) { |
| 63986 | if(response.resultsSize == 1) |
| 63987 | retval = response.results[0].statusCode; |
| 63988 | else |
| 63989 | retval = UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 63990 | } |
| 63991 | if(!UA_StatusCode_isEqualTop(s1: retval,UA_STATUSCODE_GOOD)) |
| 63992 | goto cleanup; |
| 63993 | |
| 63994 | UA_HistoryReadResult *res = response.results; |
| 63995 | |
| 63996 | /* Clear old and check / store new continuation point */ |
| 63997 | UA_ByteString_clear(p: &continuationPoint); |
| 63998 | UA_ByteString_copy(src: &res->continuationPoint, dst: &continuationPoint); |
| 63999 | continuationAvail = !UA_ByteString_equal(p1: &continuationPoint, p2: &UA_BYTESTRING_NULL); |
| 64000 | |
| 64001 | /* Client callback with possibility to request further values */ |
| 64002 | fetchMore = callback(client, nodeId, continuationAvail, &res->historyData, callbackContext); |
| 64003 | |
| 64004 | /* Regular cleanup */ |
| 64005 | UA_HistoryReadResponse_clear(p: &response); |
| 64006 | } while(continuationAvail); |
| 64007 | |
| 64008 | return retval; |
| 64009 | } |
| 64010 | |
| 64011 | UA_StatusCode |
| 64012 | UA_Client_HistoryRead_events(UA_Client *client, const UA_NodeId *nodeId, |
| 64013 | const UA_HistoricalIteratorCallback callback, |
| 64014 | UA_DateTime startTime, UA_DateTime endTime, |
| 64015 | UA_String indexRange, const UA_EventFilter filter, UA_UInt32 numValuesPerNode, |
| 64016 | UA_TimestampsToReturn timestampsToReturn, void *callbackContext) { |
| 64017 | |
| 64018 | UA_ReadEventDetails details; |
| 64019 | UA_ReadEventDetails_init(p: &details); |
| 64020 | details.filter = filter; |
| 64021 | |
| 64022 | // At least two of the following parameters must be set |
| 64023 | details.numValuesPerNode = numValuesPerNode; // 0 = return all / max server is capable of |
| 64024 | details.startTime = startTime; |
| 64025 | details.endTime = endTime; |
| 64026 | |
| 64027 | UA_ExtensionObject detailsExtensionObject; |
| 64028 | UA_ExtensionObject_init(p: &detailsExtensionObject); |
| 64029 | detailsExtensionObject.content.decoded.type = &UA_TYPES[UA_TYPES_READEVENTDETAILS]; |
| 64030 | detailsExtensionObject.content.decoded.data = &details; |
| 64031 | detailsExtensionObject.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 64032 | |
| 64033 | return __UA_Client_HistoryRead_service(client, nodeId, callback, details: &detailsExtensionObject, |
| 64034 | indexRange, timestampsToReturn, callbackContext); |
| 64035 | } |
| 64036 | |
| 64037 | static UA_StatusCode |
| 64038 | __UA_Client_HistoryRead_service_rawMod(UA_Client *client, const UA_NodeId *nodeId, |
| 64039 | const UA_HistoricalIteratorCallback callback, |
| 64040 | UA_DateTime startTime,UA_DateTime endTime, |
| 64041 | UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 numValuesPerNode, |
| 64042 | UA_Boolean readModified, UA_TimestampsToReturn timestampsToReturn, |
| 64043 | void *callbackContext) { |
| 64044 | |
| 64045 | UA_ReadRawModifiedDetails details; |
| 64046 | UA_ReadRawModifiedDetails_init(p: &details); |
| 64047 | details.isReadModified = readModified; // Return only modified values |
| 64048 | details.returnBounds = returnBounds; // Return values pre / post given range |
| 64049 | |
| 64050 | // At least two of the following parameters must be set |
| 64051 | details.numValuesPerNode = numValuesPerNode; // 0 = return all / max server is capable of |
| 64052 | details.startTime = startTime; |
| 64053 | details.endTime = endTime; |
| 64054 | |
| 64055 | UA_ExtensionObject detailsExtensionObject; |
| 64056 | UA_ExtensionObject_init(p: &detailsExtensionObject); |
| 64057 | detailsExtensionObject.content.decoded.type = &UA_TYPES[UA_TYPES_READRAWMODIFIEDDETAILS]; |
| 64058 | detailsExtensionObject.content.decoded.data = &details; |
| 64059 | detailsExtensionObject.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 64060 | |
| 64061 | return __UA_Client_HistoryRead_service(client, nodeId, callback, |
| 64062 | details: &detailsExtensionObject, indexRange, |
| 64063 | timestampsToReturn, callbackContext); |
| 64064 | } |
| 64065 | |
| 64066 | UA_StatusCode |
| 64067 | UA_Client_HistoryRead_raw(UA_Client *client, const UA_NodeId *nodeId, |
| 64068 | const UA_HistoricalIteratorCallback callback, |
| 64069 | UA_DateTime startTime, UA_DateTime endTime, |
| 64070 | UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 numValuesPerNode, |
| 64071 | UA_TimestampsToReturn timestampsToReturn, void *callbackContext) { |
| 64072 | |
| 64073 | return __UA_Client_HistoryRead_service_rawMod(client, nodeId, callback, startTime, endTime, indexRange, returnBounds, |
| 64074 | numValuesPerNode, false, timestampsToReturn, callbackContext); |
| 64075 | } |
| 64076 | |
| 64077 | UA_StatusCode |
| 64078 | UA_Client_HistoryRead_modified(UA_Client *client, const UA_NodeId *nodeId, |
| 64079 | const UA_HistoricalIteratorCallback callback, |
| 64080 | UA_DateTime startTime, UA_DateTime endTime, |
| 64081 | UA_String indexRange, UA_Boolean returnBounds, UA_UInt32 maxItems, |
| 64082 | UA_TimestampsToReturn timestampsToReturn, void *callbackContext) { |
| 64083 | return __UA_Client_HistoryRead_service_rawMod(client, nodeId, callback, startTime, |
| 64084 | endTime, indexRange, returnBounds, numValuesPerNode: maxItems, |
| 64085 | true, timestampsToReturn, callbackContext); |
| 64086 | } |
| 64087 | |
| 64088 | static UA_HistoryUpdateResponse |
| 64089 | __UA_Client_HistoryUpdate(UA_Client *client, void *details, size_t typeId) { |
| 64090 | UA_HistoryUpdateRequest request; |
| 64091 | UA_HistoryUpdateRequest_init(p: &request); |
| 64092 | |
| 64093 | UA_ExtensionObject extension; |
| 64094 | UA_ExtensionObject_init(p: &extension); |
| 64095 | request.historyUpdateDetailsSize = 1; |
| 64096 | request.historyUpdateDetails = &extension; |
| 64097 | |
| 64098 | extension.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 64099 | extension.content.decoded.type = &UA_TYPES[typeId]; |
| 64100 | extension.content.decoded.data = details; |
| 64101 | |
| 64102 | UA_HistoryUpdateResponse response; |
| 64103 | response = UA_Client_Service_historyUpdate(client, request); |
| 64104 | return response; |
| 64105 | } |
| 64106 | |
| 64107 | static UA_StatusCode |
| 64108 | __UA_Client_HistoryUpdate_updateData(UA_Client *client, const UA_NodeId *nodeId, |
| 64109 | UA_PerformUpdateType type, UA_DataValue *value) { |
| 64110 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 64111 | UA_UpdateDataDetails details; |
| 64112 | UA_UpdateDataDetails_init(p: &details); |
| 64113 | |
| 64114 | details.performInsertReplace = type; |
| 64115 | details.updateValuesSize = 1; |
| 64116 | details.updateValues = value; |
| 64117 | UA_NodeId_copy(src: nodeId, dst: &details.nodeId); |
| 64118 | |
| 64119 | UA_HistoryUpdateResponse response; |
| 64120 | response = __UA_Client_HistoryUpdate(client, details: &details, UA_TYPES_UPDATEDATADETAILS); |
| 64121 | if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 64122 | ret = response.responseHeader.serviceResult; |
| 64123 | goto cleanup; |
| 64124 | } |
| 64125 | if(response.resultsSize != 1 || response.results[0].operationResultsSize != 1) { |
| 64126 | ret = UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 64127 | goto cleanup; |
| 64128 | } |
| 64129 | if(response.results[0].statusCode != UA_STATUSCODE_GOOD) { |
| 64130 | ret = response.results[0].statusCode; |
| 64131 | goto cleanup; |
| 64132 | } |
| 64133 | ret = response.results[0].operationResults[0]; |
| 64134 | cleanup: |
| 64135 | UA_HistoryUpdateResponse_clear(p: &response); |
| 64136 | UA_NodeId_clear(p: &details.nodeId); |
| 64137 | return ret; |
| 64138 | } |
| 64139 | |
| 64140 | UA_StatusCode |
| 64141 | UA_Client_HistoryUpdate_insert(UA_Client *client, const UA_NodeId *nodeId, |
| 64142 | UA_DataValue *value) { |
| 64143 | return __UA_Client_HistoryUpdate_updateData(client, nodeId, |
| 64144 | type: UA_PERFORMUPDATETYPE_INSERT, |
| 64145 | value); |
| 64146 | } |
| 64147 | |
| 64148 | UA_StatusCode |
| 64149 | UA_Client_HistoryUpdate_replace(UA_Client *client, const UA_NodeId *nodeId, |
| 64150 | UA_DataValue *value) { |
| 64151 | return __UA_Client_HistoryUpdate_updateData(client, nodeId, |
| 64152 | type: UA_PERFORMUPDATETYPE_REPLACE, |
| 64153 | value); |
| 64154 | } |
| 64155 | |
| 64156 | UA_StatusCode |
| 64157 | UA_Client_HistoryUpdate_update(UA_Client *client, const UA_NodeId *nodeId, |
| 64158 | UA_DataValue *value) { |
| 64159 | return __UA_Client_HistoryUpdate_updateData(client, nodeId, |
| 64160 | type: UA_PERFORMUPDATETYPE_UPDATE, |
| 64161 | value); |
| 64162 | } |
| 64163 | |
| 64164 | UA_StatusCode |
| 64165 | UA_Client_HistoryUpdate_deleteRaw(UA_Client *client, const UA_NodeId *nodeId, |
| 64166 | UA_DateTime startTimestamp, UA_DateTime endTimestamp) { |
| 64167 | UA_DeleteRawModifiedDetails details; |
| 64168 | UA_DeleteRawModifiedDetails_init(p: &details); |
| 64169 | details.isDeleteModified = false; |
| 64170 | details.startTime = startTimestamp; |
| 64171 | details.endTime = endTimestamp; |
| 64172 | UA_NodeId_copy(src: nodeId, dst: &details.nodeId); |
| 64173 | |
| 64174 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 64175 | UA_HistoryUpdateResponse response; |
| 64176 | response = __UA_Client_HistoryUpdate(client, details: &details, UA_TYPES_DELETERAWMODIFIEDDETAILS); |
| 64177 | if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 64178 | ret = response.responseHeader.serviceResult; |
| 64179 | goto cleanup; |
| 64180 | } |
| 64181 | if(response.resultsSize != 1) { |
| 64182 | ret = UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 64183 | goto cleanup; |
| 64184 | } |
| 64185 | |
| 64186 | ret = response.results[0].statusCode; |
| 64187 | |
| 64188 | cleanup: |
| 64189 | UA_HistoryUpdateResponse_clear(p: &response); |
| 64190 | UA_NodeId_clear(p: &details.nodeId); |
| 64191 | return ret; |
| 64192 | } |
| 64193 | |
| 64194 | /*******************/ |
| 64195 | /* Async Functions */ |
| 64196 | /*******************/ |
| 64197 | |
| 64198 | UA_StatusCode |
| 64199 | __UA_Client_writeAttribute_async(UA_Client *client, const UA_NodeId *nodeId, |
| 64200 | UA_AttributeId attributeId, const void *in, |
| 64201 | const UA_DataType *inDataType, UA_ClientAsyncServiceCallback callback, |
| 64202 | void *userdata, UA_UInt32 *reqId) { |
| 64203 | if(!in) |
| 64204 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 64205 | |
| 64206 | UA_WriteValue wValue; |
| 64207 | UA_WriteValue_init(p: &wValue); |
| 64208 | wValue.nodeId = *nodeId; |
| 64209 | wValue.attributeId = attributeId; |
| 64210 | if(attributeId == UA_ATTRIBUTEID_VALUE) |
| 64211 | wValue.value.value = *(const UA_Variant*) in; |
| 64212 | else |
| 64213 | /* hack. is never written into. */ |
| 64214 | UA_Variant_setScalar(v: &wValue.value.value, p: (void*) (uintptr_t) in, |
| 64215 | type: inDataType); |
| 64216 | wValue.value.hasValue = true; |
| 64217 | UA_WriteRequest wReq; |
| 64218 | UA_WriteRequest_init(p: &wReq); |
| 64219 | wReq.nodesToWrite = &wValue; |
| 64220 | wReq.nodesToWriteSize = 1; |
| 64221 | |
| 64222 | return __UA_Client_AsyncService(client, request: &wReq, |
| 64223 | requestType: &UA_TYPES[UA_TYPES_WRITEREQUEST], callback, |
| 64224 | responseType: &UA_TYPES[UA_TYPES_WRITERESPONSE], userdata, requestId: reqId); |
| 64225 | } |
| 64226 | |
| 64227 | UA_StatusCode |
| 64228 | __UA_Client_addNode_async(UA_Client *client, const UA_NodeClass nodeClass, |
| 64229 | const UA_NodeId requestedNewNodeId, const UA_NodeId parentNodeId, |
| 64230 | const UA_NodeId referenceTypeId, const UA_QualifiedName browseName, |
| 64231 | const UA_NodeId typeDefinition, const UA_NodeAttributes *attr, |
| 64232 | const UA_DataType *attributeType, UA_NodeId *outNewNodeId, |
| 64233 | UA_ClientAsyncServiceCallback callback, void *userdata, |
| 64234 | UA_UInt32 *reqId) { |
| 64235 | UA_AddNodesRequest request; |
| 64236 | UA_AddNodesRequest_init(p: &request); |
| 64237 | UA_AddNodesItem item; |
| 64238 | UA_AddNodesItem_init(p: &item); |
| 64239 | item.parentNodeId.nodeId = parentNodeId; |
| 64240 | item.referenceTypeId = referenceTypeId; |
| 64241 | item.requestedNewNodeId.nodeId = requestedNewNodeId; |
| 64242 | item.browseName = browseName; |
| 64243 | item.nodeClass = nodeClass; |
| 64244 | item.typeDefinition.nodeId = typeDefinition; |
| 64245 | item.nodeAttributes.encoding = UA_EXTENSIONOBJECT_DECODED_NODELETE; |
| 64246 | item.nodeAttributes.content.decoded.type = attributeType; |
| 64247 | item.nodeAttributes.content.decoded.data = (void*) (uintptr_t) attr; // hack. is not written into. |
| 64248 | request.nodesToAdd = &item; |
| 64249 | request.nodesToAddSize = 1; |
| 64250 | |
| 64251 | return __UA_Client_AsyncService(client, request: &request, |
| 64252 | requestType: &UA_TYPES[UA_TYPES_ADDNODESREQUEST], callback, |
| 64253 | responseType: &UA_TYPES[UA_TYPES_ADDNODESRESPONSE], userdata, requestId: reqId); |
| 64254 | |
| 64255 | } |
| 64256 | |
| 64257 | UA_StatusCode |
| 64258 | __UA_Client_call_async(UA_Client *client, const UA_NodeId objectId, |
| 64259 | const UA_NodeId methodId, size_t inputSize, |
| 64260 | const UA_Variant *input, UA_ClientAsyncServiceCallback callback, |
| 64261 | void *userdata, UA_UInt32 *reqId) { |
| 64262 | UA_CallRequest request; |
| 64263 | UA_CallRequest_init(p: &request); |
| 64264 | UA_CallMethodRequest item; |
| 64265 | UA_CallMethodRequest_init(p: &item); |
| 64266 | item.methodId = methodId; |
| 64267 | item.objectId = objectId; |
| 64268 | item.inputArguments = (UA_Variant *) (void*) (uintptr_t) input; // cast const... |
| 64269 | item.inputArgumentsSize = inputSize; |
| 64270 | request.methodsToCall = &item; |
| 64271 | request.methodsToCallSize = 1; |
| 64272 | |
| 64273 | return __UA_Client_AsyncService(client, request: &request, |
| 64274 | requestType: &UA_TYPES[UA_TYPES_CALLREQUEST], callback, |
| 64275 | responseType: &UA_TYPES[UA_TYPES_CALLRESPONSE], userdata, requestId: reqId); |
| 64276 | } |
| 64277 | |
| 64278 | /* UA_StatusCode */ |
| 64279 | /* UA_Cient_translateBrowsePathsToNodeIds_async(UA_Client *client, char **paths, */ |
| 64280 | /* UA_UInt32 *ids, size_t pathSize, */ |
| 64281 | /* UA_ClientAsyncTranslateCallback callback, */ |
| 64282 | /* void *userdata, UA_UInt32 *reqId) { */ |
| 64283 | /* return UA_STATUSCODE_BADNOTIMPLEMENTED; */ |
| 64284 | /* } */ |
| 64285 | |
| 64286 | /*************************/ |
| 64287 | /* Read Single Attribute */ |
| 64288 | /*************************/ |
| 64289 | |
| 64290 | typedef struct { |
| 64291 | UA_ClientAsyncOperationCallback userCallback; |
| 64292 | void *userContext; |
| 64293 | const UA_DataType *resultType; /* DataValue -> Value attribute, |
| 64294 | * Variant -> ArrayDimensions attribute */ |
| 64295 | } UA_AttributeReadContext; |
| 64296 | |
| 64297 | static void |
| 64298 | AttributeReadCallback(UA_Client *client, void *userdata, |
| 64299 | UA_UInt32 requestId, UA_ReadResponse *rr) { |
| 64300 | UA_AttributeReadContext *ctx = (UA_AttributeReadContext*)userdata; |
| 64301 | UA_LOG_DEBUG(logger: UA_Client_getConfig(client)->logging, category: UA_LOGCATEGORY_CLIENT, |
| 64302 | msg: "Async read response for request %"PRIu32, requestId); |
| 64303 | |
| 64304 | UA_DataValue *dv = NULL; |
| 64305 | |
| 64306 | /* Check the ServiceResult */ |
| 64307 | UA_StatusCode res = rr->responseHeader.serviceResult; |
| 64308 | if(res != UA_STATUSCODE_GOOD) |
| 64309 | goto finish; |
| 64310 | |
| 64311 | /* Check result array size */ |
| 64312 | if(rr->resultsSize != 1) { |
| 64313 | res = UA_STATUSCODE_BADINTERNALERROR; |
| 64314 | goto finish; |
| 64315 | } |
| 64316 | |
| 64317 | /* A Value attribute */ |
| 64318 | dv = &rr->results[0]; |
| 64319 | if(ctx->resultType == &UA_TYPES[UA_TYPES_DATAVALUE]) { |
| 64320 | ctx->userCallback(client, ctx->userContext, requestId, |
| 64321 | UA_STATUSCODE_GOOD, dv); |
| 64322 | goto finish; |
| 64323 | } |
| 64324 | |
| 64325 | /* An ArrayDimensions attribute. Has to be an array of UInt32. */ |
| 64326 | if(ctx->resultType == &UA_TYPES[UA_TYPES_VARIANT]) { |
| 64327 | if(dv->hasValue && |
| 64328 | UA_Variant_hasArrayType(v: &dv->value, type: &UA_TYPES[UA_TYPES_UINT32])) { |
| 64329 | ctx->userCallback(client, ctx->userContext, requestId, |
| 64330 | UA_STATUSCODE_GOOD, &dv->value); |
| 64331 | } else { |
| 64332 | res = UA_STATUSCODE_BADINTERNALERROR; |
| 64333 | } |
| 64334 | goto finish; |
| 64335 | } |
| 64336 | |
| 64337 | /* Check we have a value */ |
| 64338 | if(!dv->hasValue) { |
| 64339 | res = UA_STATUSCODE_BADINTERNALERROR; |
| 64340 | goto finish; |
| 64341 | } |
| 64342 | |
| 64343 | /* Check the type. Try to adjust "in situ" if no match. */ |
| 64344 | if(!UA_Variant_hasScalarType(v: &dv->value, type: ctx->resultType)) { |
| 64345 | /* Remember the old pointer, adjustType can "unwrap" a type but won't |
| 64346 | * free the wrapper. Because the server code still keeps the wrapper. */ |
| 64347 | void *oldVal = dv->value.data; |
| 64348 | adjustType(value: &dv->value, targetType: ctx->resultType); |
| 64349 | if(dv->value.data != oldVal) |
| 64350 | UA_free(ptr: oldVal); |
| 64351 | if(!UA_Variant_hasScalarType(v: &dv->value, type: ctx->resultType)) { |
| 64352 | res = UA_STATUSCODE_BADINTERNALERROR; |
| 64353 | goto finish; |
| 64354 | } |
| 64355 | } |
| 64356 | |
| 64357 | /* Callback into userland */ |
| 64358 | ctx->userCallback(client, ctx->userContext, requestId, |
| 64359 | UA_STATUSCODE_GOOD, dv->value.data); |
| 64360 | |
| 64361 | finish: |
| 64362 | if(res != UA_STATUSCODE_GOOD) |
| 64363 | ctx->userCallback(client, ctx->userContext, requestId, res, NULL); |
| 64364 | UA_free(ptr: ctx); |
| 64365 | } |
| 64366 | |
| 64367 | static UA_StatusCode |
| 64368 | readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi, |
| 64369 | UA_TimestampsToReturn timestampsToReturn, |
| 64370 | const UA_DataType *resultType, /* For the specialized reads */ |
| 64371 | UA_ClientAsyncOperationCallback callback, |
| 64372 | void *userdata, UA_UInt32 *requestId) { |
| 64373 | UA_AttributeReadContext *ctx = (UA_AttributeReadContext*) |
| 64374 | UA_malloc(size: sizeof(UA_AttributeReadContext)); |
| 64375 | if(!ctx) |
| 64376 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 64377 | |
| 64378 | ctx->userCallback = callback; |
| 64379 | ctx->userContext = userdata; |
| 64380 | ctx->resultType = resultType; |
| 64381 | |
| 64382 | UA_ReadRequest request; |
| 64383 | UA_ReadRequest_init(p: &request); |
| 64384 | request.nodesToRead = (UA_ReadValueId*)(uintptr_t)rvi; /* hack, treated as const */ |
| 64385 | request.nodesToReadSize = 1; |
| 64386 | request.timestampsToReturn = timestampsToReturn; |
| 64387 | |
| 64388 | UA_StatusCode res = |
| 64389 | __UA_Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_READREQUEST], |
| 64390 | callback: (UA_ClientAsyncServiceCallback)AttributeReadCallback, |
| 64391 | responseType: &UA_TYPES[UA_TYPES_READRESPONSE], userdata: ctx, requestId); |
| 64392 | if(res != UA_STATUSCODE_GOOD) |
| 64393 | UA_free(ptr: ctx); |
| 64394 | return res; |
| 64395 | } |
| 64396 | |
| 64397 | UA_StatusCode |
| 64398 | UA_Client_readAttribute_async(UA_Client *client, const UA_ReadValueId *rvi, |
| 64399 | UA_TimestampsToReturn timestampsToReturn, |
| 64400 | UA_ClientAsyncReadAttributeCallback callback, |
| 64401 | void *userdata, UA_UInt32 *requestId) { |
| 64402 | return readAttribute_async(client, rvi, timestampsToReturn, |
| 64403 | resultType: &UA_TYPES[UA_TYPES_DATAVALUE], /* special handling */ |
| 64404 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64405 | userdata, requestId); |
| 64406 | } |
| 64407 | |
| 64408 | /* Helper to keep the code short */ |
| 64409 | static UA_StatusCode |
| 64410 | readAttribute_simpleAsync(UA_Client *client, const UA_NodeId *nodeId, |
| 64411 | UA_AttributeId attributeId, const UA_DataType *resultType, |
| 64412 | UA_ClientAsyncOperationCallback callback, |
| 64413 | void *userdata, UA_UInt32 *requestId) { |
| 64414 | UA_ReadValueId rvi; |
| 64415 | UA_ReadValueId_init(p: &rvi); |
| 64416 | rvi.nodeId = *nodeId; |
| 64417 | rvi.attributeId = attributeId; |
| 64418 | return readAttribute_async(client, rvi: &rvi, timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER, |
| 64419 | resultType, callback, userdata, requestId); |
| 64420 | } |
| 64421 | |
| 64422 | UA_StatusCode |
| 64423 | UA_Client_readValueAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64424 | UA_ClientAsyncReadValueAttributeCallback callback, |
| 64425 | void *userdata, UA_UInt32 *requestId) { |
| 64426 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_VALUE, |
| 64427 | resultType: &UA_TYPES[UA_TYPES_DATAVALUE], /* special hndling */ |
| 64428 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64429 | userdata, requestId); |
| 64430 | } |
| 64431 | |
| 64432 | UA_StatusCode |
| 64433 | UA_Client_readDataTypeAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64434 | UA_ClientAsyncReadDataTypeAttributeCallback callback, |
| 64435 | void *userdata, UA_UInt32 *requestId) { |
| 64436 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_DATATYPE, |
| 64437 | resultType: &UA_TYPES[UA_TYPES_NODEID], |
| 64438 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64439 | userdata, requestId); |
| 64440 | } |
| 64441 | |
| 64442 | UA_StatusCode |
| 64443 | UA_Client_readArrayDimensionsAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64444 | UA_ClientReadArrayDimensionsAttributeCallback callback, |
| 64445 | void *userdata, UA_UInt32 *requestId) { |
| 64446 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_ARRAYDIMENSIONS, |
| 64447 | resultType: &UA_TYPES[UA_TYPES_VARIANT], /* special handling */ |
| 64448 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64449 | userdata, requestId); |
| 64450 | } |
| 64451 | |
| 64452 | UA_StatusCode |
| 64453 | UA_Client_readNodeClassAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64454 | UA_ClientAsyncReadNodeClassAttributeCallback callback, |
| 64455 | void *userdata, UA_UInt32 *requestId) { |
| 64456 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_NODECLASS, |
| 64457 | resultType: &UA_TYPES[UA_TYPES_NODECLASS], |
| 64458 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64459 | userdata, requestId); |
| 64460 | } |
| 64461 | |
| 64462 | UA_StatusCode |
| 64463 | UA_Client_readBrowseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64464 | UA_ClientAsyncReadBrowseNameAttributeCallback callback, |
| 64465 | void *userdata, UA_UInt32 *requestId) { |
| 64466 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_BROWSENAME, |
| 64467 | resultType: &UA_TYPES[UA_TYPES_QUALIFIEDNAME], |
| 64468 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64469 | userdata, requestId); |
| 64470 | } |
| 64471 | |
| 64472 | UA_StatusCode |
| 64473 | UA_Client_readDisplayNameAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64474 | UA_ClientAsyncReadDisplayNameAttributeCallback callback, |
| 64475 | void *userdata, UA_UInt32 *requestId) { |
| 64476 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_DISPLAYNAME, |
| 64477 | resultType: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], |
| 64478 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64479 | userdata, requestId); |
| 64480 | } |
| 64481 | |
| 64482 | UA_StatusCode |
| 64483 | UA_Client_readDescriptionAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64484 | UA_ClientAsyncReadDescriptionAttributeCallback callback, |
| 64485 | void *userdata, UA_UInt32 *requestId) { |
| 64486 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_DESCRIPTION, |
| 64487 | resultType: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], |
| 64488 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64489 | userdata, requestId); |
| 64490 | } |
| 64491 | |
| 64492 | UA_StatusCode |
| 64493 | UA_Client_readWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64494 | UA_ClientAsyncReadWriteMaskAttributeCallback callback, |
| 64495 | void *userdata, UA_UInt32 *requestId) { |
| 64496 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_WRITEMASK, |
| 64497 | resultType: &UA_TYPES[UA_TYPES_UINT32], |
| 64498 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64499 | userdata, requestId); |
| 64500 | } |
| 64501 | |
| 64502 | UA_StatusCode UA_EXPORT |
| 64503 | UA_Client_readUserWriteMaskAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64504 | UA_ClientAsyncReadUserWriteMaskAttributeCallback callback, |
| 64505 | void *userdata, UA_UInt32 *requestId) { |
| 64506 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_USERWRITEMASK, |
| 64507 | resultType: &UA_TYPES[UA_TYPES_UINT32], |
| 64508 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64509 | userdata, requestId); |
| 64510 | } |
| 64511 | |
| 64512 | UA_StatusCode |
| 64513 | UA_Client_readIsAbstractAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64514 | UA_ClientAsyncReadIsAbstractAttributeCallback callback, |
| 64515 | void *userdata, UA_UInt32 *requestId) { |
| 64516 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_ISABSTRACT, |
| 64517 | resultType: &UA_TYPES[UA_TYPES_BOOLEAN], |
| 64518 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64519 | userdata, requestId); |
| 64520 | } |
| 64521 | |
| 64522 | UA_StatusCode |
| 64523 | UA_Client_readSymmetricAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64524 | UA_ClientAsyncReadSymmetricAttributeCallback callback, |
| 64525 | void *userdata, UA_UInt32 *requestId) { |
| 64526 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_SYMMETRIC, |
| 64527 | resultType: &UA_TYPES[UA_TYPES_BOOLEAN], |
| 64528 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64529 | userdata, requestId); |
| 64530 | } |
| 64531 | |
| 64532 | UA_StatusCode |
| 64533 | UA_Client_readInverseNameAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64534 | UA_ClientAsyncReadInverseNameAttributeCallback callback, |
| 64535 | void *userdata, UA_UInt32 *requestId) { |
| 64536 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_INVERSENAME, |
| 64537 | resultType: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT], |
| 64538 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64539 | userdata, requestId); |
| 64540 | } |
| 64541 | |
| 64542 | UA_StatusCode |
| 64543 | UA_Client_readContainsNoLoopsAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64544 | UA_ClientAsyncReadContainsNoLoopsAttributeCallback callback, |
| 64545 | void *userdata, UA_UInt32 *requestId) { |
| 64546 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_CONTAINSNOLOOPS, |
| 64547 | resultType: &UA_TYPES[UA_TYPES_BOOLEAN], |
| 64548 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64549 | userdata, requestId); |
| 64550 | } |
| 64551 | |
| 64552 | UA_StatusCode |
| 64553 | UA_Client_readEventNotifierAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64554 | UA_ClientAsyncReadEventNotifierAttributeCallback callback, |
| 64555 | void *userdata, UA_UInt32 *requestId) { |
| 64556 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_EVENTNOTIFIER, |
| 64557 | resultType: &UA_TYPES[UA_TYPES_BYTE], |
| 64558 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64559 | userdata, requestId); |
| 64560 | } |
| 64561 | |
| 64562 | UA_StatusCode |
| 64563 | UA_Client_readValueRankAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64564 | UA_ClientAsyncReadValueRankAttributeCallback callback, |
| 64565 | void *userdata, UA_UInt32 *requestId) { |
| 64566 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_VALUERANK, |
| 64567 | resultType: &UA_TYPES[UA_TYPES_INT32], |
| 64568 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64569 | userdata, requestId); |
| 64570 | } |
| 64571 | |
| 64572 | UA_StatusCode |
| 64573 | UA_Client_readAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64574 | UA_ClientAsyncReadAccessLevelAttributeCallback callback, |
| 64575 | void *userdata, UA_UInt32 *requestId) { |
| 64576 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_ACCESSLEVEL, |
| 64577 | resultType: &UA_TYPES[UA_TYPES_BYTE], |
| 64578 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64579 | userdata, requestId); |
| 64580 | } |
| 64581 | |
| 64582 | UA_StatusCode |
| 64583 | UA_Client_readAccessLevelExAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64584 | UA_ClientAsyncReadAccessLevelExAttributeCallback callback, |
| 64585 | void *userdata, UA_UInt32 *requestId) { |
| 64586 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_ACCESSLEVELEX, |
| 64587 | resultType: &UA_TYPES[UA_TYPES_UINT32], |
| 64588 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64589 | userdata, requestId); |
| 64590 | } |
| 64591 | |
| 64592 | UA_StatusCode |
| 64593 | UA_Client_readUserAccessLevelAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64594 | UA_ClientAsyncReadUserAccessLevelAttributeCallback callback, |
| 64595 | void *userdata, UA_UInt32 *requestId) { |
| 64596 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_USERACCESSLEVEL, |
| 64597 | resultType: &UA_TYPES[UA_TYPES_BYTE], |
| 64598 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64599 | userdata, requestId); |
| 64600 | } |
| 64601 | |
| 64602 | UA_StatusCode |
| 64603 | UA_Client_readMinimumSamplingIntervalAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64604 | UA_ClientAsyncReadMinimumSamplingIntervalAttributeCallback callback, |
| 64605 | void *userdata, UA_UInt32 *requestId) { |
| 64606 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_MINIMUMSAMPLINGINTERVAL, |
| 64607 | resultType: &UA_TYPES[UA_TYPES_DOUBLE], |
| 64608 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64609 | userdata, requestId); |
| 64610 | } |
| 64611 | |
| 64612 | UA_StatusCode |
| 64613 | UA_Client_readHistorizingAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64614 | UA_ClientAsyncReadHistorizingAttributeCallback callback, |
| 64615 | void *userdata, UA_UInt32 *requestId) { |
| 64616 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_HISTORIZING, |
| 64617 | resultType: &UA_TYPES[UA_TYPES_BOOLEAN], |
| 64618 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64619 | userdata, requestId); |
| 64620 | } |
| 64621 | |
| 64622 | UA_StatusCode |
| 64623 | UA_Client_readExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64624 | UA_ClientAsyncReadExecutableAttributeCallback callback, |
| 64625 | void *userdata, UA_UInt32 *requestId) { |
| 64626 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_EXECUTABLE, |
| 64627 | resultType: &UA_TYPES[UA_TYPES_BOOLEAN], |
| 64628 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64629 | userdata, requestId); |
| 64630 | } |
| 64631 | |
| 64632 | UA_StatusCode |
| 64633 | UA_Client_readUserExecutableAttribute_async(UA_Client *client, const UA_NodeId nodeId, |
| 64634 | UA_ClientAsyncReadUserExecutableAttributeCallback callback, |
| 64635 | void *userdata, UA_UInt32 *requestId) { |
| 64636 | return readAttribute_simpleAsync(client, nodeId: &nodeId, attributeId: UA_ATTRIBUTEID_USEREXECUTABLE, |
| 64637 | resultType: &UA_TYPES[UA_TYPES_BOOLEAN], |
| 64638 | callback: (UA_ClientAsyncOperationCallback)callback, |
| 64639 | userdata, requestId); |
| 64640 | } |
| 64641 | |
| 64642 | /**** amalgamated original file "/src/client/ua_client_subscriptions.c" ****/ |
| 64643 | |
| 64644 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 64645 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 64646 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 64647 | * |
| 64648 | * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 64649 | * Copyright 2015 (c) Oleksiy Vasylyev |
| 64650 | * Copyright 2016 (c) Sten Grüner |
| 64651 | * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA |
| 64652 | * Copyright 2016-2017 (c) Florian Palm |
| 64653 | * Copyright 2017 (c) Frank Meerkötter |
| 64654 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 64655 | */ |
| 64656 | |
| 64657 | |
| 64658 | |
| 64659 | struct UA_Client_MonitoredItem_ForDelete { |
| 64660 | UA_Client *client; |
| 64661 | UA_Client_Subscription *sub; |
| 64662 | UA_UInt32 *monitoredItemId; |
| 64663 | }; |
| 64664 | |
| 64665 | /*****************/ |
| 64666 | /* Subscriptions */ |
| 64667 | /*****************/ |
| 64668 | |
| 64669 | static enum ZIP_CMP |
| 64670 | /* For ZIP_TREE we use clientHandle comparison */ |
| 64671 | UA_ClientHandle_cmp(const void *a, const void *b) { |
| 64672 | const UA_Client_MonitoredItem *aa = (const UA_Client_MonitoredItem *)a; |
| 64673 | const UA_Client_MonitoredItem *bb = (const UA_Client_MonitoredItem *)b; |
| 64674 | |
| 64675 | /* Compare clientHandle */ |
| 64676 | if(aa->clientHandle < bb->clientHandle) { |
| 64677 | return ZIP_CMP_LESS; |
| 64678 | } |
| 64679 | if(aa->clientHandle > bb->clientHandle) { |
| 64680 | return ZIP_CMP_MORE; |
| 64681 | } |
| 64682 | |
| 64683 | return ZIP_CMP_EQ; |
| 64684 | } |
| 64685 | |
| 64686 | ZIP_FUNCTIONS(MonitorItemsTree, UA_Client_MonitoredItem, zipfields, |
| 64687 | UA_Client_MonitoredItem, zipfields, UA_ClientHandle_cmp) |
| 64688 | |
| 64689 | static void |
| 64690 | MonitoredItem_delete(UA_Client *client, UA_Client_Subscription *sub, |
| 64691 | UA_Client_MonitoredItem *mon); |
| 64692 | |
| 64693 | static void |
| 64694 | ua_Subscriptions_create(UA_Client *client, UA_Client_Subscription *newSub, |
| 64695 | UA_CreateSubscriptionResponse *response) { |
| 64696 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 64697 | |
| 64698 | newSub->subscriptionId = response->subscriptionId; |
| 64699 | newSub->sequenceNumber = 0; |
| 64700 | newSub->lastActivity = UA_DateTime_nowMonotonic(); |
| 64701 | newSub->publishingInterval = response->revisedPublishingInterval; |
| 64702 | newSub->maxKeepAliveCount = response->revisedMaxKeepAliveCount; |
| 64703 | ZIP_INIT(&newSub->monitoredItems); |
| 64704 | LIST_INSERT_HEAD(&client->subscriptions, newSub, listEntry); |
| 64705 | |
| 64706 | /* Immediately send the first publish requests if there are none |
| 64707 | * outstanding */ |
| 64708 | __Client_Subscriptions_backgroundPublish(client); |
| 64709 | } |
| 64710 | |
| 64711 | static void |
| 64712 | ua_Subscriptions_create_handler(UA_Client *client, void *data, |
| 64713 | UA_UInt32 requestId, void *r) { |
| 64714 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 64715 | |
| 64716 | UA_CreateSubscriptionResponse *response = (UA_CreateSubscriptionResponse *)r; |
| 64717 | CustomCallback *cc = (CustomCallback *)data; |
| 64718 | UA_Client_Subscription *newSub = (UA_Client_Subscription *)cc->clientData; |
| 64719 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 64720 | UA_free(ptr: newSub); |
| 64721 | goto cleanup; |
| 64722 | } |
| 64723 | |
| 64724 | /* Prepare the internal representation */ |
| 64725 | ua_Subscriptions_create(client, newSub, response); |
| 64726 | |
| 64727 | cleanup: |
| 64728 | if(cc->userCallback) |
| 64729 | cc->userCallback(client, cc->userData, requestId, response); |
| 64730 | UA_free(ptr: cc); |
| 64731 | } |
| 64732 | |
| 64733 | UA_CreateSubscriptionResponse |
| 64734 | UA_Client_Subscriptions_create(UA_Client *client, |
| 64735 | const UA_CreateSubscriptionRequest request, |
| 64736 | void *subscriptionContext, |
| 64737 | UA_Client_StatusChangeNotificationCallback statusChangeCallback, |
| 64738 | UA_Client_DeleteSubscriptionCallback deleteCallback) { |
| 64739 | lockClient(client); |
| 64740 | |
| 64741 | UA_CreateSubscriptionResponse response; |
| 64742 | UA_Client_Subscription *sub = (UA_Client_Subscription *) |
| 64743 | UA_malloc(size: sizeof(UA_Client_Subscription)); |
| 64744 | if(!sub) { |
| 64745 | UA_CreateSubscriptionResponse_init(p: &response); |
| 64746 | response.responseHeader.serviceResult = UA_STATUSCODE_BADOUTOFMEMORY; |
| 64747 | unlockClient(client); |
| 64748 | return response; |
| 64749 | } |
| 64750 | sub->context = subscriptionContext; |
| 64751 | sub->statusChangeCallback = statusChangeCallback; |
| 64752 | sub->deleteCallback = deleteCallback; |
| 64753 | |
| 64754 | /* Send the request as a synchronous service call */ |
| 64755 | __Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST], |
| 64756 | response: &response, responseType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE]); |
| 64757 | if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 64758 | UA_free(ptr: sub); |
| 64759 | unlockClient(client); |
| 64760 | return response; |
| 64761 | } |
| 64762 | |
| 64763 | ua_Subscriptions_create(client, newSub: sub, response: &response); |
| 64764 | |
| 64765 | unlockClient(client); |
| 64766 | return response; |
| 64767 | } |
| 64768 | |
| 64769 | UA_StatusCode |
| 64770 | UA_Client_Subscriptions_create_async(UA_Client *client, |
| 64771 | const UA_CreateSubscriptionRequest request, |
| 64772 | void *subscriptionContext, |
| 64773 | UA_Client_StatusChangeNotificationCallback statusChangeCallback, |
| 64774 | UA_Client_DeleteSubscriptionCallback deleteCallback, |
| 64775 | UA_ClientAsyncServiceCallback createCallback, |
| 64776 | void *userdata, |
| 64777 | UA_UInt32 *requestId) { |
| 64778 | CustomCallback *cc = (CustomCallback *)UA_calloc(nmemb: 1, size: sizeof(CustomCallback)); |
| 64779 | if(!cc) |
| 64780 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 64781 | |
| 64782 | UA_Client_Subscription *sub = (UA_Client_Subscription *) |
| 64783 | UA_malloc(size: sizeof(UA_Client_Subscription)); |
| 64784 | if(!sub) { |
| 64785 | UA_free(ptr: cc); |
| 64786 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 64787 | } |
| 64788 | sub->context = subscriptionContext; |
| 64789 | sub->statusChangeCallback = statusChangeCallback; |
| 64790 | sub->deleteCallback = deleteCallback; |
| 64791 | |
| 64792 | cc->userCallback = createCallback; |
| 64793 | cc->userData = userdata; |
| 64794 | cc->clientData = sub; |
| 64795 | |
| 64796 | /* Send the request as asynchronous service call */ |
| 64797 | return __UA_Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONREQUEST], |
| 64798 | callback: ua_Subscriptions_create_handler, responseType: &UA_TYPES[UA_TYPES_CREATESUBSCRIPTIONRESPONSE], |
| 64799 | userdata: cc, requestId); |
| 64800 | } |
| 64801 | |
| 64802 | static UA_Client_Subscription * |
| 64803 | findSubscription(const UA_Client *client, UA_UInt32 subscriptionId) { |
| 64804 | UA_Client_Subscription *sub = NULL; |
| 64805 | LIST_FOREACH(sub, &client->subscriptions, listEntry) { |
| 64806 | if(sub->subscriptionId == subscriptionId) |
| 64807 | break; |
| 64808 | } |
| 64809 | return sub; |
| 64810 | } |
| 64811 | |
| 64812 | static void |
| 64813 | ua_Subscriptions_modify(UA_Client *client, UA_Client_Subscription *sub, |
| 64814 | const UA_ModifySubscriptionResponse *response) { |
| 64815 | sub->publishingInterval = response->revisedPublishingInterval; |
| 64816 | sub->maxKeepAliveCount = response->revisedMaxKeepAliveCount; |
| 64817 | } |
| 64818 | |
| 64819 | static void |
| 64820 | ua_Subscriptions_modify_handler(UA_Client *client, void *data, UA_UInt32 requestId, |
| 64821 | void *r) { |
| 64822 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 64823 | |
| 64824 | UA_ModifySubscriptionResponse *response = (UA_ModifySubscriptionResponse *)r; |
| 64825 | CustomCallback *cc = (CustomCallback *)data; |
| 64826 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: (UA_UInt32)(uintptr_t)cc->clientData); |
| 64827 | if(sub) { |
| 64828 | ua_Subscriptions_modify(client, sub, response); |
| 64829 | } else { |
| 64830 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 64831 | msg: "No internal representation of subscription %"PRIu32, |
| 64832 | (UA_UInt32)(uintptr_t)cc->clientData); |
| 64833 | } |
| 64834 | |
| 64835 | if(cc->userCallback) |
| 64836 | cc->userCallback(client, cc->userData, requestId, response); |
| 64837 | UA_free(ptr: cc); |
| 64838 | } |
| 64839 | |
| 64840 | UA_ModifySubscriptionResponse |
| 64841 | UA_Client_Subscriptions_modify(UA_Client *client, |
| 64842 | const UA_ModifySubscriptionRequest request) { |
| 64843 | UA_ModifySubscriptionResponse response; |
| 64844 | UA_ModifySubscriptionResponse_init(p: &response); |
| 64845 | |
| 64846 | /* Find the internal representation */ |
| 64847 | lockClient(client); |
| 64848 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId); |
| 64849 | if(!sub) { |
| 64850 | unlockClient(client); |
| 64851 | response.responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 64852 | return response; |
| 64853 | } |
| 64854 | |
| 64855 | /* Call the service */ |
| 64856 | __Client_Service(client, |
| 64857 | request: &request, requestType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST], |
| 64858 | response: &response, responseType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE]); |
| 64859 | |
| 64860 | /* Adjust the internal representation. Lookup again for thread-safety. */ |
| 64861 | sub = findSubscription(client, subscriptionId: request.subscriptionId); |
| 64862 | if(!sub) { |
| 64863 | response.responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 64864 | unlockClient(client); |
| 64865 | return response; |
| 64866 | } |
| 64867 | ua_Subscriptions_modify(client, sub, response: &response); |
| 64868 | unlockClient(client); |
| 64869 | return response; |
| 64870 | } |
| 64871 | |
| 64872 | UA_StatusCode |
| 64873 | UA_Client_Subscriptions_modify_async(UA_Client *client, |
| 64874 | const UA_ModifySubscriptionRequest request, |
| 64875 | UA_ClientAsyncServiceCallback callback, |
| 64876 | void *userdata, UA_UInt32 *requestId) { |
| 64877 | lockClient(client); |
| 64878 | |
| 64879 | /* Find the internal representation */ |
| 64880 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId); |
| 64881 | if(!sub) { |
| 64882 | unlockClient(client); |
| 64883 | return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 64884 | } |
| 64885 | |
| 64886 | CustomCallback *cc = (CustomCallback *)UA_calloc(nmemb: 1, size: sizeof(CustomCallback)); |
| 64887 | if(!cc) { |
| 64888 | unlockClient(client); |
| 64889 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 64890 | } |
| 64891 | |
| 64892 | cc->clientData = (void *)(uintptr_t)request.subscriptionId; |
| 64893 | cc->userData = userdata; |
| 64894 | cc->userCallback = callback; |
| 64895 | |
| 64896 | UA_StatusCode res = |
| 64897 | __Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONREQUEST], |
| 64898 | callback: ua_Subscriptions_modify_handler, responseType: &UA_TYPES[UA_TYPES_MODIFYSUBSCRIPTIONRESPONSE], |
| 64899 | userdata: cc, requestId); |
| 64900 | |
| 64901 | unlockClient(client); |
| 64902 | return res; |
| 64903 | } |
| 64904 | |
| 64905 | static void * |
| 64906 | UA_MonitoredItem_delete_wrapper(void *data, UA_Client_MonitoredItem *mon) { |
| 64907 | struct UA_Client_MonitoredItem_ForDelete *deleteMonitoredItem = |
| 64908 | (struct UA_Client_MonitoredItem_ForDelete *)data; |
| 64909 | if(deleteMonitoredItem != NULL) { |
| 64910 | if(deleteMonitoredItem->monitoredItemId != NULL && |
| 64911 | (mon->monitoredItemId != *deleteMonitoredItem->monitoredItemId)) { |
| 64912 | return NULL; |
| 64913 | } |
| 64914 | MonitoredItem_delete(client: deleteMonitoredItem->client, sub: deleteMonitoredItem->sub, mon); |
| 64915 | } |
| 64916 | return NULL; |
| 64917 | } |
| 64918 | |
| 64919 | static void |
| 64920 | __Client_Subscription_deleteInternal(UA_Client *client, |
| 64921 | UA_Client_Subscription *sub) { |
| 64922 | /* Remove the MonitoredItems */ |
| 64923 | struct UA_Client_MonitoredItem_ForDelete deleteMonitoredItem; |
| 64924 | memset(s: &deleteMonitoredItem, c: 0, n: sizeof(struct UA_Client_MonitoredItem_ForDelete)); |
| 64925 | deleteMonitoredItem.client = client; |
| 64926 | deleteMonitoredItem.sub = sub; |
| 64927 | ZIP_ITER(MonitorItemsTree, &sub->monitoredItems, |
| 64928 | UA_MonitoredItem_delete_wrapper, &deleteMonitoredItem); |
| 64929 | |
| 64930 | /* Call the delete callback */ |
| 64931 | if(sub->deleteCallback) { |
| 64932 | void *subC = sub->context; |
| 64933 | UA_UInt32 subId = sub->subscriptionId; |
| 64934 | sub->deleteCallback(client, subId, subC); |
| 64935 | } |
| 64936 | |
| 64937 | /* Remove */ |
| 64938 | LIST_REMOVE(sub, listEntry); |
| 64939 | UA_free(ptr: sub); |
| 64940 | } |
| 64941 | |
| 64942 | static void |
| 64943 | __Client_Subscription_processDelete(UA_Client *client, |
| 64944 | const UA_DeleteSubscriptionsRequest *request, |
| 64945 | const UA_DeleteSubscriptionsResponse *response) { |
| 64946 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) |
| 64947 | return; |
| 64948 | |
| 64949 | /* Check that the request and response size -- use the same index for both */ |
| 64950 | if(request->subscriptionIdsSize != response->resultsSize) |
| 64951 | return; |
| 64952 | |
| 64953 | for(size_t i = 0; i < request->subscriptionIdsSize; i++) { |
| 64954 | if(response->results[i] != UA_STATUSCODE_GOOD && |
| 64955 | response->results[i] != UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID) |
| 64956 | continue; |
| 64957 | |
| 64958 | /* Get the Subscription */ |
| 64959 | UA_Client_Subscription *sub = |
| 64960 | findSubscription(client, subscriptionId: request->subscriptionIds[i]); |
| 64961 | if(!sub) { |
| 64962 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 64963 | msg: "No internal representation of subscription %"PRIu32, |
| 64964 | request->subscriptionIds[i]); |
| 64965 | continue; |
| 64966 | } |
| 64967 | |
| 64968 | /* Delete the Subscription */ |
| 64969 | __Client_Subscription_deleteInternal(client, sub); |
| 64970 | } |
| 64971 | } |
| 64972 | |
| 64973 | typedef struct { |
| 64974 | UA_DeleteSubscriptionsRequest request; |
| 64975 | UA_ClientAsyncServiceCallback userCallback; |
| 64976 | void *userData; |
| 64977 | } DeleteSubscriptionCallback; |
| 64978 | |
| 64979 | static void |
| 64980 | ua_Subscriptions_delete_handler(UA_Client *client, void *data, |
| 64981 | UA_UInt32 requestId, void *r) { |
| 64982 | UA_DeleteSubscriptionsResponse *response = |
| 64983 | (UA_DeleteSubscriptionsResponse *)r; |
| 64984 | DeleteSubscriptionCallback *dsc = |
| 64985 | (DeleteSubscriptionCallback*)data; |
| 64986 | |
| 64987 | lockClient(client); |
| 64988 | |
| 64989 | /* Delete */ |
| 64990 | __Client_Subscription_processDelete(client, request: &dsc->request, response); |
| 64991 | |
| 64992 | /* Userland Callback */ |
| 64993 | dsc->userCallback(client, dsc->userData, requestId, response); |
| 64994 | |
| 64995 | /* Cleanup */ |
| 64996 | UA_DeleteSubscriptionsRequest_clear(p: &dsc->request); |
| 64997 | UA_free(ptr: dsc); |
| 64998 | |
| 64999 | unlockClient(client); |
| 65000 | } |
| 65001 | |
| 65002 | UA_StatusCode |
| 65003 | UA_Client_Subscriptions_delete_async(UA_Client *client, |
| 65004 | const UA_DeleteSubscriptionsRequest request, |
| 65005 | UA_ClientAsyncServiceCallback callback, |
| 65006 | void *userdata, UA_UInt32 *requestId) { |
| 65007 | /* Make a copy of the request that persists into the async callback */ |
| 65008 | DeleteSubscriptionCallback *dsc = (DeleteSubscriptionCallback*) |
| 65009 | UA_malloc(size: sizeof(DeleteSubscriptionCallback)); |
| 65010 | if(!dsc) |
| 65011 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 65012 | dsc->userCallback = callback; |
| 65013 | dsc->userData = userdata; |
| 65014 | UA_StatusCode res = UA_DeleteSubscriptionsRequest_copy(src: &request, dst: &dsc->request); |
| 65015 | if(res != UA_STATUSCODE_GOOD) { |
| 65016 | UA_free(ptr: dsc); |
| 65017 | return res; |
| 65018 | } |
| 65019 | |
| 65020 | /* Make the async call */ |
| 65021 | return __UA_Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST], |
| 65022 | callback: ua_Subscriptions_delete_handler, responseType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE], |
| 65023 | userdata: dsc, requestId); |
| 65024 | } |
| 65025 | |
| 65026 | UA_DeleteSubscriptionsResponse |
| 65027 | UA_Client_Subscriptions_delete(UA_Client *client, |
| 65028 | const UA_DeleteSubscriptionsRequest request) { |
| 65029 | lockClient(client); |
| 65030 | |
| 65031 | /* Send the request */ |
| 65032 | UA_DeleteSubscriptionsResponse response; |
| 65033 | __Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSREQUEST], |
| 65034 | response: &response, responseType: &UA_TYPES[UA_TYPES_DELETESUBSCRIPTIONSRESPONSE]); |
| 65035 | |
| 65036 | /* Process */ |
| 65037 | __Client_Subscription_processDelete(client, request: &request, response: &response); |
| 65038 | |
| 65039 | unlockClient(client); |
| 65040 | return response; |
| 65041 | } |
| 65042 | |
| 65043 | UA_StatusCode |
| 65044 | UA_Client_Subscriptions_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId) { |
| 65045 | UA_DeleteSubscriptionsRequest request; |
| 65046 | UA_DeleteSubscriptionsRequest_init(p: &request); |
| 65047 | request.subscriptionIds = &subscriptionId; |
| 65048 | request.subscriptionIdsSize = 1; |
| 65049 | |
| 65050 | UA_DeleteSubscriptionsResponse response = |
| 65051 | UA_Client_Subscriptions_delete(client, request); |
| 65052 | |
| 65053 | UA_StatusCode retval = response.responseHeader.serviceResult; |
| 65054 | if(retval != UA_STATUSCODE_GOOD) { |
| 65055 | UA_DeleteSubscriptionsResponse_clear(p: &response); |
| 65056 | return retval; |
| 65057 | } |
| 65058 | |
| 65059 | if(response.resultsSize != 1) { |
| 65060 | UA_DeleteSubscriptionsResponse_clear(p: &response); |
| 65061 | return UA_STATUSCODE_BADINTERNALERROR; |
| 65062 | } |
| 65063 | |
| 65064 | retval = response.results[0]; |
| 65065 | UA_DeleteSubscriptionsResponse_clear(p: &response); |
| 65066 | return retval; |
| 65067 | } |
| 65068 | |
| 65069 | /******************/ |
| 65070 | /* MonitoredItems */ |
| 65071 | /******************/ |
| 65072 | |
| 65073 | static void |
| 65074 | MonitoredItem_delete(UA_Client *client, UA_Client_Subscription *sub, |
| 65075 | UA_Client_MonitoredItem *mon) { |
| 65076 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 65077 | |
| 65078 | ZIP_REMOVE(MonitorItemsTree, &sub->monitoredItems, mon); |
| 65079 | if(mon->deleteCallback) { |
| 65080 | void *subC = sub->context; |
| 65081 | void *monC = mon->context; |
| 65082 | UA_UInt32 subId = sub->subscriptionId; |
| 65083 | UA_UInt32 monId = mon->monitoredItemId; |
| 65084 | mon->deleteCallback(client, subId, subC, monId, monC); |
| 65085 | } |
| 65086 | UA_free(ptr: mon); |
| 65087 | } |
| 65088 | |
| 65089 | typedef struct { |
| 65090 | void **contexts; |
| 65091 | UA_Client_DeleteMonitoredItemCallback *deleteCallbacks; |
| 65092 | void **handlingCallbacks; |
| 65093 | UA_CreateMonitoredItemsRequest request; |
| 65094 | |
| 65095 | /* Notify the user that the async callback was processed */ |
| 65096 | UA_ClientAsyncServiceCallback userCallback; |
| 65097 | void *userData; |
| 65098 | } MonitoredItems_CreateData; |
| 65099 | |
| 65100 | static void |
| 65101 | MonitoredItems_CreateData_clear(UA_Client *client, MonitoredItems_CreateData *data) { |
| 65102 | UA_free(ptr: data->contexts); |
| 65103 | UA_free(ptr: data->deleteCallbacks); |
| 65104 | UA_free(ptr: data->handlingCallbacks); |
| 65105 | UA_CreateMonitoredItemsRequest_clear(p: &data->request); |
| 65106 | } |
| 65107 | |
| 65108 | static void |
| 65109 | ua_MonitoredItems_create(UA_Client *client, MonitoredItems_CreateData *data, |
| 65110 | UA_CreateMonitoredItemsResponse *response) { |
| 65111 | UA_CreateMonitoredItemsRequest *request = &data->request; |
| 65112 | UA_Client_DeleteMonitoredItemCallback *deleteCallbacks = data->deleteCallbacks; |
| 65113 | |
| 65114 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: data->request.subscriptionId); |
| 65115 | if(!sub) |
| 65116 | goto cleanup; |
| 65117 | |
| 65118 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) |
| 65119 | goto cleanup; |
| 65120 | |
| 65121 | if(response->resultsSize != request->itemsToCreateSize) { |
| 65122 | response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; |
| 65123 | goto cleanup; |
| 65124 | } |
| 65125 | |
| 65126 | /* Add internally */ |
| 65127 | for(size_t i = 0; i < request->itemsToCreateSize; i++) { |
| 65128 | if(response->results[i].statusCode != UA_STATUSCODE_GOOD) { |
| 65129 | void *subC = sub->context; |
| 65130 | UA_UInt32 subId = sub->subscriptionId; |
| 65131 | if(deleteCallbacks[i]) |
| 65132 | deleteCallbacks[i](client, subId, subC, 0, data->contexts[i]); |
| 65133 | continue; |
| 65134 | } |
| 65135 | |
| 65136 | UA_Client_MonitoredItem *newMon = (UA_Client_MonitoredItem *) |
| 65137 | UA_malloc(size: sizeof(UA_Client_MonitoredItem)); |
| 65138 | if(!newMon) { |
| 65139 | void *subC = sub->context; |
| 65140 | UA_UInt32 subId = sub->subscriptionId; |
| 65141 | if(deleteCallbacks[i]) |
| 65142 | deleteCallbacks[i](client, subId, subC, 0, data->contexts[i]); |
| 65143 | continue; |
| 65144 | } |
| 65145 | |
| 65146 | newMon->monitoredItemId = response->results[i].monitoredItemId; |
| 65147 | newMon->clientHandle = request->itemsToCreate[i].requestedParameters.clientHandle; |
| 65148 | newMon->context = data->contexts[i]; |
| 65149 | newMon->deleteCallback = deleteCallbacks[i]; |
| 65150 | newMon->handler.dataChangeCallback = |
| 65151 | (UA_Client_DataChangeNotificationCallback)(uintptr_t) |
| 65152 | data->handlingCallbacks[i]; |
| 65153 | newMon->isEventMonitoredItem = |
| 65154 | (request->itemsToCreate[i].itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER); |
| 65155 | ZIP_INSERT(MonitorItemsTree, &sub->monitoredItems, newMon); |
| 65156 | |
| 65157 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65158 | msg: "Subscription %"PRIu32 " | Added a MonitoredItem with handle %"PRIu32, |
| 65159 | sub->subscriptionId, newMon->clientHandle); |
| 65160 | } |
| 65161 | return; |
| 65162 | |
| 65163 | /* Adding failed */ |
| 65164 | cleanup: |
| 65165 | for(size_t i = 0; i < request->itemsToCreateSize; i++) { |
| 65166 | void *subC = sub ? sub->context : NULL; |
| 65167 | if(deleteCallbacks[i]) |
| 65168 | deleteCallbacks[i](client, data->request.subscriptionId, |
| 65169 | subC, 0, data->contexts[i]); |
| 65170 | } |
| 65171 | } |
| 65172 | |
| 65173 | static void |
| 65174 | ua_MonitoredItems_create_async_handler(UA_Client *client, void *d, UA_UInt32 requestId, |
| 65175 | void *r) { |
| 65176 | UA_CreateMonitoredItemsResponse *response = (UA_CreateMonitoredItemsResponse *)r; |
| 65177 | MonitoredItems_CreateData *data = (MonitoredItems_CreateData *)d; |
| 65178 | |
| 65179 | lockClient(client); |
| 65180 | |
| 65181 | ua_MonitoredItems_create(client, data, response); |
| 65182 | MonitoredItems_CreateData_clear(client, data); |
| 65183 | |
| 65184 | if(data->userCallback) |
| 65185 | data->userCallback(client, data->userData, requestId, response); |
| 65186 | |
| 65187 | UA_free(ptr: data); |
| 65188 | |
| 65189 | unlockClient(client); |
| 65190 | } |
| 65191 | |
| 65192 | static UA_StatusCode |
| 65193 | MonitoredItems_CreateData_prepare(UA_Client *client, |
| 65194 | const UA_CreateMonitoredItemsRequest *request, |
| 65195 | void **contexts, void **handlingCallbacks, |
| 65196 | UA_Client_DeleteMonitoredItemCallback *deleteCallbacks, |
| 65197 | MonitoredItems_CreateData *data) { |
| 65198 | /* Align arrays and copy over */ |
| 65199 | UA_StatusCode retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 65200 | data->contexts = (void **)UA_calloc(nmemb: request->itemsToCreateSize, size: sizeof(void *)); |
| 65201 | if(!data->contexts) |
| 65202 | goto cleanup; |
| 65203 | if(contexts) |
| 65204 | memcpy(dest: data->contexts, src: contexts, n: request->itemsToCreateSize * sizeof(void *)); |
| 65205 | |
| 65206 | data->deleteCallbacks = (UA_Client_DeleteMonitoredItemCallback *) |
| 65207 | UA_calloc(nmemb: request->itemsToCreateSize, size: sizeof(UA_Client_DeleteMonitoredItemCallback)); |
| 65208 | if(!data->deleteCallbacks) |
| 65209 | goto cleanup; |
| 65210 | if(deleteCallbacks) |
| 65211 | memcpy(dest: data->deleteCallbacks, src: deleteCallbacks, |
| 65212 | n: request->itemsToCreateSize * sizeof(UA_Client_DeleteMonitoredItemCallback)); |
| 65213 | |
| 65214 | data->handlingCallbacks = (void **) |
| 65215 | UA_calloc(nmemb: request->itemsToCreateSize, size: sizeof(void *)); |
| 65216 | if(!data->handlingCallbacks) |
| 65217 | goto cleanup; |
| 65218 | if(handlingCallbacks) |
| 65219 | memcpy(dest: data->handlingCallbacks, src: handlingCallbacks, |
| 65220 | n: request->itemsToCreateSize * sizeof(void *)); |
| 65221 | |
| 65222 | retval = UA_CreateMonitoredItemsRequest_copy(src: request, dst: &data->request); |
| 65223 | if(retval != UA_STATUSCODE_GOOD) |
| 65224 | goto cleanup; |
| 65225 | |
| 65226 | /* Set the clientHandle */ |
| 65227 | for(size_t i = 0; i < data->request.itemsToCreateSize; i++) |
| 65228 | data->request.itemsToCreate[i].requestedParameters.clientHandle = |
| 65229 | ++client->monitoredItemHandles; |
| 65230 | |
| 65231 | return UA_STATUSCODE_GOOD; |
| 65232 | |
| 65233 | cleanup: |
| 65234 | MonitoredItems_CreateData_clear(client, data); |
| 65235 | return retval; |
| 65236 | } |
| 65237 | |
| 65238 | static void |
| 65239 | ua_Client_MonitoredItems_create(UA_Client *client, |
| 65240 | const UA_CreateMonitoredItemsRequest *request, |
| 65241 | void **contexts, void **handlingCallbacks, |
| 65242 | UA_Client_DeleteMonitoredItemCallback *deleteCallbacks, |
| 65243 | UA_CreateMonitoredItemsResponse *response) { |
| 65244 | UA_CreateMonitoredItemsResponse_init(p: response); |
| 65245 | |
| 65246 | if(!request->itemsToCreateSize) { |
| 65247 | response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; |
| 65248 | return; |
| 65249 | } |
| 65250 | |
| 65251 | /* Test if the subscription is valid */ |
| 65252 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request->subscriptionId); |
| 65253 | if(!sub) { |
| 65254 | response->responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 65255 | return; |
| 65256 | } |
| 65257 | |
| 65258 | MonitoredItems_CreateData data; |
| 65259 | memset(s: &data, c: 0, n: sizeof(MonitoredItems_CreateData)); |
| 65260 | |
| 65261 | UA_StatusCode res = |
| 65262 | MonitoredItems_CreateData_prepare(client, request, contexts, handlingCallbacks, |
| 65263 | deleteCallbacks, data: &data); |
| 65264 | if(res != UA_STATUSCODE_GOOD) { |
| 65265 | response->responseHeader.serviceResult = res; |
| 65266 | return; |
| 65267 | } |
| 65268 | |
| 65269 | /* Call the service. Use data->request as it contains the client handle |
| 65270 | * information. */ |
| 65271 | __Client_Service(client, request: &data.request, |
| 65272 | requestType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST], |
| 65273 | response, responseType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE]); |
| 65274 | |
| 65275 | /* Add internal representation */ |
| 65276 | ua_MonitoredItems_create(client, data: &data, response); |
| 65277 | |
| 65278 | MonitoredItems_CreateData_clear(client, data: &data); |
| 65279 | } |
| 65280 | |
| 65281 | static UA_StatusCode |
| 65282 | createDataChanges_async(UA_Client *client, const UA_CreateMonitoredItemsRequest request, |
| 65283 | void **contexts, void **callbacks, |
| 65284 | UA_Client_DeleteMonitoredItemCallback *deleteCallbacks, |
| 65285 | UA_ClientAsyncServiceCallback createCallback, void *userdata, |
| 65286 | UA_UInt32 *requestId) { |
| 65287 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 65288 | |
| 65289 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId); |
| 65290 | if(!sub) |
| 65291 | return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 65292 | |
| 65293 | MonitoredItems_CreateData *data = (MonitoredItems_CreateData *) |
| 65294 | UA_calloc(nmemb: 1, size: sizeof(MonitoredItems_CreateData)); |
| 65295 | if(!data) |
| 65296 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 65297 | |
| 65298 | data->userCallback = createCallback; |
| 65299 | data->userData = userdata; |
| 65300 | |
| 65301 | UA_StatusCode res = |
| 65302 | MonitoredItems_CreateData_prepare(client, request: &request, contexts, |
| 65303 | handlingCallbacks: callbacks, deleteCallbacks, data); |
| 65304 | if(res != UA_STATUSCODE_GOOD) { |
| 65305 | UA_free(ptr: data); |
| 65306 | return res; |
| 65307 | } |
| 65308 | |
| 65309 | return __Client_AsyncService(client, request: &data->request, |
| 65310 | requestType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSREQUEST], |
| 65311 | callback: ua_MonitoredItems_create_async_handler, |
| 65312 | responseType: &UA_TYPES[UA_TYPES_CREATEMONITOREDITEMSRESPONSE], |
| 65313 | userdata: data, requestId); |
| 65314 | } |
| 65315 | |
| 65316 | UA_CreateMonitoredItemsResponse |
| 65317 | UA_Client_MonitoredItems_createDataChanges(UA_Client *client, |
| 65318 | const UA_CreateMonitoredItemsRequest request, |
| 65319 | void **contexts, |
| 65320 | UA_Client_DataChangeNotificationCallback *callbacks, |
| 65321 | UA_Client_DeleteMonitoredItemCallback *deleteCallbacks) { |
| 65322 | UA_CreateMonitoredItemsResponse response; |
| 65323 | lockClient(client); |
| 65324 | ua_Client_MonitoredItems_create(client, request: &request, contexts, handlingCallbacks: (void **)callbacks, |
| 65325 | deleteCallbacks, response: &response); |
| 65326 | unlockClient(client); |
| 65327 | return response; |
| 65328 | } |
| 65329 | |
| 65330 | UA_StatusCode |
| 65331 | UA_Client_MonitoredItems_createDataChanges_async(UA_Client *client, |
| 65332 | const UA_CreateMonitoredItemsRequest request, |
| 65333 | void **contexts, |
| 65334 | UA_Client_DataChangeNotificationCallback *callbacks, |
| 65335 | UA_Client_DeleteMonitoredItemCallback *deleteCallbacks, |
| 65336 | UA_ClientAsyncServiceCallback createCallback, |
| 65337 | void *userdata, UA_UInt32 *requestId) { |
| 65338 | lockClient(client); |
| 65339 | UA_StatusCode res = |
| 65340 | createDataChanges_async(client, request, contexts, callbacks: (void **)callbacks, |
| 65341 | deleteCallbacks, createCallback, userdata, requestId); |
| 65342 | unlockClient(client); |
| 65343 | return res; |
| 65344 | } |
| 65345 | |
| 65346 | UA_MonitoredItemCreateResult |
| 65347 | UA_Client_MonitoredItems_createDataChange(UA_Client *client, UA_UInt32 subscriptionId, |
| 65348 | UA_TimestampsToReturn timestampsToReturn, |
| 65349 | const UA_MonitoredItemCreateRequest item, |
| 65350 | void *context, |
| 65351 | UA_Client_DataChangeNotificationCallback callback, |
| 65352 | UA_Client_DeleteMonitoredItemCallback deleteCallback) { |
| 65353 | UA_CreateMonitoredItemsRequest request; |
| 65354 | UA_CreateMonitoredItemsRequest_init(p: &request); |
| 65355 | request.subscriptionId = subscriptionId; |
| 65356 | request.timestampsToReturn = timestampsToReturn; |
| 65357 | request.itemsToCreate = (UA_MonitoredItemCreateRequest*)(uintptr_t)&item; |
| 65358 | request.itemsToCreateSize = 1; |
| 65359 | UA_CreateMonitoredItemsResponse response = |
| 65360 | UA_Client_MonitoredItems_createDataChanges(client, request, contexts: &context, |
| 65361 | callbacks: &callback, deleteCallbacks: &deleteCallback); |
| 65362 | UA_MonitoredItemCreateResult result; |
| 65363 | UA_MonitoredItemCreateResult_init(p: &result); |
| 65364 | if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) |
| 65365 | result.statusCode = response.responseHeader.serviceResult; |
| 65366 | |
| 65367 | if(result.statusCode == UA_STATUSCODE_GOOD && |
| 65368 | response.resultsSize != 1) |
| 65369 | result.statusCode = UA_STATUSCODE_BADINTERNALERROR; |
| 65370 | |
| 65371 | if(result.statusCode == UA_STATUSCODE_GOOD) |
| 65372 | UA_MonitoredItemCreateResult_copy(src: &response.results[0] , dst: &result); |
| 65373 | UA_CreateMonitoredItemsResponse_clear(p: &response); |
| 65374 | return result; |
| 65375 | } |
| 65376 | |
| 65377 | UA_CreateMonitoredItemsResponse |
| 65378 | UA_Client_MonitoredItems_createEvents(UA_Client *client, |
| 65379 | const UA_CreateMonitoredItemsRequest request, |
| 65380 | void **contexts, |
| 65381 | UA_Client_EventNotificationCallback *callback, |
| 65382 | UA_Client_DeleteMonitoredItemCallback *deleteCallback) { |
| 65383 | UA_CreateMonitoredItemsResponse response; |
| 65384 | lockClient(client); |
| 65385 | ua_Client_MonitoredItems_create(client, request: &request, contexts, handlingCallbacks: (void **)callback, |
| 65386 | deleteCallbacks: deleteCallback, response: &response); |
| 65387 | unlockClient(client); |
| 65388 | return response; |
| 65389 | } |
| 65390 | |
| 65391 | /* Monitor the EventNotifier attribute only */ |
| 65392 | UA_StatusCode |
| 65393 | UA_Client_MonitoredItems_createEvents_async(UA_Client *client, |
| 65394 | const UA_CreateMonitoredItemsRequest request, |
| 65395 | void **contexts, |
| 65396 | UA_Client_EventNotificationCallback *callbacks, |
| 65397 | UA_Client_DeleteMonitoredItemCallback *deleteCallbacks, |
| 65398 | UA_ClientAsyncServiceCallback createCallback, |
| 65399 | void *userdata, UA_UInt32 *requestId) { |
| 65400 | lockClient(client); |
| 65401 | UA_StatusCode res = |
| 65402 | createDataChanges_async(client, request, contexts, callbacks: (void **)callbacks, deleteCallbacks, |
| 65403 | createCallback, userdata, requestId); |
| 65404 | unlockClient(client); |
| 65405 | return res; |
| 65406 | } |
| 65407 | |
| 65408 | UA_MonitoredItemCreateResult |
| 65409 | UA_Client_MonitoredItems_createEvent(UA_Client *client, UA_UInt32 subscriptionId, |
| 65410 | UA_TimestampsToReturn timestampsToReturn, |
| 65411 | const UA_MonitoredItemCreateRequest item, void *context, |
| 65412 | UA_Client_EventNotificationCallback callback, |
| 65413 | UA_Client_DeleteMonitoredItemCallback deleteCallback) { |
| 65414 | UA_CreateMonitoredItemsRequest request; |
| 65415 | UA_CreateMonitoredItemsRequest_init(p: &request); |
| 65416 | request.subscriptionId = subscriptionId; |
| 65417 | request.timestampsToReturn = timestampsToReturn; |
| 65418 | request.itemsToCreate = (UA_MonitoredItemCreateRequest*)(uintptr_t)&item; |
| 65419 | request.itemsToCreateSize = 1; |
| 65420 | UA_CreateMonitoredItemsResponse response = |
| 65421 | UA_Client_MonitoredItems_createEvents(client, request, contexts: &context, |
| 65422 | callback: &callback, deleteCallback: &deleteCallback); |
| 65423 | UA_StatusCode retval = response.responseHeader.serviceResult; |
| 65424 | UA_MonitoredItemCreateResult result; |
| 65425 | UA_MonitoredItemCreateResult_init(p: &result); |
| 65426 | if(retval != UA_STATUSCODE_GOOD) { |
| 65427 | UA_CreateMonitoredItemsResponse_clear(p: &response); |
| 65428 | result.statusCode = retval; |
| 65429 | return result; |
| 65430 | } |
| 65431 | UA_MonitoredItemCreateResult_copy(src: response.results , dst: &result); |
| 65432 | UA_CreateMonitoredItemsResponse_clear(p: &response); |
| 65433 | return result; |
| 65434 | } |
| 65435 | |
| 65436 | static void |
| 65437 | ua_MonitoredItems_delete(UA_Client *client, UA_Client_Subscription *sub, |
| 65438 | const UA_DeleteMonitoredItemsRequest *request, |
| 65439 | const UA_DeleteMonitoredItemsResponse *response) { |
| 65440 | #ifdef __clang_analyzer__ |
| 65441 | return; |
| 65442 | #endif |
| 65443 | |
| 65444 | /* Loop over deleted MonitoredItems */ |
| 65445 | struct UA_Client_MonitoredItem_ForDelete deleteMonitoredItem; |
| 65446 | memset(s: &deleteMonitoredItem, c: 0, n: sizeof(struct UA_Client_MonitoredItem_ForDelete)); |
| 65447 | deleteMonitoredItem.client = client; |
| 65448 | deleteMonitoredItem.sub = sub; |
| 65449 | |
| 65450 | for(size_t i = 0; i < response->resultsSize; i++) { |
| 65451 | if(response->results[i] != UA_STATUSCODE_GOOD && |
| 65452 | response->results[i] != UA_STATUSCODE_BADMONITOREDITEMIDINVALID) { |
| 65453 | continue; |
| 65454 | } |
| 65455 | deleteMonitoredItem.monitoredItemId = &request->monitoredItemIds[i]; |
| 65456 | /* Delete the internal representation */ |
| 65457 | ZIP_ITER(MonitorItemsTree,&sub->monitoredItems, |
| 65458 | UA_MonitoredItem_delete_wrapper, &deleteMonitoredItem); |
| 65459 | } |
| 65460 | } |
| 65461 | |
| 65462 | static void |
| 65463 | ua_MonitoredItems_delete_handler(UA_Client *client, void *d, UA_UInt32 requestId, void *r) { |
| 65464 | UA_Client_Subscription *sub = NULL; |
| 65465 | CustomCallback *cc = (CustomCallback *)d; |
| 65466 | UA_DeleteMonitoredItemsResponse *response = (UA_DeleteMonitoredItemsResponse *)r; |
| 65467 | UA_DeleteMonitoredItemsRequest *request = |
| 65468 | (UA_DeleteMonitoredItemsRequest *)cc->clientData; |
| 65469 | |
| 65470 | lockClient(client); |
| 65471 | |
| 65472 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) |
| 65473 | goto cleanup; |
| 65474 | |
| 65475 | sub = findSubscription(client, subscriptionId: request->subscriptionId); |
| 65476 | if(!sub) { |
| 65477 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65478 | msg: "No internal representation of subscription %"PRIu32, |
| 65479 | request->subscriptionId); |
| 65480 | goto cleanup; |
| 65481 | } |
| 65482 | |
| 65483 | /* Delete MonitoredItems from the internal representation */ |
| 65484 | ua_MonitoredItems_delete(client, sub, request, response); |
| 65485 | |
| 65486 | cleanup: |
| 65487 | if(cc->userCallback) |
| 65488 | cc->userCallback(client, cc->userData, requestId, response); |
| 65489 | UA_DeleteMonitoredItemsRequest_delete(p: request); |
| 65490 | UA_free(ptr: cc); |
| 65491 | |
| 65492 | unlockClient(client); |
| 65493 | } |
| 65494 | |
| 65495 | UA_DeleteMonitoredItemsResponse |
| 65496 | UA_Client_MonitoredItems_delete(UA_Client *client, |
| 65497 | const UA_DeleteMonitoredItemsRequest request) { |
| 65498 | /* Send the request */ |
| 65499 | UA_DeleteMonitoredItemsResponse response; |
| 65500 | __UA_Client_Service(client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST], |
| 65501 | response: &response, responseType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE]); |
| 65502 | |
| 65503 | /* A problem occured remote? */ |
| 65504 | if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD) |
| 65505 | return response; |
| 65506 | |
| 65507 | lockClient(client); |
| 65508 | |
| 65509 | /* Find the internal subscription representation */ |
| 65510 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId); |
| 65511 | if(!sub) { |
| 65512 | UA_LOG_INFO(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65513 | msg: "No internal representation of subscription %"PRIu32, |
| 65514 | request.subscriptionId); |
| 65515 | unlockClient(client); |
| 65516 | return response; |
| 65517 | } |
| 65518 | |
| 65519 | /* Remove MonitoredItems in the internal representation */ |
| 65520 | ua_MonitoredItems_delete(client, sub, request: &request, response: &response); |
| 65521 | |
| 65522 | unlockClient(client); |
| 65523 | |
| 65524 | return response; |
| 65525 | } |
| 65526 | |
| 65527 | UA_StatusCode |
| 65528 | UA_Client_MonitoredItems_delete_async(UA_Client *client, |
| 65529 | const UA_DeleteMonitoredItemsRequest request, |
| 65530 | UA_ClientAsyncServiceCallback callback, |
| 65531 | void *userdata, UA_UInt32 *requestId) { |
| 65532 | /* Send the request */ |
| 65533 | CustomCallback *cc = (CustomCallback *)UA_calloc(nmemb: 1, size: sizeof(CustomCallback)); |
| 65534 | if(!cc) |
| 65535 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 65536 | |
| 65537 | UA_DeleteMonitoredItemsRequest *req_copy = UA_DeleteMonitoredItemsRequest_new(); |
| 65538 | if(!req_copy) { |
| 65539 | UA_free(ptr: cc); |
| 65540 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 65541 | } |
| 65542 | |
| 65543 | UA_DeleteMonitoredItemsRequest_copy(src: &request, dst: req_copy); |
| 65544 | cc->clientData = req_copy; |
| 65545 | cc->userCallback = callback; |
| 65546 | cc->userData = userdata; |
| 65547 | |
| 65548 | return __UA_Client_AsyncService(client, request: &request, requestType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSREQUEST], |
| 65549 | callback: ua_MonitoredItems_delete_handler, |
| 65550 | responseType: &UA_TYPES[UA_TYPES_DELETEMONITOREDITEMSRESPONSE], userdata: cc, requestId); |
| 65551 | } |
| 65552 | |
| 65553 | UA_StatusCode |
| 65554 | UA_Client_MonitoredItems_deleteSingle(UA_Client *client, UA_UInt32 subscriptionId, |
| 65555 | UA_UInt32 monitoredItemId) { |
| 65556 | UA_DeleteMonitoredItemsRequest request; |
| 65557 | UA_DeleteMonitoredItemsRequest_init(p: &request); |
| 65558 | request.subscriptionId = subscriptionId; |
| 65559 | request.monitoredItemIds = &monitoredItemId; |
| 65560 | request.monitoredItemIdsSize = 1; |
| 65561 | |
| 65562 | UA_DeleteMonitoredItemsResponse response = |
| 65563 | UA_Client_MonitoredItems_delete(client, request); |
| 65564 | |
| 65565 | UA_StatusCode retval = response.responseHeader.serviceResult; |
| 65566 | if(retval != UA_STATUSCODE_GOOD) { |
| 65567 | UA_DeleteMonitoredItemsResponse_clear(p: &response); |
| 65568 | return retval; |
| 65569 | } |
| 65570 | |
| 65571 | if(response.resultsSize != 1) { |
| 65572 | UA_DeleteMonitoredItemsResponse_clear(p: &response); |
| 65573 | return UA_STATUSCODE_BADINTERNALERROR; |
| 65574 | } |
| 65575 | |
| 65576 | retval = response.results[0]; |
| 65577 | UA_DeleteMonitoredItemsResponse_clear(p: &response); |
| 65578 | return retval; |
| 65579 | } |
| 65580 | |
| 65581 | static void * |
| 65582 | UA_MonitoredItem_change_clientHandle_wrapper(void *data, UA_Client_MonitoredItem *mon) { |
| 65583 | UA_MonitoredItemModifyRequest *monitoredItemModifyRequest = |
| 65584 | (UA_MonitoredItemModifyRequest *)data; |
| 65585 | if(monitoredItemModifyRequest && |
| 65586 | mon->monitoredItemId == monitoredItemModifyRequest->monitoredItemId) |
| 65587 | monitoredItemModifyRequest->requestedParameters.clientHandle = mon->clientHandle; |
| 65588 | return NULL; |
| 65589 | } |
| 65590 | |
| 65591 | static void |
| 65592 | UA_MonitoredItem_change_clientHandle(UA_Client_Subscription *sub, |
| 65593 | UA_ModifyMonitoredItemsRequest *request) { |
| 65594 | for(size_t i = 0; i < request->itemsToModifySize; ++i) { |
| 65595 | ZIP_ITER(MonitorItemsTree, &sub->monitoredItems, |
| 65596 | UA_MonitoredItem_change_clientHandle_wrapper, |
| 65597 | &request->itemsToModify[i]); |
| 65598 | } |
| 65599 | } |
| 65600 | |
| 65601 | UA_ModifyMonitoredItemsResponse |
| 65602 | UA_Client_MonitoredItems_modify(UA_Client *client, |
| 65603 | const UA_ModifyMonitoredItemsRequest request) { |
| 65604 | UA_ModifyMonitoredItemsResponse response; |
| 65605 | UA_ModifyMonitoredItemsResponse_init(p: &response); |
| 65606 | |
| 65607 | lockClient(client); |
| 65608 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId); |
| 65609 | if(!sub) { |
| 65610 | unlockClient(client); |
| 65611 | response.responseHeader.serviceResult = UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 65612 | return response; |
| 65613 | } |
| 65614 | |
| 65615 | UA_ModifyMonitoredItemsRequest modifiedRequest; |
| 65616 | UA_ModifyMonitoredItemsRequest_copy(src: &request, dst: &modifiedRequest); |
| 65617 | UA_MonitoredItem_change_clientHandle(sub, request: &modifiedRequest); |
| 65618 | |
| 65619 | __Client_Service(client, request: &modifiedRequest, |
| 65620 | requestType: &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST], response: &response, |
| 65621 | responseType: &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE]); |
| 65622 | |
| 65623 | unlockClient(client); |
| 65624 | UA_ModifyMonitoredItemsRequest_clear(p: &modifiedRequest); |
| 65625 | return response; |
| 65626 | } |
| 65627 | |
| 65628 | UA_StatusCode |
| 65629 | UA_Client_MonitoredItems_modify_async(UA_Client *client, |
| 65630 | const UA_ModifyMonitoredItemsRequest request, |
| 65631 | UA_ClientAsyncServiceCallback callback, |
| 65632 | void *userdata, UA_UInt32 *requestId) { |
| 65633 | lockClient(client); |
| 65634 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: request.subscriptionId); |
| 65635 | if(!sub) { |
| 65636 | unlockClient(client); |
| 65637 | return UA_STATUSCODE_BADSUBSCRIPTIONIDINVALID; |
| 65638 | } |
| 65639 | |
| 65640 | UA_ModifyMonitoredItemsRequest modifiedRequest; |
| 65641 | UA_ModifyMonitoredItemsRequest_copy(src: &request, dst: &modifiedRequest); |
| 65642 | UA_MonitoredItem_change_clientHandle(sub, request: &modifiedRequest); |
| 65643 | |
| 65644 | UA_StatusCode statusCode = __Client_AsyncService( |
| 65645 | client, request: &modifiedRequest, requestType: &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSREQUEST], |
| 65646 | callback, responseType: &UA_TYPES[UA_TYPES_MODIFYMONITOREDITEMSRESPONSE], userdata, requestId); |
| 65647 | |
| 65648 | unlockClient(client); |
| 65649 | UA_ModifyMonitoredItemsRequest_clear(p: &modifiedRequest); |
| 65650 | return statusCode; |
| 65651 | } |
| 65652 | |
| 65653 | /*************************************/ |
| 65654 | /* Async Processing of Notifications */ |
| 65655 | /*************************************/ |
| 65656 | |
| 65657 | /* Assume the request is already initialized */ |
| 65658 | UA_StatusCode |
| 65659 | __Client_preparePublishRequest(UA_Client *client, UA_PublishRequest *request) { |
| 65660 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 65661 | |
| 65662 | /* Count acks */ |
| 65663 | UA_Client_NotificationsAckNumber *ack; |
| 65664 | LIST_FOREACH(ack, &client->pendingNotificationsAcks, listEntry) |
| 65665 | ++request->subscriptionAcknowledgementsSize; |
| 65666 | |
| 65667 | /* Create the array. Returns a sentinel pointer if the length is zero. */ |
| 65668 | request->subscriptionAcknowledgements = (UA_SubscriptionAcknowledgement*) |
| 65669 | UA_Array_new(size: request->subscriptionAcknowledgementsSize, |
| 65670 | type: &UA_TYPES[UA_TYPES_SUBSCRIPTIONACKNOWLEDGEMENT]); |
| 65671 | if(!request->subscriptionAcknowledgements) { |
| 65672 | request->subscriptionAcknowledgementsSize = 0; |
| 65673 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 65674 | } |
| 65675 | |
| 65676 | size_t i = 0; |
| 65677 | UA_Client_NotificationsAckNumber *ack_tmp; |
| 65678 | LIST_FOREACH_SAFE(ack, &client->pendingNotificationsAcks, listEntry, ack_tmp) { |
| 65679 | request->subscriptionAcknowledgements[i].sequenceNumber = ack->subAck.sequenceNumber; |
| 65680 | request->subscriptionAcknowledgements[i].subscriptionId = ack->subAck.subscriptionId; |
| 65681 | ++i; |
| 65682 | LIST_REMOVE(ack, listEntry); |
| 65683 | UA_free(ptr: ack); |
| 65684 | } |
| 65685 | return UA_STATUSCODE_GOOD; |
| 65686 | } |
| 65687 | |
| 65688 | /* According to OPC Unified Architecture, Part 4 5.13.1.1 i) */ |
| 65689 | /* The value 0 is never used for the sequence number */ |
| 65690 | static UA_UInt32 |
| 65691 | __nextSequenceNumber(UA_UInt32 sequenceNumber) { |
| 65692 | UA_UInt32 nextSequenceNumber = sequenceNumber + 1; |
| 65693 | if(nextSequenceNumber == 0) |
| 65694 | nextSequenceNumber = 1; |
| 65695 | return nextSequenceNumber; |
| 65696 | } |
| 65697 | |
| 65698 | static void |
| 65699 | processDataChangeNotification(UA_Client *client, UA_Client_Subscription *sub, |
| 65700 | UA_DataChangeNotification *dataChangeNotification) { |
| 65701 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 65702 | |
| 65703 | for(size_t j = 0; j < dataChangeNotification->monitoredItemsSize; ++j) { |
| 65704 | UA_MonitoredItemNotification *min = &dataChangeNotification->monitoredItems[j]; |
| 65705 | |
| 65706 | /* Find the MonitoredItem */ |
| 65707 | UA_Client_MonitoredItem *mon; |
| 65708 | UA_Client_MonitoredItem dummy; |
| 65709 | dummy.clientHandle = min->clientHandle; |
| 65710 | mon = ZIP_FIND(MonitorItemsTree, &sub->monitoredItems, &dummy); |
| 65711 | |
| 65712 | if(!mon) { |
| 65713 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65714 | msg: "Could not process a notification with clienthandle %"PRIu32 |
| 65715 | " on subscription %"PRIu32, min->clientHandle, sub->subscriptionId); |
| 65716 | continue; |
| 65717 | } |
| 65718 | |
| 65719 | if(mon->isEventMonitoredItem) { |
| 65720 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65721 | msg: "MonitoredItem is configured for Events. But received a " |
| 65722 | "DataChangeNotification."); |
| 65723 | continue; |
| 65724 | } |
| 65725 | |
| 65726 | if(mon->handler.dataChangeCallback) { |
| 65727 | void *subC = sub->context; |
| 65728 | void *monC = mon->context; |
| 65729 | UA_UInt32 subId = sub->subscriptionId; |
| 65730 | UA_UInt32 monId = mon->monitoredItemId; |
| 65731 | mon->handler.dataChangeCallback(client, subId, subC, monId, monC, &min->value); |
| 65732 | } |
| 65733 | } |
| 65734 | } |
| 65735 | |
| 65736 | static void |
| 65737 | processEventNotification(UA_Client *client, UA_Client_Subscription *sub, |
| 65738 | UA_EventNotificationList *eventNotificationList) { |
| 65739 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 65740 | |
| 65741 | for(size_t j = 0; j < eventNotificationList->eventsSize; ++j) { |
| 65742 | UA_EventFieldList *eventFieldList = &eventNotificationList->events[j]; |
| 65743 | |
| 65744 | /* Find the MonitoredItem */ |
| 65745 | UA_Client_MonitoredItem *mon; |
| 65746 | UA_Client_MonitoredItem dummy; |
| 65747 | dummy.clientHandle = eventFieldList->clientHandle; |
| 65748 | mon = ZIP_FIND(MonitorItemsTree, &sub->monitoredItems, &dummy); |
| 65749 | |
| 65750 | if(!mon) { |
| 65751 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65752 | msg: "Could not process a notification with clienthandle %"PRIu32 |
| 65753 | " on subscription %"PRIu32, eventFieldList->clientHandle, |
| 65754 | sub->subscriptionId); |
| 65755 | continue; |
| 65756 | } |
| 65757 | |
| 65758 | if(!mon->isEventMonitoredItem) { |
| 65759 | UA_LOG_DEBUG(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65760 | msg: "MonitoredItem is configured for DataChanges. But received a " |
| 65761 | "EventNotification."); |
| 65762 | continue; |
| 65763 | } |
| 65764 | |
| 65765 | void *subC = sub->context; |
| 65766 | void *monC = mon->context; |
| 65767 | UA_UInt32 subId = sub->subscriptionId; |
| 65768 | UA_UInt32 monId = mon->monitoredItemId; |
| 65769 | mon->handler.eventCallback(client, subId, subC, monId, monC, |
| 65770 | eventFieldList->eventFieldsSize, |
| 65771 | eventFieldList->eventFields); |
| 65772 | } |
| 65773 | } |
| 65774 | |
| 65775 | static void |
| 65776 | processNotificationMessage(UA_Client *client, UA_Client_Subscription *sub, |
| 65777 | UA_ExtensionObject *msg) { |
| 65778 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 65779 | |
| 65780 | if(msg->encoding != UA_EXTENSIONOBJECT_DECODED) |
| 65781 | return; |
| 65782 | |
| 65783 | /* Handle DataChangeNotification */ |
| 65784 | if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]) { |
| 65785 | UA_DataChangeNotification *dataChangeNotification = |
| 65786 | (UA_DataChangeNotification *)msg->content.decoded.data; |
| 65787 | processDataChangeNotification(client, sub, dataChangeNotification); |
| 65788 | return; |
| 65789 | } |
| 65790 | |
| 65791 | /* Handle EventNotification */ |
| 65792 | if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]) { |
| 65793 | UA_EventNotificationList *eventNotificationList = |
| 65794 | (UA_EventNotificationList *)msg->content.decoded.data; |
| 65795 | processEventNotification(client, sub, eventNotificationList); |
| 65796 | return; |
| 65797 | } |
| 65798 | |
| 65799 | /* Handle StatusChangeNotification */ |
| 65800 | if(msg->content.decoded.type == &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]) { |
| 65801 | if(sub->statusChangeCallback) { |
| 65802 | void *subC = sub->context; |
| 65803 | UA_UInt32 subId = sub->subscriptionId; |
| 65804 | sub->statusChangeCallback(client, subId, subC, |
| 65805 | (UA_StatusChangeNotification*)msg->content.decoded.data); |
| 65806 | } else { |
| 65807 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65808 | msg: "Dropped a StatusChangeNotification since no " |
| 65809 | "callback is registered"); |
| 65810 | } |
| 65811 | return; |
| 65812 | } |
| 65813 | |
| 65814 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65815 | msg: "Unknown notification message type"); |
| 65816 | } |
| 65817 | |
| 65818 | static void |
| 65819 | __Client_Subscriptions_processPublishResponse(UA_Client *client, UA_PublishRequest *request, |
| 65820 | UA_PublishResponse *response) { |
| 65821 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 65822 | |
| 65823 | UA_NotificationMessage *msg = &response->notificationMessage; |
| 65824 | |
| 65825 | client->currentlyOutStandingPublishRequests--; |
| 65826 | |
| 65827 | if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS) { |
| 65828 | if(client->config.outStandingPublishRequests > 1) { |
| 65829 | client->config.outStandingPublishRequests--; |
| 65830 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65831 | msg: "Too many publishrequest, reduce outStandingPublishRequests " |
| 65832 | "to %"PRId16, client->config.outStandingPublishRequests); |
| 65833 | } else { |
| 65834 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65835 | msg: "Too many publishrequest when outStandingPublishRequests = 1"); |
| 65836 | UA_Client_Subscriptions_deleteSingle(client, subscriptionId: response->subscriptionId); |
| 65837 | } |
| 65838 | return; |
| 65839 | } |
| 65840 | |
| 65841 | if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSHUTDOWN) |
| 65842 | return; |
| 65843 | |
| 65844 | if(response->responseHeader.serviceResult == UA_STATUSCODE_BADNOSUBSCRIPTION) |
| 65845 | { |
| 65846 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65847 | msg: "Received BadNoSubscription, delete internal information about subscription"); |
| 65848 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: response->subscriptionId); |
| 65849 | if(sub != NULL) |
| 65850 | __Client_Subscription_deleteInternal(client, sub); |
| 65851 | return; |
| 65852 | } |
| 65853 | |
| 65854 | if(!LIST_FIRST(&client->subscriptions)) { |
| 65855 | response->responseHeader.serviceResult = UA_STATUSCODE_BADNOSUBSCRIPTION; |
| 65856 | return; |
| 65857 | } |
| 65858 | |
| 65859 | UA_Client_Subscription *sub = findSubscription(client, subscriptionId: response->subscriptionId); |
| 65860 | if(!sub) { |
| 65861 | response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR; |
| 65862 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65863 | msg: "Received Publish Response for a non-existant subscription"); |
| 65864 | return; |
| 65865 | } |
| 65866 | |
| 65867 | if(response->responseHeader.serviceResult == UA_STATUSCODE_BADSESSIONCLOSED) { |
| 65868 | if(client->sessionState != UA_SESSIONSTATE_ACTIVATED) { |
| 65869 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65870 | msg: "Received Publish Response with code %s", |
| 65871 | UA_StatusCode_name(code: response->responseHeader.serviceResult)); |
| 65872 | __Client_Subscription_deleteInternal(client, sub); |
| 65873 | } |
| 65874 | return; |
| 65875 | } |
| 65876 | |
| 65877 | if(response->responseHeader.serviceResult == UA_STATUSCODE_BADTIMEOUT) { |
| 65878 | if(client->config.subscriptionInactivityCallback) { |
| 65879 | void *subC = sub->context; |
| 65880 | UA_UInt32 subId = sub->subscriptionId; |
| 65881 | client->config.subscriptionInactivityCallback(client, subId, subC); |
| 65882 | } |
| 65883 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65884 | msg: "Received Timeout for Publish Response"); |
| 65885 | return; |
| 65886 | } |
| 65887 | |
| 65888 | if(response->responseHeader.serviceResult != UA_STATUSCODE_GOOD) { |
| 65889 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65890 | msg: "Received Publish Response with code %s", |
| 65891 | UA_StatusCode_name(code: response->responseHeader.serviceResult)); |
| 65892 | return; |
| 65893 | } |
| 65894 | |
| 65895 | sub->lastActivity = UA_DateTime_nowMonotonic(); |
| 65896 | |
| 65897 | /* Detect missing message - OPC Unified Architecture, Part 4 5.13.1.1 e) */ |
| 65898 | if(__nextSequenceNumber(sequenceNumber: sub->sequenceNumber) != msg->sequenceNumber) { |
| 65899 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65900 | msg: "Invalid subscription sequence number: expected %"PRIu32 |
| 65901 | " but got %"PRIu32, __nextSequenceNumber(sequenceNumber: sub->sequenceNumber), |
| 65902 | msg->sequenceNumber); |
| 65903 | /* This is an error. But we do not abort the connection. Some server |
| 65904 | * SDKs misbehave from time to time and send out-of-order sequence |
| 65905 | * numbers. (Probably some multi-threading synchronization issue.) */ |
| 65906 | /* UA_Client_disconnect(client); |
| 65907 | return; */ |
| 65908 | } |
| 65909 | /* According to f), a keep-alive message contains no notifications and has |
| 65910 | * the sequence number of the next NotificationMessage that is to be sent => |
| 65911 | * More than one consecutive keep-alive message or a NotificationMessage |
| 65912 | * following a keep-alive message will share the same sequence number. */ |
| 65913 | if (msg->notificationDataSize) |
| 65914 | sub->sequenceNumber = msg->sequenceNumber; |
| 65915 | |
| 65916 | /* Process the notification messages */ |
| 65917 | for(size_t k = 0; k < msg->notificationDataSize; ++k) |
| 65918 | processNotificationMessage(client, sub, msg: &msg->notificationData[k]); |
| 65919 | |
| 65920 | /* Add to the list of pending acks */ |
| 65921 | for(size_t i = 0; i < response->availableSequenceNumbersSize; i++) { |
| 65922 | if(response->availableSequenceNumbers[i] != msg->sequenceNumber) |
| 65923 | continue; |
| 65924 | UA_Client_NotificationsAckNumber *tmpAck = (UA_Client_NotificationsAckNumber*) |
| 65925 | UA_malloc(size: sizeof(UA_Client_NotificationsAckNumber)); |
| 65926 | if(!tmpAck) { |
| 65927 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 65928 | msg: "Not enough memory to store the acknowledgement for a publish " |
| 65929 | "message on subscription %"PRIu32, sub->subscriptionId); |
| 65930 | break; |
| 65931 | } |
| 65932 | tmpAck->subAck.sequenceNumber = msg->sequenceNumber; |
| 65933 | tmpAck->subAck.subscriptionId = sub->subscriptionId; |
| 65934 | LIST_INSERT_HEAD(&client->pendingNotificationsAcks, tmpAck, listEntry); |
| 65935 | break; |
| 65936 | } |
| 65937 | } |
| 65938 | |
| 65939 | static void |
| 65940 | processPublishResponseAsync(UA_Client *client, void *userdata, |
| 65941 | UA_UInt32 requestId, void *response) { |
| 65942 | UA_PublishRequest *req = (UA_PublishRequest*)userdata; |
| 65943 | UA_PublishResponse *res = (UA_PublishResponse*)response; |
| 65944 | |
| 65945 | lockClient(client); |
| 65946 | |
| 65947 | /* Process the response */ |
| 65948 | __Client_Subscriptions_processPublishResponse(client, request: req, response: res); |
| 65949 | |
| 65950 | /* Delete the cached request */ |
| 65951 | UA_PublishRequest_delete(p: req); |
| 65952 | |
| 65953 | /* Fill up the outstanding publish requests */ |
| 65954 | __Client_Subscriptions_backgroundPublish(client); |
| 65955 | |
| 65956 | unlockClient(client); |
| 65957 | } |
| 65958 | |
| 65959 | void |
| 65960 | __Client_Subscriptions_clean(UA_Client *client) { |
| 65961 | UA_Client_NotificationsAckNumber *n; |
| 65962 | UA_Client_NotificationsAckNumber *tmp; |
| 65963 | LIST_FOREACH_SAFE(n, &client->pendingNotificationsAcks, listEntry, tmp) { |
| 65964 | LIST_REMOVE(n, listEntry); |
| 65965 | UA_free(ptr: n); |
| 65966 | } |
| 65967 | |
| 65968 | UA_Client_Subscription *sub; |
| 65969 | UA_Client_Subscription *tmps; |
| 65970 | LIST_FOREACH_SAFE(sub, &client->subscriptions, listEntry, tmps) |
| 65971 | __Client_Subscription_deleteInternal(client, sub); /* force local removal */ |
| 65972 | |
| 65973 | client->monitoredItemHandles = 0; |
| 65974 | } |
| 65975 | |
| 65976 | void |
| 65977 | __Client_Subscriptions_backgroundPublishInactivityCheck(UA_Client *client) { |
| 65978 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 65979 | |
| 65980 | if(client->sessionState < UA_SESSIONSTATE_ACTIVATED) |
| 65981 | return; |
| 65982 | |
| 65983 | /* Is the lack of responses the client's fault? */ |
| 65984 | if(client->currentlyOutStandingPublishRequests == 0) |
| 65985 | return; |
| 65986 | |
| 65987 | UA_Client_Subscription *sub; |
| 65988 | LIST_FOREACH(sub, &client->subscriptions, listEntry) { |
| 65989 | UA_DateTime maxSilence = (UA_DateTime) |
| 65990 | ((sub->publishingInterval * sub->maxKeepAliveCount) + |
| 65991 | client->config.timeout) * UA_DATETIME_MSEC; |
| 65992 | if(maxSilence + sub->lastActivity < UA_DateTime_nowMonotonic()) { |
| 65993 | /* Reset activity */ |
| 65994 | sub->lastActivity = UA_DateTime_nowMonotonic(); |
| 65995 | |
| 65996 | if(client->config.subscriptionInactivityCallback) { |
| 65997 | void *subC = sub->context; |
| 65998 | UA_UInt32 subId = sub->subscriptionId; |
| 65999 | client->config.subscriptionInactivityCallback(client, subId, subC); |
| 66000 | } |
| 66001 | UA_LOG_WARNING(logger: client->config.logging, category: UA_LOGCATEGORY_CLIENT, |
| 66002 | msg: "Inactivity for Subscription %"PRIu32 ".", sub->subscriptionId); |
| 66003 | } |
| 66004 | } |
| 66005 | } |
| 66006 | |
| 66007 | void |
| 66008 | __Client_Subscriptions_backgroundPublish(UA_Client *client) { |
| 66009 | UA_LOCK_ASSERT(&client->clientMutex, 1); |
| 66010 | |
| 66011 | if(client->sessionState != UA_SESSIONSTATE_ACTIVATED) |
| 66012 | return; |
| 66013 | |
| 66014 | /* The session must have at least one subscription */ |
| 66015 | if(!LIST_FIRST(&client->subscriptions)) |
| 66016 | return; |
| 66017 | |
| 66018 | while(client->currentlyOutStandingPublishRequests < client->config.outStandingPublishRequests) { |
| 66019 | UA_PublishRequest *request = UA_PublishRequest_new(); |
| 66020 | if(!request) |
| 66021 | return; |
| 66022 | |
| 66023 | /* Publish requests are valid for 10 minutes */ |
| 66024 | request->requestHeader.timeoutHint = 10 * 60 * 1000; |
| 66025 | |
| 66026 | UA_StatusCode retval = __Client_preparePublishRequest(client, request); |
| 66027 | if(retval != UA_STATUSCODE_GOOD) { |
| 66028 | UA_PublishRequest_delete(p: request); |
| 66029 | return; |
| 66030 | } |
| 66031 | |
| 66032 | retval = __Client_AsyncService(client, request, |
| 66033 | requestType: &UA_TYPES[UA_TYPES_PUBLISHREQUEST], |
| 66034 | callback: processPublishResponseAsync, |
| 66035 | responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE], |
| 66036 | userdata: (void*)request, NULL); |
| 66037 | if(retval != UA_STATUSCODE_GOOD) { |
| 66038 | UA_PublishRequest_delete(p: request); |
| 66039 | return; |
| 66040 | } |
| 66041 | |
| 66042 | client->currentlyOutStandingPublishRequests++; |
| 66043 | } |
| 66044 | } |
| 66045 | |
| 66046 | /**** amalgamated original file "/deps/libc_time.c" ****/ |
| 66047 | |
| 66048 | /* Originally released by the musl project (http://www.musl-libc.org/) under the |
| 66049 | * MIT license. Taken from the file /src/time/__secs_to_tm.c */ |
| 66050 | |
| 66051 | #include <limits.h> |
| 66052 | |
| 66053 | /* 2000-03-01 (mod 400 year, immediately after feb29 */ |
| 66054 | #define LEAPOCH (946684800LL + 86400*(31+29)) |
| 66055 | |
| 66056 | #define DAYS_PER_400Y (365*400 + 97) |
| 66057 | #define DAYS_PER_100Y (365*100 + 24) |
| 66058 | #define DAYS_PER_4Y (365*4 + 1) |
| 66059 | |
| 66060 | int |
| 66061 | musl_secs_to_tm(long long t, struct musl_tm *tm) { |
| 66062 | long long days, secs, years; |
| 66063 | int remdays, remsecs, remyears; |
| 66064 | int qc_cycles, c_cycles, q_cycles; |
| 66065 | int months; |
| 66066 | int wday, yday, leap; |
| 66067 | static const char days_in_month[] = {31,30,31,30,31,31,30,31,30,31,31,29}; |
| 66068 | |
| 66069 | /* Reject time_t values whose year would overflow int */ |
| 66070 | if (t < INT_MIN * 31622400LL || t > INT_MAX * 31622400LL) |
| 66071 | return -1; |
| 66072 | |
| 66073 | secs = t - LEAPOCH; |
| 66074 | days = secs / 86400LL; |
| 66075 | remsecs = (int)(secs % 86400); |
| 66076 | if (remsecs < 0) { |
| 66077 | remsecs += 86400; |
| 66078 | --days; |
| 66079 | } |
| 66080 | |
| 66081 | wday = (3+days)%7; |
| 66082 | if (wday < 0) wday += 7; |
| 66083 | |
| 66084 | qc_cycles = (int)(days / DAYS_PER_400Y); |
| 66085 | remdays = (int)(days % DAYS_PER_400Y); |
| 66086 | if (remdays < 0) { |
| 66087 | remdays += DAYS_PER_400Y; |
| 66088 | --qc_cycles; |
| 66089 | } |
| 66090 | |
| 66091 | c_cycles = remdays / DAYS_PER_100Y; |
| 66092 | if (c_cycles == 4) --c_cycles; |
| 66093 | remdays -= c_cycles * DAYS_PER_100Y; |
| 66094 | |
| 66095 | q_cycles = remdays / DAYS_PER_4Y; |
| 66096 | if (q_cycles == 25) --q_cycles; |
| 66097 | remdays -= q_cycles * DAYS_PER_4Y; |
| 66098 | |
| 66099 | remyears = remdays / 365; |
| 66100 | if (remyears == 4) --remyears; |
| 66101 | remdays -= remyears * 365; |
| 66102 | |
| 66103 | leap = !remyears && (q_cycles || !c_cycles); |
| 66104 | yday = remdays + 31 + 28 + leap; |
| 66105 | if (yday >= 365+leap) yday -= 365+leap; |
| 66106 | |
| 66107 | years = remyears + 4*q_cycles + 100*c_cycles + 400LL*qc_cycles; |
| 66108 | |
| 66109 | for (months=0; days_in_month[months] <= remdays; months++) |
| 66110 | remdays -= days_in_month[months]; |
| 66111 | |
| 66112 | if (months >= 10) { |
| 66113 | months -= 12; |
| 66114 | years++; |
| 66115 | } |
| 66116 | |
| 66117 | if (years+100 > INT_MAX || years+100 < INT_MIN) |
| 66118 | return -1; |
| 66119 | |
| 66120 | tm->tm_year = (int)(years + 100); |
| 66121 | tm->tm_mon = months + 2; |
| 66122 | tm->tm_mday = remdays + 1; |
| 66123 | tm->tm_wday = wday; |
| 66124 | tm->tm_yday = yday; |
| 66125 | |
| 66126 | tm->tm_hour = remsecs / 3600; |
| 66127 | tm->tm_min = remsecs / 60 % 60; |
| 66128 | tm->tm_sec = remsecs % 60; |
| 66129 | |
| 66130 | return 0; |
| 66131 | } |
| 66132 | |
| 66133 | static const int secs_through_month[] = |
| 66134 | {0, 31*86400, 59*86400, 90*86400, |
| 66135 | 120*86400, 151*86400, 181*86400, 212*86400, |
| 66136 | 243*86400, 273*86400, 304*86400, 334*86400 }; |
| 66137 | |
| 66138 | static int |
| 66139 | musl_month_to_secs(int month, int is_leap) { |
| 66140 | int t = secs_through_month[month]; |
| 66141 | if (is_leap && month >= 2) |
| 66142 | t+=86400; |
| 66143 | return t; |
| 66144 | } |
| 66145 | |
| 66146 | static long long |
| 66147 | musl_year_to_secs(const long long year, int *is_leap) { |
| 66148 | if (year-2ULL <= 136) { |
| 66149 | int y = (int)year; |
| 66150 | int leaps = (y-68)>>2; |
| 66151 | if (!((y-68)&3)) { |
| 66152 | leaps--; |
| 66153 | if (is_leap) *is_leap = 1; |
| 66154 | } else if (is_leap) *is_leap = 0; |
| 66155 | return 31536000*(y-70) + 86400*leaps; |
| 66156 | } |
| 66157 | |
| 66158 | int cycles, centuries, leaps, rem, dummy; |
| 66159 | |
| 66160 | if (!is_leap) is_leap = &dummy; |
| 66161 | cycles = (int)((year-100) / 400); |
| 66162 | rem = (year-100) % 400; |
| 66163 | if (rem < 0) { |
| 66164 | cycles--; |
| 66165 | rem += 400; |
| 66166 | } |
| 66167 | if (!rem) { |
| 66168 | *is_leap = 1; |
| 66169 | centuries = 0; |
| 66170 | leaps = 0; |
| 66171 | } else { |
| 66172 | if (rem >= 200) { |
| 66173 | if (rem >= 300) centuries = 3, rem -= 300; |
| 66174 | else centuries = 2, rem -= 200; |
| 66175 | } else { |
| 66176 | if (rem >= 100) centuries = 1, rem -= 100; |
| 66177 | else centuries = 0; |
| 66178 | } |
| 66179 | if (!rem) { |
| 66180 | *is_leap = 0; |
| 66181 | leaps = 0; |
| 66182 | } else { |
| 66183 | leaps = rem / 4U; |
| 66184 | rem %= 4U; |
| 66185 | *is_leap = !rem; |
| 66186 | } |
| 66187 | } |
| 66188 | |
| 66189 | leaps += 97*cycles + 24*centuries - *is_leap; |
| 66190 | |
| 66191 | return (year-100) * 31536000LL + leaps * 86400LL + 946684800 + 86400; |
| 66192 | } |
| 66193 | |
| 66194 | long long |
| 66195 | musl_tm_to_secs(const struct musl_tm *tm) { |
| 66196 | int is_leap; |
| 66197 | long long year = tm->tm_year; |
| 66198 | int month = tm->tm_mon; |
| 66199 | if (month >= 12 || month < 0) { |
| 66200 | int adj = month / 12; |
| 66201 | month %= 12; |
| 66202 | if (month < 0) { |
| 66203 | adj--; |
| 66204 | month += 12; |
| 66205 | } |
| 66206 | year += adj; |
| 66207 | } |
| 66208 | long long t = musl_year_to_secs(year, is_leap: &is_leap); |
| 66209 | t += musl_month_to_secs(month, is_leap); |
| 66210 | t += 86400LL * (tm->tm_mday-1); |
| 66211 | t += 3600LL * tm->tm_hour; |
| 66212 | t += 60LL * tm->tm_min; |
| 66213 | t += tm->tm_sec; |
| 66214 | return t; |
| 66215 | } |
| 66216 | |
| 66217 | /**** amalgamated original file "/deps/pcg_basic.c" ****/ |
| 66218 | |
| 66219 | /* |
| 66220 | * PCG Random Number Generation for C. |
| 66221 | * |
| 66222 | * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org> |
| 66223 | * |
| 66224 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 66225 | * you may not use this file except in compliance with the License. |
| 66226 | * You may obtain a copy of the License at |
| 66227 | * |
| 66228 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 66229 | * |
| 66230 | * Unless required by applicable law or agreed to in writing, software |
| 66231 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 66232 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 66233 | * See the License for the specific language governing permissions and |
| 66234 | * limitations under the License. |
| 66235 | * |
| 66236 | * For additional information about the PCG random number generation scheme, |
| 66237 | * including its license and other licensing options, visit |
| 66238 | * |
| 66239 | * http://www.pcg-random.org |
| 66240 | */ |
| 66241 | |
| 66242 | |
| 66243 | void pcg32_srandom_r(pcg32_random_t* rng, uint64_t initial_state, uint64_t initseq) { |
| 66244 | rng->state = 0U; |
| 66245 | rng->inc = (initseq << 1u) | 1u; |
| 66246 | pcg32_random_r(rng); |
| 66247 | rng->state += initial_state; |
| 66248 | pcg32_random_r(rng); |
| 66249 | } |
| 66250 | |
| 66251 | uint32_t pcg32_random_r(pcg32_random_t* rng) { |
| 66252 | uint64_t oldstate = rng->state; |
| 66253 | rng->state = oldstate * 6364136223846793005ULL + rng->inc; |
| 66254 | uint32_t xorshifted = (uint32_t)(((oldstate >> 18u) ^ oldstate) >> 27u); |
| 66255 | uint32_t rot = (uint32_t)(oldstate >> 59u); |
| 66256 | return (xorshifted >> rot) | (xorshifted << ((~rot + 1u) & 31)); /* was (xorshifted >> rot) | (xorshifted << ((-rot) & 31)) */ |
| 66257 | } |
| 66258 | |
| 66259 | /**** amalgamated original file "/deps/base64.c" ****/ |
| 66260 | |
| 66261 | /* |
| 66262 | * Base64 encoding/decoding (RFC1341) |
| 66263 | * Copyright (c) 2005-2011, Jouni Malinen <j@w1.fi> |
| 66264 | * |
| 66265 | * This software may be distributed under the terms of the BSD license. |
| 66266 | * See README for more details. |
| 66267 | */ |
| 66268 | |
| 66269 | |
| 66270 | static const unsigned char base64_table[65] = |
| 66271 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 66272 | |
| 66273 | unsigned char * |
| 66274 | UA_base64(const unsigned char *src, size_t len, size_t *out_len) { |
| 66275 | if(len == 0) { |
| 66276 | *out_len = 0; |
| 66277 | return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL; |
| 66278 | } |
| 66279 | |
| 66280 | size_t olen = 4*((len + 2) / 3); /* 3-byte blocks to 4-byte */ |
| 66281 | if(olen < len) |
| 66282 | return NULL; /* integer overflow */ |
| 66283 | |
| 66284 | unsigned char *out = (unsigned char*)UA_malloc(size: olen); |
| 66285 | if(!out) |
| 66286 | return NULL; |
| 66287 | |
| 66288 | *out_len = UA_base64_buf(src, len, out); |
| 66289 | return out; |
| 66290 | } |
| 66291 | |
| 66292 | size_t |
| 66293 | UA_base64_buf(const unsigned char *src, size_t len, unsigned char *out) { |
| 66294 | const unsigned char *end = src + len; |
| 66295 | const unsigned char *in = src; |
| 66296 | unsigned char *pos = out; |
| 66297 | while(end - in >= 3) { |
| 66298 | *pos++ = base64_table[in[0] >> 2]; |
| 66299 | *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; |
| 66300 | *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)]; |
| 66301 | *pos++ = base64_table[in[2] & 0x3f]; |
| 66302 | in += 3; |
| 66303 | } |
| 66304 | |
| 66305 | if(end - in) { |
| 66306 | *pos++ = base64_table[in[0] >> 2]; |
| 66307 | if(end - in == 1) { |
| 66308 | *pos++ = base64_table[(in[0] & 0x03) << 4]; |
| 66309 | *pos++ = '='; |
| 66310 | } else { |
| 66311 | *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)]; |
| 66312 | *pos++ = base64_table[(in[1] & 0x0f) << 2]; |
| 66313 | } |
| 66314 | *pos++ = '='; |
| 66315 | } |
| 66316 | |
| 66317 | return (size_t)(pos - out); |
| 66318 | } |
| 66319 | |
| 66320 | static unsigned char dtable[256] = { |
| 66321 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 66322 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 66323 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 62 , 0x80, 62 , 0x80, 63 , |
| 66324 | 52 , 53 , 54 , 55 , 56 , 57 , 58 , 59 , 60 , 61 , 0x80, 0x80, 0x80, 0, 0x80, 0x80, |
| 66325 | 0x80, 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , |
| 66326 | 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 , 0x80, 0x80, 0x80, 0x80, 63 , |
| 66327 | 0x80, 26 , 27 , 28 , 29 , 30 , 31 , 32 , 33 , 34 , 35 , 36 , 37 , 38 , 39 , 40 , |
| 66328 | 41 , 42 , 43 , 44 , 45 , 46 , 47 , 48 , 49 , 50 , 51 , 0x80, 0x80, 0x80, 0x80, 0x80, |
| 66329 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 66330 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 66331 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 66332 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 66333 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 66334 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 66335 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, |
| 66336 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 |
| 66337 | }; |
| 66338 | |
| 66339 | unsigned char * |
| 66340 | UA_unbase64(const unsigned char *src, size_t len, size_t *out_len) { |
| 66341 | /* Empty base64 results in an empty byte-string */ |
| 66342 | if(len == 0) { |
| 66343 | *out_len = 0; |
| 66344 | return (unsigned char*)UA_EMPTY_ARRAY_SENTINEL; |
| 66345 | } |
| 66346 | |
| 66347 | /* The input length must be a multiple of four */ |
| 66348 | if(len % 4 != 0) |
| 66349 | return NULL; |
| 66350 | |
| 66351 | /* Allocate the output string */ |
| 66352 | size_t olen = len / 4 * 3; |
| 66353 | unsigned char *out = (unsigned char*)UA_malloc(size: olen); |
| 66354 | if(!out) |
| 66355 | return NULL; |
| 66356 | |
| 66357 | /* Iterate over the input */ |
| 66358 | size_t pad = 0; |
| 66359 | unsigned char count = 0; |
| 66360 | unsigned char block[4]; |
| 66361 | unsigned char *pos = out; |
| 66362 | for(size_t i = 0; i < len; i++) { |
| 66363 | unsigned char tmp = dtable[src[i]]; |
| 66364 | if(tmp == 0x80) |
| 66365 | goto error; /* Invalid input */ |
| 66366 | |
| 66367 | if(src[i] == '=') |
| 66368 | pad++; |
| 66369 | |
| 66370 | block[count] = tmp; |
| 66371 | count++; |
| 66372 | if(count == 4) { |
| 66373 | *pos++ = (unsigned char)((block[0] << 2) | (block[1] >> 4)); |
| 66374 | *pos++ = (unsigned char)((block[1] << 4) | (block[2] >> 2)); |
| 66375 | *pos++ = (unsigned char)((block[2] << 6) | block[3]); |
| 66376 | if(pad) { |
| 66377 | if(pad == 1) |
| 66378 | pos--; |
| 66379 | else if(pad == 2) |
| 66380 | pos -= 2; |
| 66381 | else |
| 66382 | goto error; /* Invalid padding */ |
| 66383 | break; |
| 66384 | } |
| 66385 | count = 0; |
| 66386 | } |
| 66387 | } |
| 66388 | |
| 66389 | *out_len = (size_t)(pos - out); |
| 66390 | return out; |
| 66391 | |
| 66392 | error: |
| 66393 | UA_free(ptr: out); |
| 66394 | return NULL; |
| 66395 | } |
| 66396 | |
| 66397 | /**** amalgamated original file "/deps/dtoa.c" ****/ |
| 66398 | |
| 66399 | // Copyright 2013, Andreas Samoljuk |
| 66400 | // Copyright 2023, Julius Pfrommer |
| 66401 | // |
| 66402 | // Boost Software License - Version 1.0 - August 17th, 2003 |
| 66403 | // |
| 66404 | // Permission is hereby granted, free of charge, to any person or organization |
| 66405 | // obtaining a copy of the software and accompanying documentation covered by |
| 66406 | // this license (the "Software") to use, reproduce, display, distribute, |
| 66407 | // execute, and transmit the Software, and to prepare derivative works of the |
| 66408 | // Software, and to permit third-parties to whom the Software is furnished to |
| 66409 | // do so, all subject to the following: |
| 66410 | // |
| 66411 | // The copyright notices in the Software and this entire statement, including |
| 66412 | // the above license grant, this restriction and the following disclaimer, |
| 66413 | // must be included in all copies of the Software, in whole or in part, and |
| 66414 | // all derivative works of the Software, unless such copies or derivative |
| 66415 | // works are solely in the form of machine-executable object code generated by |
| 66416 | // a source language processor. |
| 66417 | // |
| 66418 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 66419 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 66420 | // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT |
| 66421 | // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE |
| 66422 | // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, |
| 66423 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| 66424 | // DEALINGS IN THE SOFTWARE. |
| 66425 | |
| 66426 | #include <stdint.h> |
| 66427 | #include <stdbool.h> |
| 66428 | #include <string.h> |
| 66429 | |
| 66430 | #define mantissa_bits 52 |
| 66431 | #define exponent_bits 11 |
| 66432 | #define fracmask 0x000FFFFFFFFFFFFFU |
| 66433 | #define expmask 0x7FF0000000000000U |
| 66434 | #define hiddenbit 0x0010000000000000U |
| 66435 | #define signmask 0x8000000000000000U |
| 66436 | #define expbias (1023 + 52) |
| 66437 | |
| 66438 | #define absv(n) ((n) < 0 ? -(n) : (n)) |
| 66439 | #define minv(a, b) ((a) < (b) ? (a) : (b)) |
| 66440 | |
| 66441 | static uint64_t tens[] = { |
| 66442 | 10000000000000000000U, 1000000000000000000U, 100000000000000000U, |
| 66443 | 10000000000000000U, 1000000000000000U, 100000000000000U, |
| 66444 | 10000000000000U, 1000000000000U, 100000000000U, |
| 66445 | 10000000000U, 1000000000U, 100000000U, |
| 66446 | 10000000U, 1000000U, 100000U, |
| 66447 | 10000U, 1000U, 100U, |
| 66448 | 10U, 1U |
| 66449 | }; |
| 66450 | |
| 66451 | #define npowers 87 |
| 66452 | #define steppowers 8 |
| 66453 | #define firstpower -348 /* 10 ^ -348 */ |
| 66454 | #define expmax -32 |
| 66455 | #define expmin -60 |
| 66456 | |
| 66457 | typedef struct Fp { |
| 66458 | uint64_t frac; |
| 66459 | int exp; |
| 66460 | } Fp; |
| 66461 | |
| 66462 | static Fp powers_ten[] = { |
| 66463 | { 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 }, |
| 66464 | { 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 }, |
| 66465 | { 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 }, |
| 66466 | { 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 }, |
| 66467 | { 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 }, |
| 66468 | { 15227053142812498563U, -954 }, { 11345038669416679861U, -927 }, |
| 66469 | { 16905424996341287883U, -901 }, { 12595523146049147757U, -874 }, |
| 66470 | { 9384396036005875287U, -847 }, { 13983839803942852151U, -821 }, |
| 66471 | { 10418772551374772303U, -794 }, { 15525180923007089351U, -768 }, |
| 66472 | { 11567161174868858868U, -741 }, { 17236413322193710309U, -715 }, |
| 66473 | { 12842128665889583758U, -688 }, { 9568131466127621947U, -661 }, |
| 66474 | { 14257626930069360058U, -635 }, { 10622759856335341974U, -608 }, |
| 66475 | { 15829145694278690180U, -582 }, { 11793632577567316726U, -555 }, |
| 66476 | { 17573882009934360870U, -529 }, { 13093562431584567480U, -502 }, |
| 66477 | { 9755464219737475723U, -475 }, { 14536774485912137811U, -449 }, |
| 66478 | { 10830740992659433045U, -422 }, { 16139061738043178685U, -396 }, |
| 66479 | { 12024538023802026127U, -369 }, { 17917957937422433684U, -343 }, |
| 66480 | { 13349918974505688015U, -316 }, { 9946464728195732843U, -289 }, |
| 66481 | { 14821387422376473014U, -263 }, { 11042794154864902060U, -236 }, |
| 66482 | { 16455045573212060422U, -210 }, { 12259964326927110867U, -183 }, |
| 66483 | { 18268770466636286478U, -157 }, { 13611294676837538539U, -130 }, |
| 66484 | { 10141204801825835212U, -103 }, { 15111572745182864684U, -77 }, |
| 66485 | { 11258999068426240000U, -50 }, { 16777216000000000000U, -24 }, |
| 66486 | { 12500000000000000000U, 3 }, { 9313225746154785156U, 30 }, |
| 66487 | { 13877787807814456755U, 56 }, { 10339757656912845936U, 83 }, |
| 66488 | { 15407439555097886824U, 109 }, { 11479437019748901445U, 136 }, |
| 66489 | { 17105694144590052135U, 162 }, { 12744735289059618216U, 189 }, |
| 66490 | { 9495567745759798747U, 216 }, { 14149498560666738074U, 242 }, |
| 66491 | { 10542197943230523224U, 269 }, { 15709099088952724970U, 295 }, |
| 66492 | { 11704190886730495818U, 322 }, { 17440603504673385349U, 348 }, |
| 66493 | { 12994262207056124023U, 375 }, { 9681479787123295682U, 402 }, |
| 66494 | { 14426529090290212157U, 428 }, { 10748601772107342003U, 455 }, |
| 66495 | { 16016664761464807395U, 481 }, { 11933345169920330789U, 508 }, |
| 66496 | { 17782069995880619868U, 534 }, { 13248674568444952270U, 561 }, |
| 66497 | { 9871031767461413346U, 588 }, { 14708983551653345445U, 614 }, |
| 66498 | { 10959046745042015199U, 641 }, { 16330252207878254650U, 667 }, |
| 66499 | { 12166986024289022870U, 694 }, { 18130221999122236476U, 720 }, |
| 66500 | { 13508068024458167312U, 747 }, { 10064294952495520794U, 774 }, |
| 66501 | { 14996968138956309548U, 800 }, { 11173611982879273257U, 827 }, |
| 66502 | { 16649979327439178909U, 853 }, { 12405201291620119593U, 880 }, |
| 66503 | { 9242595204427927429U, 907 }, { 13772540099066387757U, 933 }, |
| 66504 | { 10261342003245940623U, 960 }, { 15290591125556738113U, 986 }, |
| 66505 | { 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 }, |
| 66506 | { 12648080533535911531U, 1066 } |
| 66507 | }; |
| 66508 | |
| 66509 | static Fp |
| 66510 | find_cachedpow10(int exp, int* k) { |
| 66511 | const double one_log_ten = 0.30102999566398114; |
| 66512 | int approx = (int)(-(exp + npowers) * one_log_ten); |
| 66513 | int idx = (approx - firstpower) / steppowers; |
| 66514 | while(1) { |
| 66515 | int current = exp + powers_ten[idx].exp + 64; |
| 66516 | if(current < expmin) { |
| 66517 | idx++; |
| 66518 | continue; |
| 66519 | } |
| 66520 | if(current > expmax) { |
| 66521 | idx--; |
| 66522 | continue; |
| 66523 | } |
| 66524 | *k = (firstpower + idx * steppowers); |
| 66525 | return powers_ten[idx]; |
| 66526 | } |
| 66527 | } |
| 66528 | |
| 66529 | static Fp build_fp(uint64_t bits) { |
| 66530 | Fp fp; |
| 66531 | fp.frac = bits & fracmask; |
| 66532 | fp.exp = (bits & expmask) >> 52; |
| 66533 | if(fp.exp) { |
| 66534 | fp.frac += hiddenbit; |
| 66535 | fp.exp -= expbias; |
| 66536 | } else { |
| 66537 | fp.exp = -expbias + 1; |
| 66538 | } |
| 66539 | return fp; |
| 66540 | } |
| 66541 | |
| 66542 | static void normalize(Fp* fp) { |
| 66543 | while((fp->frac & hiddenbit) == 0) { |
| 66544 | fp->frac <<= 1; |
| 66545 | fp->exp--; |
| 66546 | } |
| 66547 | int shift = 64 - 52 - 1; |
| 66548 | fp->frac <<= shift; |
| 66549 | fp->exp -= shift; |
| 66550 | } |
| 66551 | |
| 66552 | static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper) { |
| 66553 | upper->frac = (fp->frac << 1) + 1; |
| 66554 | upper->exp = fp->exp - 1; |
| 66555 | while ((upper->frac & (hiddenbit << 1)) == 0) { |
| 66556 | upper->frac <<= 1; |
| 66557 | upper->exp--; |
| 66558 | } |
| 66559 | |
| 66560 | int u_shift = 64 - 52 - 2; |
| 66561 | upper->frac <<= u_shift; |
| 66562 | upper->exp = upper->exp - u_shift; |
| 66563 | |
| 66564 | int l_shift = fp->frac == hiddenbit ? 2 : 1; |
| 66565 | lower->frac = (fp->frac << l_shift) - 1; |
| 66566 | lower->exp = fp->exp - l_shift; |
| 66567 | lower->frac <<= lower->exp - upper->exp; |
| 66568 | lower->exp = upper->exp; |
| 66569 | } |
| 66570 | |
| 66571 | static Fp multiply(Fp* a, Fp* b) { |
| 66572 | const uint64_t lomask = 0x00000000FFFFFFFF; |
| 66573 | uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask); |
| 66574 | uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32); |
| 66575 | uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask); |
| 66576 | uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32); |
| 66577 | uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32); |
| 66578 | /* round up */ |
| 66579 | tmp += 1U << 31; |
| 66580 | Fp fp; |
| 66581 | fp.frac = ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32); |
| 66582 | fp.exp = a->exp + b->exp + 64; |
| 66583 | return fp; |
| 66584 | } |
| 66585 | |
| 66586 | static void round_digit(char* digits, unsigned ndigits, uint64_t delta, |
| 66587 | uint64_t rem, uint64_t kappa, uint64_t frac) { |
| 66588 | while(rem < frac && delta - rem >= kappa && |
| 66589 | (rem + kappa < frac || frac - rem > rem + kappa - frac)) { |
| 66590 | digits[ndigits - 1]--; |
| 66591 | rem += kappa; |
| 66592 | } |
| 66593 | } |
| 66594 | |
| 66595 | static unsigned generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K) { |
| 66596 | uint64_t wfrac = upper->frac - fp->frac; |
| 66597 | uint64_t delta = upper->frac - lower->frac; |
| 66598 | |
| 66599 | Fp one; |
| 66600 | one.frac = 1ULL << -upper->exp; |
| 66601 | one.exp = upper->exp; |
| 66602 | |
| 66603 | uint64_t part1 = upper->frac >> -one.exp; |
| 66604 | uint64_t part2 = upper->frac & (one.frac - 1); |
| 66605 | |
| 66606 | unsigned idx = 0; |
| 66607 | int kappa = 10; |
| 66608 | uint64_t* divp; |
| 66609 | |
| 66610 | /* 1000000000 */ |
| 66611 | for(divp = tens + 10; kappa > 0; divp++) { |
| 66612 | uint64_t div = *divp; |
| 66613 | uint64_t digit = part1 / div; |
| 66614 | if(digit || idx) { |
| 66615 | digits[idx++] = (char)(digit + '0'); |
| 66616 | } |
| 66617 | |
| 66618 | part1 -= digit * div; |
| 66619 | kappa--; |
| 66620 | |
| 66621 | uint64_t tmp = (part1 <<-one.exp) + part2; |
| 66622 | if(tmp <= delta) { |
| 66623 | *K += kappa; |
| 66624 | round_digit(digits, ndigits: idx, delta, rem: tmp, kappa: div << -one.exp, frac: wfrac); |
| 66625 | return idx; |
| 66626 | } |
| 66627 | } |
| 66628 | |
| 66629 | /* 10 */ |
| 66630 | uint64_t* unit = tens + 18; |
| 66631 | while(true) { |
| 66632 | part2 *= 10; |
| 66633 | delta *= 10; |
| 66634 | kappa--; |
| 66635 | |
| 66636 | uint64_t digit = part2 >> -one.exp; |
| 66637 | if(digit || idx) { |
| 66638 | digits[idx++] = (char)(digit + '0'); |
| 66639 | } |
| 66640 | |
| 66641 | part2 &= one.frac - 1; |
| 66642 | if(part2 < delta) { |
| 66643 | *K += kappa; |
| 66644 | round_digit(digits, ndigits: idx, delta, rem: part2, kappa: one.frac, frac: wfrac * *unit); |
| 66645 | break; |
| 66646 | } |
| 66647 | unit--; |
| 66648 | } |
| 66649 | return idx; |
| 66650 | } |
| 66651 | |
| 66652 | static unsigned grisu2(uint64_t bits, char* digits, int* K) { |
| 66653 | Fp w = build_fp(bits); |
| 66654 | Fp lower, upper; |
| 66655 | get_normalized_boundaries(fp: &w, lower: &lower, upper: &upper); |
| 66656 | normalize(fp: &w); |
| 66657 | int k; |
| 66658 | Fp cp = find_cachedpow10(exp: upper.exp, k: &k); |
| 66659 | w = multiply(a: &w, b: &cp); |
| 66660 | upper = multiply(a: &upper, b: &cp); |
| 66661 | lower = multiply(a: &lower, b: &cp); |
| 66662 | lower.frac++; |
| 66663 | upper.frac--; |
| 66664 | *K = -k; |
| 66665 | return generate_digits(fp: &w, upper: &upper, lower: &lower, digits, K); |
| 66666 | } |
| 66667 | |
| 66668 | static unsigned |
| 66669 | emit_digits(char* digits, unsigned ndigits, char* dest, int K, bool neg) { |
| 66670 | int exp = absv(K + (int)ndigits - 1); |
| 66671 | |
| 66672 | /* write plain integer */ |
| 66673 | if(K >= 0 && (exp < (int)ndigits + 7)) { |
| 66674 | memcpy(dest: dest, src: digits, n: ndigits); |
| 66675 | memset(s: dest + ndigits, c: '0', n: (unsigned)K); |
| 66676 | memcpy(dest: dest + ndigits + (unsigned)K, src: ".0", n: 2); /* always append .0 for naked integers */ |
| 66677 | return (unsigned)(ndigits + (unsigned)K + 2); |
| 66678 | } |
| 66679 | |
| 66680 | /* write decimal w/o scientific notation */ |
| 66681 | if(K < 0 && (K > -7 || exp < 4)) { |
| 66682 | int offset = (int)ndigits - absv(K); |
| 66683 | if(offset <= 0) { |
| 66684 | /* fp < 1.0 -> write leading zero */ |
| 66685 | offset = -offset; |
| 66686 | dest[0] = '0'; |
| 66687 | dest[1] = '.'; |
| 66688 | memset(s: dest + 2, c: '0', n: (size_t)offset); |
| 66689 | memcpy(dest: dest + offset + 2, src: digits, n: ndigits); |
| 66690 | return ndigits + 2 + (unsigned)offset; |
| 66691 | } else { |
| 66692 | /* fp > 1.0 */ |
| 66693 | memcpy(dest: dest, src: digits, n: (size_t)offset); |
| 66694 | dest[offset] = '.'; |
| 66695 | memcpy(dest: dest + offset + 1, src: digits + offset, n: ndigits - (unsigned)offset); |
| 66696 | return ndigits + 1; |
| 66697 | } |
| 66698 | } |
| 66699 | |
| 66700 | /* write decimal w/ scientific notation */ |
| 66701 | ndigits = minv(ndigits, (unsigned)(18 - neg)); |
| 66702 | unsigned idx = 0; |
| 66703 | dest[idx++] = digits[0]; |
| 66704 | if(ndigits > 1) { |
| 66705 | dest[idx++] = '.'; |
| 66706 | memcpy(dest: dest + idx, src: digits + 1, n: ndigits - 1); |
| 66707 | idx += ndigits - 1; |
| 66708 | } |
| 66709 | |
| 66710 | dest[idx++] = 'e'; |
| 66711 | |
| 66712 | char sign = K + (int)ndigits - 1 < 0 ? '-' : '+'; |
| 66713 | dest[idx++] = sign; |
| 66714 | |
| 66715 | int cent = 0; |
| 66716 | if(exp > 99) { |
| 66717 | cent = exp / 100; |
| 66718 | dest[idx++] = (char)(cent + '0'); |
| 66719 | exp -= cent * 100; |
| 66720 | } |
| 66721 | if(exp > 9) { |
| 66722 | int dec = exp / 10; |
| 66723 | dest[idx++] = (char)(dec + '0'); |
| 66724 | exp -= dec * 10; |
| 66725 | |
| 66726 | } else if(cent) { |
| 66727 | dest[idx++] = '0'; |
| 66728 | } |
| 66729 | dest[idx++] = (char)(exp % 10 + '0'); |
| 66730 | return idx; |
| 66731 | } |
| 66732 | |
| 66733 | unsigned dtoa(double d, char* buffer) { |
| 66734 | uint64_t bits = 0; |
| 66735 | memcpy(dest: &bits, src: &d, n: sizeof(double)); |
| 66736 | |
| 66737 | uint64_t mantissa = bits & ((1ull << mantissa_bits) - 1); |
| 66738 | uint32_t exponent = (uint32_t) |
| 66739 | ((bits >> mantissa_bits) & ((1u << exponent_bits) - 1)); |
| 66740 | |
| 66741 | if(exponent == 0 && mantissa == 0) { |
| 66742 | memcpy(dest: buffer, src: "0.0", n: 3); |
| 66743 | return 3; |
| 66744 | } |
| 66745 | |
| 66746 | bool sign = ((bits >> (mantissa_bits + exponent_bits)) & 1) != 0; |
| 66747 | unsigned pos = 0; |
| 66748 | if(sign) { |
| 66749 | buffer[0] = '-'; |
| 66750 | pos++; |
| 66751 | buffer++; |
| 66752 | } |
| 66753 | |
| 66754 | if(exponent == ((1u << exponent_bits) - 1u)) { |
| 66755 | if(mantissa != 0) { |
| 66756 | memcpy(dest: buffer, src: "nan", n: 3); |
| 66757 | return 3; |
| 66758 | } else { |
| 66759 | memcpy(dest: &buffer[pos], src: "inf", n: 3); |
| 66760 | return pos + 3; |
| 66761 | } |
| 66762 | } |
| 66763 | |
| 66764 | int K = 0; |
| 66765 | char digits[18]; |
| 66766 | memset(s: digits, c: 0, n: 18); |
| 66767 | unsigned ndigits = grisu2(bits, digits, K: &K); |
| 66768 | return pos + emit_digits(digits, ndigits, dest: buffer, K, neg: sign); |
| 66769 | } |
| 66770 | |
| 66771 | /**** amalgamated original file "/deps/mp_printf.c" ****/ |
| 66772 | |
| 66773 | /** |
| 66774 | * @author (c) Julius Pfrommer |
| 66775 | * 2023, Fraunhofer IOSB, Germany |
| 66776 | * @author (c) Eyal Rozenberg <eyalroz1@gmx.com> |
| 66777 | * 2021-2023, Haifa, Palestine/Israel |
| 66778 | * @author (c) Marco Paland (info@paland.com) |
| 66779 | * 2014-2019, PALANDesign Hannover, Germany |
| 66780 | * |
| 66781 | * @note Others have made smaller contributions to this file: see the |
| 66782 | * contributors page at https://github.com/eyalroz/printf/graphs/contributors |
| 66783 | * or ask one of the authors. The original code for exponential specifiers was |
| 66784 | * contributed by Martijn Jasperse <m.jasperse@gmail.com>. |
| 66785 | * |
| 66786 | * @brief Small stand-alone implementation of the printf family of functions |
| 66787 | * (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems with |
| 66788 | * limited resources. |
| 66789 | * |
| 66790 | * @note the implementations are thread-safe; re-entrant; use no functions from |
| 66791 | * the standard library; and do not dynamically allocate any memory. |
| 66792 | * |
| 66793 | * @license The MIT License (MIT) |
| 66794 | * |
| 66795 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 66796 | * of this software and associated documentation files (the "Software"), to deal |
| 66797 | * in the Software without restriction, including without limitation the rights |
| 66798 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 66799 | * copies of the Software, and to permit persons to whom the Software is |
| 66800 | * furnished to do so, subject to the following conditions: |
| 66801 | * |
| 66802 | * The above copyright notice and this permission notice shall be included in |
| 66803 | * all copies or substantial portions of the Software. |
| 66804 | * |
| 66805 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 66806 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 66807 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 66808 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 66809 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 66810 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 66811 | * THE SOFTWARE. |
| 66812 | */ |
| 66813 | |
| 66814 | |
| 66815 | #include <stdint.h> |
| 66816 | #include <stdbool.h> |
| 66817 | |
| 66818 | // 'ntoa' conversion buffer size, this must be big enough to hold one converted |
| 66819 | // numeric number including padded zeros (dynamically created on stack) |
| 66820 | #define PRINTF_INTEGER_BUFFER_SIZE 32 |
| 66821 | |
| 66822 | // size of the fixed (on-stack) buffer for printing individual decimal numbers. |
| 66823 | // this must be big enough to hold one converted floating-point value including |
| 66824 | // padded zeros. |
| 66825 | #define PRINTF_DECIMAL_BUFFER_SIZE 32 |
| 66826 | |
| 66827 | // Default precision for the floating point conversion specifiers (the C |
| 66828 | // standard sets this at 6) |
| 66829 | #define PRINTF_DEFAULT_FLOAT_PRECISION 6 |
| 66830 | |
| 66831 | // internal flag definitions |
| 66832 | #define FLAGS_ZEROPAD (1U << 0U) |
| 66833 | #define FLAGS_LEFT (1U << 1U) |
| 66834 | #define FLAGS_PLUS (1U << 2U) |
| 66835 | #define FLAGS_SPACE (1U << 3U) |
| 66836 | #define FLAGS_HASH (1U << 4U) |
| 66837 | #define FLAGS_UPPERCASE (1U << 5U) |
| 66838 | #define FLAGS_CHAR (1U << 6U) |
| 66839 | #define FLAGS_SHORT (1U << 7U) |
| 66840 | // Only used with PRINTF_SUPPORT_MSVC_STYLE_INTEGER_SPECIFIERS |
| 66841 | #define FLAGS_LONG (1U << 9U) |
| 66842 | #define FLAGS_LONG_LONG (1U << 10U) |
| 66843 | #define FLAGS_PRECISION (1U << 11U) |
| 66844 | #define FLAGS_ADAPT_EXP (1U << 12U) |
| 66845 | #define FLAGS_POINTER (1U << 13U) |
| 66846 | // Note: Similar, but not identical, effect as FLAGS_HASH |
| 66847 | #define FLAGS_SIGNED (1U << 14U) |
| 66848 | |
| 66849 | #define BASE_BINARY 2 |
| 66850 | #define BASE_OCTAL 8 |
| 66851 | #define BASE_DECIMAL 10 |
| 66852 | #define BASE_HEX 16 |
| 66853 | |
| 66854 | typedef unsigned int printf_flags_t; |
| 66855 | typedef uint8_t numeric_base_t; |
| 66856 | typedef unsigned long long printf_unsigned_value_t; |
| 66857 | typedef long long printf_signed_value_t; |
| 66858 | |
| 66859 | // Note in particular the behavior here on LONG_MIN or LLONG_MIN; it is valid |
| 66860 | // and well-defined, but if you're not careful you can easily trigger undefined |
| 66861 | // behavior with -LONG_MIN or -LLONG_MIN |
| 66862 | #define ABS_FOR_PRINTING(_x) \ |
| 66863 | ((printf_unsigned_value_t)((_x) > 0 ? (_x) : -((printf_signed_value_t)_x))) |
| 66864 | |
| 66865 | // internal secure strlen @return The length of the string (excluding the |
| 66866 | // terminating 0) limited by 'maxsize' @note strlen uses size_t, but wes only |
| 66867 | // use this function with size_t variables - hence the signature. |
| 66868 | static size_t |
| 66869 | strnlen_s_(const char *str, size_t maxsize) { |
| 66870 | for(size_t i = 0; i < maxsize; i++) { |
| 66871 | if(!str[i]) |
| 66872 | return i; |
| 66873 | } |
| 66874 | return maxsize; |
| 66875 | } |
| 66876 | |
| 66877 | // internal test if char is a digit (0-9) |
| 66878 | // @return true if char is a digit |
| 66879 | static bool is_digit_(char ch) { return (ch >= '0') && (ch <= '9'); } |
| 66880 | |
| 66881 | // internal ASCII string to size_t conversion |
| 66882 | static size_t |
| 66883 | atou_(const char **str) { |
| 66884 | size_t i = 0U; |
| 66885 | while(is_digit_(ch: **str)) { |
| 66886 | i = i * 10U + (size_t)(*((*str)++) - '0'); |
| 66887 | } |
| 66888 | return i; |
| 66889 | } |
| 66890 | |
| 66891 | // Output buffer |
| 66892 | typedef struct { |
| 66893 | char *buffer; |
| 66894 | size_t pos; |
| 66895 | size_t max_chars; |
| 66896 | } output_t; |
| 66897 | |
| 66898 | static void |
| 66899 | putchar_(output_t *out, char c) { |
| 66900 | size_t write_pos = out->pos++; |
| 66901 | // We're _always_ increasing pos, so as to count how may characters |
| 66902 | // _would_ have been written if not for the max_chars limitation |
| 66903 | if(write_pos >= out->max_chars) |
| 66904 | return; |
| 66905 | // it must be the case that out->buffer != NULL , due to the constraint |
| 66906 | // on output_t ; and note we're relying on write_pos being non-negative. |
| 66907 | out->buffer[write_pos] = c; |
| 66908 | } |
| 66909 | |
| 66910 | static void |
| 66911 | out_(output_t *out, const char *buf, size_t len) { |
| 66912 | if(out->pos < out->max_chars) { |
| 66913 | size_t write_len = len; |
| 66914 | if(out->pos + len > out->max_chars) |
| 66915 | write_len = out->max_chars - out->pos; |
| 66916 | for(size_t i = 0; i < write_len; i++) |
| 66917 | out->buffer[out->pos + i] = buf[i]; |
| 66918 | } |
| 66919 | out->pos += len; // Always increase pos by len |
| 66920 | } |
| 66921 | |
| 66922 | // output the specified string in reverse, taking care of any zero-padding |
| 66923 | static void |
| 66924 | out_rev_(output_t *output, const char *buf, size_t len, size_t width, |
| 66925 | printf_flags_t flags) { |
| 66926 | const size_t start_pos = output->pos; |
| 66927 | |
| 66928 | // pad spaces up to given width |
| 66929 | if(!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) { |
| 66930 | for(size_t i = len; i < width; i++) { |
| 66931 | putchar_(out: output, c: ' '); |
| 66932 | } |
| 66933 | } |
| 66934 | |
| 66935 | // reverse string |
| 66936 | while(len) { |
| 66937 | putchar_(out: output, c: buf[--len]); |
| 66938 | } |
| 66939 | |
| 66940 | // append pad spaces up to given width |
| 66941 | if(flags & FLAGS_LEFT) { |
| 66942 | while(output->pos - start_pos < width) { |
| 66943 | putchar_(out: output, c: ' '); |
| 66944 | } |
| 66945 | } |
| 66946 | } |
| 66947 | |
| 66948 | // Invoked by print_integer after the actual number has been printed, performing |
| 66949 | // necessary work on the number's prefix (as the number is initially printed in |
| 66950 | // reverse order) |
| 66951 | static void |
| 66952 | print_integer_finalization(output_t *output, char *buf, size_t len, bool negative, |
| 66953 | numeric_base_t base, size_t precision, size_t width, |
| 66954 | printf_flags_t flags) { |
| 66955 | size_t unpadded_len = len; |
| 66956 | |
| 66957 | // pad with leading zeros |
| 66958 | if(!(flags & FLAGS_LEFT)) { |
| 66959 | if(width && (flags & FLAGS_ZEROPAD) && |
| 66960 | (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) { |
| 66961 | width--; |
| 66962 | } |
| 66963 | while((flags & FLAGS_ZEROPAD) && (len < width) && |
| 66964 | (len < PRINTF_INTEGER_BUFFER_SIZE)) { |
| 66965 | buf[len++] = '0'; |
| 66966 | } |
| 66967 | } |
| 66968 | |
| 66969 | while((len < precision) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { |
| 66970 | buf[len++] = '0'; |
| 66971 | } |
| 66972 | |
| 66973 | if(base == BASE_OCTAL && (len > unpadded_len)) { |
| 66974 | // Since we've written some zeros, we've satisfied the alternative format |
| 66975 | // leading space requirement |
| 66976 | flags &= ~FLAGS_HASH; |
| 66977 | } |
| 66978 | |
| 66979 | // handle hash |
| 66980 | if(flags & (FLAGS_HASH | FLAGS_POINTER)) { |
| 66981 | if(!(flags & FLAGS_PRECISION) && len && ((len == precision) || (len == width))) { |
| 66982 | // Let's take back some padding digits to fit in what will eventually be |
| 66983 | // the format-specific prefix |
| 66984 | if(unpadded_len < len) { |
| 66985 | len--; // This should suffice for BASE_OCTAL |
| 66986 | } |
| 66987 | if(len && (base == BASE_HEX || base == BASE_BINARY) && (unpadded_len < len)) { |
| 66988 | len--; // ... and an extra one for 0x or 0b |
| 66989 | } |
| 66990 | } |
| 66991 | if((base == BASE_HEX) && !(flags & FLAGS_UPPERCASE) && |
| 66992 | (len < PRINTF_INTEGER_BUFFER_SIZE)) { |
| 66993 | buf[len++] = 'x'; |
| 66994 | } else if((base == BASE_HEX) && (flags & FLAGS_UPPERCASE) && |
| 66995 | (len < PRINTF_INTEGER_BUFFER_SIZE)) { |
| 66996 | buf[len++] = 'X'; |
| 66997 | } else if((base == BASE_BINARY) && (len < PRINTF_INTEGER_BUFFER_SIZE)) { |
| 66998 | buf[len++] = 'b'; |
| 66999 | } |
| 67000 | if(len < PRINTF_INTEGER_BUFFER_SIZE) { |
| 67001 | buf[len++] = '0'; |
| 67002 | } |
| 67003 | } |
| 67004 | |
| 67005 | if(len < PRINTF_INTEGER_BUFFER_SIZE) { |
| 67006 | if(negative) { |
| 67007 | buf[len++] = '-'; |
| 67008 | } else if(flags & FLAGS_PLUS) { |
| 67009 | buf[len++] = '+'; // ignore the space if the '+' exists |
| 67010 | } else if(flags & FLAGS_SPACE) { |
| 67011 | buf[len++] = ' '; |
| 67012 | } |
| 67013 | } |
| 67014 | |
| 67015 | out_rev_(output, buf, len, width, flags); |
| 67016 | } |
| 67017 | |
| 67018 | // An internal itoa-like function |
| 67019 | static void |
| 67020 | print_integer(output_t *output, printf_unsigned_value_t value, bool negative, |
| 67021 | numeric_base_t base, size_t precision, size_t width, printf_flags_t flags) { |
| 67022 | char buf[PRINTF_INTEGER_BUFFER_SIZE]; |
| 67023 | size_t len = 0U; |
| 67024 | |
| 67025 | if(!value) { |
| 67026 | if(!(flags & FLAGS_PRECISION)) { |
| 67027 | buf[len++] = '0'; |
| 67028 | flags &= ~FLAGS_HASH; |
| 67029 | // We drop this flag this since either the alternative and regular modes |
| 67030 | // of the specifier don't differ on 0 values, or (in the case of octal) |
| 67031 | // we've already provided the special handling for this mode. |
| 67032 | } else if(base == BASE_HEX) { |
| 67033 | flags &= ~FLAGS_HASH; |
| 67034 | // We drop this flag this since either the alternative and regular modes |
| 67035 | // of the specifier don't differ on 0 values |
| 67036 | } |
| 67037 | } else { |
| 67038 | do { |
| 67039 | const char digit = (char)(value % base); |
| 67040 | buf[len++] = |
| 67041 | (char)(digit < 10 ? '0' + digit |
| 67042 | : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10); |
| 67043 | value /= base; |
| 67044 | } while(value && (len < PRINTF_INTEGER_BUFFER_SIZE)); |
| 67045 | } |
| 67046 | |
| 67047 | print_integer_finalization(output, buf, len, negative, base, precision, width, flags); |
| 67048 | } |
| 67049 | |
| 67050 | static void |
| 67051 | print_floating_point(output_t *output, double value, size_t precision, |
| 67052 | size_t width, printf_flags_t flags) { |
| 67053 | if((flags & FLAGS_PLUS) && value > 0.0) |
| 67054 | putchar_(out: output, c: '+'); |
| 67055 | |
| 67056 | // set default precision, if not set explicitly |
| 67057 | //if(!(flags & FLAGS_PRECISION) || precision > PRINTF_DECIMAL_BUFFER_SIZE - 5) |
| 67058 | // precision = PRINTF_DEFAULT_FLOAT_PRECISION; |
| 67059 | |
| 67060 | char buf[PRINTF_DECIMAL_BUFFER_SIZE]; |
| 67061 | unsigned len = dtoa(d: value, buffer: buf); // Fill the buffer (TODO: Consider precision) |
| 67062 | out_(out: output, buf, len); // Print the buffer |
| 67063 | } |
| 67064 | |
| 67065 | // Advances the format pointer past the flags, and returns the parsed flags |
| 67066 | // due to the characters passed |
| 67067 | static printf_flags_t |
| 67068 | parse_flags(const char **format) { |
| 67069 | printf_flags_t flags = 0U; |
| 67070 | do { |
| 67071 | switch(**format) { |
| 67072 | case '0': flags |= FLAGS_ZEROPAD; break; |
| 67073 | case '-': flags |= FLAGS_LEFT; break; |
| 67074 | case '+': flags |= FLAGS_PLUS; break; |
| 67075 | case ' ': flags |= FLAGS_SPACE; break; |
| 67076 | case '#': flags |= FLAGS_HASH; break; |
| 67077 | default: return flags; |
| 67078 | } |
| 67079 | (*format)++; |
| 67080 | } while(true); |
| 67081 | } |
| 67082 | |
| 67083 | #define ADVANCE_IN_FORMAT_STRING(cptr_) \ |
| 67084 | do { \ |
| 67085 | (cptr_)++; \ |
| 67086 | if(!*(cptr_)) \ |
| 67087 | return; \ |
| 67088 | } while(0) |
| 67089 | |
| 67090 | static void |
| 67091 | format_string_loop(output_t *output, const char *format, va_list args) { |
| 67092 | while(*format) { |
| 67093 | if(*format != '%') { |
| 67094 | // A regular content character |
| 67095 | putchar_(out: output, c: *format); |
| 67096 | format++; |
| 67097 | continue; |
| 67098 | } |
| 67099 | // We're parsing a format specifier: %[flags][width][.precision][length] |
| 67100 | ADVANCE_IN_FORMAT_STRING(format); |
| 67101 | |
| 67102 | printf_flags_t flags = parse_flags(format: &format); |
| 67103 | |
| 67104 | // evaluate width field |
| 67105 | size_t width = 0U; |
| 67106 | if(is_digit_(ch: *format)) { |
| 67107 | width = atou_(str: &format); |
| 67108 | } else if(*format == '*') { |
| 67109 | const int w = va_arg(args, int); |
| 67110 | if(w < 0) { |
| 67111 | flags |= FLAGS_LEFT; // reverse padding |
| 67112 | width = (size_t)-w; |
| 67113 | } else { |
| 67114 | width = (size_t)w; |
| 67115 | } |
| 67116 | ADVANCE_IN_FORMAT_STRING(format); |
| 67117 | } |
| 67118 | |
| 67119 | // evaluate precision field |
| 67120 | size_t precision = 0U; |
| 67121 | if(*format == '.') { |
| 67122 | flags |= FLAGS_PRECISION; |
| 67123 | ADVANCE_IN_FORMAT_STRING(format); |
| 67124 | if(is_digit_(ch: *format)) { |
| 67125 | precision = atou_(str: &format); |
| 67126 | } else if(*format == '*') { |
| 67127 | const int precision_ = va_arg(args, int); |
| 67128 | precision = precision_ > 0 ? (size_t)precision_ : 0U; |
| 67129 | ADVANCE_IN_FORMAT_STRING(format); |
| 67130 | } |
| 67131 | } |
| 67132 | |
| 67133 | // evaluate length field |
| 67134 | switch(*format) { |
| 67135 | case 'l': |
| 67136 | flags |= FLAGS_LONG; |
| 67137 | ADVANCE_IN_FORMAT_STRING(format); |
| 67138 | if(*format == 'l') { |
| 67139 | flags |= FLAGS_LONG_LONG; |
| 67140 | ADVANCE_IN_FORMAT_STRING(format); |
| 67141 | } |
| 67142 | break; |
| 67143 | case 'h': |
| 67144 | flags |= FLAGS_SHORT; |
| 67145 | ADVANCE_IN_FORMAT_STRING(format); |
| 67146 | if(*format == 'h') { |
| 67147 | flags |= FLAGS_CHAR; |
| 67148 | ADVANCE_IN_FORMAT_STRING(format); |
| 67149 | } |
| 67150 | break; |
| 67151 | case 't': |
| 67152 | flags |= |
| 67153 | (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); |
| 67154 | ADVANCE_IN_FORMAT_STRING(format); |
| 67155 | break; |
| 67156 | case 'j': |
| 67157 | flags |= |
| 67158 | (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); |
| 67159 | ADVANCE_IN_FORMAT_STRING(format); |
| 67160 | break; |
| 67161 | case 'z': |
| 67162 | flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG); |
| 67163 | ADVANCE_IN_FORMAT_STRING(format); |
| 67164 | break; |
| 67165 | default: |
| 67166 | break; |
| 67167 | } |
| 67168 | |
| 67169 | // evaluate specifier |
| 67170 | switch(*format) { |
| 67171 | case 'd': |
| 67172 | case 'i': |
| 67173 | case 'u': |
| 67174 | case 'x': |
| 67175 | case 'X': |
| 67176 | case 'o': |
| 67177 | case 'b': { |
| 67178 | if(*format == 'd' || *format == 'i') { |
| 67179 | flags |= FLAGS_SIGNED; |
| 67180 | } |
| 67181 | |
| 67182 | numeric_base_t base; |
| 67183 | if(*format == 'x' || *format == 'X') { |
| 67184 | base = BASE_HEX; |
| 67185 | } else if(*format == 'o') { |
| 67186 | base = BASE_OCTAL; |
| 67187 | } else if(*format == 'b') { |
| 67188 | base = BASE_BINARY; |
| 67189 | } else { |
| 67190 | base = BASE_DECIMAL; |
| 67191 | flags &= |
| 67192 | ~FLAGS_HASH; // decimal integers have no alternative presentation |
| 67193 | } |
| 67194 | |
| 67195 | if(*format == 'X') { |
| 67196 | flags |= FLAGS_UPPERCASE; |
| 67197 | } |
| 67198 | |
| 67199 | format++; |
| 67200 | // ignore '0' flag when precision is given |
| 67201 | if(flags & FLAGS_PRECISION) { |
| 67202 | flags &= ~FLAGS_ZEROPAD; |
| 67203 | } |
| 67204 | |
| 67205 | if(flags & FLAGS_SIGNED) { |
| 67206 | // A signed specifier: d, i or possibly I + bit size if enabled |
| 67207 | if(flags & FLAGS_LONG_LONG) { |
| 67208 | const long long value = va_arg(args, long long); |
| 67209 | print_integer(output, ABS_FOR_PRINTING(value), negative: value < 0, base, |
| 67210 | precision, width, flags); |
| 67211 | } else if(flags & FLAGS_LONG) { |
| 67212 | const long value = va_arg(args, long); |
| 67213 | print_integer(output, ABS_FOR_PRINTING(value), negative: value < 0, base, |
| 67214 | precision, width, flags); |
| 67215 | } else { |
| 67216 | // We never try to interpret the argument as something |
| 67217 | // potentially-smaller than int, due to integer promotion rules: |
| 67218 | // Even if the user passed a short int, short unsigned etc. - |
| 67219 | // these will come in after promotion, as int's (or unsigned for |
| 67220 | // the case of short unsigned when it has the same size as int) |
| 67221 | const int value = |
| 67222 | (flags & FLAGS_CHAR) ? (signed char)va_arg(args, int) |
| 67223 | : (flags & FLAGS_SHORT) ? (short int)va_arg(args, int) |
| 67224 | : va_arg(args, int); |
| 67225 | print_integer(output, ABS_FOR_PRINTING(value), negative: value < 0, base, |
| 67226 | precision, width, flags); |
| 67227 | } |
| 67228 | } else { |
| 67229 | // An unsigned specifier: u, x, X, o, b |
| 67230 | flags &= ~(FLAGS_PLUS | FLAGS_SPACE); |
| 67231 | |
| 67232 | if(flags & FLAGS_LONG_LONG) { |
| 67233 | print_integer(output, value: (printf_unsigned_value_t) |
| 67234 | va_arg(args, unsigned long long), |
| 67235 | false, base, precision, width, flags); |
| 67236 | } else if(flags & FLAGS_LONG) { |
| 67237 | print_integer(output, value: (printf_unsigned_value_t) |
| 67238 | va_arg(args, unsigned long), |
| 67239 | false, base, precision, width, flags); |
| 67240 | } else { |
| 67241 | const unsigned int value = (flags & FLAGS_CHAR) |
| 67242 | ? (unsigned char)va_arg(args, unsigned int) |
| 67243 | : (flags & FLAGS_SHORT) |
| 67244 | ? (unsigned short int)va_arg(args, unsigned int) |
| 67245 | : va_arg(args, unsigned int); |
| 67246 | print_integer(output, value: (printf_unsigned_value_t)value, false, base, |
| 67247 | precision, width, flags); |
| 67248 | } |
| 67249 | } |
| 67250 | break; |
| 67251 | } |
| 67252 | |
| 67253 | case 'f': |
| 67254 | case 'F': |
| 67255 | if(*format == 'F') |
| 67256 | flags |= FLAGS_UPPERCASE; |
| 67257 | print_floating_point(output, value: (double)va_arg(args, double), |
| 67258 | precision, width, flags); |
| 67259 | format++; |
| 67260 | break; |
| 67261 | |
| 67262 | case 'c': { |
| 67263 | size_t l = 1U; |
| 67264 | // pre padding |
| 67265 | if(!(flags & FLAGS_LEFT)) { |
| 67266 | while(l++ < width) { |
| 67267 | putchar_(out: output, c: ' '); |
| 67268 | } |
| 67269 | } |
| 67270 | // char output |
| 67271 | putchar_(out: output, c: (char)va_arg(args, int)); |
| 67272 | // post padding |
| 67273 | if(flags & FLAGS_LEFT) { |
| 67274 | while(l++ < width) { |
| 67275 | putchar_(out: output, c: ' '); |
| 67276 | } |
| 67277 | } |
| 67278 | format++; |
| 67279 | break; |
| 67280 | } |
| 67281 | |
| 67282 | case 's': { |
| 67283 | const char *p = va_arg(args, char *); |
| 67284 | if(p == NULL) { |
| 67285 | out_rev_(output, buf: ")llun(", len: 6, width, flags); |
| 67286 | } else { |
| 67287 | // string length |
| 67288 | size_t l = strnlen_s_(str: p, maxsize: precision ? precision : INT32_MAX); |
| 67289 | if(flags & FLAGS_PRECISION) { |
| 67290 | l = (l < precision ? l : precision); |
| 67291 | } |
| 67292 | |
| 67293 | // pre padding |
| 67294 | if(!(flags & FLAGS_LEFT)) { |
| 67295 | for(size_t i = 0; l + i < width; i++) { |
| 67296 | putchar_(out: output, c: ' '); |
| 67297 | } |
| 67298 | } |
| 67299 | |
| 67300 | // string output |
| 67301 | out_(out: output, buf: p, len: l); |
| 67302 | |
| 67303 | // post padding |
| 67304 | if(flags & FLAGS_LEFT) { |
| 67305 | for(size_t i = 0; l + i < width; i++) { |
| 67306 | putchar_(out: output, c: ' '); |
| 67307 | } |
| 67308 | } |
| 67309 | } |
| 67310 | format++; |
| 67311 | break; |
| 67312 | } |
| 67313 | |
| 67314 | case 'p': { |
| 67315 | width = |
| 67316 | sizeof(void *) * 2U + 2; // 2 hex chars per byte + the "0x" prefix |
| 67317 | flags |= FLAGS_ZEROPAD | FLAGS_POINTER; |
| 67318 | uintptr_t value = (uintptr_t)va_arg(args, void *); |
| 67319 | (value == (uintptr_t)NULL) |
| 67320 | ? out_rev_(output, buf: ")lin(", len: 5, width, flags) |
| 67321 | : print_integer(output, value: (printf_unsigned_value_t)value, false, |
| 67322 | BASE_HEX, precision, width, flags); |
| 67323 | format++; |
| 67324 | break; |
| 67325 | } |
| 67326 | |
| 67327 | case '%': |
| 67328 | putchar_(out: output, c: '%'); |
| 67329 | format++; |
| 67330 | break; |
| 67331 | |
| 67332 | default: |
| 67333 | putchar_(out: output, c: *format); |
| 67334 | format++; |
| 67335 | break; |
| 67336 | } |
| 67337 | } |
| 67338 | } |
| 67339 | |
| 67340 | int |
| 67341 | mp_vsnprintf(char *s, size_t n, const char *format, va_list arg) { |
| 67342 | // Check that the inputs are sane |
| 67343 | if(!s || n < 1) |
| 67344 | return -1; |
| 67345 | |
| 67346 | // Format the string |
| 67347 | output_t out = {s, 0, n}; |
| 67348 | format_string_loop(output: &out, format, args: arg); |
| 67349 | |
| 67350 | // Write the string-terminating '\0' character |
| 67351 | size_t null_char_pos = out.pos < out.max_chars ? out.pos : out.max_chars - 1; |
| 67352 | out.buffer[null_char_pos] = '\0'; |
| 67353 | |
| 67354 | // Return written chars without terminating \0 |
| 67355 | return (int)out.pos; |
| 67356 | } |
| 67357 | |
| 67358 | int |
| 67359 | mp_snprintf(char *s, size_t n, const char *format, ...) { |
| 67360 | va_list args; |
| 67361 | va_start(args, format); |
| 67362 | const int ret = mp_vsnprintf(s, n, format, arg: args); |
| 67363 | va_end(args); |
| 67364 | return ret; |
| 67365 | } |
| 67366 | |
| 67367 | /**** amalgamated original file "/deps/itoa.c" ****/ |
| 67368 | |
| 67369 | /* |
| 67370 | * Copyright 2017 Techie Delight |
| 67371 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 67372 | * of this software and associated documentation files (the "Software"), to deal |
| 67373 | * in the Software without restriction, including without limitation the rights |
| 67374 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 67375 | * copies of the Software, and to permit persons to whom the Software is |
| 67376 | * furnished to do so, subject to the following conditions: |
| 67377 | * |
| 67378 | * The above copyright notice and this permission notice shall be included |
| 67379 | * in all copies or substantial portions of the Software. |
| 67380 | * |
| 67381 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 67382 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 67383 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 67384 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 67385 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF |
| 67386 | * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 67387 | */ |
| 67388 | |
| 67389 | /* Originally released by techiedelight.com |
| 67390 | * (http://www.techiedelight.com/implement-itoa-function-in-c/) under the |
| 67391 | * MIT license. */ |
| 67392 | |
| 67393 | |
| 67394 | static void swap(char *x, char *y) { |
| 67395 | char t = *x; |
| 67396 | *x = *y; |
| 67397 | *y = t; |
| 67398 | } |
| 67399 | |
| 67400 | /* function to reverse buffer */ |
| 67401 | static char* reverse(char *buffer, UA_UInt16 i, UA_UInt16 j) { |
| 67402 | while (i < j) |
| 67403 | swap(x: &buffer[i++], y: &buffer[j--]); |
| 67404 | |
| 67405 | return buffer; |
| 67406 | } |
| 67407 | |
| 67408 | /* adapted from http://www.techiedelight.com/implement-itoa-function-in-c/ to use UA_... types */ |
| 67409 | UA_UInt16 itoaUnsigned(UA_UInt64 value, char* buffer, UA_Byte base) { |
| 67410 | /* consider absolute value of number */ |
| 67411 | UA_UInt64 n = value; |
| 67412 | |
| 67413 | UA_UInt16 i = 0; |
| 67414 | while (n) { |
| 67415 | UA_UInt64 r = n % base; |
| 67416 | |
| 67417 | if (r >= 10) |
| 67418 | buffer[i++] = (char)(65 + (r - 10)); |
| 67419 | else |
| 67420 | buffer[i++] = (char)(48 + r); |
| 67421 | |
| 67422 | n = n / base; |
| 67423 | } |
| 67424 | /* if number is 0 */ |
| 67425 | if (i == 0) |
| 67426 | buffer[i++] = '0'; |
| 67427 | |
| 67428 | buffer[i] = '\0'; /* null terminate string */ |
| 67429 | i--; |
| 67430 | /* reverse the string */ |
| 67431 | reverse(buffer, i: 0, j: i); |
| 67432 | i++; |
| 67433 | return i; |
| 67434 | } |
| 67435 | |
| 67436 | /* adapted from http://www.techiedelight.com/implement-itoa-function-in-c/ */ |
| 67437 | UA_UInt16 itoaSigned(UA_Int64 value, char* buffer) { |
| 67438 | /* Special case for UA_INT64_MIN which can not simply be negated */ |
| 67439 | /* it will cause a signed integer overflow */ |
| 67440 | UA_UInt64 n; |
| 67441 | if(value == UA_INT64_MIN) { |
| 67442 | n = (UA_UInt64)UA_INT64_MAX + 1; |
| 67443 | } else { |
| 67444 | n = (UA_UInt64)value; |
| 67445 | if(value < 0){ |
| 67446 | n = (UA_UInt64)-value; |
| 67447 | } |
| 67448 | } |
| 67449 | |
| 67450 | UA_UInt16 i = 0; |
| 67451 | while(n) { |
| 67452 | UA_UInt64 r = n % 10; |
| 67453 | buffer[i++] = (char)('0' + r); |
| 67454 | n = n / 10; |
| 67455 | } |
| 67456 | |
| 67457 | if(i == 0) |
| 67458 | buffer[i++] = '0'; /* if number is 0 */ |
| 67459 | if(value < 0) |
| 67460 | buffer[i++] = '-'; |
| 67461 | buffer[i] = '\0'; /* null terminate string */ |
| 67462 | i--; |
| 67463 | reverse(buffer, i: 0, j: i); /* reverse the string and return it */ |
| 67464 | i++; |
| 67465 | return i; |
| 67466 | } |
| 67467 | |
| 67468 | |
| 67469 | /**** amalgamated original file "/deps/ziptree.c" ****/ |
| 67470 | |
| 67471 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 67472 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 67473 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 67474 | * |
| 67475 | * Copyright 2021-2022 (c) Julius Pfrommer |
| 67476 | */ |
| 67477 | |
| 67478 | |
| 67479 | /* Dummy types */ |
| 67480 | struct zip_elem; |
| 67481 | typedef struct zip_elem zip_elem; |
| 67482 | typedef ZIP_ENTRY(zip_elem) zip_entry; |
| 67483 | typedef ZIP_HEAD(, zip_elem) zip_head; |
| 67484 | |
| 67485 | /* Access macros */ |
| 67486 | #define ZIP_ENTRY_PTR(x) ((zip_entry*)((char*)x + fieldoffset)) |
| 67487 | #define ZIP_KEY_PTR(x) (const void*)((const char*)x + keyoffset) |
| 67488 | |
| 67489 | /* Hash pointers to keep the tie-breeaking of equal keys (mostly) uncorrelated |
| 67490 | * from the rank (pointer order). Hashing code taken from sdbm-hash |
| 67491 | * (http://www.cse.yorku.ca/~oz/hash.html). */ |
| 67492 | static unsigned int |
| 67493 | __ZIP_PTR_HASH(const void *p) { |
| 67494 | unsigned int h = 0; |
| 67495 | const unsigned char *data = (const unsigned char*)&p; |
| 67496 | for(size_t i = 0; i < (sizeof(void*) / sizeof(char)); i++) |
| 67497 | h = data[i] + (h << 6) + (h << 16) - h; |
| 67498 | return h; |
| 67499 | } |
| 67500 | |
| 67501 | static ZIP_INLINE enum ZIP_CMP |
| 67502 | __ZIP_RANK_CMP(const void *p1, const void *p2) { |
| 67503 | /* assert(p1 != p2); */ |
| 67504 | unsigned int h1 = __ZIP_PTR_HASH(p: p1); |
| 67505 | unsigned int h2 = __ZIP_PTR_HASH(p: p2); |
| 67506 | if(h1 == h2) |
| 67507 | return (p1 < p2) ? ZIP_CMP_LESS : ZIP_CMP_MORE; |
| 67508 | return (h1 < h2) ? ZIP_CMP_LESS : ZIP_CMP_MORE; |
| 67509 | } |
| 67510 | |
| 67511 | static ZIP_INLINE enum ZIP_CMP |
| 67512 | __ZIP_UNIQUE_CMP(zip_cmp_cb cmp, const void *p1, const void *p2) { |
| 67513 | if(p1 == p2) |
| 67514 | return ZIP_CMP_EQ; |
| 67515 | enum ZIP_CMP order = cmp(p1, p2); |
| 67516 | if(order == ZIP_CMP_EQ) |
| 67517 | return (p1 < p2) ? ZIP_CMP_LESS : ZIP_CMP_MORE; |
| 67518 | return order; |
| 67519 | } |
| 67520 | |
| 67521 | #if 0 |
| 67522 | #include <assert.h> |
| 67523 | ZIP_UNUSED static ZIP_INLINE void |
| 67524 | __ZIP_VALIDATE(zip_cmp_cb cmp, unsigned short fieldoffset, |
| 67525 | unsigned short keyoffset, void *elm, |
| 67526 | void *min_elm, void *max_elm) { |
| 67527 | if(!elm) |
| 67528 | return; |
| 67529 | enum ZIP_CMP c1 = __ZIP_UNIQUE_CMP(cmp, ZIP_KEY_PTR(min_elm), ZIP_KEY_PTR(elm)); |
| 67530 | assert((elm == min_elm && c1 == ZIP_CMP_EQ) || c1 == ZIP_CMP_LESS); |
| 67531 | |
| 67532 | enum ZIP_CMP c2 = __ZIP_UNIQUE_CMP(cmp, ZIP_KEY_PTR(max_elm), ZIP_KEY_PTR(elm)); |
| 67533 | assert((elm == max_elm && c2 == ZIP_CMP_EQ) || c2 == ZIP_CMP_MORE); |
| 67534 | |
| 67535 | assert(!ZIP_ENTRY_PTR(elm)->right || |
| 67536 | __ZIP_RANK_CMP(elm, ZIP_ENTRY_PTR(elm)->right) == ZIP_CMP_MORE); |
| 67537 | assert(!ZIP_ENTRY_PTR(elm)->left || |
| 67538 | __ZIP_RANK_CMP(elm, ZIP_ENTRY_PTR(elm)->left) == ZIP_CMP_MORE); |
| 67539 | |
| 67540 | __ZIP_VALIDATE(cmp, fieldoffset, keyoffset, ZIP_ENTRY_PTR(elm)->right, elm, max_elm); |
| 67541 | __ZIP_VALIDATE(cmp, fieldoffset, keyoffset, ZIP_ENTRY_PTR(elm)->left, min_elm, elm); |
| 67542 | } |
| 67543 | #endif |
| 67544 | |
| 67545 | /* Walk down the right-side spine of cur. Elements that are larger than x_key |
| 67546 | * are moved under x->right. */ |
| 67547 | static void |
| 67548 | __ZIP_INSERT_MOVE_RIGHT(zip_cmp_cb cmp, unsigned short fieldoffset, |
| 67549 | unsigned short keyoffset, const void *x_key, |
| 67550 | zip_elem **fix_edge, zip_elem *cur) { |
| 67551 | while(ZIP_ENTRY_PTR(cur)->right) { |
| 67552 | zip_elem *move_candidate = ZIP_ENTRY_PTR(cur)->right; |
| 67553 | if(__ZIP_UNIQUE_CMP(cmp, p1: x_key, ZIP_KEY_PTR(move_candidate)) == ZIP_CMP_MORE) { |
| 67554 | cur = ZIP_ENTRY_PTR(cur)->right; |
| 67555 | continue; |
| 67556 | } |
| 67557 | ZIP_ENTRY_PTR(cur)->right = ZIP_ENTRY_PTR(move_candidate)->left; |
| 67558 | ZIP_ENTRY_PTR(move_candidate)->left = NULL; |
| 67559 | *fix_edge = move_candidate; |
| 67560 | fix_edge = &ZIP_ENTRY_PTR(move_candidate)->left; |
| 67561 | } |
| 67562 | } |
| 67563 | |
| 67564 | static void |
| 67565 | __ZIP_INSERT_MOVE_LEFT(zip_cmp_cb cmp, unsigned short fieldoffset, |
| 67566 | unsigned short keyoffset, const void *x_key, |
| 67567 | zip_elem **fix_edge, zip_elem *cur) { |
| 67568 | while(ZIP_ENTRY_PTR(cur)->left) { |
| 67569 | zip_elem *move_candidate = ZIP_ENTRY_PTR(cur)->left; |
| 67570 | if(__ZIP_UNIQUE_CMP(cmp, p1: x_key, ZIP_KEY_PTR(move_candidate)) == ZIP_CMP_LESS) { |
| 67571 | cur = ZIP_ENTRY_PTR(cur)->left; |
| 67572 | continue; |
| 67573 | } |
| 67574 | ZIP_ENTRY_PTR(cur)->left = ZIP_ENTRY_PTR(move_candidate)->right; |
| 67575 | ZIP_ENTRY_PTR(move_candidate)->right = NULL; |
| 67576 | *fix_edge = move_candidate; |
| 67577 | fix_edge = &ZIP_ENTRY_PTR(move_candidate)->right; |
| 67578 | } |
| 67579 | } |
| 67580 | |
| 67581 | void |
| 67582 | __ZIP_INSERT(void *h, zip_cmp_cb cmp, unsigned short fieldoffset, |
| 67583 | unsigned short keyoffset, void *elm) { |
| 67584 | zip_elem *x = (zip_elem*)elm; |
| 67585 | ZIP_ENTRY_PTR(x)->left = NULL; |
| 67586 | ZIP_ENTRY_PTR(x)->right = NULL; |
| 67587 | |
| 67588 | const void *x_key = ZIP_KEY_PTR(x); |
| 67589 | zip_head *head = (zip_head*)h; |
| 67590 | if(!head->root) { |
| 67591 | head->root = x; |
| 67592 | return; |
| 67593 | } |
| 67594 | |
| 67595 | /* Go down the tree to find the top element "cur" that has a rank smaller |
| 67596 | * than "x" */ |
| 67597 | zip_elem *prev = NULL; |
| 67598 | zip_elem *cur = head->root; |
| 67599 | enum ZIP_CMP cur_order, prev_order; |
| 67600 | do { |
| 67601 | cur_order = __ZIP_UNIQUE_CMP(cmp, p1: x_key, ZIP_KEY_PTR(cur)); |
| 67602 | if(cur_order == ZIP_CMP_EQ) |
| 67603 | return; /* x is already inserted */ |
| 67604 | if(__ZIP_RANK_CMP(p1: cur, p2: x) == ZIP_CMP_LESS) |
| 67605 | break; |
| 67606 | prev = cur; |
| 67607 | prev_order = cur_order; |
| 67608 | cur = (cur_order == ZIP_CMP_MORE) ? |
| 67609 | ZIP_ENTRY_PTR(cur)->right : ZIP_ENTRY_PTR(cur)->left; |
| 67610 | } while(cur); |
| 67611 | |
| 67612 | /* Insert "x" instead of "cur" under its parent "prev" */ |
| 67613 | if(cur == head->root) { |
| 67614 | head->root = x; |
| 67615 | } else { |
| 67616 | if(prev_order == ZIP_CMP_MORE) |
| 67617 | ZIP_ENTRY_PTR(prev)->right = x; |
| 67618 | else |
| 67619 | ZIP_ENTRY_PTR(prev)->left = x; |
| 67620 | } |
| 67621 | |
| 67622 | if(!cur) |
| 67623 | return; |
| 67624 | |
| 67625 | /* Re-insert "cur" under "x". Repair by moving elements that ended up on the |
| 67626 | * wrong side of "x". */ |
| 67627 | if(cur_order == ZIP_CMP_MORE) { |
| 67628 | ZIP_ENTRY_PTR(x)->left = cur; |
| 67629 | __ZIP_INSERT_MOVE_RIGHT(cmp, fieldoffset, keyoffset, |
| 67630 | x_key, fix_edge: &ZIP_ENTRY_PTR(x)->right, cur); |
| 67631 | } else { |
| 67632 | ZIP_ENTRY_PTR(x)->right = cur; |
| 67633 | __ZIP_INSERT_MOVE_LEFT(cmp, fieldoffset, keyoffset, |
| 67634 | x_key, fix_edge: &ZIP_ENTRY_PTR(x)->left, cur); |
| 67635 | } |
| 67636 | } |
| 67637 | |
| 67638 | void * |
| 67639 | __ZIP_REMOVE(void *h, zip_cmp_cb cmp, unsigned short fieldoffset, |
| 67640 | unsigned short keyoffset, void *elm) { |
| 67641 | zip_head *head = (zip_head*)h; |
| 67642 | zip_elem *x = (zip_elem*)elm; |
| 67643 | zip_elem *cur = head->root; |
| 67644 | if(!cur) |
| 67645 | return NULL; |
| 67646 | |
| 67647 | const void *x_key = ZIP_KEY_PTR(x); |
| 67648 | zip_elem **prev_edge = &head->root; |
| 67649 | enum ZIP_CMP cur_order = __ZIP_UNIQUE_CMP(cmp, p1: x_key, ZIP_KEY_PTR(cur)); |
| 67650 | while(cur_order != ZIP_CMP_EQ) { |
| 67651 | prev_edge = (cur_order == ZIP_CMP_LESS) ? |
| 67652 | &ZIP_ENTRY_PTR(cur)->left : &ZIP_ENTRY_PTR(cur)->right; |
| 67653 | cur = *prev_edge; |
| 67654 | if(!cur) |
| 67655 | return NULL; |
| 67656 | cur_order = __ZIP_UNIQUE_CMP(cmp, p1: x_key, ZIP_KEY_PTR(cur)); |
| 67657 | } |
| 67658 | *prev_edge = (zip_elem*)__ZIP_ZIP(fieldoffset, |
| 67659 | ZIP_ENTRY_PTR(cur)->left, |
| 67660 | ZIP_ENTRY_PTR(cur)->right); |
| 67661 | return cur; |
| 67662 | } |
| 67663 | |
| 67664 | void * |
| 67665 | __ZIP_ITER(unsigned short fieldoffset, zip_iter_cb cb, |
| 67666 | void *context, void *elm) { |
| 67667 | if(!elm) |
| 67668 | return NULL; |
| 67669 | zip_elem *left = ZIP_ENTRY_PTR(elm)->left; |
| 67670 | zip_elem *right = ZIP_ENTRY_PTR(elm)->right; |
| 67671 | void *res = __ZIP_ITER(fieldoffset, cb, context, elm: left); |
| 67672 | if(res) |
| 67673 | return res; |
| 67674 | res = cb(context, elm); |
| 67675 | if(res) |
| 67676 | return res; |
| 67677 | return __ZIP_ITER(fieldoffset, cb, context, elm: right); |
| 67678 | } |
| 67679 | |
| 67680 | void * |
| 67681 | __ZIP_ITER_KEY(zip_cmp_cb cmp, unsigned short fieldoffset, |
| 67682 | unsigned short keyoffset, const void *key, |
| 67683 | zip_iter_cb cb, void *context, void *elm) { |
| 67684 | if(!elm) |
| 67685 | return NULL; |
| 67686 | |
| 67687 | void *res; |
| 67688 | enum ZIP_CMP eq = cmp(key, ZIP_KEY_PTR(elm)); |
| 67689 | if(eq != ZIP_CMP_MORE) { |
| 67690 | res = __ZIP_ITER_KEY(cmp, fieldoffset, keyoffset, key, |
| 67691 | cb, context, ZIP_ENTRY_PTR(elm)->left); |
| 67692 | if(res) |
| 67693 | return res; |
| 67694 | } |
| 67695 | |
| 67696 | if(eq == ZIP_CMP_EQ) { |
| 67697 | res = cb(context, elm); |
| 67698 | if(res) |
| 67699 | return res; |
| 67700 | } |
| 67701 | |
| 67702 | if(eq != ZIP_CMP_LESS) { |
| 67703 | res = __ZIP_ITER_KEY(cmp, fieldoffset, keyoffset, key, |
| 67704 | cb, context, ZIP_ENTRY_PTR(elm)->right); |
| 67705 | if(res) |
| 67706 | return res; |
| 67707 | } |
| 67708 | |
| 67709 | return NULL; |
| 67710 | } |
| 67711 | |
| 67712 | void * |
| 67713 | __ZIP_ZIP(unsigned short fieldoffset, void *left, void *right) { |
| 67714 | if(!left) |
| 67715 | return right; |
| 67716 | if(!right) |
| 67717 | return left; |
| 67718 | zip_elem *l = (zip_elem*)left; |
| 67719 | zip_elem *r = (zip_elem*)right; |
| 67720 | zip_elem *root = NULL; |
| 67721 | zip_elem **prev_edge = &root; |
| 67722 | while(l && r) { |
| 67723 | if(__ZIP_RANK_CMP(p1: l, p2: r) == ZIP_CMP_LESS) { |
| 67724 | *prev_edge = r; |
| 67725 | prev_edge = &ZIP_ENTRY_PTR(r)->left; |
| 67726 | r = ZIP_ENTRY_PTR(r)->left; |
| 67727 | } else { |
| 67728 | *prev_edge = l; |
| 67729 | prev_edge = &ZIP_ENTRY_PTR(l)->right; |
| 67730 | l = ZIP_ENTRY_PTR(l)->right; |
| 67731 | } |
| 67732 | } |
| 67733 | *prev_edge = (l) ? l : r; |
| 67734 | return root; |
| 67735 | } |
| 67736 | |
| 67737 | /* Walk down from cur and move all elements <= split-key to the left side. All |
| 67738 | * elements that are moved over have to be below left_rightmost. Returns the |
| 67739 | * hierarchy of elements that remain on the right side. */ |
| 67740 | static void |
| 67741 | __ZIP_UNZIP_MOVE_LEFT(zip_cmp_cb cmp, unsigned short fieldoffset, |
| 67742 | unsigned short keyoffset, const void *key, |
| 67743 | zip_elem **fix_edge, zip_elem *cur) { |
| 67744 | while(ZIP_ENTRY_PTR(cur)->left) { |
| 67745 | zip_elem *next = ZIP_ENTRY_PTR(cur)->left; |
| 67746 | if(cmp(key, ZIP_KEY_PTR(next)) == ZIP_CMP_LESS) { |
| 67747 | cur = next; |
| 67748 | continue; |
| 67749 | } |
| 67750 | *fix_edge = next; |
| 67751 | ZIP_ENTRY_PTR(cur)->left = ZIP_ENTRY_PTR(next)->right; |
| 67752 | ZIP_ENTRY_PTR(next)->right = NULL; |
| 67753 | fix_edge = &ZIP_ENTRY_PTR(next)->right; |
| 67754 | } |
| 67755 | } |
| 67756 | |
| 67757 | static void |
| 67758 | __ZIP_UNZIP_MOVE_RIGHT(zip_cmp_cb cmp, unsigned short fieldoffset, |
| 67759 | unsigned short keyoffset, const void *key, |
| 67760 | zip_elem **fix_edge, zip_elem *cur) { |
| 67761 | while(ZIP_ENTRY_PTR(cur)->right) { |
| 67762 | zip_elem *next = ZIP_ENTRY_PTR(cur)->right; |
| 67763 | if(cmp(key, ZIP_KEY_PTR(next)) != ZIP_CMP_LESS) { |
| 67764 | cur = next; |
| 67765 | continue; |
| 67766 | } |
| 67767 | *fix_edge = next; |
| 67768 | ZIP_ENTRY_PTR(cur)->right = ZIP_ENTRY_PTR(next)->left; |
| 67769 | ZIP_ENTRY_PTR(next)->left = NULL; |
| 67770 | fix_edge = &ZIP_ENTRY_PTR(next)->left; |
| 67771 | } |
| 67772 | } |
| 67773 | |
| 67774 | /* Split the tree into a left side with keys <= split-key and a right side with |
| 67775 | * key > split-key. */ |
| 67776 | void |
| 67777 | __ZIP_UNZIP(zip_cmp_cb cmp, unsigned short fieldoffset, |
| 67778 | unsigned short keyoffset, const void *key, |
| 67779 | void *h, void *l, void *r) { |
| 67780 | zip_elem *prev; |
| 67781 | zip_head *head = (zip_head*)h; |
| 67782 | zip_head *left = (zip_head*)l; |
| 67783 | zip_head *right = (zip_head*)r; |
| 67784 | if(!head->root) { |
| 67785 | left->root = NULL; |
| 67786 | right->root = NULL; |
| 67787 | return; |
| 67788 | } |
| 67789 | zip_elem *cur = head->root; |
| 67790 | if(cmp(key, ZIP_KEY_PTR(cur)) != ZIP_CMP_LESS) { |
| 67791 | left->root = cur; |
| 67792 | do { |
| 67793 | prev = cur; |
| 67794 | cur = ZIP_ENTRY_PTR(cur)->right; |
| 67795 | if(!cur) { |
| 67796 | right->root = NULL; |
| 67797 | return; |
| 67798 | } |
| 67799 | } while(cmp(key, ZIP_KEY_PTR(cur)) != ZIP_CMP_LESS); |
| 67800 | ZIP_ENTRY_PTR(prev)->right = NULL; |
| 67801 | right->root = cur; |
| 67802 | __ZIP_UNZIP_MOVE_LEFT(cmp, fieldoffset, keyoffset, key, |
| 67803 | fix_edge: &ZIP_ENTRY_PTR(prev)->right, cur); |
| 67804 | } else { |
| 67805 | right->root = cur; |
| 67806 | do { |
| 67807 | prev = cur; |
| 67808 | cur = ZIP_ENTRY_PTR(cur)->left; |
| 67809 | if(!cur) { |
| 67810 | left->root = NULL; |
| 67811 | return; |
| 67812 | } |
| 67813 | } while(cmp(key, ZIP_KEY_PTR(cur)) == ZIP_CMP_LESS); |
| 67814 | ZIP_ENTRY_PTR(prev)->left = NULL; |
| 67815 | left->root = cur; |
| 67816 | __ZIP_UNZIP_MOVE_RIGHT(cmp, fieldoffset, keyoffset, key, |
| 67817 | fix_edge: &ZIP_ENTRY_PTR(prev)->left, cur); |
| 67818 | } |
| 67819 | } |
| 67820 | |
| 67821 | /**** amalgamated original file "/build/src_generated/open62541/namespace0_generated.c" ****/ |
| 67822 | |
| 67823 | /* WARNING: This is a generated file. |
| 67824 | * Any manual changes will be overwritten. */ |
| 67825 | |
| 67826 | |
| 67827 | |
| 67828 | /* HasDataSetReader - ns=0;i=15297 */ |
| 67829 | |
| 67830 | static UA_StatusCode function_namespace0_generated_0_begin(UA_Server *server, UA_UInt16* ns) { |
| 67831 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 67832 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 67833 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "IsReaderInGroup"); |
| 67834 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasDataSetReader"); |
| 67835 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 67836 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15297LU), |
| 67837 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 67838 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 67839 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasDataSetReader"), |
| 67840 | typeDefinition: UA_NODEID_NULL, |
| 67841 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 67842 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 67843 | return retVal; |
| 67844 | } |
| 67845 | |
| 67846 | static UA_StatusCode function_namespace0_generated_0_finish(UA_Server *server, UA_UInt16* ns) { |
| 67847 | return UA_Server_addNode_finish(server, |
| 67848 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15297LU) |
| 67849 | ); |
| 67850 | } |
| 67851 | |
| 67852 | /* HasDataSetWriter - ns=0;i=15296 */ |
| 67853 | |
| 67854 | static UA_StatusCode function_namespace0_generated_1_begin(UA_Server *server, UA_UInt16* ns) { |
| 67855 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 67856 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 67857 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "IsWriterInGroup"); |
| 67858 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasDataSetWriter"); |
| 67859 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 67860 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15296LU), |
| 67861 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 67862 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 67863 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasDataSetWriter"), |
| 67864 | typeDefinition: UA_NODEID_NULL, |
| 67865 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 67866 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 67867 | return retVal; |
| 67868 | } |
| 67869 | |
| 67870 | static UA_StatusCode function_namespace0_generated_1_finish(UA_Server *server, UA_UInt16* ns) { |
| 67871 | return UA_Server_addNode_finish(server, |
| 67872 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15296LU) |
| 67873 | ); |
| 67874 | } |
| 67875 | |
| 67876 | /* HasPubSubConnection - ns=0;i=14476 */ |
| 67877 | |
| 67878 | static UA_StatusCode function_namespace0_generated_2_begin(UA_Server *server, UA_UInt16* ns) { |
| 67879 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 67880 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 67881 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "PubSubConnectionOf"); |
| 67882 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasPubSubConnection"); |
| 67883 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 67884 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14476LU), |
| 67885 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 67886 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 67887 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasPubSubConnection"), |
| 67888 | typeDefinition: UA_NODEID_NULL, |
| 67889 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 67890 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 67891 | return retVal; |
| 67892 | } |
| 67893 | |
| 67894 | static UA_StatusCode function_namespace0_generated_2_finish(UA_Server *server, UA_UInt16* ns) { |
| 67895 | return UA_Server_addNode_finish(server, |
| 67896 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14476LU) |
| 67897 | ); |
| 67898 | } |
| 67899 | |
| 67900 | /* DataSetToWriter - ns=0;i=14936 */ |
| 67901 | |
| 67902 | static UA_StatusCode function_namespace0_generated_3_begin(UA_Server *server, UA_UInt16* ns) { |
| 67903 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 67904 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 67905 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "WriterToDataSet"); |
| 67906 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetToWriter"); |
| 67907 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 67908 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14936LU), |
| 67909 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 33LU), |
| 67910 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 67911 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetToWriter"), |
| 67912 | typeDefinition: UA_NODEID_NULL, |
| 67913 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 67914 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 67915 | return retVal; |
| 67916 | } |
| 67917 | |
| 67918 | static UA_StatusCode function_namespace0_generated_3_finish(UA_Server *server, UA_UInt16* ns) { |
| 67919 | return UA_Server_addNode_finish(server, |
| 67920 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14936LU) |
| 67921 | ); |
| 67922 | } |
| 67923 | |
| 67924 | /* AlwaysGeneratesEvent - ns=0;i=3065 */ |
| 67925 | |
| 67926 | static UA_StatusCode function_namespace0_generated_4_begin(UA_Server *server, UA_UInt16* ns) { |
| 67927 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 67928 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 67929 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "AlwaysGeneratedBy"); |
| 67930 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AlwaysGeneratesEvent"); |
| 67931 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 67932 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3065LU), |
| 67933 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 41LU), |
| 67934 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 67935 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AlwaysGeneratesEvent"), |
| 67936 | typeDefinition: UA_NODEID_NULL, |
| 67937 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 67938 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 67939 | return retVal; |
| 67940 | } |
| 67941 | |
| 67942 | static UA_StatusCode function_namespace0_generated_4_finish(UA_Server *server, UA_UInt16* ns) { |
| 67943 | return UA_Server_addNode_finish(server, |
| 67944 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3065LU) |
| 67945 | ); |
| 67946 | } |
| 67947 | |
| 67948 | /* HasAddIn - ns=0;i=17604 */ |
| 67949 | |
| 67950 | static UA_StatusCode function_namespace0_generated_5_begin(UA_Server *server, UA_UInt16* ns) { |
| 67951 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 67952 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 67953 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "AddInOf"); |
| 67954 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasAddIn"); |
| 67955 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 67956 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17604LU), |
| 67957 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU), |
| 67958 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 67959 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasAddIn"), |
| 67960 | typeDefinition: UA_NODEID_NULL, |
| 67961 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 67962 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 67963 | return retVal; |
| 67964 | } |
| 67965 | |
| 67966 | static UA_StatusCode function_namespace0_generated_5_finish(UA_Server *server, UA_UInt16* ns) { |
| 67967 | return UA_Server_addNode_finish(server, |
| 67968 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17604LU) |
| 67969 | ); |
| 67970 | } |
| 67971 | |
| 67972 | /* HasHistoricalConfiguration - ns=0;i=56 */ |
| 67973 | |
| 67974 | static UA_StatusCode function_namespace0_generated_6_begin(UA_Server *server, UA_UInt16* ns) { |
| 67975 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 67976 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 67977 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "HistoricalConfigurationOf"); |
| 67978 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasHistoricalConfiguration"); |
| 67979 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 67980 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 56LU), |
| 67981 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 44LU), |
| 67982 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 67983 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasHistoricalConfiguration"), |
| 67984 | typeDefinition: UA_NODEID_NULL, |
| 67985 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 67986 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 67987 | return retVal; |
| 67988 | } |
| 67989 | |
| 67990 | static UA_StatusCode function_namespace0_generated_6_finish(UA_Server *server, UA_UInt16* ns) { |
| 67991 | return UA_Server_addNode_finish(server, |
| 67992 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 56LU) |
| 67993 | ); |
| 67994 | } |
| 67995 | |
| 67996 | /* HasEffect - ns=0;i=54 */ |
| 67997 | |
| 67998 | static UA_StatusCode function_namespace0_generated_7_begin(UA_Server *server, UA_UInt16* ns) { |
| 67999 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68000 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 68001 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "MayBeEffectedBy"); |
| 68002 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasEffect"); |
| 68003 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 68004 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 54LU), |
| 68005 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU), |
| 68006 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68007 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasEffect"), |
| 68008 | typeDefinition: UA_NODEID_NULL, |
| 68009 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 68010 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68011 | return retVal; |
| 68012 | } |
| 68013 | |
| 68014 | static UA_StatusCode function_namespace0_generated_7_finish(UA_Server *server, UA_UInt16* ns) { |
| 68015 | return UA_Server_addNode_finish(server, |
| 68016 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 54LU) |
| 68017 | ); |
| 68018 | } |
| 68019 | |
| 68020 | /* HasCause - ns=0;i=53 */ |
| 68021 | |
| 68022 | static UA_StatusCode function_namespace0_generated_8_begin(UA_Server *server, UA_UInt16* ns) { |
| 68023 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68024 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 68025 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "MayBeCausedBy"); |
| 68026 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HasCause"); |
| 68027 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 68028 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 53LU), |
| 68029 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU), |
| 68030 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68031 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HasCause"), |
| 68032 | typeDefinition: UA_NODEID_NULL, |
| 68033 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 68034 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68035 | return retVal; |
| 68036 | } |
| 68037 | |
| 68038 | static UA_StatusCode function_namespace0_generated_8_finish(UA_Server *server, UA_UInt16* ns) { |
| 68039 | return UA_Server_addNode_finish(server, |
| 68040 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 53LU) |
| 68041 | ); |
| 68042 | } |
| 68043 | |
| 68044 | /* ToState - ns=0;i=52 */ |
| 68045 | |
| 68046 | static UA_StatusCode function_namespace0_generated_9_begin(UA_Server *server, UA_UInt16* ns) { |
| 68047 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68048 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 68049 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "FromTransition"); |
| 68050 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ToState"); |
| 68051 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 68052 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 52LU), |
| 68053 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU), |
| 68054 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68055 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ToState"), |
| 68056 | typeDefinition: UA_NODEID_NULL, |
| 68057 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 68058 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68059 | return retVal; |
| 68060 | } |
| 68061 | |
| 68062 | static UA_StatusCode function_namespace0_generated_9_finish(UA_Server *server, UA_UInt16* ns) { |
| 68063 | return UA_Server_addNode_finish(server, |
| 68064 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 52LU) |
| 68065 | ); |
| 68066 | } |
| 68067 | |
| 68068 | /* FromState - ns=0;i=51 */ |
| 68069 | |
| 68070 | static UA_StatusCode function_namespace0_generated_10_begin(UA_Server *server, UA_UInt16* ns) { |
| 68071 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68072 | UA_ReferenceTypeAttributes attr = UA_ReferenceTypeAttributes_default; |
| 68073 | attr.inverseName = UA_LOCALIZEDTEXT(locale: "", text: "ToTransition"); |
| 68074 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FromState"); |
| 68075 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_REFERENCETYPE, |
| 68076 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 51LU), |
| 68077 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32LU), |
| 68078 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68079 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "FromState"), |
| 68080 | typeDefinition: UA_NODEID_NULL, |
| 68081 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_REFERENCETYPEATTRIBUTES],NULL, NULL); |
| 68082 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68083 | return retVal; |
| 68084 | } |
| 68085 | |
| 68086 | static UA_StatusCode function_namespace0_generated_10_finish(UA_Server *server, UA_UInt16* ns) { |
| 68087 | return UA_Server_addNode_finish(server, |
| 68088 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 51LU) |
| 68089 | ); |
| 68090 | } |
| 68091 | |
| 68092 | /* DiagnosticInfo - ns=0;i=25 */ |
| 68093 | |
| 68094 | static UA_StatusCode function_namespace0_generated_11_begin(UA_Server *server, UA_UInt16* ns) { |
| 68095 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68096 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68097 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DiagnosticInfo"); |
| 68098 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68099 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25LU), |
| 68100 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 68101 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68102 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DiagnosticInfo"), |
| 68103 | typeDefinition: UA_NODEID_NULL, |
| 68104 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68105 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68106 | return retVal; |
| 68107 | } |
| 68108 | |
| 68109 | static UA_StatusCode function_namespace0_generated_11_finish(UA_Server *server, UA_UInt16* ns) { |
| 68110 | return UA_Server_addNode_finish(server, |
| 68111 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25LU) |
| 68112 | ); |
| 68113 | } |
| 68114 | |
| 68115 | /* DataValue - ns=0;i=23 */ |
| 68116 | |
| 68117 | static UA_StatusCode function_namespace0_generated_12_begin(UA_Server *server, UA_UInt16* ns) { |
| 68118 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68119 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68120 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataValue"); |
| 68121 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68122 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23LU), |
| 68123 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 68124 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68125 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataValue"), |
| 68126 | typeDefinition: UA_NODEID_NULL, |
| 68127 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68128 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68129 | return retVal; |
| 68130 | } |
| 68131 | |
| 68132 | static UA_StatusCode function_namespace0_generated_12_finish(UA_Server *server, UA_UInt16* ns) { |
| 68133 | return UA_Server_addNode_finish(server, |
| 68134 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23LU) |
| 68135 | ); |
| 68136 | } |
| 68137 | |
| 68138 | /* Structure - ns=0;i=22 */ |
| 68139 | |
| 68140 | static UA_StatusCode function_namespace0_generated_13_begin(UA_Server *server, UA_UInt16* ns) { |
| 68141 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68142 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68143 | attr.isAbstract = true; |
| 68144 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Structure"); |
| 68145 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68146 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68147 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 68148 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68149 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Structure"), |
| 68150 | typeDefinition: UA_NODEID_NULL, |
| 68151 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68152 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68153 | return retVal; |
| 68154 | } |
| 68155 | |
| 68156 | static UA_StatusCode function_namespace0_generated_13_finish(UA_Server *server, UA_UInt16* ns) { |
| 68157 | return UA_Server_addNode_finish(server, |
| 68158 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU) |
| 68159 | ); |
| 68160 | } |
| 68161 | |
| 68162 | /* TimeZoneDataType - ns=0;i=8912 */ |
| 68163 | |
| 68164 | static UA_StatusCode function_namespace0_generated_14_begin(UA_Server *server, UA_UInt16* ns) { |
| 68165 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68166 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68167 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TimeZoneDataType"); |
| 68168 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68169 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8912LU), |
| 68170 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68171 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68172 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TimeZoneDataType"), |
| 68173 | typeDefinition: UA_NODEID_NULL, |
| 68174 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68175 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68176 | return retVal; |
| 68177 | } |
| 68178 | |
| 68179 | static UA_StatusCode function_namespace0_generated_14_finish(UA_Server *server, UA_UInt16* ns) { |
| 68180 | return UA_Server_addNode_finish(server, |
| 68181 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8912LU) |
| 68182 | ); |
| 68183 | } |
| 68184 | |
| 68185 | /* EUInformation - ns=0;i=887 */ |
| 68186 | |
| 68187 | static UA_StatusCode function_namespace0_generated_15_begin(UA_Server *server, UA_UInt16* ns) { |
| 68188 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68189 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68190 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EUInformation"); |
| 68191 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68192 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 887LU), |
| 68193 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68194 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68195 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EUInformation"), |
| 68196 | typeDefinition: UA_NODEID_NULL, |
| 68197 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68198 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68199 | return retVal; |
| 68200 | } |
| 68201 | |
| 68202 | static UA_StatusCode function_namespace0_generated_15_finish(UA_Server *server, UA_UInt16* ns) { |
| 68203 | return UA_Server_addNode_finish(server, |
| 68204 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 887LU) |
| 68205 | ); |
| 68206 | } |
| 68207 | |
| 68208 | /* Range - ns=0;i=884 */ |
| 68209 | |
| 68210 | static UA_StatusCode function_namespace0_generated_16_begin(UA_Server *server, UA_UInt16* ns) { |
| 68211 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68212 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68213 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Range"); |
| 68214 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68215 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU), |
| 68216 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68217 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68218 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Range"), |
| 68219 | typeDefinition: UA_NODEID_NULL, |
| 68220 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68221 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68222 | return retVal; |
| 68223 | } |
| 68224 | |
| 68225 | static UA_StatusCode function_namespace0_generated_16_finish(UA_Server *server, UA_UInt16* ns) { |
| 68226 | return UA_Server_addNode_finish(server, |
| 68227 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU) |
| 68228 | ); |
| 68229 | } |
| 68230 | |
| 68231 | /* ModelChangeStructureDataType - ns=0;i=877 */ |
| 68232 | |
| 68233 | static UA_StatusCode function_namespace0_generated_17_begin(UA_Server *server, UA_UInt16* ns) { |
| 68234 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68235 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68236 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModelChangeStructureDataType"); |
| 68237 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68238 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 877LU), |
| 68239 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68240 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68241 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModelChangeStructureDataType"), |
| 68242 | typeDefinition: UA_NODEID_NULL, |
| 68243 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68244 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68245 | return retVal; |
| 68246 | } |
| 68247 | |
| 68248 | static UA_StatusCode function_namespace0_generated_17_finish(UA_Server *server, UA_UInt16* ns) { |
| 68249 | return UA_Server_addNode_finish(server, |
| 68250 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 877LU) |
| 68251 | ); |
| 68252 | } |
| 68253 | |
| 68254 | /* SubscriptionDiagnosticsDataType - ns=0;i=874 */ |
| 68255 | |
| 68256 | static UA_StatusCode function_namespace0_generated_18_begin(UA_Server *server, UA_UInt16* ns) { |
| 68257 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68258 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68259 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscriptionDiagnosticsDataType"); |
| 68260 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68261 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 874LU), |
| 68262 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68263 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68264 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscriptionDiagnosticsDataType"), |
| 68265 | typeDefinition: UA_NODEID_NULL, |
| 68266 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68267 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68268 | return retVal; |
| 68269 | } |
| 68270 | |
| 68271 | static UA_StatusCode function_namespace0_generated_18_finish(UA_Server *server, UA_UInt16* ns) { |
| 68272 | return UA_Server_addNode_finish(server, |
| 68273 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 874LU) |
| 68274 | ); |
| 68275 | } |
| 68276 | |
| 68277 | /* ServiceCounterDataType - ns=0;i=871 */ |
| 68278 | |
| 68279 | static UA_StatusCode function_namespace0_generated_19_begin(UA_Server *server, UA_UInt16* ns) { |
| 68280 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68281 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68282 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServiceCounterDataType"); |
| 68283 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68284 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU), |
| 68285 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68286 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68287 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServiceCounterDataType"), |
| 68288 | typeDefinition: UA_NODEID_NULL, |
| 68289 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68290 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68291 | return retVal; |
| 68292 | } |
| 68293 | |
| 68294 | static UA_StatusCode function_namespace0_generated_19_finish(UA_Server *server, UA_UInt16* ns) { |
| 68295 | return UA_Server_addNode_finish(server, |
| 68296 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU) |
| 68297 | ); |
| 68298 | } |
| 68299 | |
| 68300 | /* SessionSecurityDiagnosticsDataType - ns=0;i=868 */ |
| 68301 | |
| 68302 | static UA_StatusCode function_namespace0_generated_20_begin(UA_Server *server, UA_UInt16* ns) { |
| 68303 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68304 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68305 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionSecurityDiagnosticsDataType"); |
| 68306 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68307 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 868LU), |
| 68308 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68309 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68310 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionSecurityDiagnosticsDataType"), |
| 68311 | typeDefinition: UA_NODEID_NULL, |
| 68312 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68313 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68314 | return retVal; |
| 68315 | } |
| 68316 | |
| 68317 | static UA_StatusCode function_namespace0_generated_20_finish(UA_Server *server, UA_UInt16* ns) { |
| 68318 | return UA_Server_addNode_finish(server, |
| 68319 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 868LU) |
| 68320 | ); |
| 68321 | } |
| 68322 | |
| 68323 | /* SessionDiagnosticsDataType - ns=0;i=865 */ |
| 68324 | |
| 68325 | static UA_StatusCode function_namespace0_generated_21_begin(UA_Server *server, UA_UInt16* ns) { |
| 68326 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68327 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68328 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionDiagnosticsDataType"); |
| 68329 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68330 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 865LU), |
| 68331 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68332 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68333 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionDiagnosticsDataType"), |
| 68334 | typeDefinition: UA_NODEID_NULL, |
| 68335 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68336 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68337 | return retVal; |
| 68338 | } |
| 68339 | |
| 68340 | static UA_StatusCode function_namespace0_generated_21_finish(UA_Server *server, UA_UInt16* ns) { |
| 68341 | return UA_Server_addNode_finish(server, |
| 68342 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 865LU) |
| 68343 | ); |
| 68344 | } |
| 68345 | |
| 68346 | /* ServerStatusDataType - ns=0;i=862 */ |
| 68347 | |
| 68348 | static UA_StatusCode function_namespace0_generated_22_begin(UA_Server *server, UA_UInt16* ns) { |
| 68349 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68350 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68351 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerStatusDataType"); |
| 68352 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68353 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU), |
| 68354 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68355 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68356 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerStatusDataType"), |
| 68357 | typeDefinition: UA_NODEID_NULL, |
| 68358 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68359 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68360 | return retVal; |
| 68361 | } |
| 68362 | |
| 68363 | static UA_StatusCode function_namespace0_generated_22_finish(UA_Server *server, UA_UInt16* ns) { |
| 68364 | return UA_Server_addNode_finish(server, |
| 68365 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU) |
| 68366 | ); |
| 68367 | } |
| 68368 | |
| 68369 | /* ServerDiagnosticsSummaryDataType - ns=0;i=859 */ |
| 68370 | |
| 68371 | static UA_StatusCode function_namespace0_generated_23_begin(UA_Server *server, UA_UInt16* ns) { |
| 68372 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68373 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68374 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerDiagnosticsSummaryDataType"); |
| 68375 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68376 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 859LU), |
| 68377 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68378 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68379 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerDiagnosticsSummaryDataType"), |
| 68380 | typeDefinition: UA_NODEID_NULL, |
| 68381 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68382 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68383 | return retVal; |
| 68384 | } |
| 68385 | |
| 68386 | static UA_StatusCode function_namespace0_generated_23_finish(UA_Server *server, UA_UInt16* ns) { |
| 68387 | return UA_Server_addNode_finish(server, |
| 68388 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 859LU) |
| 68389 | ); |
| 68390 | } |
| 68391 | |
| 68392 | /* SamplingIntervalDiagnosticsDataType - ns=0;i=856 */ |
| 68393 | |
| 68394 | static UA_StatusCode function_namespace0_generated_24_begin(UA_Server *server, UA_UInt16* ns) { |
| 68395 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68396 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68397 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SamplingIntervalDiagnosticsDataType"); |
| 68398 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68399 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 856LU), |
| 68400 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68401 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68402 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SamplingIntervalDiagnosticsDataType"), |
| 68403 | typeDefinition: UA_NODEID_NULL, |
| 68404 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68405 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68406 | return retVal; |
| 68407 | } |
| 68408 | |
| 68409 | static UA_StatusCode function_namespace0_generated_24_finish(UA_Server *server, UA_UInt16* ns) { |
| 68410 | return UA_Server_addNode_finish(server, |
| 68411 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 856LU) |
| 68412 | ); |
| 68413 | } |
| 68414 | |
| 68415 | /* EnumValueType - ns=0;i=7594 */ |
| 68416 | |
| 68417 | static UA_StatusCode function_namespace0_generated_25_begin(UA_Server *server, UA_UInt16* ns) { |
| 68418 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68419 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68420 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValueType"); |
| 68421 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68422 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU), |
| 68423 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68424 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68425 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValueType"), |
| 68426 | typeDefinition: UA_NODEID_NULL, |
| 68427 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68428 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68429 | return retVal; |
| 68430 | } |
| 68431 | |
| 68432 | static UA_StatusCode function_namespace0_generated_25_finish(UA_Server *server, UA_UInt16* ns) { |
| 68433 | return UA_Server_addNode_finish(server, |
| 68434 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU) |
| 68435 | ); |
| 68436 | } |
| 68437 | |
| 68438 | /* SignedSoftwareCertificate - ns=0;i=344 */ |
| 68439 | |
| 68440 | static UA_StatusCode function_namespace0_generated_26_begin(UA_Server *server, UA_UInt16* ns) { |
| 68441 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68442 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68443 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SignedSoftwareCertificate"); |
| 68444 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68445 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 344LU), |
| 68446 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68447 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68448 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SignedSoftwareCertificate"), |
| 68449 | typeDefinition: UA_NODEID_NULL, |
| 68450 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68451 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68452 | return retVal; |
| 68453 | } |
| 68454 | |
| 68455 | static UA_StatusCode function_namespace0_generated_26_finish(UA_Server *server, UA_UInt16* ns) { |
| 68456 | return UA_Server_addNode_finish(server, |
| 68457 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 344LU) |
| 68458 | ); |
| 68459 | } |
| 68460 | |
| 68461 | /* BuildInfo - ns=0;i=338 */ |
| 68462 | |
| 68463 | static UA_StatusCode function_namespace0_generated_27_begin(UA_Server *server, UA_UInt16* ns) { |
| 68464 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68465 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68466 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildInfo"); |
| 68467 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68468 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU), |
| 68469 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68470 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68471 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildInfo"), |
| 68472 | typeDefinition: UA_NODEID_NULL, |
| 68473 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68474 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68475 | return retVal; |
| 68476 | } |
| 68477 | |
| 68478 | static UA_StatusCode function_namespace0_generated_27_finish(UA_Server *server, UA_UInt16* ns) { |
| 68479 | return UA_Server_addNode_finish(server, |
| 68480 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU) |
| 68481 | ); |
| 68482 | } |
| 68483 | |
| 68484 | /* ApplicationDescription - ns=0;i=308 */ |
| 68485 | |
| 68486 | static UA_StatusCode function_namespace0_generated_28_begin(UA_Server *server, UA_UInt16* ns) { |
| 68487 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68488 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68489 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ApplicationDescription"); |
| 68490 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68491 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 308LU), |
| 68492 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68493 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68494 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ApplicationDescription"), |
| 68495 | typeDefinition: UA_NODEID_NULL, |
| 68496 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68497 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68498 | return retVal; |
| 68499 | } |
| 68500 | |
| 68501 | static UA_StatusCode function_namespace0_generated_28_finish(UA_Server *server, UA_UInt16* ns) { |
| 68502 | return UA_Server_addNode_finish(server, |
| 68503 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 308LU) |
| 68504 | ); |
| 68505 | } |
| 68506 | |
| 68507 | /* Argument - ns=0;i=296 */ |
| 68508 | |
| 68509 | static UA_StatusCode function_namespace0_generated_29_begin(UA_Server *server, UA_UInt16* ns) { |
| 68510 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68511 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68512 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Argument"); |
| 68513 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68514 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU), |
| 68515 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68516 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68517 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Argument"), |
| 68518 | typeDefinition: UA_NODEID_NULL, |
| 68519 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68520 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68521 | return retVal; |
| 68522 | } |
| 68523 | |
| 68524 | static UA_StatusCode function_namespace0_generated_29_finish(UA_Server *server, UA_UInt16* ns) { |
| 68525 | return UA_Server_addNode_finish(server, |
| 68526 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU) |
| 68527 | ); |
| 68528 | } |
| 68529 | |
| 68530 | /* AdditionalParametersType - ns=0;i=16313 */ |
| 68531 | |
| 68532 | static UA_StatusCode function_namespace0_generated_30_begin(UA_Server *server, UA_UInt16* ns) { |
| 68533 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68534 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68535 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AdditionalParametersType"); |
| 68536 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68537 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16313LU), |
| 68538 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68539 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68540 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AdditionalParametersType"), |
| 68541 | typeDefinition: UA_NODEID_NULL, |
| 68542 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68543 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68544 | return retVal; |
| 68545 | } |
| 68546 | |
| 68547 | static UA_StatusCode function_namespace0_generated_30_finish(UA_Server *server, UA_UInt16* ns) { |
| 68548 | return UA_Server_addNode_finish(server, |
| 68549 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16313LU) |
| 68550 | ); |
| 68551 | } |
| 68552 | |
| 68553 | /* PubSubConnectionDataType - ns=0;i=15617 */ |
| 68554 | |
| 68555 | static UA_StatusCode function_namespace0_generated_31_begin(UA_Server *server, UA_UInt16* ns) { |
| 68556 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68557 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68558 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PubSubConnectionDataType"); |
| 68559 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68560 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15617LU), |
| 68561 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68562 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68563 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PubSubConnectionDataType"), |
| 68564 | typeDefinition: UA_NODEID_NULL, |
| 68565 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68566 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68567 | return retVal; |
| 68568 | } |
| 68569 | |
| 68570 | static UA_StatusCode function_namespace0_generated_31_finish(UA_Server *server, UA_UInt16* ns) { |
| 68571 | return UA_Server_addNode_finish(server, |
| 68572 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15617LU) |
| 68573 | ); |
| 68574 | } |
| 68575 | |
| 68576 | /* PublishedDataSetSourceDataType - ns=0;i=15580 */ |
| 68577 | |
| 68578 | static UA_StatusCode function_namespace0_generated_32_begin(UA_Server *server, UA_UInt16* ns) { |
| 68579 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68580 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68581 | attr.isAbstract = true; |
| 68582 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishedDataSetSourceDataType"); |
| 68583 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68584 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15580LU), |
| 68585 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68586 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68587 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishedDataSetSourceDataType"), |
| 68588 | typeDefinition: UA_NODEID_NULL, |
| 68589 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68590 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68591 | return retVal; |
| 68592 | } |
| 68593 | |
| 68594 | static UA_StatusCode function_namespace0_generated_32_finish(UA_Server *server, UA_UInt16* ns) { |
| 68595 | return UA_Server_addNode_finish(server, |
| 68596 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15580LU) |
| 68597 | ); |
| 68598 | } |
| 68599 | |
| 68600 | /* PublishedDataItemsDataType - ns=0;i=15581 */ |
| 68601 | |
| 68602 | static UA_StatusCode function_namespace0_generated_33_begin(UA_Server *server, UA_UInt16* ns) { |
| 68603 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68604 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68605 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishedDataItemsDataType"); |
| 68606 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68607 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15581LU), |
| 68608 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15580LU), |
| 68609 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68610 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishedDataItemsDataType"), |
| 68611 | typeDefinition: UA_NODEID_NULL, |
| 68612 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68613 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68614 | return retVal; |
| 68615 | } |
| 68616 | |
| 68617 | static UA_StatusCode function_namespace0_generated_33_finish(UA_Server *server, UA_UInt16* ns) { |
| 68618 | return UA_Server_addNode_finish(server, |
| 68619 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15581LU) |
| 68620 | ); |
| 68621 | } |
| 68622 | |
| 68623 | /* PublishedDataSetDataType - ns=0;i=15578 */ |
| 68624 | |
| 68625 | static UA_StatusCode function_namespace0_generated_34_begin(UA_Server *server, UA_UInt16* ns) { |
| 68626 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68627 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68628 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishedDataSetDataType"); |
| 68629 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68630 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15578LU), |
| 68631 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68632 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68633 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishedDataSetDataType"), |
| 68634 | typeDefinition: UA_NODEID_NULL, |
| 68635 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68636 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68637 | return retVal; |
| 68638 | } |
| 68639 | |
| 68640 | static UA_StatusCode function_namespace0_generated_34_finish(UA_Server *server, UA_UInt16* ns) { |
| 68641 | return UA_Server_addNode_finish(server, |
| 68642 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15578LU) |
| 68643 | ); |
| 68644 | } |
| 68645 | |
| 68646 | /* DataTypeSchemaHeader - ns=0;i=15534 */ |
| 68647 | |
| 68648 | static UA_StatusCode function_namespace0_generated_35_begin(UA_Server *server, UA_UInt16* ns) { |
| 68649 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68650 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68651 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeSchemaHeader"); |
| 68652 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68653 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15534LU), |
| 68654 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68655 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68656 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeSchemaHeader"), |
| 68657 | typeDefinition: UA_NODEID_NULL, |
| 68658 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68659 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68660 | return retVal; |
| 68661 | } |
| 68662 | |
| 68663 | static UA_StatusCode function_namespace0_generated_35_finish(UA_Server *server, UA_UInt16* ns) { |
| 68664 | return UA_Server_addNode_finish(server, |
| 68665 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15534LU) |
| 68666 | ); |
| 68667 | } |
| 68668 | |
| 68669 | /* DataSetMetaDataType - ns=0;i=14523 */ |
| 68670 | |
| 68671 | static UA_StatusCode function_namespace0_generated_36_begin(UA_Server *server, UA_UInt16* ns) { |
| 68672 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68673 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68674 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetMetaDataType"); |
| 68675 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68676 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14523LU), |
| 68677 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15534LU), |
| 68678 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68679 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetMetaDataType"), |
| 68680 | typeDefinition: UA_NODEID_NULL, |
| 68681 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68682 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68683 | return retVal; |
| 68684 | } |
| 68685 | |
| 68686 | static UA_StatusCode function_namespace0_generated_36_finish(UA_Server *server, UA_UInt16* ns) { |
| 68687 | return UA_Server_addNode_finish(server, |
| 68688 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14523LU) |
| 68689 | ); |
| 68690 | } |
| 68691 | |
| 68692 | /* ConfigurationVersionDataType - ns=0;i=14593 */ |
| 68693 | |
| 68694 | static UA_StatusCode function_namespace0_generated_37_begin(UA_Server *server, UA_UInt16* ns) { |
| 68695 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68696 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68697 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConfigurationVersionDataType"); |
| 68698 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68699 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14593LU), |
| 68700 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68701 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68702 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConfigurationVersionDataType"), |
| 68703 | typeDefinition: UA_NODEID_NULL, |
| 68704 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68705 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68706 | return retVal; |
| 68707 | } |
| 68708 | |
| 68709 | static UA_StatusCode function_namespace0_generated_37_finish(UA_Server *server, UA_UInt16* ns) { |
| 68710 | return UA_Server_addNode_finish(server, |
| 68711 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14593LU) |
| 68712 | ); |
| 68713 | } |
| 68714 | |
| 68715 | /* KeyValuePair - ns=0;i=14533 */ |
| 68716 | |
| 68717 | static UA_StatusCode function_namespace0_generated_38_begin(UA_Server *server, UA_UInt16* ns) { |
| 68718 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68719 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68720 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "KeyValuePair"); |
| 68721 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68722 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14533LU), |
| 68723 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68724 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68725 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "KeyValuePair"), |
| 68726 | typeDefinition: UA_NODEID_NULL, |
| 68727 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68728 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68729 | return retVal; |
| 68730 | } |
| 68731 | |
| 68732 | static UA_StatusCode function_namespace0_generated_38_finish(UA_Server *server, UA_UInt16* ns) { |
| 68733 | return UA_Server_addNode_finish(server, |
| 68734 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14533LU) |
| 68735 | ); |
| 68736 | } |
| 68737 | |
| 68738 | /* FieldMetaData - ns=0;i=14524 */ |
| 68739 | |
| 68740 | static UA_StatusCode function_namespace0_generated_39_begin(UA_Server *server, UA_UInt16* ns) { |
| 68741 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68742 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68743 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FieldMetaData"); |
| 68744 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68745 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14524LU), |
| 68746 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68747 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68748 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "FieldMetaData"), |
| 68749 | typeDefinition: UA_NODEID_NULL, |
| 68750 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68751 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68752 | return retVal; |
| 68753 | } |
| 68754 | |
| 68755 | static UA_StatusCode function_namespace0_generated_39_finish(UA_Server *server, UA_UInt16* ns) { |
| 68756 | return UA_Server_addNode_finish(server, |
| 68757 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14524LU) |
| 68758 | ); |
| 68759 | } |
| 68760 | |
| 68761 | /* PublishedVariableDataType - ns=0;i=14273 */ |
| 68762 | |
| 68763 | static UA_StatusCode function_namespace0_generated_40_begin(UA_Server *server, UA_UInt16* ns) { |
| 68764 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68765 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68766 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishedVariableDataType"); |
| 68767 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68768 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14273LU), |
| 68769 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68770 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68771 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishedVariableDataType"), |
| 68772 | typeDefinition: UA_NODEID_NULL, |
| 68773 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68774 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68775 | return retVal; |
| 68776 | } |
| 68777 | |
| 68778 | static UA_StatusCode function_namespace0_generated_40_finish(UA_Server *server, UA_UInt16* ns) { |
| 68779 | return UA_Server_addNode_finish(server, |
| 68780 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14273LU) |
| 68781 | ); |
| 68782 | } |
| 68783 | |
| 68784 | /* Union - ns=0;i=12756 */ |
| 68785 | |
| 68786 | static UA_StatusCode function_namespace0_generated_41_begin(UA_Server *server, UA_UInt16* ns) { |
| 68787 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68788 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68789 | attr.isAbstract = true; |
| 68790 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Union"); |
| 68791 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68792 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12756LU), |
| 68793 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 22LU), |
| 68794 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68795 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Union"), |
| 68796 | typeDefinition: UA_NODEID_NULL, |
| 68797 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68798 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68799 | return retVal; |
| 68800 | } |
| 68801 | |
| 68802 | static UA_StatusCode function_namespace0_generated_41_finish(UA_Server *server, UA_UInt16* ns) { |
| 68803 | return UA_Server_addNode_finish(server, |
| 68804 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12756LU) |
| 68805 | ); |
| 68806 | } |
| 68807 | |
| 68808 | /* LocalizedText - ns=0;i=21 */ |
| 68809 | |
| 68810 | static UA_StatusCode function_namespace0_generated_42_begin(UA_Server *server, UA_UInt16* ns) { |
| 68811 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68812 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68813 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocalizedText"); |
| 68814 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68815 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU), |
| 68816 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 68817 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68818 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocalizedText"), |
| 68819 | typeDefinition: UA_NODEID_NULL, |
| 68820 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68821 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68822 | return retVal; |
| 68823 | } |
| 68824 | |
| 68825 | static UA_StatusCode function_namespace0_generated_42_finish(UA_Server *server, UA_UInt16* ns) { |
| 68826 | return UA_Server_addNode_finish(server, |
| 68827 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU) |
| 68828 | ); |
| 68829 | } |
| 68830 | |
| 68831 | /* QualifiedName - ns=0;i=20 */ |
| 68832 | |
| 68833 | static UA_StatusCode function_namespace0_generated_43_begin(UA_Server *server, UA_UInt16* ns) { |
| 68834 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68835 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68836 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QualifiedName"); |
| 68837 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68838 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 20LU), |
| 68839 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 68840 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68841 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QualifiedName"), |
| 68842 | typeDefinition: UA_NODEID_NULL, |
| 68843 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68844 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68845 | return retVal; |
| 68846 | } |
| 68847 | |
| 68848 | static UA_StatusCode function_namespace0_generated_43_finish(UA_Server *server, UA_UInt16* ns) { |
| 68849 | return UA_Server_addNode_finish(server, |
| 68850 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 20LU) |
| 68851 | ); |
| 68852 | } |
| 68853 | |
| 68854 | /* StatusCode - ns=0;i=19 */ |
| 68855 | |
| 68856 | static UA_StatusCode function_namespace0_generated_44_begin(UA_Server *server, UA_UInt16* ns) { |
| 68857 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68858 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68859 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "StatusCode"); |
| 68860 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68861 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU), |
| 68862 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 68863 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68864 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "StatusCode"), |
| 68865 | typeDefinition: UA_NODEID_NULL, |
| 68866 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68867 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68868 | return retVal; |
| 68869 | } |
| 68870 | |
| 68871 | static UA_StatusCode function_namespace0_generated_44_finish(UA_Server *server, UA_UInt16* ns) { |
| 68872 | return UA_Server_addNode_finish(server, |
| 68873 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU) |
| 68874 | ); |
| 68875 | } |
| 68876 | |
| 68877 | /* ExpandedNodeId - ns=0;i=18 */ |
| 68878 | |
| 68879 | static UA_StatusCode function_namespace0_generated_45_begin(UA_Server *server, UA_UInt16* ns) { |
| 68880 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68881 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68882 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ExpandedNodeId"); |
| 68883 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68884 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 18LU), |
| 68885 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 68886 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68887 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ExpandedNodeId"), |
| 68888 | typeDefinition: UA_NODEID_NULL, |
| 68889 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68890 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68891 | return retVal; |
| 68892 | } |
| 68893 | |
| 68894 | static UA_StatusCode function_namespace0_generated_45_finish(UA_Server *server, UA_UInt16* ns) { |
| 68895 | return UA_Server_addNode_finish(server, |
| 68896 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 18LU) |
| 68897 | ); |
| 68898 | } |
| 68899 | |
| 68900 | /* NodeId - ns=0;i=17 */ |
| 68901 | |
| 68902 | static UA_StatusCode function_namespace0_generated_46_begin(UA_Server *server, UA_UInt16* ns) { |
| 68903 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68904 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68905 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NodeId"); |
| 68906 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68907 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU), |
| 68908 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 68909 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68910 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NodeId"), |
| 68911 | typeDefinition: UA_NODEID_NULL, |
| 68912 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68913 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68914 | return retVal; |
| 68915 | } |
| 68916 | |
| 68917 | static UA_StatusCode function_namespace0_generated_46_finish(UA_Server *server, UA_UInt16* ns) { |
| 68918 | return UA_Server_addNode_finish(server, |
| 68919 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU) |
| 68920 | ); |
| 68921 | } |
| 68922 | |
| 68923 | /* XmlElement - ns=0;i=16 */ |
| 68924 | |
| 68925 | static UA_StatusCode function_namespace0_generated_47_begin(UA_Server *server, UA_UInt16* ns) { |
| 68926 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68927 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68928 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "XmlElement"); |
| 68929 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68930 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16LU), |
| 68931 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 68932 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68933 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "XmlElement"), |
| 68934 | typeDefinition: UA_NODEID_NULL, |
| 68935 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68936 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68937 | return retVal; |
| 68938 | } |
| 68939 | |
| 68940 | static UA_StatusCode function_namespace0_generated_47_finish(UA_Server *server, UA_UInt16* ns) { |
| 68941 | return UA_Server_addNode_finish(server, |
| 68942 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16LU) |
| 68943 | ); |
| 68944 | } |
| 68945 | |
| 68946 | /* ByteString - ns=0;i=15 */ |
| 68947 | |
| 68948 | static UA_StatusCode function_namespace0_generated_48_begin(UA_Server *server, UA_UInt16* ns) { |
| 68949 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68950 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68951 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ByteString"); |
| 68952 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68953 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU), |
| 68954 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 68955 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68956 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ByteString"), |
| 68957 | typeDefinition: UA_NODEID_NULL, |
| 68958 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68959 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68960 | return retVal; |
| 68961 | } |
| 68962 | |
| 68963 | static UA_StatusCode function_namespace0_generated_48_finish(UA_Server *server, UA_UInt16* ns) { |
| 68964 | return UA_Server_addNode_finish(server, |
| 68965 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU) |
| 68966 | ); |
| 68967 | } |
| 68968 | |
| 68969 | /* Image - ns=0;i=30 */ |
| 68970 | |
| 68971 | static UA_StatusCode function_namespace0_generated_49_begin(UA_Server *server, UA_UInt16* ns) { |
| 68972 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68973 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68974 | attr.isAbstract = true; |
| 68975 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Image"); |
| 68976 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 68977 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 30LU), |
| 68978 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU), |
| 68979 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 68980 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Image"), |
| 68981 | typeDefinition: UA_NODEID_NULL, |
| 68982 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 68983 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 68984 | return retVal; |
| 68985 | } |
| 68986 | |
| 68987 | static UA_StatusCode function_namespace0_generated_49_finish(UA_Server *server, UA_UInt16* ns) { |
| 68988 | return UA_Server_addNode_finish(server, |
| 68989 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 30LU) |
| 68990 | ); |
| 68991 | } |
| 68992 | |
| 68993 | /* Guid - ns=0;i=14 */ |
| 68994 | |
| 68995 | static UA_StatusCode function_namespace0_generated_50_begin(UA_Server *server, UA_UInt16* ns) { |
| 68996 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 68997 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 68998 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Guid"); |
| 68999 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69000 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14LU), |
| 69001 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 69002 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69003 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Guid"), |
| 69004 | typeDefinition: UA_NODEID_NULL, |
| 69005 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69006 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69007 | return retVal; |
| 69008 | } |
| 69009 | |
| 69010 | static UA_StatusCode function_namespace0_generated_50_finish(UA_Server *server, UA_UInt16* ns) { |
| 69011 | return UA_Server_addNode_finish(server, |
| 69012 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14LU) |
| 69013 | ); |
| 69014 | } |
| 69015 | |
| 69016 | /* DateTime - ns=0;i=13 */ |
| 69017 | |
| 69018 | static UA_StatusCode function_namespace0_generated_51_begin(UA_Server *server, UA_UInt16* ns) { |
| 69019 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69020 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69021 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DateTime"); |
| 69022 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69023 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 13LU), |
| 69024 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 69025 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69026 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DateTime"), |
| 69027 | typeDefinition: UA_NODEID_NULL, |
| 69028 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69029 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69030 | return retVal; |
| 69031 | } |
| 69032 | |
| 69033 | static UA_StatusCode function_namespace0_generated_51_finish(UA_Server *server, UA_UInt16* ns) { |
| 69034 | return UA_Server_addNode_finish(server, |
| 69035 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 13LU) |
| 69036 | ); |
| 69037 | } |
| 69038 | |
| 69039 | /* UtcTime - ns=0;i=294 */ |
| 69040 | |
| 69041 | static UA_StatusCode function_namespace0_generated_52_begin(UA_Server *server, UA_UInt16* ns) { |
| 69042 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69043 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69044 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UtcTime"); |
| 69045 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69046 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU), |
| 69047 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 13LU), |
| 69048 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69049 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UtcTime"), |
| 69050 | typeDefinition: UA_NODEID_NULL, |
| 69051 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69052 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69053 | return retVal; |
| 69054 | } |
| 69055 | |
| 69056 | static UA_StatusCode function_namespace0_generated_52_finish(UA_Server *server, UA_UInt16* ns) { |
| 69057 | return UA_Server_addNode_finish(server, |
| 69058 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU) |
| 69059 | ); |
| 69060 | } |
| 69061 | |
| 69062 | /* String - ns=0;i=12 */ |
| 69063 | |
| 69064 | static UA_StatusCode function_namespace0_generated_53_begin(UA_Server *server, UA_UInt16* ns) { |
| 69065 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69066 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69067 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "String"); |
| 69068 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69069 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU), |
| 69070 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 69071 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69072 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "String"), |
| 69073 | typeDefinition: UA_NODEID_NULL, |
| 69074 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69075 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69076 | return retVal; |
| 69077 | } |
| 69078 | |
| 69079 | static UA_StatusCode function_namespace0_generated_53_finish(UA_Server *server, UA_UInt16* ns) { |
| 69080 | return UA_Server_addNode_finish(server, |
| 69081 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU) |
| 69082 | ); |
| 69083 | } |
| 69084 | |
| 69085 | /* LocaleId - ns=0;i=295 */ |
| 69086 | |
| 69087 | static UA_StatusCode function_namespace0_generated_54_begin(UA_Server *server, UA_UInt16* ns) { |
| 69088 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69089 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69090 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleId"); |
| 69091 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69092 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU), |
| 69093 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU), |
| 69094 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69095 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleId"), |
| 69096 | typeDefinition: UA_NODEID_NULL, |
| 69097 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69098 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69099 | return retVal; |
| 69100 | } |
| 69101 | |
| 69102 | static UA_StatusCode function_namespace0_generated_54_finish(UA_Server *server, UA_UInt16* ns) { |
| 69103 | return UA_Server_addNode_finish(server, |
| 69104 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU) |
| 69105 | ); |
| 69106 | } |
| 69107 | |
| 69108 | /* Boolean - ns=0;i=1 */ |
| 69109 | |
| 69110 | static UA_StatusCode function_namespace0_generated_55_begin(UA_Server *server, UA_UInt16* ns) { |
| 69111 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69112 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69113 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Boolean"); |
| 69114 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69115 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU), |
| 69116 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 69117 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69118 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Boolean"), |
| 69119 | typeDefinition: UA_NODEID_NULL, |
| 69120 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69121 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69122 | return retVal; |
| 69123 | } |
| 69124 | |
| 69125 | static UA_StatusCode function_namespace0_generated_55_finish(UA_Server *server, UA_UInt16* ns) { |
| 69126 | return UA_Server_addNode_finish(server, |
| 69127 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU) |
| 69128 | ); |
| 69129 | } |
| 69130 | |
| 69131 | /* Enumeration - ns=0;i=29 */ |
| 69132 | |
| 69133 | static UA_StatusCode function_namespace0_generated_56_begin(UA_Server *server, UA_UInt16* ns) { |
| 69134 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69135 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69136 | attr.isAbstract = true; |
| 69137 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Enumeration"); |
| 69138 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69139 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU), |
| 69140 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 69141 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69142 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Enumeration"), |
| 69143 | typeDefinition: UA_NODEID_NULL, |
| 69144 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69145 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69146 | return retVal; |
| 69147 | } |
| 69148 | |
| 69149 | static UA_StatusCode function_namespace0_generated_56_finish(UA_Server *server, UA_UInt16* ns) { |
| 69150 | return UA_Server_addNode_finish(server, |
| 69151 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU) |
| 69152 | ); |
| 69153 | } |
| 69154 | |
| 69155 | /* ServerState - ns=0;i=852 */ |
| 69156 | |
| 69157 | static UA_StatusCode function_namespace0_generated_57_begin(UA_Server *server, UA_UInt16* ns) { |
| 69158 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69159 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69160 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerState"); |
| 69161 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69162 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 852LU), |
| 69163 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU), |
| 69164 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69165 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerState"), |
| 69166 | typeDefinition: UA_NODEID_NULL, |
| 69167 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69168 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69169 | return retVal; |
| 69170 | } |
| 69171 | |
| 69172 | static UA_StatusCode function_namespace0_generated_57_finish(UA_Server *server, UA_UInt16* ns) { |
| 69173 | return UA_Server_addNode_finish(server, |
| 69174 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 852LU) |
| 69175 | ); |
| 69176 | } |
| 69177 | |
| 69178 | /* RedundancySupport - ns=0;i=851 */ |
| 69179 | |
| 69180 | static UA_StatusCode function_namespace0_generated_58_begin(UA_Server *server, UA_UInt16* ns) { |
| 69181 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69182 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69183 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RedundancySupport"); |
| 69184 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69185 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU), |
| 69186 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU), |
| 69187 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69188 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RedundancySupport"), |
| 69189 | typeDefinition: UA_NODEID_NULL, |
| 69190 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69191 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69192 | return retVal; |
| 69193 | } |
| 69194 | |
| 69195 | static UA_StatusCode function_namespace0_generated_58_finish(UA_Server *server, UA_UInt16* ns) { |
| 69196 | return UA_Server_addNode_finish(server, |
| 69197 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU) |
| 69198 | ); |
| 69199 | } |
| 69200 | |
| 69201 | /* EnumStrings - ns=0;i=7611 */ |
| 69202 | |
| 69203 | static UA_StatusCode function_namespace0_generated_59_begin(UA_Server *server, UA_UInt16* ns) { |
| 69204 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69205 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 69206 | attr.minimumSamplingInterval = 0.000000; |
| 69207 | attr.userAccessLevel = 1; |
| 69208 | attr.accessLevel = 1; |
| 69209 | attr.valueRank = 1; |
| 69210 | attr.arrayDimensionsSize = 1; |
| 69211 | UA_UInt32 arrayDimensions[1]; |
| 69212 | arrayDimensions[0] = 0; |
| 69213 | attr.arrayDimensions = &arrayDimensions[0]; |
| 69214 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 69215 | UA_LocalizedText variablenode_ns_0_i_7611_variant_DataContents[6]; |
| 69216 | variablenode_ns_0_i_7611_variant_DataContents[0] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69217 | variablenode_ns_0_i_7611_variant_DataContents[1] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69218 | variablenode_ns_0_i_7611_variant_DataContents[2] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69219 | variablenode_ns_0_i_7611_variant_DataContents[3] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69220 | variablenode_ns_0_i_7611_variant_DataContents[4] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69221 | variablenode_ns_0_i_7611_variant_DataContents[5] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69222 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_7611_variant_DataContents, arraySize: (UA_Int32) 6, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 69223 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings"); |
| 69224 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 69225 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7611LU), |
| 69226 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU), |
| 69227 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 69228 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"), |
| 69229 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 69230 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 69231 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69232 | return retVal; |
| 69233 | } |
| 69234 | |
| 69235 | static UA_StatusCode function_namespace0_generated_59_finish(UA_Server *server, UA_UInt16* ns) { |
| 69236 | return UA_Server_addNode_finish(server, |
| 69237 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7611LU) |
| 69238 | ); |
| 69239 | } |
| 69240 | |
| 69241 | /* ApplicationType - ns=0;i=307 */ |
| 69242 | |
| 69243 | static UA_StatusCode function_namespace0_generated_60_begin(UA_Server *server, UA_UInt16* ns) { |
| 69244 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69245 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69246 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ApplicationType"); |
| 69247 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69248 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 307LU), |
| 69249 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU), |
| 69250 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69251 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ApplicationType"), |
| 69252 | typeDefinition: UA_NODEID_NULL, |
| 69253 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69254 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69255 | return retVal; |
| 69256 | } |
| 69257 | |
| 69258 | static UA_StatusCode function_namespace0_generated_60_finish(UA_Server *server, UA_UInt16* ns) { |
| 69259 | return UA_Server_addNode_finish(server, |
| 69260 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 307LU) |
| 69261 | ); |
| 69262 | } |
| 69263 | |
| 69264 | /* EnumStrings - ns=0;i=7597 */ |
| 69265 | |
| 69266 | static UA_StatusCode function_namespace0_generated_61_begin(UA_Server *server, UA_UInt16* ns) { |
| 69267 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69268 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 69269 | attr.minimumSamplingInterval = 0.000000; |
| 69270 | attr.userAccessLevel = 1; |
| 69271 | attr.accessLevel = 1; |
| 69272 | attr.valueRank = 1; |
| 69273 | attr.arrayDimensionsSize = 1; |
| 69274 | UA_UInt32 arrayDimensions[1]; |
| 69275 | arrayDimensions[0] = 0; |
| 69276 | attr.arrayDimensions = &arrayDimensions[0]; |
| 69277 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 69278 | UA_LocalizedText variablenode_ns_0_i_7597_variant_DataContents[4]; |
| 69279 | variablenode_ns_0_i_7597_variant_DataContents[0] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69280 | variablenode_ns_0_i_7597_variant_DataContents[1] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69281 | variablenode_ns_0_i_7597_variant_DataContents[2] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69282 | variablenode_ns_0_i_7597_variant_DataContents[3] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69283 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_7597_variant_DataContents, arraySize: (UA_Int32) 4, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 69284 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings"); |
| 69285 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 69286 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7597LU), |
| 69287 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 307LU), |
| 69288 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 69289 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"), |
| 69290 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 69291 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 69292 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69293 | return retVal; |
| 69294 | } |
| 69295 | |
| 69296 | static UA_StatusCode function_namespace0_generated_61_finish(UA_Server *server, UA_UInt16* ns) { |
| 69297 | return UA_Server_addNode_finish(server, |
| 69298 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7597LU) |
| 69299 | ); |
| 69300 | } |
| 69301 | |
| 69302 | /* MessageSecurityMode - ns=0;i=302 */ |
| 69303 | |
| 69304 | static UA_StatusCode function_namespace0_generated_62_begin(UA_Server *server, UA_UInt16* ns) { |
| 69305 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69306 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69307 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MessageSecurityMode"); |
| 69308 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69309 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 302LU), |
| 69310 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU), |
| 69311 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69312 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MessageSecurityMode"), |
| 69313 | typeDefinition: UA_NODEID_NULL, |
| 69314 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69315 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69316 | return retVal; |
| 69317 | } |
| 69318 | |
| 69319 | static UA_StatusCode function_namespace0_generated_62_finish(UA_Server *server, UA_UInt16* ns) { |
| 69320 | return UA_Server_addNode_finish(server, |
| 69321 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 302LU) |
| 69322 | ); |
| 69323 | } |
| 69324 | |
| 69325 | /* EnumStrings - ns=0;i=7595 */ |
| 69326 | |
| 69327 | static UA_StatusCode function_namespace0_generated_63_begin(UA_Server *server, UA_UInt16* ns) { |
| 69328 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69329 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 69330 | attr.minimumSamplingInterval = 0.000000; |
| 69331 | attr.userAccessLevel = 1; |
| 69332 | attr.accessLevel = 1; |
| 69333 | attr.valueRank = 1; |
| 69334 | attr.arrayDimensionsSize = 1; |
| 69335 | UA_UInt32 arrayDimensions[1]; |
| 69336 | arrayDimensions[0] = 0; |
| 69337 | attr.arrayDimensions = &arrayDimensions[0]; |
| 69338 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 69339 | UA_LocalizedText variablenode_ns_0_i_7595_variant_DataContents[4]; |
| 69340 | variablenode_ns_0_i_7595_variant_DataContents[0] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69341 | variablenode_ns_0_i_7595_variant_DataContents[1] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69342 | variablenode_ns_0_i_7595_variant_DataContents[2] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69343 | variablenode_ns_0_i_7595_variant_DataContents[3] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69344 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_7595_variant_DataContents, arraySize: (UA_Int32) 4, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 69345 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings"); |
| 69346 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 69347 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7595LU), |
| 69348 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 302LU), |
| 69349 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 69350 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"), |
| 69351 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 69352 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 69353 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69354 | return retVal; |
| 69355 | } |
| 69356 | |
| 69357 | static UA_StatusCode function_namespace0_generated_63_finish(UA_Server *server, UA_UInt16* ns) { |
| 69358 | return UA_Server_addNode_finish(server, |
| 69359 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7595LU) |
| 69360 | ); |
| 69361 | } |
| 69362 | |
| 69363 | /* PubSubState - ns=0;i=14647 */ |
| 69364 | |
| 69365 | static UA_StatusCode function_namespace0_generated_64_begin(UA_Server *server, UA_UInt16* ns) { |
| 69366 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69367 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69368 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PubSubState"); |
| 69369 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69370 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14647LU), |
| 69371 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU), |
| 69372 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69373 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PubSubState"), |
| 69374 | typeDefinition: UA_NODEID_NULL, |
| 69375 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69376 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69377 | return retVal; |
| 69378 | } |
| 69379 | |
| 69380 | static UA_StatusCode function_namespace0_generated_64_finish(UA_Server *server, UA_UInt16* ns) { |
| 69381 | return UA_Server_addNode_finish(server, |
| 69382 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14647LU) |
| 69383 | ); |
| 69384 | } |
| 69385 | |
| 69386 | /* EnumStrings - ns=0;i=14648 */ |
| 69387 | |
| 69388 | static UA_StatusCode function_namespace0_generated_65_begin(UA_Server *server, UA_UInt16* ns) { |
| 69389 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69390 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 69391 | attr.minimumSamplingInterval = 0.000000; |
| 69392 | attr.userAccessLevel = 1; |
| 69393 | attr.accessLevel = 1; |
| 69394 | attr.valueRank = 1; |
| 69395 | attr.arrayDimensionsSize = 1; |
| 69396 | UA_UInt32 arrayDimensions[1]; |
| 69397 | arrayDimensions[0] = 0; |
| 69398 | attr.arrayDimensions = &arrayDimensions[0]; |
| 69399 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 69400 | UA_LocalizedText variablenode_ns_0_i_14648_variant_DataContents[4]; |
| 69401 | variablenode_ns_0_i_14648_variant_DataContents[0] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69402 | variablenode_ns_0_i_14648_variant_DataContents[1] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69403 | variablenode_ns_0_i_14648_variant_DataContents[2] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69404 | variablenode_ns_0_i_14648_variant_DataContents[3] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69405 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_14648_variant_DataContents, arraySize: (UA_Int32) 4, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 69406 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings"); |
| 69407 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 69408 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14648LU), |
| 69409 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14647LU), |
| 69410 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 69411 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"), |
| 69412 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 69413 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 69414 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69415 | return retVal; |
| 69416 | } |
| 69417 | |
| 69418 | static UA_StatusCode function_namespace0_generated_65_finish(UA_Server *server, UA_UInt16* ns) { |
| 69419 | return UA_Server_addNode_finish(server, |
| 69420 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14648LU) |
| 69421 | ); |
| 69422 | } |
| 69423 | |
| 69424 | /* AxisScaleEnumeration - ns=0;i=12077 */ |
| 69425 | |
| 69426 | static UA_StatusCode function_namespace0_generated_66_begin(UA_Server *server, UA_UInt16* ns) { |
| 69427 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69428 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69429 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AxisScaleEnumeration"); |
| 69430 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69431 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12077LU), |
| 69432 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU), |
| 69433 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69434 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AxisScaleEnumeration"), |
| 69435 | typeDefinition: UA_NODEID_NULL, |
| 69436 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69437 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69438 | return retVal; |
| 69439 | } |
| 69440 | |
| 69441 | static UA_StatusCode function_namespace0_generated_66_finish(UA_Server *server, UA_UInt16* ns) { |
| 69442 | return UA_Server_addNode_finish(server, |
| 69443 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12077LU) |
| 69444 | ); |
| 69445 | } |
| 69446 | |
| 69447 | /* EnumStrings - ns=0;i=12078 */ |
| 69448 | |
| 69449 | static UA_StatusCode function_namespace0_generated_67_begin(UA_Server *server, UA_UInt16* ns) { |
| 69450 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69451 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 69452 | attr.minimumSamplingInterval = 0.000000; |
| 69453 | attr.userAccessLevel = 1; |
| 69454 | attr.accessLevel = 1; |
| 69455 | attr.valueRank = 1; |
| 69456 | attr.arrayDimensionsSize = 1; |
| 69457 | UA_UInt32 arrayDimensions[1]; |
| 69458 | arrayDimensions[0] = 0; |
| 69459 | attr.arrayDimensions = &arrayDimensions[0]; |
| 69460 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 69461 | UA_LocalizedText variablenode_ns_0_i_12078_variant_DataContents[3]; |
| 69462 | variablenode_ns_0_i_12078_variant_DataContents[0] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69463 | variablenode_ns_0_i_12078_variant_DataContents[1] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69464 | variablenode_ns_0_i_12078_variant_DataContents[2] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69465 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_12078_variant_DataContents, arraySize: (UA_Int32) 3, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 69466 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings"); |
| 69467 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 69468 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12078LU), |
| 69469 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12077LU), |
| 69470 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 69471 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"), |
| 69472 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 69473 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 69474 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69475 | return retVal; |
| 69476 | } |
| 69477 | |
| 69478 | static UA_StatusCode function_namespace0_generated_67_finish(UA_Server *server, UA_UInt16* ns) { |
| 69479 | return UA_Server_addNode_finish(server, |
| 69480 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12078LU) |
| 69481 | ); |
| 69482 | } |
| 69483 | |
| 69484 | /* NamingRuleType - ns=0;i=120 */ |
| 69485 | |
| 69486 | static UA_StatusCode function_namespace0_generated_68_begin(UA_Server *server, UA_UInt16* ns) { |
| 69487 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69488 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69489 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRuleType"); |
| 69490 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69491 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU), |
| 69492 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 29LU), |
| 69493 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69494 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRuleType"), |
| 69495 | typeDefinition: UA_NODEID_NULL, |
| 69496 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69497 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69498 | return retVal; |
| 69499 | } |
| 69500 | |
| 69501 | static UA_StatusCode function_namespace0_generated_68_finish(UA_Server *server, UA_UInt16* ns) { |
| 69502 | return UA_Server_addNode_finish(server, |
| 69503 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU) |
| 69504 | ); |
| 69505 | } |
| 69506 | |
| 69507 | /* EnumValues - ns=0;i=12169 */ |
| 69508 | |
| 69509 | static UA_StatusCode function_namespace0_generated_69_begin(UA_Server *server, UA_UInt16* ns) { |
| 69510 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69511 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 69512 | attr.minimumSamplingInterval = 0.000000; |
| 69513 | attr.userAccessLevel = 1; |
| 69514 | attr.accessLevel = 1; |
| 69515 | attr.valueRank = 1; |
| 69516 | attr.arrayDimensionsSize = 1; |
| 69517 | UA_UInt32 arrayDimensions[1]; |
| 69518 | arrayDimensions[0] = 0; |
| 69519 | attr.arrayDimensions = &arrayDimensions[0]; |
| 69520 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU); |
| 69521 | UA_EnumValueType variablenode_ns_0_i_12169_variant_DataContents[3]; |
| 69522 | |
| 69523 | UA_init(p: &variablenode_ns_0_i_12169_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]); |
| 69524 | variablenode_ns_0_i_12169_variant_DataContents[0].value = (UA_Int64) 1; |
| 69525 | variablenode_ns_0_i_12169_variant_DataContents[0].displayName = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69526 | variablenode_ns_0_i_12169_variant_DataContents[0].description = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69527 | |
| 69528 | UA_init(p: &variablenode_ns_0_i_12169_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]); |
| 69529 | variablenode_ns_0_i_12169_variant_DataContents[1].value = (UA_Int64) 2; |
| 69530 | variablenode_ns_0_i_12169_variant_DataContents[1].displayName = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69531 | variablenode_ns_0_i_12169_variant_DataContents[1].description = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69532 | |
| 69533 | UA_init(p: &variablenode_ns_0_i_12169_variant_DataContents[2], type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]); |
| 69534 | variablenode_ns_0_i_12169_variant_DataContents[2].value = (UA_Int64) 3; |
| 69535 | variablenode_ns_0_i_12169_variant_DataContents[2].displayName = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69536 | variablenode_ns_0_i_12169_variant_DataContents[2].description = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69537 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_12169_variant_DataContents, arraySize: (UA_Int32) 3, type: &UA_TYPES[UA_TYPES_ENUMVALUETYPE]); |
| 69538 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValues"); |
| 69539 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 69540 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12169LU), |
| 69541 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU), |
| 69542 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 69543 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValues"), |
| 69544 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 69545 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 69546 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69547 | |
| 69548 | |
| 69549 | |
| 69550 | return retVal; |
| 69551 | } |
| 69552 | |
| 69553 | static UA_StatusCode function_namespace0_generated_69_finish(UA_Server *server, UA_UInt16* ns) { |
| 69554 | return UA_Server_addNode_finish(server, |
| 69555 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12169LU) |
| 69556 | ); |
| 69557 | } |
| 69558 | |
| 69559 | /* Number - ns=0;i=26 */ |
| 69560 | |
| 69561 | static UA_StatusCode function_namespace0_generated_70_begin(UA_Server *server, UA_UInt16* ns) { |
| 69562 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69563 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69564 | attr.isAbstract = true; |
| 69565 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Number"); |
| 69566 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69567 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU), |
| 69568 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU), |
| 69569 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69570 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Number"), |
| 69571 | typeDefinition: UA_NODEID_NULL, |
| 69572 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69573 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69574 | return retVal; |
| 69575 | } |
| 69576 | |
| 69577 | static UA_StatusCode function_namespace0_generated_70_finish(UA_Server *server, UA_UInt16* ns) { |
| 69578 | return UA_Server_addNode_finish(server, |
| 69579 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU) |
| 69580 | ); |
| 69581 | } |
| 69582 | |
| 69583 | /* Decimal - ns=0;i=50 */ |
| 69584 | |
| 69585 | static UA_StatusCode function_namespace0_generated_71_begin(UA_Server *server, UA_UInt16* ns) { |
| 69586 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69587 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69588 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Decimal"); |
| 69589 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69590 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 50LU), |
| 69591 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU), |
| 69592 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69593 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Decimal"), |
| 69594 | typeDefinition: UA_NODEID_NULL, |
| 69595 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69596 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69597 | return retVal; |
| 69598 | } |
| 69599 | |
| 69600 | static UA_StatusCode function_namespace0_generated_71_finish(UA_Server *server, UA_UInt16* ns) { |
| 69601 | return UA_Server_addNode_finish(server, |
| 69602 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 50LU) |
| 69603 | ); |
| 69604 | } |
| 69605 | |
| 69606 | /* UInteger - ns=0;i=28 */ |
| 69607 | |
| 69608 | static UA_StatusCode function_namespace0_generated_72_begin(UA_Server *server, UA_UInt16* ns) { |
| 69609 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69610 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69611 | attr.isAbstract = true; |
| 69612 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInteger"); |
| 69613 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69614 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU), |
| 69615 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU), |
| 69616 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69617 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInteger"), |
| 69618 | typeDefinition: UA_NODEID_NULL, |
| 69619 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69620 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69621 | return retVal; |
| 69622 | } |
| 69623 | |
| 69624 | static UA_StatusCode function_namespace0_generated_72_finish(UA_Server *server, UA_UInt16* ns) { |
| 69625 | return UA_Server_addNode_finish(server, |
| 69626 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU) |
| 69627 | ); |
| 69628 | } |
| 69629 | |
| 69630 | /* UInt64 - ns=0;i=9 */ |
| 69631 | |
| 69632 | static UA_StatusCode function_namespace0_generated_73_begin(UA_Server *server, UA_UInt16* ns) { |
| 69633 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69634 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69635 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInt64"); |
| 69636 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69637 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9LU), |
| 69638 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU), |
| 69639 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69640 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInt64"), |
| 69641 | typeDefinition: UA_NODEID_NULL, |
| 69642 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69643 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69644 | return retVal; |
| 69645 | } |
| 69646 | |
| 69647 | static UA_StatusCode function_namespace0_generated_73_finish(UA_Server *server, UA_UInt16* ns) { |
| 69648 | return UA_Server_addNode_finish(server, |
| 69649 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9LU) |
| 69650 | ); |
| 69651 | } |
| 69652 | |
| 69653 | /* UInt32 - ns=0;i=7 */ |
| 69654 | |
| 69655 | static UA_StatusCode function_namespace0_generated_74_begin(UA_Server *server, UA_UInt16* ns) { |
| 69656 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69657 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69658 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInt32"); |
| 69659 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69660 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU), |
| 69661 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU), |
| 69662 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69663 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInt32"), |
| 69664 | typeDefinition: UA_NODEID_NULL, |
| 69665 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69666 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69667 | return retVal; |
| 69668 | } |
| 69669 | |
| 69670 | static UA_StatusCode function_namespace0_generated_74_finish(UA_Server *server, UA_UInt16* ns) { |
| 69671 | return UA_Server_addNode_finish(server, |
| 69672 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU) |
| 69673 | ); |
| 69674 | } |
| 69675 | |
| 69676 | /* VersionTime - ns=0;i=20998 */ |
| 69677 | |
| 69678 | static UA_StatusCode function_namespace0_generated_75_begin(UA_Server *server, UA_UInt16* ns) { |
| 69679 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69680 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69681 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "VersionTime"); |
| 69682 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69683 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 20998LU), |
| 69684 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU), |
| 69685 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69686 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "VersionTime"), |
| 69687 | typeDefinition: UA_NODEID_NULL, |
| 69688 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69689 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69690 | return retVal; |
| 69691 | } |
| 69692 | |
| 69693 | static UA_StatusCode function_namespace0_generated_75_finish(UA_Server *server, UA_UInt16* ns) { |
| 69694 | return UA_Server_addNode_finish(server, |
| 69695 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 20998LU) |
| 69696 | ); |
| 69697 | } |
| 69698 | |
| 69699 | /* DataSetFieldContentMask - ns=0;i=15583 */ |
| 69700 | |
| 69701 | static UA_StatusCode function_namespace0_generated_76_begin(UA_Server *server, UA_UInt16* ns) { |
| 69702 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69703 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69704 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetFieldContentMask"); |
| 69705 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69706 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15583LU), |
| 69707 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU), |
| 69708 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69709 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetFieldContentMask"), |
| 69710 | typeDefinition: UA_NODEID_NULL, |
| 69711 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69712 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69713 | return retVal; |
| 69714 | } |
| 69715 | |
| 69716 | static UA_StatusCode function_namespace0_generated_76_finish(UA_Server *server, UA_UInt16* ns) { |
| 69717 | return UA_Server_addNode_finish(server, |
| 69718 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15583LU) |
| 69719 | ); |
| 69720 | } |
| 69721 | |
| 69722 | /* OptionSetValues - ns=0;i=15584 */ |
| 69723 | |
| 69724 | static UA_StatusCode function_namespace0_generated_77_begin(UA_Server *server, UA_UInt16* ns) { |
| 69725 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69726 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 69727 | attr.minimumSamplingInterval = 0.000000; |
| 69728 | attr.userAccessLevel = 1; |
| 69729 | attr.accessLevel = 1; |
| 69730 | attr.valueRank = 1; |
| 69731 | attr.arrayDimensionsSize = 1; |
| 69732 | UA_UInt32 arrayDimensions[1]; |
| 69733 | arrayDimensions[0] = 0; |
| 69734 | attr.arrayDimensions = &arrayDimensions[0]; |
| 69735 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 69736 | UA_LocalizedText variablenode_ns_0_i_15584_variant_DataContents[6]; |
| 69737 | variablenode_ns_0_i_15584_variant_DataContents[0] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69738 | variablenode_ns_0_i_15584_variant_DataContents[1] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69739 | variablenode_ns_0_i_15584_variant_DataContents[2] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69740 | variablenode_ns_0_i_15584_variant_DataContents[3] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69741 | variablenode_ns_0_i_15584_variant_DataContents[4] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69742 | variablenode_ns_0_i_15584_variant_DataContents[5] = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 69743 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_15584_variant_DataContents, arraySize: (UA_Int32) 6, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 69744 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OptionSetValues"); |
| 69745 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 69746 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15584LU), |
| 69747 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15583LU), |
| 69748 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 69749 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OptionSetValues"), |
| 69750 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 69751 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 69752 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69753 | return retVal; |
| 69754 | } |
| 69755 | |
| 69756 | static UA_StatusCode function_namespace0_generated_77_finish(UA_Server *server, UA_UInt16* ns) { |
| 69757 | return UA_Server_addNode_finish(server, |
| 69758 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15584LU) |
| 69759 | ); |
| 69760 | } |
| 69761 | |
| 69762 | /* UInt16 - ns=0;i=5 */ |
| 69763 | |
| 69764 | static UA_StatusCode function_namespace0_generated_78_begin(UA_Server *server, UA_UInt16* ns) { |
| 69765 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69766 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69767 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UInt16"); |
| 69768 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69769 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU), |
| 69770 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU), |
| 69771 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69772 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UInt16"), |
| 69773 | typeDefinition: UA_NODEID_NULL, |
| 69774 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69775 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69776 | return retVal; |
| 69777 | } |
| 69778 | |
| 69779 | static UA_StatusCode function_namespace0_generated_78_finish(UA_Server *server, UA_UInt16* ns) { |
| 69780 | return UA_Server_addNode_finish(server, |
| 69781 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU) |
| 69782 | ); |
| 69783 | } |
| 69784 | |
| 69785 | /* Byte - ns=0;i=3 */ |
| 69786 | |
| 69787 | static UA_StatusCode function_namespace0_generated_79_begin(UA_Server *server, UA_UInt16* ns) { |
| 69788 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69789 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69790 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Byte"); |
| 69791 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69792 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU), |
| 69793 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU), |
| 69794 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69795 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Byte"), |
| 69796 | typeDefinition: UA_NODEID_NULL, |
| 69797 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69798 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69799 | return retVal; |
| 69800 | } |
| 69801 | |
| 69802 | static UA_StatusCode function_namespace0_generated_79_finish(UA_Server *server, UA_UInt16* ns) { |
| 69803 | return UA_Server_addNode_finish(server, |
| 69804 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU) |
| 69805 | ); |
| 69806 | } |
| 69807 | |
| 69808 | /* Integer - ns=0;i=27 */ |
| 69809 | |
| 69810 | static UA_StatusCode function_namespace0_generated_80_begin(UA_Server *server, UA_UInt16* ns) { |
| 69811 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69812 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69813 | attr.isAbstract = true; |
| 69814 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Integer"); |
| 69815 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69816 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU), |
| 69817 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU), |
| 69818 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69819 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Integer"), |
| 69820 | typeDefinition: UA_NODEID_NULL, |
| 69821 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69822 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69823 | return retVal; |
| 69824 | } |
| 69825 | |
| 69826 | static UA_StatusCode function_namespace0_generated_80_finish(UA_Server *server, UA_UInt16* ns) { |
| 69827 | return UA_Server_addNode_finish(server, |
| 69828 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU) |
| 69829 | ); |
| 69830 | } |
| 69831 | |
| 69832 | /* Int64 - ns=0;i=8 */ |
| 69833 | |
| 69834 | static UA_StatusCode function_namespace0_generated_81_begin(UA_Server *server, UA_UInt16* ns) { |
| 69835 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69836 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69837 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Int64"); |
| 69838 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69839 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8LU), |
| 69840 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU), |
| 69841 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69842 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Int64"), |
| 69843 | typeDefinition: UA_NODEID_NULL, |
| 69844 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69845 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69846 | return retVal; |
| 69847 | } |
| 69848 | |
| 69849 | static UA_StatusCode function_namespace0_generated_81_finish(UA_Server *server, UA_UInt16* ns) { |
| 69850 | return UA_Server_addNode_finish(server, |
| 69851 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8LU) |
| 69852 | ); |
| 69853 | } |
| 69854 | |
| 69855 | /* Int32 - ns=0;i=6 */ |
| 69856 | |
| 69857 | static UA_StatusCode function_namespace0_generated_82_begin(UA_Server *server, UA_UInt16* ns) { |
| 69858 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69859 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69860 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Int32"); |
| 69861 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69862 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 6LU), |
| 69863 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU), |
| 69864 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69865 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Int32"), |
| 69866 | typeDefinition: UA_NODEID_NULL, |
| 69867 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69868 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69869 | return retVal; |
| 69870 | } |
| 69871 | |
| 69872 | static UA_StatusCode function_namespace0_generated_82_finish(UA_Server *server, UA_UInt16* ns) { |
| 69873 | return UA_Server_addNode_finish(server, |
| 69874 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 6LU) |
| 69875 | ); |
| 69876 | } |
| 69877 | |
| 69878 | /* Int16 - ns=0;i=4 */ |
| 69879 | |
| 69880 | static UA_StatusCode function_namespace0_generated_83_begin(UA_Server *server, UA_UInt16* ns) { |
| 69881 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69882 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69883 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Int16"); |
| 69884 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69885 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 4LU), |
| 69886 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU), |
| 69887 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69888 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Int16"), |
| 69889 | typeDefinition: UA_NODEID_NULL, |
| 69890 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69891 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69892 | return retVal; |
| 69893 | } |
| 69894 | |
| 69895 | static UA_StatusCode function_namespace0_generated_83_finish(UA_Server *server, UA_UInt16* ns) { |
| 69896 | return UA_Server_addNode_finish(server, |
| 69897 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 4LU) |
| 69898 | ); |
| 69899 | } |
| 69900 | |
| 69901 | /* SByte - ns=0;i=2 */ |
| 69902 | |
| 69903 | static UA_StatusCode function_namespace0_generated_84_begin(UA_Server *server, UA_UInt16* ns) { |
| 69904 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69905 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69906 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SByte"); |
| 69907 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69908 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2LU), |
| 69909 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 27LU), |
| 69910 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69911 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SByte"), |
| 69912 | typeDefinition: UA_NODEID_NULL, |
| 69913 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69914 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69915 | return retVal; |
| 69916 | } |
| 69917 | |
| 69918 | static UA_StatusCode function_namespace0_generated_84_finish(UA_Server *server, UA_UInt16* ns) { |
| 69919 | return UA_Server_addNode_finish(server, |
| 69920 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2LU) |
| 69921 | ); |
| 69922 | } |
| 69923 | |
| 69924 | /* Double - ns=0;i=11 */ |
| 69925 | |
| 69926 | static UA_StatusCode function_namespace0_generated_85_begin(UA_Server *server, UA_UInt16* ns) { |
| 69927 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69928 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69929 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Double"); |
| 69930 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69931 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU), |
| 69932 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU), |
| 69933 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69934 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Double"), |
| 69935 | typeDefinition: UA_NODEID_NULL, |
| 69936 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69937 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69938 | return retVal; |
| 69939 | } |
| 69940 | |
| 69941 | static UA_StatusCode function_namespace0_generated_85_finish(UA_Server *server, UA_UInt16* ns) { |
| 69942 | return UA_Server_addNode_finish(server, |
| 69943 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU) |
| 69944 | ); |
| 69945 | } |
| 69946 | |
| 69947 | /* Duration - ns=0;i=290 */ |
| 69948 | |
| 69949 | static UA_StatusCode function_namespace0_generated_86_begin(UA_Server *server, UA_UInt16* ns) { |
| 69950 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69951 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69952 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Duration"); |
| 69953 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69954 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU), |
| 69955 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU), |
| 69956 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69957 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Duration"), |
| 69958 | typeDefinition: UA_NODEID_NULL, |
| 69959 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69960 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69961 | return retVal; |
| 69962 | } |
| 69963 | |
| 69964 | static UA_StatusCode function_namespace0_generated_86_finish(UA_Server *server, UA_UInt16* ns) { |
| 69965 | return UA_Server_addNode_finish(server, |
| 69966 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU) |
| 69967 | ); |
| 69968 | } |
| 69969 | |
| 69970 | /* Float - ns=0;i=10 */ |
| 69971 | |
| 69972 | static UA_StatusCode function_namespace0_generated_87_begin(UA_Server *server, UA_UInt16* ns) { |
| 69973 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69974 | UA_DataTypeAttributes attr = UA_DataTypeAttributes_default; |
| 69975 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Float"); |
| 69976 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_DATATYPE, |
| 69977 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 10LU), |
| 69978 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU), |
| 69979 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 69980 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Float"), |
| 69981 | typeDefinition: UA_NODEID_NULL, |
| 69982 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_DATATYPEATTRIBUTES],NULL, NULL); |
| 69983 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 69984 | return retVal; |
| 69985 | } |
| 69986 | |
| 69987 | static UA_StatusCode function_namespace0_generated_87_finish(UA_Server *server, UA_UInt16* ns) { |
| 69988 | return UA_Server_addNode_finish(server, |
| 69989 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 10LU) |
| 69990 | ); |
| 69991 | } |
| 69992 | |
| 69993 | /* DataItemType - ns=0;i=2365 */ |
| 69994 | |
| 69995 | static UA_StatusCode function_namespace0_generated_88_begin(UA_Server *server, UA_UInt16* ns) { |
| 69996 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 69997 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 69998 | attr.valueRank = -2; |
| 69999 | /* DataType inherited */ |
| 70000 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 70001 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataItemType"); |
| 70002 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 70003 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A variable that contains live automation data."); |
| 70004 | #endif |
| 70005 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 70006 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU), |
| 70007 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 70008 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70009 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataItemType"), |
| 70010 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 70011 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 70012 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70013 | return retVal; |
| 70014 | } |
| 70015 | |
| 70016 | static UA_StatusCode function_namespace0_generated_88_finish(UA_Server *server, UA_UInt16* ns) { |
| 70017 | return UA_Server_addNode_finish(server, |
| 70018 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU) |
| 70019 | ); |
| 70020 | } |
| 70021 | |
| 70022 | /* DiscreteItemType - ns=0;i=2372 */ |
| 70023 | |
| 70024 | static UA_StatusCode function_namespace0_generated_89_begin(UA_Server *server, UA_UInt16* ns) { |
| 70025 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70026 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 70027 | attr.isAbstract = true; |
| 70028 | attr.valueRank = -2; |
| 70029 | /* DataType inherited */ |
| 70030 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 70031 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DiscreteItemType"); |
| 70032 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 70033 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU), |
| 70034 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU), |
| 70035 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70036 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DiscreteItemType"), |
| 70037 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 70038 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 70039 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70040 | return retVal; |
| 70041 | } |
| 70042 | |
| 70043 | static UA_StatusCode function_namespace0_generated_89_finish(UA_Server *server, UA_UInt16* ns) { |
| 70044 | return UA_Server_addNode_finish(server, |
| 70045 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU) |
| 70046 | ); |
| 70047 | } |
| 70048 | |
| 70049 | /* MultiStateDiscreteType - ns=0;i=2376 */ |
| 70050 | |
| 70051 | static UA_StatusCode function_namespace0_generated_90_begin(UA_Server *server, UA_UInt16* ns) { |
| 70052 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70053 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 70054 | attr.valueRank = -2; |
| 70055 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 28LU); |
| 70056 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MultiStateDiscreteType"); |
| 70057 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 70058 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2376LU), |
| 70059 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU), |
| 70060 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70061 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MultiStateDiscreteType"), |
| 70062 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 70063 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 70064 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70065 | return retVal; |
| 70066 | } |
| 70067 | |
| 70068 | static UA_StatusCode function_namespace0_generated_90_finish(UA_Server *server, UA_UInt16* ns) { |
| 70069 | return UA_Server_addNode_finish(server, |
| 70070 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2376LU) |
| 70071 | ); |
| 70072 | } |
| 70073 | |
| 70074 | /* EnumStrings - ns=0;i=2377 */ |
| 70075 | |
| 70076 | static UA_StatusCode function_namespace0_generated_91_begin(UA_Server *server, UA_UInt16* ns) { |
| 70077 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70078 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70079 | attr.minimumSamplingInterval = 0.000000; |
| 70080 | attr.userAccessLevel = 1; |
| 70081 | attr.accessLevel = 1; |
| 70082 | attr.valueRank = 1; |
| 70083 | attr.arrayDimensionsSize = 1; |
| 70084 | UA_UInt32 arrayDimensions[1]; |
| 70085 | arrayDimensions[0] = 0; |
| 70086 | attr.arrayDimensions = &arrayDimensions[0]; |
| 70087 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 70088 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumStrings"); |
| 70089 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70090 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2377LU), |
| 70091 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2376LU), |
| 70092 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70093 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumStrings"), |
| 70094 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70095 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70096 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70097 | return retVal; |
| 70098 | } |
| 70099 | |
| 70100 | static UA_StatusCode function_namespace0_generated_91_finish(UA_Server *server, UA_UInt16* ns) { |
| 70101 | return UA_Server_addNode_finish(server, |
| 70102 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2377LU) |
| 70103 | ); |
| 70104 | } |
| 70105 | |
| 70106 | /* TwoStateDiscreteType - ns=0;i=2373 */ |
| 70107 | |
| 70108 | static UA_StatusCode function_namespace0_generated_92_begin(UA_Server *server, UA_UInt16* ns) { |
| 70109 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70110 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 70111 | attr.valueRank = -2; |
| 70112 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 70113 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TwoStateDiscreteType"); |
| 70114 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 70115 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU), |
| 70116 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU), |
| 70117 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70118 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TwoStateDiscreteType"), |
| 70119 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 70120 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 70121 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70122 | return retVal; |
| 70123 | } |
| 70124 | |
| 70125 | static UA_StatusCode function_namespace0_generated_92_finish(UA_Server *server, UA_UInt16* ns) { |
| 70126 | return UA_Server_addNode_finish(server, |
| 70127 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU) |
| 70128 | ); |
| 70129 | } |
| 70130 | |
| 70131 | /* TrueState - ns=0;i=2375 */ |
| 70132 | |
| 70133 | static UA_StatusCode function_namespace0_generated_93_begin(UA_Server *server, UA_UInt16* ns) { |
| 70134 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70135 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70136 | attr.minimumSamplingInterval = 0.000000; |
| 70137 | attr.userAccessLevel = 1; |
| 70138 | attr.accessLevel = 1; |
| 70139 | /* Value rank inherited */ |
| 70140 | attr.valueRank = -2; |
| 70141 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 70142 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TrueState"); |
| 70143 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70144 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2375LU), |
| 70145 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU), |
| 70146 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70147 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TrueState"), |
| 70148 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70149 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70150 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70151 | return retVal; |
| 70152 | } |
| 70153 | |
| 70154 | static UA_StatusCode function_namespace0_generated_93_finish(UA_Server *server, UA_UInt16* ns) { |
| 70155 | return UA_Server_addNode_finish(server, |
| 70156 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2375LU) |
| 70157 | ); |
| 70158 | } |
| 70159 | |
| 70160 | /* FalseState - ns=0;i=2374 */ |
| 70161 | |
| 70162 | static UA_StatusCode function_namespace0_generated_94_begin(UA_Server *server, UA_UInt16* ns) { |
| 70163 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70164 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70165 | attr.minimumSamplingInterval = 0.000000; |
| 70166 | attr.userAccessLevel = 1; |
| 70167 | attr.accessLevel = 1; |
| 70168 | /* Value rank inherited */ |
| 70169 | attr.valueRank = -2; |
| 70170 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 70171 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FalseState"); |
| 70172 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70173 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2374LU), |
| 70174 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2373LU), |
| 70175 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70176 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "FalseState"), |
| 70177 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70178 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70179 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70180 | return retVal; |
| 70181 | } |
| 70182 | |
| 70183 | static UA_StatusCode function_namespace0_generated_94_finish(UA_Server *server, UA_UInt16* ns) { |
| 70184 | return UA_Server_addNode_finish(server, |
| 70185 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2374LU) |
| 70186 | ); |
| 70187 | } |
| 70188 | |
| 70189 | /* MultiStateValueDiscreteType - ns=0;i=11238 */ |
| 70190 | |
| 70191 | static UA_StatusCode function_namespace0_generated_95_begin(UA_Server *server, UA_UInt16* ns) { |
| 70192 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70193 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 70194 | attr.valueRank = -2; |
| 70195 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU); |
| 70196 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MultiStateValueDiscreteType"); |
| 70197 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 70198 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU), |
| 70199 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2372LU), |
| 70200 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70201 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MultiStateValueDiscreteType"), |
| 70202 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 70203 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 70204 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70205 | return retVal; |
| 70206 | } |
| 70207 | |
| 70208 | static UA_StatusCode function_namespace0_generated_95_finish(UA_Server *server, UA_UInt16* ns) { |
| 70209 | return UA_Server_addNode_finish(server, |
| 70210 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU) |
| 70211 | ); |
| 70212 | } |
| 70213 | |
| 70214 | /* ValueAsText - ns=0;i=11461 */ |
| 70215 | |
| 70216 | static UA_StatusCode function_namespace0_generated_96_begin(UA_Server *server, UA_UInt16* ns) { |
| 70217 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70218 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70219 | attr.minimumSamplingInterval = 0.000000; |
| 70220 | attr.userAccessLevel = 1; |
| 70221 | attr.accessLevel = 1; |
| 70222 | /* Value rank inherited */ |
| 70223 | attr.valueRank = -2; |
| 70224 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 70225 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ValueAsText"); |
| 70226 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70227 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11461LU), |
| 70228 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU), |
| 70229 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70230 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ValueAsText"), |
| 70231 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70232 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70233 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70234 | return retVal; |
| 70235 | } |
| 70236 | |
| 70237 | static UA_StatusCode function_namespace0_generated_96_finish(UA_Server *server, UA_UInt16* ns) { |
| 70238 | return UA_Server_addNode_finish(server, |
| 70239 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11461LU) |
| 70240 | ); |
| 70241 | } |
| 70242 | |
| 70243 | /* EnumValues - ns=0;i=11241 */ |
| 70244 | |
| 70245 | static UA_StatusCode function_namespace0_generated_97_begin(UA_Server *server, UA_UInt16* ns) { |
| 70246 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70247 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70248 | attr.minimumSamplingInterval = 0.000000; |
| 70249 | attr.userAccessLevel = 1; |
| 70250 | attr.accessLevel = 1; |
| 70251 | attr.valueRank = 1; |
| 70252 | attr.arrayDimensionsSize = 1; |
| 70253 | UA_UInt32 arrayDimensions[1]; |
| 70254 | arrayDimensions[0] = 0; |
| 70255 | attr.arrayDimensions = &arrayDimensions[0]; |
| 70256 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU); |
| 70257 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValues"); |
| 70258 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70259 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11241LU), |
| 70260 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11238LU), |
| 70261 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70262 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValues"), |
| 70263 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70264 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70265 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70266 | return retVal; |
| 70267 | } |
| 70268 | |
| 70269 | static UA_StatusCode function_namespace0_generated_97_finish(UA_Server *server, UA_UInt16* ns) { |
| 70270 | return UA_Server_addNode_finish(server, |
| 70271 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11241LU) |
| 70272 | ); |
| 70273 | } |
| 70274 | |
| 70275 | /* AnalogItemType - ns=0;i=2368 */ |
| 70276 | |
| 70277 | static UA_StatusCode function_namespace0_generated_98_begin(UA_Server *server, UA_UInt16* ns) { |
| 70278 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70279 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 70280 | attr.valueRank = -2; |
| 70281 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 26LU); |
| 70282 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AnalogItemType"); |
| 70283 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 70284 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU), |
| 70285 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU), |
| 70286 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70287 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AnalogItemType"), |
| 70288 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 70289 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 70290 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70291 | return retVal; |
| 70292 | } |
| 70293 | |
| 70294 | static UA_StatusCode function_namespace0_generated_98_finish(UA_Server *server, UA_UInt16* ns) { |
| 70295 | return UA_Server_addNode_finish(server, |
| 70296 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU) |
| 70297 | ); |
| 70298 | } |
| 70299 | |
| 70300 | /* EngineeringUnits - ns=0;i=2371 */ |
| 70301 | |
| 70302 | static UA_StatusCode function_namespace0_generated_99_begin(UA_Server *server, UA_UInt16* ns) { |
| 70303 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70304 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70305 | attr.minimumSamplingInterval = 0.000000; |
| 70306 | attr.userAccessLevel = 1; |
| 70307 | attr.accessLevel = 1; |
| 70308 | /* Value rank inherited */ |
| 70309 | attr.valueRank = -2; |
| 70310 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 887LU); |
| 70311 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EngineeringUnits"); |
| 70312 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70313 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2371LU), |
| 70314 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU), |
| 70315 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70316 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EngineeringUnits"), |
| 70317 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70318 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70319 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70320 | return retVal; |
| 70321 | } |
| 70322 | |
| 70323 | static UA_StatusCode function_namespace0_generated_99_finish(UA_Server *server, UA_UInt16* ns) { |
| 70324 | return UA_Server_addNode_finish(server, |
| 70325 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2371LU) |
| 70326 | ); |
| 70327 | } |
| 70328 | |
| 70329 | /* InstrumentRange - ns=0;i=2370 */ |
| 70330 | |
| 70331 | static UA_StatusCode function_namespace0_generated_100_begin(UA_Server *server, UA_UInt16* ns) { |
| 70332 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70333 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70334 | attr.minimumSamplingInterval = 0.000000; |
| 70335 | attr.userAccessLevel = 1; |
| 70336 | attr.accessLevel = 1; |
| 70337 | /* Value rank inherited */ |
| 70338 | attr.valueRank = -2; |
| 70339 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU); |
| 70340 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InstrumentRange"); |
| 70341 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70342 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2370LU), |
| 70343 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU), |
| 70344 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70345 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InstrumentRange"), |
| 70346 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70347 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70348 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70349 | return retVal; |
| 70350 | } |
| 70351 | |
| 70352 | static UA_StatusCode function_namespace0_generated_100_finish(UA_Server *server, UA_UInt16* ns) { |
| 70353 | return UA_Server_addNode_finish(server, |
| 70354 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2370LU) |
| 70355 | ); |
| 70356 | } |
| 70357 | |
| 70358 | /* EURange - ns=0;i=2369 */ |
| 70359 | |
| 70360 | static UA_StatusCode function_namespace0_generated_101_begin(UA_Server *server, UA_UInt16* ns) { |
| 70361 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70362 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70363 | attr.minimumSamplingInterval = 0.000000; |
| 70364 | attr.userAccessLevel = 3; |
| 70365 | attr.accessLevel = 3; |
| 70366 | /* Value rank inherited */ |
| 70367 | attr.valueRank = -2; |
| 70368 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU); |
| 70369 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EURange"); |
| 70370 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70371 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2369LU), |
| 70372 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2368LU), |
| 70373 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70374 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EURange"), |
| 70375 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70376 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70377 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70378 | return retVal; |
| 70379 | } |
| 70380 | |
| 70381 | static UA_StatusCode function_namespace0_generated_101_finish(UA_Server *server, UA_UInt16* ns) { |
| 70382 | return UA_Server_addNode_finish(server, |
| 70383 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2369LU) |
| 70384 | ); |
| 70385 | } |
| 70386 | |
| 70387 | /* ValuePrecision - ns=0;i=2367 */ |
| 70388 | |
| 70389 | static UA_StatusCode function_namespace0_generated_102_begin(UA_Server *server, UA_UInt16* ns) { |
| 70390 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70391 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70392 | attr.minimumSamplingInterval = 0.000000; |
| 70393 | attr.userAccessLevel = 1; |
| 70394 | attr.accessLevel = 1; |
| 70395 | /* Value rank inherited */ |
| 70396 | attr.valueRank = -2; |
| 70397 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11LU); |
| 70398 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ValuePrecision"); |
| 70399 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 70400 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "The maximum precision that the server can maintain for the item based on restrictions in the target environment."); |
| 70401 | #endif |
| 70402 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70403 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2367LU), |
| 70404 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU), |
| 70405 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70406 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ValuePrecision"), |
| 70407 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70408 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70409 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70410 | return retVal; |
| 70411 | } |
| 70412 | |
| 70413 | static UA_StatusCode function_namespace0_generated_102_finish(UA_Server *server, UA_UInt16* ns) { |
| 70414 | return UA_Server_addNode_finish(server, |
| 70415 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2367LU) |
| 70416 | ); |
| 70417 | } |
| 70418 | |
| 70419 | /* Definition - ns=0;i=2366 */ |
| 70420 | |
| 70421 | static UA_StatusCode function_namespace0_generated_103_begin(UA_Server *server, UA_UInt16* ns) { |
| 70422 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70423 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70424 | attr.minimumSamplingInterval = 0.000000; |
| 70425 | attr.userAccessLevel = 1; |
| 70426 | attr.accessLevel = 1; |
| 70427 | /* Value rank inherited */ |
| 70428 | attr.valueRank = -2; |
| 70429 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 70430 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Definition"); |
| 70431 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 70432 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A vendor-specific, human readable string that specifies how the value of this DataItem is calculated."); |
| 70433 | #endif |
| 70434 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70435 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2366LU), |
| 70436 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2365LU), |
| 70437 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70438 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Definition"), |
| 70439 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70440 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70441 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70442 | return retVal; |
| 70443 | } |
| 70444 | |
| 70445 | static UA_StatusCode function_namespace0_generated_103_finish(UA_Server *server, UA_UInt16* ns) { |
| 70446 | return UA_Server_addNode_finish(server, |
| 70447 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2366LU) |
| 70448 | ); |
| 70449 | } |
| 70450 | |
| 70451 | /* SubscribedDataSetType - ns=0;i=15108 */ |
| 70452 | |
| 70453 | static UA_StatusCode function_namespace0_generated_104_begin(UA_Server *server, UA_UInt16* ns) { |
| 70454 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70455 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 70456 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscribedDataSetType"); |
| 70457 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 70458 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15108LU), |
| 70459 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 70460 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70461 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscribedDataSetType"), |
| 70462 | typeDefinition: UA_NODEID_NULL, |
| 70463 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 70464 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70465 | return retVal; |
| 70466 | } |
| 70467 | |
| 70468 | static UA_StatusCode function_namespace0_generated_104_finish(UA_Server *server, UA_UInt16* ns) { |
| 70469 | return UA_Server_addNode_finish(server, |
| 70470 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15108LU) |
| 70471 | ); |
| 70472 | } |
| 70473 | |
| 70474 | /* TargetVariablesType - ns=0;i=15111 */ |
| 70475 | |
| 70476 | static UA_StatusCode function_namespace0_generated_105_begin(UA_Server *server, UA_UInt16* ns) { |
| 70477 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70478 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 70479 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TargetVariablesType"); |
| 70480 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 70481 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15111LU), |
| 70482 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15108LU), |
| 70483 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70484 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TargetVariablesType"), |
| 70485 | typeDefinition: UA_NODEID_NULL, |
| 70486 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 70487 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70488 | return retVal; |
| 70489 | } |
| 70490 | |
| 70491 | static UA_StatusCode function_namespace0_generated_105_finish(UA_Server *server, UA_UInt16* ns) { |
| 70492 | return UA_Server_addNode_finish(server, |
| 70493 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15111LU) |
| 70494 | ); |
| 70495 | } |
| 70496 | |
| 70497 | /* RemoveTargetVariables - ns=0;i=15118 */ |
| 70498 | |
| 70499 | static UA_StatusCode function_namespace0_generated_106_begin(UA_Server *server, UA_UInt16* ns) { |
| 70500 | #ifdef UA_ENABLE_METHODCALLS |
| 70501 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70502 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 70503 | attr.executable = true; |
| 70504 | attr.userExecutable = true; |
| 70505 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveTargetVariables"); |
| 70506 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 70507 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15118LU), |
| 70508 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15108LU), |
| 70509 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 70510 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveTargetVariables"), |
| 70511 | typeDefinition: UA_NODEID_NULL, |
| 70512 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 70513 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70514 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15118LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15111LU), false); |
| 70515 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70516 | return retVal; |
| 70517 | #else |
| 70518 | return UA_STATUSCODE_GOOD; |
| 70519 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70520 | } |
| 70521 | |
| 70522 | static UA_StatusCode function_namespace0_generated_106_finish(UA_Server *server, UA_UInt16* ns) { |
| 70523 | #ifdef UA_ENABLE_METHODCALLS |
| 70524 | return UA_Server_addMethodNode_finish(server, |
| 70525 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15118LU) |
| 70526 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 70527 | #else |
| 70528 | return UA_STATUSCODE_GOOD; |
| 70529 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70530 | } |
| 70531 | |
| 70532 | /* OutputArguments - ns=0;i=15120 */ |
| 70533 | |
| 70534 | static UA_StatusCode function_namespace0_generated_107_begin(UA_Server *server, UA_UInt16* ns) { |
| 70535 | #ifdef UA_ENABLE_METHODCALLS |
| 70536 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70537 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70538 | attr.minimumSamplingInterval = 0.000000; |
| 70539 | attr.userAccessLevel = 1; |
| 70540 | attr.accessLevel = 1; |
| 70541 | attr.valueRank = 1; |
| 70542 | attr.arrayDimensionsSize = 1; |
| 70543 | UA_UInt32 arrayDimensions[1]; |
| 70544 | arrayDimensions[0] = 0; |
| 70545 | attr.arrayDimensions = &arrayDimensions[0]; |
| 70546 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 70547 | UA_Argument variablenode_ns_0_i_15120_variant_DataContents[1]; |
| 70548 | |
| 70549 | UA_init(p: &variablenode_ns_0_i_15120_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 70550 | variablenode_ns_0_i_15120_variant_DataContents[0].name = UA_STRING(chars: "AddResults"); |
| 70551 | variablenode_ns_0_i_15120_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU); |
| 70552 | variablenode_ns_0_i_15120_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 70553 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_15120_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 70554 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 70555 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70556 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15120LU), |
| 70557 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15118LU), |
| 70558 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70559 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 70560 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70561 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70562 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70563 | |
| 70564 | return retVal; |
| 70565 | #else |
| 70566 | return UA_STATUSCODE_GOOD; |
| 70567 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70568 | } |
| 70569 | |
| 70570 | static UA_StatusCode function_namespace0_generated_107_finish(UA_Server *server, UA_UInt16* ns) { |
| 70571 | #ifdef UA_ENABLE_METHODCALLS |
| 70572 | return UA_Server_addNode_finish(server, |
| 70573 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15120LU) |
| 70574 | ); |
| 70575 | #else |
| 70576 | return UA_STATUSCODE_GOOD; |
| 70577 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70578 | } |
| 70579 | |
| 70580 | /* InputArguments - ns=0;i=15119 */ |
| 70581 | |
| 70582 | static UA_StatusCode function_namespace0_generated_108_begin(UA_Server *server, UA_UInt16* ns) { |
| 70583 | #ifdef UA_ENABLE_METHODCALLS |
| 70584 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70585 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70586 | attr.minimumSamplingInterval = 0.000000; |
| 70587 | attr.userAccessLevel = 1; |
| 70588 | attr.accessLevel = 1; |
| 70589 | attr.valueRank = 1; |
| 70590 | attr.arrayDimensionsSize = 1; |
| 70591 | UA_UInt32 arrayDimensions[1]; |
| 70592 | arrayDimensions[0] = 0; |
| 70593 | attr.arrayDimensions = &arrayDimensions[0]; |
| 70594 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 70595 | UA_Argument variablenode_ns_0_i_15119_variant_DataContents[1]; |
| 70596 | |
| 70597 | UA_init(p: &variablenode_ns_0_i_15119_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 70598 | variablenode_ns_0_i_15119_variant_DataContents[0].name = UA_STRING(chars: "ConfigurationVersion"); |
| 70599 | variablenode_ns_0_i_15119_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14593LU); |
| 70600 | variablenode_ns_0_i_15119_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 70601 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_15119_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 70602 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 70603 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70604 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15119LU), |
| 70605 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15118LU), |
| 70606 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70607 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 70608 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70609 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70610 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70611 | |
| 70612 | return retVal; |
| 70613 | #else |
| 70614 | return UA_STATUSCODE_GOOD; |
| 70615 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70616 | } |
| 70617 | |
| 70618 | static UA_StatusCode function_namespace0_generated_108_finish(UA_Server *server, UA_UInt16* ns) { |
| 70619 | #ifdef UA_ENABLE_METHODCALLS |
| 70620 | return UA_Server_addNode_finish(server, |
| 70621 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15119LU) |
| 70622 | ); |
| 70623 | #else |
| 70624 | return UA_STATUSCODE_GOOD; |
| 70625 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70626 | } |
| 70627 | |
| 70628 | /* AddTargetVariables - ns=0;i=15115 */ |
| 70629 | |
| 70630 | static UA_StatusCode function_namespace0_generated_109_begin(UA_Server *server, UA_UInt16* ns) { |
| 70631 | #ifdef UA_ENABLE_METHODCALLS |
| 70632 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70633 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 70634 | attr.executable = true; |
| 70635 | attr.userExecutable = true; |
| 70636 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddTargetVariables"); |
| 70637 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 70638 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15115LU), |
| 70639 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15108LU), |
| 70640 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 70641 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddTargetVariables"), |
| 70642 | typeDefinition: UA_NODEID_NULL, |
| 70643 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 70644 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70645 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15115LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15111LU), false); |
| 70646 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70647 | return retVal; |
| 70648 | #else |
| 70649 | return UA_STATUSCODE_GOOD; |
| 70650 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70651 | } |
| 70652 | |
| 70653 | static UA_StatusCode function_namespace0_generated_109_finish(UA_Server *server, UA_UInt16* ns) { |
| 70654 | #ifdef UA_ENABLE_METHODCALLS |
| 70655 | return UA_Server_addMethodNode_finish(server, |
| 70656 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15115LU) |
| 70657 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 70658 | #else |
| 70659 | return UA_STATUSCODE_GOOD; |
| 70660 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70661 | } |
| 70662 | |
| 70663 | /* OutputArguments - ns=0;i=15117 */ |
| 70664 | |
| 70665 | static UA_StatusCode function_namespace0_generated_110_begin(UA_Server *server, UA_UInt16* ns) { |
| 70666 | #ifdef UA_ENABLE_METHODCALLS |
| 70667 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70668 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70669 | attr.minimumSamplingInterval = 0.000000; |
| 70670 | attr.userAccessLevel = 1; |
| 70671 | attr.accessLevel = 1; |
| 70672 | attr.valueRank = 1; |
| 70673 | attr.arrayDimensionsSize = 1; |
| 70674 | UA_UInt32 arrayDimensions[1]; |
| 70675 | arrayDimensions[0] = 0; |
| 70676 | attr.arrayDimensions = &arrayDimensions[0]; |
| 70677 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 70678 | UA_Argument variablenode_ns_0_i_15117_variant_DataContents[1]; |
| 70679 | |
| 70680 | UA_init(p: &variablenode_ns_0_i_15117_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 70681 | variablenode_ns_0_i_15117_variant_DataContents[0].name = UA_STRING(chars: "AddResults"); |
| 70682 | variablenode_ns_0_i_15117_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU); |
| 70683 | variablenode_ns_0_i_15117_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 70684 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_15117_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 70685 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 70686 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70687 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15117LU), |
| 70688 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15115LU), |
| 70689 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70690 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 70691 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70692 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70693 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70694 | |
| 70695 | return retVal; |
| 70696 | #else |
| 70697 | return UA_STATUSCODE_GOOD; |
| 70698 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70699 | } |
| 70700 | |
| 70701 | static UA_StatusCode function_namespace0_generated_110_finish(UA_Server *server, UA_UInt16* ns) { |
| 70702 | #ifdef UA_ENABLE_METHODCALLS |
| 70703 | return UA_Server_addNode_finish(server, |
| 70704 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15117LU) |
| 70705 | ); |
| 70706 | #else |
| 70707 | return UA_STATUSCODE_GOOD; |
| 70708 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70709 | } |
| 70710 | |
| 70711 | /* InputArguments - ns=0;i=15116 */ |
| 70712 | |
| 70713 | static UA_StatusCode function_namespace0_generated_111_begin(UA_Server *server, UA_UInt16* ns) { |
| 70714 | #ifdef UA_ENABLE_METHODCALLS |
| 70715 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70716 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70717 | attr.minimumSamplingInterval = 0.000000; |
| 70718 | attr.userAccessLevel = 1; |
| 70719 | attr.accessLevel = 1; |
| 70720 | attr.valueRank = 1; |
| 70721 | attr.arrayDimensionsSize = 1; |
| 70722 | UA_UInt32 arrayDimensions[1]; |
| 70723 | arrayDimensions[0] = 0; |
| 70724 | attr.arrayDimensions = &arrayDimensions[0]; |
| 70725 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 70726 | UA_Argument variablenode_ns_0_i_15116_variant_DataContents[1]; |
| 70727 | |
| 70728 | UA_init(p: &variablenode_ns_0_i_15116_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 70729 | variablenode_ns_0_i_15116_variant_DataContents[0].name = UA_STRING(chars: "ConfigurationVersion"); |
| 70730 | variablenode_ns_0_i_15116_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14593LU); |
| 70731 | variablenode_ns_0_i_15116_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 70732 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_15116_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 70733 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 70734 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70735 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15116LU), |
| 70736 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15115LU), |
| 70737 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70738 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 70739 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70740 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70741 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70742 | |
| 70743 | return retVal; |
| 70744 | #else |
| 70745 | return UA_STATUSCODE_GOOD; |
| 70746 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70747 | } |
| 70748 | |
| 70749 | static UA_StatusCode function_namespace0_generated_111_finish(UA_Server *server, UA_UInt16* ns) { |
| 70750 | #ifdef UA_ENABLE_METHODCALLS |
| 70751 | return UA_Server_addNode_finish(server, |
| 70752 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15116LU) |
| 70753 | ); |
| 70754 | #else |
| 70755 | return UA_STATUSCODE_GOOD; |
| 70756 | #endif /* UA_ENABLE_METHODCALLS */ |
| 70757 | } |
| 70758 | |
| 70759 | /* TargetVariables - ns=0;i=15114 */ |
| 70760 | |
| 70761 | static UA_StatusCode function_namespace0_generated_112_begin(UA_Server *server, UA_UInt16* ns) { |
| 70762 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70763 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70764 | attr.minimumSamplingInterval = 0.000000; |
| 70765 | attr.userAccessLevel = 1; |
| 70766 | attr.accessLevel = 1; |
| 70767 | /* Value rank inherited */ |
| 70768 | attr.valueRank = -2; |
| 70769 | /* DataType inherited */ |
| 70770 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 70771 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TargetVariables"); |
| 70772 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70773 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15114LU), |
| 70774 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15111LU), |
| 70775 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70776 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TargetVariables"), |
| 70777 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70778 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70779 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70780 | return retVal; |
| 70781 | } |
| 70782 | |
| 70783 | static UA_StatusCode function_namespace0_generated_112_finish(UA_Server *server, UA_UInt16* ns) { |
| 70784 | return UA_Server_addNode_finish(server, |
| 70785 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15114LU) |
| 70786 | ); |
| 70787 | } |
| 70788 | |
| 70789 | /* DataSetReaderMessageType - ns=0;i=21104 */ |
| 70790 | |
| 70791 | static UA_StatusCode function_namespace0_generated_113_begin(UA_Server *server, UA_UInt16* ns) { |
| 70792 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70793 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 70794 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetReaderMessageType"); |
| 70795 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 70796 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21104LU), |
| 70797 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 70798 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70799 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetReaderMessageType"), |
| 70800 | typeDefinition: UA_NODEID_NULL, |
| 70801 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 70802 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70803 | return retVal; |
| 70804 | } |
| 70805 | |
| 70806 | static UA_StatusCode function_namespace0_generated_113_finish(UA_Server *server, UA_UInt16* ns) { |
| 70807 | return UA_Server_addNode_finish(server, |
| 70808 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21104LU) |
| 70809 | ); |
| 70810 | } |
| 70811 | |
| 70812 | /* UadpDataSetReaderMessageType - ns=0;i=21116 */ |
| 70813 | |
| 70814 | static UA_StatusCode function_namespace0_generated_114_begin(UA_Server *server, UA_UInt16* ns) { |
| 70815 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70816 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 70817 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UadpDataSetReaderMessageType"); |
| 70818 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 70819 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21116LU), |
| 70820 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21104LU), |
| 70821 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70822 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UadpDataSetReaderMessageType"), |
| 70823 | typeDefinition: UA_NODEID_NULL, |
| 70824 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 70825 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70826 | return retVal; |
| 70827 | } |
| 70828 | |
| 70829 | static UA_StatusCode function_namespace0_generated_114_finish(UA_Server *server, UA_UInt16* ns) { |
| 70830 | return UA_Server_addNode_finish(server, |
| 70831 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21116LU) |
| 70832 | ); |
| 70833 | } |
| 70834 | |
| 70835 | /* DataSetReaderTransportType - ns=0;i=15319 */ |
| 70836 | |
| 70837 | static UA_StatusCode function_namespace0_generated_115_begin(UA_Server *server, UA_UInt16* ns) { |
| 70838 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70839 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 70840 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetReaderTransportType"); |
| 70841 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 70842 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15319LU), |
| 70843 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 70844 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70845 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetReaderTransportType"), |
| 70846 | typeDefinition: UA_NODEID_NULL, |
| 70847 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 70848 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70849 | return retVal; |
| 70850 | } |
| 70851 | |
| 70852 | static UA_StatusCode function_namespace0_generated_115_finish(UA_Server *server, UA_UInt16* ns) { |
| 70853 | return UA_Server_addNode_finish(server, |
| 70854 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15319LU) |
| 70855 | ); |
| 70856 | } |
| 70857 | |
| 70858 | /* BrokerDataSetReaderTransportType - ns=0;i=21142 */ |
| 70859 | |
| 70860 | static UA_StatusCode function_namespace0_generated_116_begin(UA_Server *server, UA_UInt16* ns) { |
| 70861 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70862 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 70863 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BrokerDataSetReaderTransportType"); |
| 70864 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 70865 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21142LU), |
| 70866 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 70867 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70868 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BrokerDataSetReaderTransportType"), |
| 70869 | typeDefinition: UA_NODEID_NULL, |
| 70870 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 70871 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70872 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21142LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15319LU), false); |
| 70873 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70874 | return retVal; |
| 70875 | } |
| 70876 | |
| 70877 | static UA_StatusCode function_namespace0_generated_116_finish(UA_Server *server, UA_UInt16* ns) { |
| 70878 | return UA_Server_addNode_finish(server, |
| 70879 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21142LU) |
| 70880 | ); |
| 70881 | } |
| 70882 | |
| 70883 | /* DataSetReaderType - ns=0;i=15306 */ |
| 70884 | |
| 70885 | static UA_StatusCode function_namespace0_generated_117_begin(UA_Server *server, UA_UInt16* ns) { |
| 70886 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70887 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 70888 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetReaderType"); |
| 70889 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 70890 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 70891 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 70892 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 70893 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetReaderType"), |
| 70894 | typeDefinition: UA_NODEID_NULL, |
| 70895 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 70896 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70897 | return retVal; |
| 70898 | } |
| 70899 | |
| 70900 | static UA_StatusCode function_namespace0_generated_117_finish(UA_Server *server, UA_UInt16* ns) { |
| 70901 | return UA_Server_addNode_finish(server, |
| 70902 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU) |
| 70903 | ); |
| 70904 | } |
| 70905 | |
| 70906 | /* MessageSettings - ns=0;i=21103 */ |
| 70907 | |
| 70908 | static UA_StatusCode function_namespace0_generated_118_begin(UA_Server *server, UA_UInt16* ns) { |
| 70909 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70910 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 70911 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MessageSettings"); |
| 70912 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 70913 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21103LU), |
| 70914 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 70915 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 70916 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MessageSettings"), |
| 70917 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21104LU), |
| 70918 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 70919 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70920 | return retVal; |
| 70921 | } |
| 70922 | |
| 70923 | static UA_StatusCode function_namespace0_generated_118_finish(UA_Server *server, UA_UInt16* ns) { |
| 70924 | return UA_Server_addNode_finish(server, |
| 70925 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21103LU) |
| 70926 | ); |
| 70927 | } |
| 70928 | |
| 70929 | /* MessageReceiveTimeout - ns=0;i=21102 */ |
| 70930 | |
| 70931 | static UA_StatusCode function_namespace0_generated_119_begin(UA_Server *server, UA_UInt16* ns) { |
| 70932 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70933 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70934 | attr.minimumSamplingInterval = 0.000000; |
| 70935 | attr.userAccessLevel = 1; |
| 70936 | attr.accessLevel = 1; |
| 70937 | /* Value rank inherited */ |
| 70938 | attr.valueRank = -2; |
| 70939 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 70940 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MessageReceiveTimeout"); |
| 70941 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70942 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21102LU), |
| 70943 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 70944 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70945 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MessageReceiveTimeout"), |
| 70946 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70947 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70948 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70949 | return retVal; |
| 70950 | } |
| 70951 | |
| 70952 | static UA_StatusCode function_namespace0_generated_119_finish(UA_Server *server, UA_UInt16* ns) { |
| 70953 | return UA_Server_addNode_finish(server, |
| 70954 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21102LU) |
| 70955 | ); |
| 70956 | } |
| 70957 | |
| 70958 | /* DataSetFieldContentMask - ns=0;i=21101 */ |
| 70959 | |
| 70960 | static UA_StatusCode function_namespace0_generated_120_begin(UA_Server *server, UA_UInt16* ns) { |
| 70961 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70962 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70963 | attr.minimumSamplingInterval = 0.000000; |
| 70964 | attr.userAccessLevel = 1; |
| 70965 | attr.accessLevel = 1; |
| 70966 | /* Value rank inherited */ |
| 70967 | attr.valueRank = -2; |
| 70968 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15583LU); |
| 70969 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetFieldContentMask"); |
| 70970 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 70971 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21101LU), |
| 70972 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 70973 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 70974 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetFieldContentMask"), |
| 70975 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 70976 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 70977 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 70978 | return retVal; |
| 70979 | } |
| 70980 | |
| 70981 | static UA_StatusCode function_namespace0_generated_120_finish(UA_Server *server, UA_UInt16* ns) { |
| 70982 | return UA_Server_addNode_finish(server, |
| 70983 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21101LU) |
| 70984 | ); |
| 70985 | } |
| 70986 | |
| 70987 | /* DataSetMetaData - ns=0;i=21100 */ |
| 70988 | |
| 70989 | static UA_StatusCode function_namespace0_generated_121_begin(UA_Server *server, UA_UInt16* ns) { |
| 70990 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 70991 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 70992 | attr.minimumSamplingInterval = 0.000000; |
| 70993 | attr.userAccessLevel = 1; |
| 70994 | attr.accessLevel = 1; |
| 70995 | /* Value rank inherited */ |
| 70996 | attr.valueRank = -2; |
| 70997 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14523LU); |
| 70998 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetMetaData"); |
| 70999 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71000 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21100LU), |
| 71001 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 71002 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71003 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetMetaData"), |
| 71004 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71005 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71006 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71007 | return retVal; |
| 71008 | } |
| 71009 | |
| 71010 | static UA_StatusCode function_namespace0_generated_121_finish(UA_Server *server, UA_UInt16* ns) { |
| 71011 | return UA_Server_addNode_finish(server, |
| 71012 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21100LU) |
| 71013 | ); |
| 71014 | } |
| 71015 | |
| 71016 | /* DataSetWriterId - ns=0;i=21099 */ |
| 71017 | |
| 71018 | static UA_StatusCode function_namespace0_generated_122_begin(UA_Server *server, UA_UInt16* ns) { |
| 71019 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71020 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71021 | attr.minimumSamplingInterval = 0.000000; |
| 71022 | attr.userAccessLevel = 1; |
| 71023 | attr.accessLevel = 1; |
| 71024 | /* Value rank inherited */ |
| 71025 | attr.valueRank = -2; |
| 71026 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 71027 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetWriterId"); |
| 71028 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71029 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21099LU), |
| 71030 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 71031 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71032 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetWriterId"), |
| 71033 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71034 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71035 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71036 | return retVal; |
| 71037 | } |
| 71038 | |
| 71039 | static UA_StatusCode function_namespace0_generated_122_finish(UA_Server *server, UA_UInt16* ns) { |
| 71040 | return UA_Server_addNode_finish(server, |
| 71041 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21099LU) |
| 71042 | ); |
| 71043 | } |
| 71044 | |
| 71045 | /* WriterGroupId - ns=0;i=21098 */ |
| 71046 | |
| 71047 | static UA_StatusCode function_namespace0_generated_123_begin(UA_Server *server, UA_UInt16* ns) { |
| 71048 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71049 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71050 | attr.minimumSamplingInterval = 0.000000; |
| 71051 | attr.userAccessLevel = 1; |
| 71052 | attr.accessLevel = 1; |
| 71053 | /* Value rank inherited */ |
| 71054 | attr.valueRank = -2; |
| 71055 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 71056 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "WriterGroupId"); |
| 71057 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71058 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21098LU), |
| 71059 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 71060 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71061 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "WriterGroupId"), |
| 71062 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71063 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71064 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71065 | return retVal; |
| 71066 | } |
| 71067 | |
| 71068 | static UA_StatusCode function_namespace0_generated_123_finish(UA_Server *server, UA_UInt16* ns) { |
| 71069 | return UA_Server_addNode_finish(server, |
| 71070 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21098LU) |
| 71071 | ); |
| 71072 | } |
| 71073 | |
| 71074 | /* PublisherId - ns=0;i=21097 */ |
| 71075 | |
| 71076 | static UA_StatusCode function_namespace0_generated_124_begin(UA_Server *server, UA_UInt16* ns) { |
| 71077 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71078 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71079 | attr.minimumSamplingInterval = 0.000000; |
| 71080 | attr.userAccessLevel = 1; |
| 71081 | attr.accessLevel = 1; |
| 71082 | /* Value rank inherited */ |
| 71083 | attr.valueRank = -2; |
| 71084 | /* DataType inherited */ |
| 71085 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 71086 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublisherId"); |
| 71087 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71088 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21097LU), |
| 71089 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 71090 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71091 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublisherId"), |
| 71092 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71093 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71094 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71095 | return retVal; |
| 71096 | } |
| 71097 | |
| 71098 | static UA_StatusCode function_namespace0_generated_124_finish(UA_Server *server, UA_UInt16* ns) { |
| 71099 | return UA_Server_addNode_finish(server, |
| 71100 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21097LU) |
| 71101 | ); |
| 71102 | } |
| 71103 | |
| 71104 | /* DataSetReaderProperties - ns=0;i=17494 */ |
| 71105 | |
| 71106 | static UA_StatusCode function_namespace0_generated_125_begin(UA_Server *server, UA_UInt16* ns) { |
| 71107 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71108 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71109 | attr.minimumSamplingInterval = 0.000000; |
| 71110 | attr.userAccessLevel = 1; |
| 71111 | attr.accessLevel = 1; |
| 71112 | attr.valueRank = 1; |
| 71113 | attr.arrayDimensionsSize = 1; |
| 71114 | UA_UInt32 arrayDimensions[1]; |
| 71115 | arrayDimensions[0] = 0; |
| 71116 | attr.arrayDimensions = &arrayDimensions[0]; |
| 71117 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14533LU); |
| 71118 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetReaderProperties"); |
| 71119 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71120 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17494LU), |
| 71121 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 71122 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71123 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetReaderProperties"), |
| 71124 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71125 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71126 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71127 | return retVal; |
| 71128 | } |
| 71129 | |
| 71130 | static UA_StatusCode function_namespace0_generated_125_finish(UA_Server *server, UA_UInt16* ns) { |
| 71131 | return UA_Server_addNode_finish(server, |
| 71132 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17494LU) |
| 71133 | ); |
| 71134 | } |
| 71135 | |
| 71136 | /* SubscribedDataSet - ns=0;i=15316 */ |
| 71137 | |
| 71138 | static UA_StatusCode function_namespace0_generated_126_begin(UA_Server *server, UA_UInt16* ns) { |
| 71139 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71140 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 71141 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscribedDataSet"); |
| 71142 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 71143 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15316LU), |
| 71144 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 71145 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 71146 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscribedDataSet"), |
| 71147 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15108LU), |
| 71148 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 71149 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71150 | return retVal; |
| 71151 | } |
| 71152 | |
| 71153 | static UA_StatusCode function_namespace0_generated_126_finish(UA_Server *server, UA_UInt16* ns) { |
| 71154 | return UA_Server_addNode_finish(server, |
| 71155 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15316LU) |
| 71156 | ); |
| 71157 | } |
| 71158 | |
| 71159 | /* TransportSettings - ns=0;i=15311 */ |
| 71160 | |
| 71161 | static UA_StatusCode function_namespace0_generated_127_begin(UA_Server *server, UA_UInt16* ns) { |
| 71162 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71163 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 71164 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransportSettings"); |
| 71165 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 71166 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15311LU), |
| 71167 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 71168 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 71169 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransportSettings"), |
| 71170 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15319LU), |
| 71171 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 71172 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71173 | return retVal; |
| 71174 | } |
| 71175 | |
| 71176 | static UA_StatusCode function_namespace0_generated_127_finish(UA_Server *server, UA_UInt16* ns) { |
| 71177 | return UA_Server_addNode_finish(server, |
| 71178 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15311LU) |
| 71179 | ); |
| 71180 | } |
| 71181 | |
| 71182 | /* DataSetWriterMessageType - ns=0;i=21096 */ |
| 71183 | |
| 71184 | static UA_StatusCode function_namespace0_generated_128_begin(UA_Server *server, UA_UInt16* ns) { |
| 71185 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71186 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 71187 | attr.isAbstract = true; |
| 71188 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetWriterMessageType"); |
| 71189 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 71190 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21096LU), |
| 71191 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 71192 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 71193 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetWriterMessageType"), |
| 71194 | typeDefinition: UA_NODEID_NULL, |
| 71195 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 71196 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71197 | return retVal; |
| 71198 | } |
| 71199 | |
| 71200 | static UA_StatusCode function_namespace0_generated_128_finish(UA_Server *server, UA_UInt16* ns) { |
| 71201 | return UA_Server_addNode_finish(server, |
| 71202 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21096LU) |
| 71203 | ); |
| 71204 | } |
| 71205 | |
| 71206 | /* UadpDataSetWriterMessageType - ns=0;i=21111 */ |
| 71207 | |
| 71208 | static UA_StatusCode function_namespace0_generated_129_begin(UA_Server *server, UA_UInt16* ns) { |
| 71209 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71210 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 71211 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UadpDataSetWriterMessageType"); |
| 71212 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 71213 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21111LU), |
| 71214 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21096LU), |
| 71215 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 71216 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UadpDataSetWriterMessageType"), |
| 71217 | typeDefinition: UA_NODEID_NULL, |
| 71218 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 71219 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71220 | return retVal; |
| 71221 | } |
| 71222 | |
| 71223 | static UA_StatusCode function_namespace0_generated_129_finish(UA_Server *server, UA_UInt16* ns) { |
| 71224 | return UA_Server_addNode_finish(server, |
| 71225 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21111LU) |
| 71226 | ); |
| 71227 | } |
| 71228 | |
| 71229 | /* WriterGroupMessageType - ns=0;i=17998 */ |
| 71230 | |
| 71231 | static UA_StatusCode function_namespace0_generated_130_begin(UA_Server *server, UA_UInt16* ns) { |
| 71232 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71233 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 71234 | attr.isAbstract = true; |
| 71235 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "WriterGroupMessageType"); |
| 71236 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 71237 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17998LU), |
| 71238 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 71239 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 71240 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "WriterGroupMessageType"), |
| 71241 | typeDefinition: UA_NODEID_NULL, |
| 71242 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 71243 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71244 | return retVal; |
| 71245 | } |
| 71246 | |
| 71247 | static UA_StatusCode function_namespace0_generated_130_finish(UA_Server *server, UA_UInt16* ns) { |
| 71248 | return UA_Server_addNode_finish(server, |
| 71249 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17998LU) |
| 71250 | ); |
| 71251 | } |
| 71252 | |
| 71253 | /* UadpWriterGroupMessageType - ns=0;i=21105 */ |
| 71254 | |
| 71255 | static UA_StatusCode function_namespace0_generated_131_begin(UA_Server *server, UA_UInt16* ns) { |
| 71256 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71257 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 71258 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UadpWriterGroupMessageType"); |
| 71259 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 71260 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21105LU), |
| 71261 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17998LU), |
| 71262 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 71263 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UadpWriterGroupMessageType"), |
| 71264 | typeDefinition: UA_NODEID_NULL, |
| 71265 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 71266 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71267 | return retVal; |
| 71268 | } |
| 71269 | |
| 71270 | static UA_StatusCode function_namespace0_generated_131_finish(UA_Server *server, UA_UInt16* ns) { |
| 71271 | return UA_Server_addNode_finish(server, |
| 71272 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21105LU) |
| 71273 | ); |
| 71274 | } |
| 71275 | |
| 71276 | /* SelectionListType - ns=0;i=16309 */ |
| 71277 | |
| 71278 | static UA_StatusCode function_namespace0_generated_132_begin(UA_Server *server, UA_UInt16* ns) { |
| 71279 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71280 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 71281 | attr.valueRank = -2; |
| 71282 | /* DataType inherited */ |
| 71283 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 71284 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SelectionListType"); |
| 71285 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 71286 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16309LU), |
| 71287 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 71288 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 71289 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SelectionListType"), |
| 71290 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 71291 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 71292 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71293 | return retVal; |
| 71294 | } |
| 71295 | |
| 71296 | static UA_StatusCode function_namespace0_generated_132_finish(UA_Server *server, UA_UInt16* ns) { |
| 71297 | return UA_Server_addNode_finish(server, |
| 71298 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16309LU) |
| 71299 | ); |
| 71300 | } |
| 71301 | |
| 71302 | /* SelectionDescriptions - ns=0;i=17633 */ |
| 71303 | |
| 71304 | static UA_StatusCode function_namespace0_generated_133_begin(UA_Server *server, UA_UInt16* ns) { |
| 71305 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71306 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71307 | attr.minimumSamplingInterval = 0.000000; |
| 71308 | attr.userAccessLevel = 1; |
| 71309 | attr.accessLevel = 1; |
| 71310 | attr.valueRank = 1; |
| 71311 | attr.arrayDimensionsSize = 1; |
| 71312 | UA_UInt32 arrayDimensions[1]; |
| 71313 | arrayDimensions[0] = 0; |
| 71314 | attr.arrayDimensions = &arrayDimensions[0]; |
| 71315 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 71316 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SelectionDescriptions"); |
| 71317 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71318 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17633LU), |
| 71319 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16309LU), |
| 71320 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71321 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SelectionDescriptions"), |
| 71322 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71323 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71324 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71325 | return retVal; |
| 71326 | } |
| 71327 | |
| 71328 | static UA_StatusCode function_namespace0_generated_133_finish(UA_Server *server, UA_UInt16* ns) { |
| 71329 | return UA_Server_addNode_finish(server, |
| 71330 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17633LU) |
| 71331 | ); |
| 71332 | } |
| 71333 | |
| 71334 | /* Selections - ns=0;i=17632 */ |
| 71335 | |
| 71336 | static UA_StatusCode function_namespace0_generated_134_begin(UA_Server *server, UA_UInt16* ns) { |
| 71337 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71338 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71339 | attr.minimumSamplingInterval = 0.000000; |
| 71340 | attr.userAccessLevel = 1; |
| 71341 | attr.accessLevel = 1; |
| 71342 | attr.valueRank = 1; |
| 71343 | attr.arrayDimensionsSize = 1; |
| 71344 | UA_UInt32 arrayDimensions[1]; |
| 71345 | arrayDimensions[0] = 0; |
| 71346 | attr.arrayDimensions = &arrayDimensions[0]; |
| 71347 | /* DataType inherited */ |
| 71348 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 71349 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Selections"); |
| 71350 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71351 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17632LU), |
| 71352 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16309LU), |
| 71353 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71354 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Selections"), |
| 71355 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71356 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71357 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71358 | return retVal; |
| 71359 | } |
| 71360 | |
| 71361 | static UA_StatusCode function_namespace0_generated_134_finish(UA_Server *server, UA_UInt16* ns) { |
| 71362 | return UA_Server_addNode_finish(server, |
| 71363 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17632LU) |
| 71364 | ); |
| 71365 | } |
| 71366 | |
| 71367 | /* RestrictToList - ns=0;i=16312 */ |
| 71368 | |
| 71369 | static UA_StatusCode function_namespace0_generated_135_begin(UA_Server *server, UA_UInt16* ns) { |
| 71370 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71371 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71372 | attr.minimumSamplingInterval = 0.000000; |
| 71373 | attr.userAccessLevel = 1; |
| 71374 | attr.accessLevel = 1; |
| 71375 | /* Value rank inherited */ |
| 71376 | attr.valueRank = -2; |
| 71377 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 71378 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RestrictToList"); |
| 71379 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71380 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16312LU), |
| 71381 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16309LU), |
| 71382 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71383 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RestrictToList"), |
| 71384 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71385 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71386 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71387 | return retVal; |
| 71388 | } |
| 71389 | |
| 71390 | static UA_StatusCode function_namespace0_generated_135_finish(UA_Server *server, UA_UInt16* ns) { |
| 71391 | return UA_Server_addNode_finish(server, |
| 71392 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16312LU) |
| 71393 | ); |
| 71394 | } |
| 71395 | |
| 71396 | /* PubSubStatusType - ns=0;i=14643 */ |
| 71397 | |
| 71398 | static UA_StatusCode function_namespace0_generated_136_begin(UA_Server *server, UA_UInt16* ns) { |
| 71399 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71400 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 71401 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PubSubStatusType"); |
| 71402 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 71403 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14643LU), |
| 71404 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 71405 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 71406 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PubSubStatusType"), |
| 71407 | typeDefinition: UA_NODEID_NULL, |
| 71408 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 71409 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71410 | return retVal; |
| 71411 | } |
| 71412 | |
| 71413 | static UA_StatusCode function_namespace0_generated_136_finish(UA_Server *server, UA_UInt16* ns) { |
| 71414 | return UA_Server_addNode_finish(server, |
| 71415 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14643LU) |
| 71416 | ); |
| 71417 | } |
| 71418 | |
| 71419 | /* Disable - ns=0;i=14646 */ |
| 71420 | |
| 71421 | static UA_StatusCode function_namespace0_generated_137_begin(UA_Server *server, UA_UInt16* ns) { |
| 71422 | #ifdef UA_ENABLE_METHODCALLS |
| 71423 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71424 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 71425 | attr.executable = true; |
| 71426 | attr.userExecutable = true; |
| 71427 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Disable"); |
| 71428 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 71429 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14646LU), |
| 71430 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14643LU), |
| 71431 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 71432 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Disable"), |
| 71433 | typeDefinition: UA_NODEID_NULL, |
| 71434 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 71435 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71436 | return retVal; |
| 71437 | #else |
| 71438 | return UA_STATUSCODE_GOOD; |
| 71439 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71440 | } |
| 71441 | |
| 71442 | static UA_StatusCode function_namespace0_generated_137_finish(UA_Server *server, UA_UInt16* ns) { |
| 71443 | #ifdef UA_ENABLE_METHODCALLS |
| 71444 | return UA_Server_addMethodNode_finish(server, |
| 71445 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14646LU) |
| 71446 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 71447 | #else |
| 71448 | return UA_STATUSCODE_GOOD; |
| 71449 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71450 | } |
| 71451 | |
| 71452 | /* Enable - ns=0;i=14645 */ |
| 71453 | |
| 71454 | static UA_StatusCode function_namespace0_generated_138_begin(UA_Server *server, UA_UInt16* ns) { |
| 71455 | #ifdef UA_ENABLE_METHODCALLS |
| 71456 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71457 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 71458 | attr.executable = true; |
| 71459 | attr.userExecutable = true; |
| 71460 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Enable"); |
| 71461 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 71462 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14645LU), |
| 71463 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14643LU), |
| 71464 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 71465 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Enable"), |
| 71466 | typeDefinition: UA_NODEID_NULL, |
| 71467 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 71468 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71469 | return retVal; |
| 71470 | #else |
| 71471 | return UA_STATUSCODE_GOOD; |
| 71472 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71473 | } |
| 71474 | |
| 71475 | static UA_StatusCode function_namespace0_generated_138_finish(UA_Server *server, UA_UInt16* ns) { |
| 71476 | #ifdef UA_ENABLE_METHODCALLS |
| 71477 | return UA_Server_addMethodNode_finish(server, |
| 71478 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14645LU) |
| 71479 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 71480 | #else |
| 71481 | return UA_STATUSCODE_GOOD; |
| 71482 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71483 | } |
| 71484 | |
| 71485 | /* State - ns=0;i=14644 */ |
| 71486 | |
| 71487 | static UA_StatusCode function_namespace0_generated_139_begin(UA_Server *server, UA_UInt16* ns) { |
| 71488 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71489 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71490 | attr.minimumSamplingInterval = 0.000000; |
| 71491 | attr.userAccessLevel = 1; |
| 71492 | attr.accessLevel = 1; |
| 71493 | /* Value rank inherited */ |
| 71494 | attr.valueRank = -2; |
| 71495 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14647LU); |
| 71496 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "State"); |
| 71497 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71498 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14644LU), |
| 71499 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14643LU), |
| 71500 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 71501 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "State"), |
| 71502 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 71503 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71504 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71505 | return retVal; |
| 71506 | } |
| 71507 | |
| 71508 | static UA_StatusCode function_namespace0_generated_139_finish(UA_Server *server, UA_UInt16* ns) { |
| 71509 | return UA_Server_addNode_finish(server, |
| 71510 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14644LU) |
| 71511 | ); |
| 71512 | } |
| 71513 | |
| 71514 | /* StandaloneSubscribedDataSetType - ns=0;i=23828 */ |
| 71515 | |
| 71516 | static UA_StatusCode function_namespace0_generated_140_begin(UA_Server *server, UA_UInt16* ns) { |
| 71517 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71518 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 71519 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "StandaloneSubscribedDataSetType"); |
| 71520 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 71521 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23828LU), |
| 71522 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 71523 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 71524 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "StandaloneSubscribedDataSetType"), |
| 71525 | typeDefinition: UA_NODEID_NULL, |
| 71526 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 71527 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71528 | return retVal; |
| 71529 | } |
| 71530 | |
| 71531 | static UA_StatusCode function_namespace0_generated_140_finish(UA_Server *server, UA_UInt16* ns) { |
| 71532 | return UA_Server_addNode_finish(server, |
| 71533 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23828LU) |
| 71534 | ); |
| 71535 | } |
| 71536 | |
| 71537 | /* IsConnected - ns=0;i=23831 */ |
| 71538 | |
| 71539 | static UA_StatusCode function_namespace0_generated_141_begin(UA_Server *server, UA_UInt16* ns) { |
| 71540 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71541 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71542 | attr.minimumSamplingInterval = 0.000000; |
| 71543 | attr.userAccessLevel = 1; |
| 71544 | attr.accessLevel = 1; |
| 71545 | /* Value rank inherited */ |
| 71546 | attr.valueRank = -2; |
| 71547 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 71548 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "IsConnected"); |
| 71549 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71550 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23831LU), |
| 71551 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23828LU), |
| 71552 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71553 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "IsConnected"), |
| 71554 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71555 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71556 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71557 | return retVal; |
| 71558 | } |
| 71559 | |
| 71560 | static UA_StatusCode function_namespace0_generated_141_finish(UA_Server *server, UA_UInt16* ns) { |
| 71561 | return UA_Server_addNode_finish(server, |
| 71562 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23831LU) |
| 71563 | ); |
| 71564 | } |
| 71565 | |
| 71566 | /* DataSetMetaData - ns=0;i=23830 */ |
| 71567 | |
| 71568 | static UA_StatusCode function_namespace0_generated_142_begin(UA_Server *server, UA_UInt16* ns) { |
| 71569 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71570 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71571 | attr.minimumSamplingInterval = 0.000000; |
| 71572 | attr.userAccessLevel = 1; |
| 71573 | attr.accessLevel = 1; |
| 71574 | /* Value rank inherited */ |
| 71575 | attr.valueRank = -2; |
| 71576 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14523LU); |
| 71577 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetMetaData"); |
| 71578 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71579 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23830LU), |
| 71580 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23828LU), |
| 71581 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71582 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetMetaData"), |
| 71583 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71584 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71585 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71586 | return retVal; |
| 71587 | } |
| 71588 | |
| 71589 | static UA_StatusCode function_namespace0_generated_142_finish(UA_Server *server, UA_UInt16* ns) { |
| 71590 | return UA_Server_addNode_finish(server, |
| 71591 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23830LU) |
| 71592 | ); |
| 71593 | } |
| 71594 | |
| 71595 | /* SubscribedDataSet - ns=0;i=23829 */ |
| 71596 | |
| 71597 | static UA_StatusCode function_namespace0_generated_143_begin(UA_Server *server, UA_UInt16* ns) { |
| 71598 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71599 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 71600 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscribedDataSet"); |
| 71601 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 71602 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23829LU), |
| 71603 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23828LU), |
| 71604 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 71605 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscribedDataSet"), |
| 71606 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15108LU), |
| 71607 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 71608 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71609 | return retVal; |
| 71610 | } |
| 71611 | |
| 71612 | static UA_StatusCode function_namespace0_generated_143_finish(UA_Server *server, UA_UInt16* ns) { |
| 71613 | return UA_Server_addNode_finish(server, |
| 71614 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23829LU) |
| 71615 | ); |
| 71616 | } |
| 71617 | |
| 71618 | /* SubscribedDataSetFolderType - ns=0;i=23795 */ |
| 71619 | |
| 71620 | static UA_StatusCode function_namespace0_generated_144_begin(UA_Server *server, UA_UInt16* ns) { |
| 71621 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71622 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 71623 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscribedDataSetFolderType"); |
| 71624 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 71625 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU), |
| 71626 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU), |
| 71627 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 71628 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscribedDataSetFolderType"), |
| 71629 | typeDefinition: UA_NODEID_NULL, |
| 71630 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 71631 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71632 | return retVal; |
| 71633 | } |
| 71634 | |
| 71635 | static UA_StatusCode function_namespace0_generated_144_finish(UA_Server *server, UA_UInt16* ns) { |
| 71636 | return UA_Server_addNode_finish(server, |
| 71637 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU) |
| 71638 | ); |
| 71639 | } |
| 71640 | |
| 71641 | /* RemoveDataSetFolder - ns=0;i=23819 */ |
| 71642 | |
| 71643 | static UA_StatusCode function_namespace0_generated_145_begin(UA_Server *server, UA_UInt16* ns) { |
| 71644 | #ifdef UA_ENABLE_METHODCALLS |
| 71645 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71646 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 71647 | attr.executable = true; |
| 71648 | attr.userExecutable = true; |
| 71649 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveDataSetFolder"); |
| 71650 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 71651 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23819LU), |
| 71652 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU), |
| 71653 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 71654 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveDataSetFolder"), |
| 71655 | typeDefinition: UA_NODEID_NULL, |
| 71656 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 71657 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71658 | return retVal; |
| 71659 | #else |
| 71660 | return UA_STATUSCODE_GOOD; |
| 71661 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71662 | } |
| 71663 | |
| 71664 | static UA_StatusCode function_namespace0_generated_145_finish(UA_Server *server, UA_UInt16* ns) { |
| 71665 | #ifdef UA_ENABLE_METHODCALLS |
| 71666 | return UA_Server_addMethodNode_finish(server, |
| 71667 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23819LU) |
| 71668 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 71669 | #else |
| 71670 | return UA_STATUSCODE_GOOD; |
| 71671 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71672 | } |
| 71673 | |
| 71674 | /* InputArguments - ns=0;i=23820 */ |
| 71675 | |
| 71676 | static UA_StatusCode function_namespace0_generated_146_begin(UA_Server *server, UA_UInt16* ns) { |
| 71677 | #ifdef UA_ENABLE_METHODCALLS |
| 71678 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71679 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71680 | attr.minimumSamplingInterval = 0.000000; |
| 71681 | attr.userAccessLevel = 1; |
| 71682 | attr.accessLevel = 1; |
| 71683 | attr.valueRank = 1; |
| 71684 | attr.arrayDimensionsSize = 1; |
| 71685 | UA_UInt32 arrayDimensions[1]; |
| 71686 | arrayDimensions[0] = 1; |
| 71687 | attr.arrayDimensions = &arrayDimensions[0]; |
| 71688 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 71689 | UA_Argument variablenode_ns_0_i_23820_variant_DataContents[1]; |
| 71690 | |
| 71691 | UA_init(p: &variablenode_ns_0_i_23820_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 71692 | variablenode_ns_0_i_23820_variant_DataContents[0].name = UA_STRING(chars: "DataSetFolderNodeId"); |
| 71693 | variablenode_ns_0_i_23820_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 71694 | variablenode_ns_0_i_23820_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 71695 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23820_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 71696 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 71697 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71698 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23820LU), |
| 71699 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23819LU), |
| 71700 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71701 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 71702 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71703 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71704 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71705 | |
| 71706 | return retVal; |
| 71707 | #else |
| 71708 | return UA_STATUSCODE_GOOD; |
| 71709 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71710 | } |
| 71711 | |
| 71712 | static UA_StatusCode function_namespace0_generated_146_finish(UA_Server *server, UA_UInt16* ns) { |
| 71713 | #ifdef UA_ENABLE_METHODCALLS |
| 71714 | return UA_Server_addNode_finish(server, |
| 71715 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23820LU) |
| 71716 | ); |
| 71717 | #else |
| 71718 | return UA_STATUSCODE_GOOD; |
| 71719 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71720 | } |
| 71721 | |
| 71722 | /* AddDataSetFolder - ns=0;i=23816 */ |
| 71723 | |
| 71724 | static UA_StatusCode function_namespace0_generated_147_begin(UA_Server *server, UA_UInt16* ns) { |
| 71725 | #ifdef UA_ENABLE_METHODCALLS |
| 71726 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71727 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 71728 | attr.executable = true; |
| 71729 | attr.userExecutable = true; |
| 71730 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddDataSetFolder"); |
| 71731 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 71732 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23816LU), |
| 71733 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU), |
| 71734 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 71735 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddDataSetFolder"), |
| 71736 | typeDefinition: UA_NODEID_NULL, |
| 71737 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 71738 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71739 | return retVal; |
| 71740 | #else |
| 71741 | return UA_STATUSCODE_GOOD; |
| 71742 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71743 | } |
| 71744 | |
| 71745 | static UA_StatusCode function_namespace0_generated_147_finish(UA_Server *server, UA_UInt16* ns) { |
| 71746 | #ifdef UA_ENABLE_METHODCALLS |
| 71747 | return UA_Server_addMethodNode_finish(server, |
| 71748 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23816LU) |
| 71749 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 71750 | #else |
| 71751 | return UA_STATUSCODE_GOOD; |
| 71752 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71753 | } |
| 71754 | |
| 71755 | /* OutputArguments - ns=0;i=23818 */ |
| 71756 | |
| 71757 | static UA_StatusCode function_namespace0_generated_148_begin(UA_Server *server, UA_UInt16* ns) { |
| 71758 | #ifdef UA_ENABLE_METHODCALLS |
| 71759 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71760 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71761 | attr.minimumSamplingInterval = 0.000000; |
| 71762 | attr.userAccessLevel = 1; |
| 71763 | attr.accessLevel = 1; |
| 71764 | attr.valueRank = 1; |
| 71765 | attr.arrayDimensionsSize = 1; |
| 71766 | UA_UInt32 arrayDimensions[1]; |
| 71767 | arrayDimensions[0] = 1; |
| 71768 | attr.arrayDimensions = &arrayDimensions[0]; |
| 71769 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 71770 | UA_Argument variablenode_ns_0_i_23818_variant_DataContents[1]; |
| 71771 | |
| 71772 | UA_init(p: &variablenode_ns_0_i_23818_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 71773 | variablenode_ns_0_i_23818_variant_DataContents[0].name = UA_STRING(chars: "DataSetFolderNodeId"); |
| 71774 | variablenode_ns_0_i_23818_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 71775 | variablenode_ns_0_i_23818_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 71776 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23818_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 71777 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 71778 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71779 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23818LU), |
| 71780 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23816LU), |
| 71781 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71782 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 71783 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71784 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71785 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71786 | |
| 71787 | return retVal; |
| 71788 | #else |
| 71789 | return UA_STATUSCODE_GOOD; |
| 71790 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71791 | } |
| 71792 | |
| 71793 | static UA_StatusCode function_namespace0_generated_148_finish(UA_Server *server, UA_UInt16* ns) { |
| 71794 | #ifdef UA_ENABLE_METHODCALLS |
| 71795 | return UA_Server_addNode_finish(server, |
| 71796 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23818LU) |
| 71797 | ); |
| 71798 | #else |
| 71799 | return UA_STATUSCODE_GOOD; |
| 71800 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71801 | } |
| 71802 | |
| 71803 | /* InputArguments - ns=0;i=23817 */ |
| 71804 | |
| 71805 | static UA_StatusCode function_namespace0_generated_149_begin(UA_Server *server, UA_UInt16* ns) { |
| 71806 | #ifdef UA_ENABLE_METHODCALLS |
| 71807 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71808 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71809 | attr.minimumSamplingInterval = 0.000000; |
| 71810 | attr.userAccessLevel = 1; |
| 71811 | attr.accessLevel = 1; |
| 71812 | attr.valueRank = 1; |
| 71813 | attr.arrayDimensionsSize = 1; |
| 71814 | UA_UInt32 arrayDimensions[1]; |
| 71815 | arrayDimensions[0] = 1; |
| 71816 | attr.arrayDimensions = &arrayDimensions[0]; |
| 71817 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 71818 | UA_Argument variablenode_ns_0_i_23817_variant_DataContents[1]; |
| 71819 | |
| 71820 | UA_init(p: &variablenode_ns_0_i_23817_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 71821 | variablenode_ns_0_i_23817_variant_DataContents[0].name = UA_STRING(chars: "Name"); |
| 71822 | variablenode_ns_0_i_23817_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 71823 | variablenode_ns_0_i_23817_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 71824 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23817_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 71825 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 71826 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71827 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23817LU), |
| 71828 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23816LU), |
| 71829 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71830 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 71831 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71832 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71833 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71834 | |
| 71835 | return retVal; |
| 71836 | #else |
| 71837 | return UA_STATUSCODE_GOOD; |
| 71838 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71839 | } |
| 71840 | |
| 71841 | static UA_StatusCode function_namespace0_generated_149_finish(UA_Server *server, UA_UInt16* ns) { |
| 71842 | #ifdef UA_ENABLE_METHODCALLS |
| 71843 | return UA_Server_addNode_finish(server, |
| 71844 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23817LU) |
| 71845 | ); |
| 71846 | #else |
| 71847 | return UA_STATUSCODE_GOOD; |
| 71848 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71849 | } |
| 71850 | |
| 71851 | /* RemoveSubscribedDataSet - ns=0;i=23814 */ |
| 71852 | |
| 71853 | static UA_StatusCode function_namespace0_generated_150_begin(UA_Server *server, UA_UInt16* ns) { |
| 71854 | #ifdef UA_ENABLE_METHODCALLS |
| 71855 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71856 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 71857 | attr.executable = true; |
| 71858 | attr.userExecutable = true; |
| 71859 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveSubscribedDataSet"); |
| 71860 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 71861 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23814LU), |
| 71862 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU), |
| 71863 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 71864 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveSubscribedDataSet"), |
| 71865 | typeDefinition: UA_NODEID_NULL, |
| 71866 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 71867 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71868 | return retVal; |
| 71869 | #else |
| 71870 | return UA_STATUSCODE_GOOD; |
| 71871 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71872 | } |
| 71873 | |
| 71874 | static UA_StatusCode function_namespace0_generated_150_finish(UA_Server *server, UA_UInt16* ns) { |
| 71875 | #ifdef UA_ENABLE_METHODCALLS |
| 71876 | return UA_Server_addMethodNode_finish(server, |
| 71877 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23814LU) |
| 71878 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 71879 | #else |
| 71880 | return UA_STATUSCODE_GOOD; |
| 71881 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71882 | } |
| 71883 | |
| 71884 | /* InputArguments - ns=0;i=23815 */ |
| 71885 | |
| 71886 | static UA_StatusCode function_namespace0_generated_151_begin(UA_Server *server, UA_UInt16* ns) { |
| 71887 | #ifdef UA_ENABLE_METHODCALLS |
| 71888 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71889 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71890 | attr.minimumSamplingInterval = 0.000000; |
| 71891 | attr.userAccessLevel = 1; |
| 71892 | attr.accessLevel = 1; |
| 71893 | attr.valueRank = 1; |
| 71894 | attr.arrayDimensionsSize = 1; |
| 71895 | UA_UInt32 arrayDimensions[1]; |
| 71896 | arrayDimensions[0] = 1; |
| 71897 | attr.arrayDimensions = &arrayDimensions[0]; |
| 71898 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 71899 | UA_Argument variablenode_ns_0_i_23815_variant_DataContents[1]; |
| 71900 | |
| 71901 | UA_init(p: &variablenode_ns_0_i_23815_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 71902 | variablenode_ns_0_i_23815_variant_DataContents[0].name = UA_STRING(chars: "SubscribedDataSetNodeId"); |
| 71903 | variablenode_ns_0_i_23815_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 71904 | variablenode_ns_0_i_23815_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 71905 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23815_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 71906 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 71907 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71908 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23815LU), |
| 71909 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23814LU), |
| 71910 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71911 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 71912 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71913 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71914 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71915 | |
| 71916 | return retVal; |
| 71917 | #else |
| 71918 | return UA_STATUSCODE_GOOD; |
| 71919 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71920 | } |
| 71921 | |
| 71922 | static UA_StatusCode function_namespace0_generated_151_finish(UA_Server *server, UA_UInt16* ns) { |
| 71923 | #ifdef UA_ENABLE_METHODCALLS |
| 71924 | return UA_Server_addNode_finish(server, |
| 71925 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23815LU) |
| 71926 | ); |
| 71927 | #else |
| 71928 | return UA_STATUSCODE_GOOD; |
| 71929 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71930 | } |
| 71931 | |
| 71932 | /* AddSubscribedDataSet - ns=0;i=23811 */ |
| 71933 | |
| 71934 | static UA_StatusCode function_namespace0_generated_152_begin(UA_Server *server, UA_UInt16* ns) { |
| 71935 | #ifdef UA_ENABLE_METHODCALLS |
| 71936 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71937 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 71938 | attr.executable = true; |
| 71939 | attr.userExecutable = true; |
| 71940 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddSubscribedDataSet"); |
| 71941 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 71942 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23811LU), |
| 71943 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU), |
| 71944 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 71945 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddSubscribedDataSet"), |
| 71946 | typeDefinition: UA_NODEID_NULL, |
| 71947 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 71948 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71949 | return retVal; |
| 71950 | #else |
| 71951 | return UA_STATUSCODE_GOOD; |
| 71952 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71953 | } |
| 71954 | |
| 71955 | static UA_StatusCode function_namespace0_generated_152_finish(UA_Server *server, UA_UInt16* ns) { |
| 71956 | #ifdef UA_ENABLE_METHODCALLS |
| 71957 | return UA_Server_addMethodNode_finish(server, |
| 71958 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23811LU) |
| 71959 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 71960 | #else |
| 71961 | return UA_STATUSCODE_GOOD; |
| 71962 | #endif /* UA_ENABLE_METHODCALLS */ |
| 71963 | } |
| 71964 | |
| 71965 | /* OutputArguments - ns=0;i=23813 */ |
| 71966 | |
| 71967 | static UA_StatusCode function_namespace0_generated_153_begin(UA_Server *server, UA_UInt16* ns) { |
| 71968 | #ifdef UA_ENABLE_METHODCALLS |
| 71969 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 71970 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 71971 | attr.minimumSamplingInterval = 0.000000; |
| 71972 | attr.userAccessLevel = 1; |
| 71973 | attr.accessLevel = 1; |
| 71974 | attr.valueRank = 1; |
| 71975 | attr.arrayDimensionsSize = 1; |
| 71976 | UA_UInt32 arrayDimensions[1]; |
| 71977 | arrayDimensions[0] = 1; |
| 71978 | attr.arrayDimensions = &arrayDimensions[0]; |
| 71979 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 71980 | UA_Argument variablenode_ns_0_i_23813_variant_DataContents[1]; |
| 71981 | |
| 71982 | UA_init(p: &variablenode_ns_0_i_23813_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 71983 | variablenode_ns_0_i_23813_variant_DataContents[0].name = UA_STRING(chars: "SubscribedDataSetNodeId"); |
| 71984 | variablenode_ns_0_i_23813_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 71985 | variablenode_ns_0_i_23813_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 71986 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23813_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 71987 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 71988 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 71989 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23813LU), |
| 71990 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23811LU), |
| 71991 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 71992 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 71993 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 71994 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 71995 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 71996 | |
| 71997 | return retVal; |
| 71998 | #else |
| 71999 | return UA_STATUSCODE_GOOD; |
| 72000 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72001 | } |
| 72002 | |
| 72003 | static UA_StatusCode function_namespace0_generated_153_finish(UA_Server *server, UA_UInt16* ns) { |
| 72004 | #ifdef UA_ENABLE_METHODCALLS |
| 72005 | return UA_Server_addNode_finish(server, |
| 72006 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23813LU) |
| 72007 | ); |
| 72008 | #else |
| 72009 | return UA_STATUSCODE_GOOD; |
| 72010 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72011 | } |
| 72012 | |
| 72013 | /* InputArguments - ns=0;i=23812 */ |
| 72014 | |
| 72015 | static UA_StatusCode function_namespace0_generated_154_begin(UA_Server *server, UA_UInt16* ns) { |
| 72016 | #ifdef UA_ENABLE_METHODCALLS |
| 72017 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72018 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72019 | attr.minimumSamplingInterval = 0.000000; |
| 72020 | attr.userAccessLevel = 1; |
| 72021 | attr.accessLevel = 1; |
| 72022 | attr.valueRank = 1; |
| 72023 | attr.arrayDimensionsSize = 1; |
| 72024 | UA_UInt32 arrayDimensions[1]; |
| 72025 | arrayDimensions[0] = 1; |
| 72026 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72027 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 72028 | UA_Argument variablenode_ns_0_i_23812_variant_DataContents[1]; |
| 72029 | |
| 72030 | UA_init(p: &variablenode_ns_0_i_23812_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72031 | variablenode_ns_0_i_23812_variant_DataContents[0].name = UA_STRING(chars: "SubscribedDataSet"); |
| 72032 | variablenode_ns_0_i_23812_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23600LU); |
| 72033 | variablenode_ns_0_i_23812_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 72034 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23812_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72035 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 72036 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72037 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23812LU), |
| 72038 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23811LU), |
| 72039 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72040 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 72041 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72042 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72043 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72044 | |
| 72045 | return retVal; |
| 72046 | #else |
| 72047 | return UA_STATUSCODE_GOOD; |
| 72048 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72049 | } |
| 72050 | |
| 72051 | static UA_StatusCode function_namespace0_generated_154_finish(UA_Server *server, UA_UInt16* ns) { |
| 72052 | #ifdef UA_ENABLE_METHODCALLS |
| 72053 | return UA_Server_addNode_finish(server, |
| 72054 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23812LU) |
| 72055 | ); |
| 72056 | #else |
| 72057 | return UA_STATUSCODE_GOOD; |
| 72058 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72059 | } |
| 72060 | |
| 72061 | /* <StandaloneSubscribedDataSetName> - ns=0;i=23807 */ |
| 72062 | |
| 72063 | static UA_StatusCode function_namespace0_generated_155_begin(UA_Server *server, UA_UInt16* ns) { |
| 72064 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72065 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 72066 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "<StandaloneSubscribedDataSetName>"); |
| 72067 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 72068 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23807LU), |
| 72069 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU), |
| 72070 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 72071 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "<StandaloneSubscribedDataSetName>"), |
| 72072 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23828LU), |
| 72073 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 72074 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72075 | return retVal; |
| 72076 | } |
| 72077 | |
| 72078 | static UA_StatusCode function_namespace0_generated_155_finish(UA_Server *server, UA_UInt16* ns) { |
| 72079 | return UA_Server_addNode_finish(server, |
| 72080 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23807LU) |
| 72081 | ); |
| 72082 | } |
| 72083 | |
| 72084 | /* IsConnected - ns=0;i=23810 */ |
| 72085 | |
| 72086 | static UA_StatusCode function_namespace0_generated_156_begin(UA_Server *server, UA_UInt16* ns) { |
| 72087 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72088 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72089 | attr.minimumSamplingInterval = 0.000000; |
| 72090 | attr.userAccessLevel = 1; |
| 72091 | attr.accessLevel = 1; |
| 72092 | /* Value rank inherited */ |
| 72093 | attr.valueRank = -2; |
| 72094 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 72095 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "IsConnected"); |
| 72096 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72097 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23810LU), |
| 72098 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23807LU), |
| 72099 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72100 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "IsConnected"), |
| 72101 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72102 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72103 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72104 | return retVal; |
| 72105 | } |
| 72106 | |
| 72107 | static UA_StatusCode function_namespace0_generated_156_finish(UA_Server *server, UA_UInt16* ns) { |
| 72108 | return UA_Server_addNode_finish(server, |
| 72109 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23810LU) |
| 72110 | ); |
| 72111 | } |
| 72112 | |
| 72113 | /* DataSetMetaData - ns=0;i=23809 */ |
| 72114 | |
| 72115 | static UA_StatusCode function_namespace0_generated_157_begin(UA_Server *server, UA_UInt16* ns) { |
| 72116 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72117 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72118 | attr.minimumSamplingInterval = 0.000000; |
| 72119 | attr.userAccessLevel = 1; |
| 72120 | attr.accessLevel = 1; |
| 72121 | /* Value rank inherited */ |
| 72122 | attr.valueRank = -2; |
| 72123 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14523LU); |
| 72124 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetMetaData"); |
| 72125 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72126 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23809LU), |
| 72127 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23807LU), |
| 72128 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72129 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetMetaData"), |
| 72130 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72131 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72132 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72133 | return retVal; |
| 72134 | } |
| 72135 | |
| 72136 | static UA_StatusCode function_namespace0_generated_157_finish(UA_Server *server, UA_UInt16* ns) { |
| 72137 | return UA_Server_addNode_finish(server, |
| 72138 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23809LU) |
| 72139 | ); |
| 72140 | } |
| 72141 | |
| 72142 | /* SubscribedDataSet - ns=0;i=23808 */ |
| 72143 | |
| 72144 | static UA_StatusCode function_namespace0_generated_158_begin(UA_Server *server, UA_UInt16* ns) { |
| 72145 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72146 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 72147 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscribedDataSet"); |
| 72148 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 72149 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23808LU), |
| 72150 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23807LU), |
| 72151 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 72152 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscribedDataSet"), |
| 72153 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15108LU), |
| 72154 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 72155 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72156 | return retVal; |
| 72157 | } |
| 72158 | |
| 72159 | static UA_StatusCode function_namespace0_generated_158_finish(UA_Server *server, UA_UInt16* ns) { |
| 72160 | return UA_Server_addNode_finish(server, |
| 72161 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23808LU) |
| 72162 | ); |
| 72163 | } |
| 72164 | |
| 72165 | /* <SubscribedDataSetFolderName> - ns=0;i=23796 */ |
| 72166 | |
| 72167 | static UA_StatusCode function_namespace0_generated_159_begin(UA_Server *server, UA_UInt16* ns) { |
| 72168 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72169 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 72170 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "<SubscribedDataSetFolderName>"); |
| 72171 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 72172 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23796LU), |
| 72173 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU), |
| 72174 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU), |
| 72175 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "<SubscribedDataSetFolderName>"), |
| 72176 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU), |
| 72177 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 72178 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72179 | return retVal; |
| 72180 | } |
| 72181 | |
| 72182 | static UA_StatusCode function_namespace0_generated_159_finish(UA_Server *server, UA_UInt16* ns) { |
| 72183 | return UA_Server_addNode_finish(server, |
| 72184 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23796LU) |
| 72185 | ); |
| 72186 | } |
| 72187 | |
| 72188 | /* RemoveDataSetFolder - ns=0;i=23805 */ |
| 72189 | |
| 72190 | static UA_StatusCode function_namespace0_generated_160_begin(UA_Server *server, UA_UInt16* ns) { |
| 72191 | #ifdef UA_ENABLE_METHODCALLS |
| 72192 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72193 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 72194 | attr.executable = true; |
| 72195 | attr.userExecutable = true; |
| 72196 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveDataSetFolder"); |
| 72197 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 72198 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23805LU), |
| 72199 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23796LU), |
| 72200 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 72201 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveDataSetFolder"), |
| 72202 | typeDefinition: UA_NODEID_NULL, |
| 72203 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 72204 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72205 | return retVal; |
| 72206 | #else |
| 72207 | return UA_STATUSCODE_GOOD; |
| 72208 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72209 | } |
| 72210 | |
| 72211 | static UA_StatusCode function_namespace0_generated_160_finish(UA_Server *server, UA_UInt16* ns) { |
| 72212 | #ifdef UA_ENABLE_METHODCALLS |
| 72213 | return UA_Server_addMethodNode_finish(server, |
| 72214 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23805LU) |
| 72215 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 72216 | #else |
| 72217 | return UA_STATUSCODE_GOOD; |
| 72218 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72219 | } |
| 72220 | |
| 72221 | /* InputArguments - ns=0;i=23806 */ |
| 72222 | |
| 72223 | static UA_StatusCode function_namespace0_generated_161_begin(UA_Server *server, UA_UInt16* ns) { |
| 72224 | #ifdef UA_ENABLE_METHODCALLS |
| 72225 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72226 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72227 | attr.minimumSamplingInterval = 0.000000; |
| 72228 | attr.userAccessLevel = 1; |
| 72229 | attr.accessLevel = 1; |
| 72230 | attr.valueRank = 1; |
| 72231 | attr.arrayDimensionsSize = 1; |
| 72232 | UA_UInt32 arrayDimensions[1]; |
| 72233 | arrayDimensions[0] = 1; |
| 72234 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72235 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 72236 | UA_Argument variablenode_ns_0_i_23806_variant_DataContents[1]; |
| 72237 | |
| 72238 | UA_init(p: &variablenode_ns_0_i_23806_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72239 | variablenode_ns_0_i_23806_variant_DataContents[0].name = UA_STRING(chars: "DataSetFolderNodeId"); |
| 72240 | variablenode_ns_0_i_23806_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 72241 | variablenode_ns_0_i_23806_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 72242 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23806_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72243 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 72244 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72245 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23806LU), |
| 72246 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23805LU), |
| 72247 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72248 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 72249 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72250 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72251 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72252 | |
| 72253 | return retVal; |
| 72254 | #else |
| 72255 | return UA_STATUSCODE_GOOD; |
| 72256 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72257 | } |
| 72258 | |
| 72259 | static UA_StatusCode function_namespace0_generated_161_finish(UA_Server *server, UA_UInt16* ns) { |
| 72260 | #ifdef UA_ENABLE_METHODCALLS |
| 72261 | return UA_Server_addNode_finish(server, |
| 72262 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23806LU) |
| 72263 | ); |
| 72264 | #else |
| 72265 | return UA_STATUSCODE_GOOD; |
| 72266 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72267 | } |
| 72268 | |
| 72269 | /* AddDataSetFolder - ns=0;i=23802 */ |
| 72270 | |
| 72271 | static UA_StatusCode function_namespace0_generated_162_begin(UA_Server *server, UA_UInt16* ns) { |
| 72272 | #ifdef UA_ENABLE_METHODCALLS |
| 72273 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72274 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 72275 | attr.executable = true; |
| 72276 | attr.userExecutable = true; |
| 72277 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddDataSetFolder"); |
| 72278 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 72279 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23802LU), |
| 72280 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23796LU), |
| 72281 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 72282 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddDataSetFolder"), |
| 72283 | typeDefinition: UA_NODEID_NULL, |
| 72284 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 72285 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72286 | return retVal; |
| 72287 | #else |
| 72288 | return UA_STATUSCODE_GOOD; |
| 72289 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72290 | } |
| 72291 | |
| 72292 | static UA_StatusCode function_namespace0_generated_162_finish(UA_Server *server, UA_UInt16* ns) { |
| 72293 | #ifdef UA_ENABLE_METHODCALLS |
| 72294 | return UA_Server_addMethodNode_finish(server, |
| 72295 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23802LU) |
| 72296 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 72297 | #else |
| 72298 | return UA_STATUSCODE_GOOD; |
| 72299 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72300 | } |
| 72301 | |
| 72302 | /* OutputArguments - ns=0;i=23804 */ |
| 72303 | |
| 72304 | static UA_StatusCode function_namespace0_generated_163_begin(UA_Server *server, UA_UInt16* ns) { |
| 72305 | #ifdef UA_ENABLE_METHODCALLS |
| 72306 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72307 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72308 | attr.minimumSamplingInterval = 0.000000; |
| 72309 | attr.userAccessLevel = 1; |
| 72310 | attr.accessLevel = 1; |
| 72311 | attr.valueRank = 1; |
| 72312 | attr.arrayDimensionsSize = 1; |
| 72313 | UA_UInt32 arrayDimensions[1]; |
| 72314 | arrayDimensions[0] = 1; |
| 72315 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72316 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 72317 | UA_Argument variablenode_ns_0_i_23804_variant_DataContents[1]; |
| 72318 | |
| 72319 | UA_init(p: &variablenode_ns_0_i_23804_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72320 | variablenode_ns_0_i_23804_variant_DataContents[0].name = UA_STRING(chars: "DataSetFolderNodeId"); |
| 72321 | variablenode_ns_0_i_23804_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 72322 | variablenode_ns_0_i_23804_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 72323 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23804_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72324 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 72325 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72326 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23804LU), |
| 72327 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23802LU), |
| 72328 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72329 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 72330 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72331 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72332 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72333 | |
| 72334 | return retVal; |
| 72335 | #else |
| 72336 | return UA_STATUSCODE_GOOD; |
| 72337 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72338 | } |
| 72339 | |
| 72340 | static UA_StatusCode function_namespace0_generated_163_finish(UA_Server *server, UA_UInt16* ns) { |
| 72341 | #ifdef UA_ENABLE_METHODCALLS |
| 72342 | return UA_Server_addNode_finish(server, |
| 72343 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23804LU) |
| 72344 | ); |
| 72345 | #else |
| 72346 | return UA_STATUSCODE_GOOD; |
| 72347 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72348 | } |
| 72349 | |
| 72350 | /* InputArguments - ns=0;i=23803 */ |
| 72351 | |
| 72352 | static UA_StatusCode function_namespace0_generated_164_begin(UA_Server *server, UA_UInt16* ns) { |
| 72353 | #ifdef UA_ENABLE_METHODCALLS |
| 72354 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72355 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72356 | attr.minimumSamplingInterval = 0.000000; |
| 72357 | attr.userAccessLevel = 1; |
| 72358 | attr.accessLevel = 1; |
| 72359 | attr.valueRank = 1; |
| 72360 | attr.arrayDimensionsSize = 1; |
| 72361 | UA_UInt32 arrayDimensions[1]; |
| 72362 | arrayDimensions[0] = 1; |
| 72363 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72364 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 72365 | UA_Argument variablenode_ns_0_i_23803_variant_DataContents[1]; |
| 72366 | |
| 72367 | UA_init(p: &variablenode_ns_0_i_23803_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72368 | variablenode_ns_0_i_23803_variant_DataContents[0].name = UA_STRING(chars: "Name"); |
| 72369 | variablenode_ns_0_i_23803_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 72370 | variablenode_ns_0_i_23803_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 72371 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23803_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72372 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 72373 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72374 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23803LU), |
| 72375 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23802LU), |
| 72376 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72377 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 72378 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72379 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72380 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72381 | |
| 72382 | return retVal; |
| 72383 | #else |
| 72384 | return UA_STATUSCODE_GOOD; |
| 72385 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72386 | } |
| 72387 | |
| 72388 | static UA_StatusCode function_namespace0_generated_164_finish(UA_Server *server, UA_UInt16* ns) { |
| 72389 | #ifdef UA_ENABLE_METHODCALLS |
| 72390 | return UA_Server_addNode_finish(server, |
| 72391 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23803LU) |
| 72392 | ); |
| 72393 | #else |
| 72394 | return UA_STATUSCODE_GOOD; |
| 72395 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72396 | } |
| 72397 | |
| 72398 | /* RemoveSubscribedDataSet - ns=0;i=23800 */ |
| 72399 | |
| 72400 | static UA_StatusCode function_namespace0_generated_165_begin(UA_Server *server, UA_UInt16* ns) { |
| 72401 | #ifdef UA_ENABLE_METHODCALLS |
| 72402 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72403 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 72404 | attr.executable = true; |
| 72405 | attr.userExecutable = true; |
| 72406 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveSubscribedDataSet"); |
| 72407 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 72408 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23800LU), |
| 72409 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23796LU), |
| 72410 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 72411 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveSubscribedDataSet"), |
| 72412 | typeDefinition: UA_NODEID_NULL, |
| 72413 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 72414 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72415 | return retVal; |
| 72416 | #else |
| 72417 | return UA_STATUSCODE_GOOD; |
| 72418 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72419 | } |
| 72420 | |
| 72421 | static UA_StatusCode function_namespace0_generated_165_finish(UA_Server *server, UA_UInt16* ns) { |
| 72422 | #ifdef UA_ENABLE_METHODCALLS |
| 72423 | return UA_Server_addMethodNode_finish(server, |
| 72424 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23800LU) |
| 72425 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 72426 | #else |
| 72427 | return UA_STATUSCODE_GOOD; |
| 72428 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72429 | } |
| 72430 | |
| 72431 | /* InputArguments - ns=0;i=23801 */ |
| 72432 | |
| 72433 | static UA_StatusCode function_namespace0_generated_166_begin(UA_Server *server, UA_UInt16* ns) { |
| 72434 | #ifdef UA_ENABLE_METHODCALLS |
| 72435 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72436 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72437 | attr.minimumSamplingInterval = 0.000000; |
| 72438 | attr.userAccessLevel = 1; |
| 72439 | attr.accessLevel = 1; |
| 72440 | attr.valueRank = 1; |
| 72441 | attr.arrayDimensionsSize = 1; |
| 72442 | UA_UInt32 arrayDimensions[1]; |
| 72443 | arrayDimensions[0] = 1; |
| 72444 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72445 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 72446 | UA_Argument variablenode_ns_0_i_23801_variant_DataContents[1]; |
| 72447 | |
| 72448 | UA_init(p: &variablenode_ns_0_i_23801_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72449 | variablenode_ns_0_i_23801_variant_DataContents[0].name = UA_STRING(chars: "SubscribedDataSetNodeId"); |
| 72450 | variablenode_ns_0_i_23801_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 72451 | variablenode_ns_0_i_23801_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 72452 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23801_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72453 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 72454 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72455 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23801LU), |
| 72456 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23800LU), |
| 72457 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72458 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 72459 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72460 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72461 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72462 | |
| 72463 | return retVal; |
| 72464 | #else |
| 72465 | return UA_STATUSCODE_GOOD; |
| 72466 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72467 | } |
| 72468 | |
| 72469 | static UA_StatusCode function_namespace0_generated_166_finish(UA_Server *server, UA_UInt16* ns) { |
| 72470 | #ifdef UA_ENABLE_METHODCALLS |
| 72471 | return UA_Server_addNode_finish(server, |
| 72472 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23801LU) |
| 72473 | ); |
| 72474 | #else |
| 72475 | return UA_STATUSCODE_GOOD; |
| 72476 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72477 | } |
| 72478 | |
| 72479 | /* AddSubscribedDataSet - ns=0;i=23797 */ |
| 72480 | |
| 72481 | static UA_StatusCode function_namespace0_generated_167_begin(UA_Server *server, UA_UInt16* ns) { |
| 72482 | #ifdef UA_ENABLE_METHODCALLS |
| 72483 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72484 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 72485 | attr.executable = true; |
| 72486 | attr.userExecutable = true; |
| 72487 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddSubscribedDataSet"); |
| 72488 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 72489 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23797LU), |
| 72490 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23796LU), |
| 72491 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 72492 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddSubscribedDataSet"), |
| 72493 | typeDefinition: UA_NODEID_NULL, |
| 72494 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 72495 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72496 | return retVal; |
| 72497 | #else |
| 72498 | return UA_STATUSCODE_GOOD; |
| 72499 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72500 | } |
| 72501 | |
| 72502 | static UA_StatusCode function_namespace0_generated_167_finish(UA_Server *server, UA_UInt16* ns) { |
| 72503 | #ifdef UA_ENABLE_METHODCALLS |
| 72504 | return UA_Server_addMethodNode_finish(server, |
| 72505 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23797LU) |
| 72506 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 72507 | #else |
| 72508 | return UA_STATUSCODE_GOOD; |
| 72509 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72510 | } |
| 72511 | |
| 72512 | /* OutputArguments - ns=0;i=23799 */ |
| 72513 | |
| 72514 | static UA_StatusCode function_namespace0_generated_168_begin(UA_Server *server, UA_UInt16* ns) { |
| 72515 | #ifdef UA_ENABLE_METHODCALLS |
| 72516 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72517 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72518 | attr.minimumSamplingInterval = 0.000000; |
| 72519 | attr.userAccessLevel = 1; |
| 72520 | attr.accessLevel = 1; |
| 72521 | attr.valueRank = 1; |
| 72522 | attr.arrayDimensionsSize = 1; |
| 72523 | UA_UInt32 arrayDimensions[1]; |
| 72524 | arrayDimensions[0] = 1; |
| 72525 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72526 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 72527 | UA_Argument variablenode_ns_0_i_23799_variant_DataContents[1]; |
| 72528 | |
| 72529 | UA_init(p: &variablenode_ns_0_i_23799_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72530 | variablenode_ns_0_i_23799_variant_DataContents[0].name = UA_STRING(chars: "SubscribedDataSetNodeId"); |
| 72531 | variablenode_ns_0_i_23799_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 72532 | variablenode_ns_0_i_23799_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 72533 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23799_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72534 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 72535 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72536 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23799LU), |
| 72537 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23797LU), |
| 72538 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72539 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 72540 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72541 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72542 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72543 | |
| 72544 | return retVal; |
| 72545 | #else |
| 72546 | return UA_STATUSCODE_GOOD; |
| 72547 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72548 | } |
| 72549 | |
| 72550 | static UA_StatusCode function_namespace0_generated_168_finish(UA_Server *server, UA_UInt16* ns) { |
| 72551 | #ifdef UA_ENABLE_METHODCALLS |
| 72552 | return UA_Server_addNode_finish(server, |
| 72553 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23799LU) |
| 72554 | ); |
| 72555 | #else |
| 72556 | return UA_STATUSCODE_GOOD; |
| 72557 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72558 | } |
| 72559 | |
| 72560 | /* InputArguments - ns=0;i=23798 */ |
| 72561 | |
| 72562 | static UA_StatusCode function_namespace0_generated_169_begin(UA_Server *server, UA_UInt16* ns) { |
| 72563 | #ifdef UA_ENABLE_METHODCALLS |
| 72564 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72565 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72566 | attr.minimumSamplingInterval = 0.000000; |
| 72567 | attr.userAccessLevel = 1; |
| 72568 | attr.accessLevel = 1; |
| 72569 | attr.valueRank = 1; |
| 72570 | attr.arrayDimensionsSize = 1; |
| 72571 | UA_UInt32 arrayDimensions[1]; |
| 72572 | arrayDimensions[0] = 1; |
| 72573 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72574 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 72575 | UA_Argument variablenode_ns_0_i_23798_variant_DataContents[1]; |
| 72576 | |
| 72577 | UA_init(p: &variablenode_ns_0_i_23798_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72578 | variablenode_ns_0_i_23798_variant_DataContents[0].name = UA_STRING(chars: "SubscribedDataSet"); |
| 72579 | variablenode_ns_0_i_23798_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23600LU); |
| 72580 | variablenode_ns_0_i_23798_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 72581 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_23798_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72582 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 72583 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72584 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23798LU), |
| 72585 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23797LU), |
| 72586 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72587 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 72588 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72589 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72590 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72591 | |
| 72592 | return retVal; |
| 72593 | #else |
| 72594 | return UA_STATUSCODE_GOOD; |
| 72595 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72596 | } |
| 72597 | |
| 72598 | static UA_StatusCode function_namespace0_generated_169_finish(UA_Server *server, UA_UInt16* ns) { |
| 72599 | #ifdef UA_ENABLE_METHODCALLS |
| 72600 | return UA_Server_addNode_finish(server, |
| 72601 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23798LU) |
| 72602 | ); |
| 72603 | #else |
| 72604 | return UA_STATUSCODE_GOOD; |
| 72605 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72606 | } |
| 72607 | |
| 72608 | /* DataSetWriterType - ns=0;i=15298 */ |
| 72609 | |
| 72610 | static UA_StatusCode function_namespace0_generated_170_begin(UA_Server *server, UA_UInt16* ns) { |
| 72611 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72612 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 72613 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetWriterType"); |
| 72614 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 72615 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15298LU), |
| 72616 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 72617 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 72618 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetWriterType"), |
| 72619 | typeDefinition: UA_NODEID_NULL, |
| 72620 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 72621 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72622 | return retVal; |
| 72623 | } |
| 72624 | |
| 72625 | static UA_StatusCode function_namespace0_generated_170_finish(UA_Server *server, UA_UInt16* ns) { |
| 72626 | return UA_Server_addNode_finish(server, |
| 72627 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15298LU) |
| 72628 | ); |
| 72629 | } |
| 72630 | |
| 72631 | /* KeyFrameCount - ns=0;i=21094 */ |
| 72632 | |
| 72633 | static UA_StatusCode function_namespace0_generated_171_begin(UA_Server *server, UA_UInt16* ns) { |
| 72634 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72635 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72636 | attr.minimumSamplingInterval = 0.000000; |
| 72637 | attr.userAccessLevel = 1; |
| 72638 | attr.accessLevel = 1; |
| 72639 | /* Value rank inherited */ |
| 72640 | attr.valueRank = -2; |
| 72641 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 72642 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "KeyFrameCount"); |
| 72643 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72644 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21094LU), |
| 72645 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15298LU), |
| 72646 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72647 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "KeyFrameCount"), |
| 72648 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72649 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72650 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72651 | return retVal; |
| 72652 | } |
| 72653 | |
| 72654 | static UA_StatusCode function_namespace0_generated_171_finish(UA_Server *server, UA_UInt16* ns) { |
| 72655 | return UA_Server_addNode_finish(server, |
| 72656 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21094LU) |
| 72657 | ); |
| 72658 | } |
| 72659 | |
| 72660 | /* DataSetFieldContentMask - ns=0;i=21093 */ |
| 72661 | |
| 72662 | static UA_StatusCode function_namespace0_generated_172_begin(UA_Server *server, UA_UInt16* ns) { |
| 72663 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72664 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72665 | attr.minimumSamplingInterval = 0.000000; |
| 72666 | attr.userAccessLevel = 1; |
| 72667 | attr.accessLevel = 1; |
| 72668 | /* Value rank inherited */ |
| 72669 | attr.valueRank = -2; |
| 72670 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15583LU); |
| 72671 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetFieldContentMask"); |
| 72672 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72673 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21093LU), |
| 72674 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15298LU), |
| 72675 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72676 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetFieldContentMask"), |
| 72677 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72678 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72679 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72680 | return retVal; |
| 72681 | } |
| 72682 | |
| 72683 | static UA_StatusCode function_namespace0_generated_172_finish(UA_Server *server, UA_UInt16* ns) { |
| 72684 | return UA_Server_addNode_finish(server, |
| 72685 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21093LU) |
| 72686 | ); |
| 72687 | } |
| 72688 | |
| 72689 | /* DataSetWriterId - ns=0;i=21092 */ |
| 72690 | |
| 72691 | static UA_StatusCode function_namespace0_generated_173_begin(UA_Server *server, UA_UInt16* ns) { |
| 72692 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72693 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72694 | attr.minimumSamplingInterval = 0.000000; |
| 72695 | attr.userAccessLevel = 1; |
| 72696 | attr.accessLevel = 1; |
| 72697 | /* Value rank inherited */ |
| 72698 | attr.valueRank = -2; |
| 72699 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 72700 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetWriterId"); |
| 72701 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72702 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21092LU), |
| 72703 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15298LU), |
| 72704 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72705 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetWriterId"), |
| 72706 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72707 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72708 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72709 | return retVal; |
| 72710 | } |
| 72711 | |
| 72712 | static UA_StatusCode function_namespace0_generated_173_finish(UA_Server *server, UA_UInt16* ns) { |
| 72713 | return UA_Server_addNode_finish(server, |
| 72714 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21092LU) |
| 72715 | ); |
| 72716 | } |
| 72717 | |
| 72718 | /* DataSetWriterProperties - ns=0;i=17493 */ |
| 72719 | |
| 72720 | static UA_StatusCode function_namespace0_generated_174_begin(UA_Server *server, UA_UInt16* ns) { |
| 72721 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72722 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72723 | attr.minimumSamplingInterval = 0.000000; |
| 72724 | attr.userAccessLevel = 1; |
| 72725 | attr.accessLevel = 1; |
| 72726 | attr.valueRank = 1; |
| 72727 | attr.arrayDimensionsSize = 1; |
| 72728 | UA_UInt32 arrayDimensions[1]; |
| 72729 | arrayDimensions[0] = 0; |
| 72730 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72731 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14533LU); |
| 72732 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetWriterProperties"); |
| 72733 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72734 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17493LU), |
| 72735 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15298LU), |
| 72736 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72737 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetWriterProperties"), |
| 72738 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72739 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72740 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72741 | return retVal; |
| 72742 | } |
| 72743 | |
| 72744 | static UA_StatusCode function_namespace0_generated_174_finish(UA_Server *server, UA_UInt16* ns) { |
| 72745 | return UA_Server_addNode_finish(server, |
| 72746 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17493LU) |
| 72747 | ); |
| 72748 | } |
| 72749 | |
| 72750 | /* TransportSettings - ns=0;i=15303 */ |
| 72751 | |
| 72752 | static UA_StatusCode function_namespace0_generated_175_begin(UA_Server *server, UA_UInt16* ns) { |
| 72753 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72754 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 72755 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransportSettings"); |
| 72756 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 72757 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15303LU), |
| 72758 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15298LU), |
| 72759 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 72760 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransportSettings"), |
| 72761 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 72762 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 72763 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72764 | return retVal; |
| 72765 | } |
| 72766 | |
| 72767 | static UA_StatusCode function_namespace0_generated_175_finish(UA_Server *server, UA_UInt16* ns) { |
| 72768 | return UA_Server_addNode_finish(server, |
| 72769 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15303LU) |
| 72770 | ); |
| 72771 | } |
| 72772 | |
| 72773 | /* PubSubGroupType - ns=0;i=14232 */ |
| 72774 | |
| 72775 | static UA_StatusCode function_namespace0_generated_176_begin(UA_Server *server, UA_UInt16* ns) { |
| 72776 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72777 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 72778 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PubSubGroupType"); |
| 72779 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 72780 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14232LU), |
| 72781 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 72782 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 72783 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PubSubGroupType"), |
| 72784 | typeDefinition: UA_NODEID_NULL, |
| 72785 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 72786 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72787 | return retVal; |
| 72788 | } |
| 72789 | |
| 72790 | static UA_StatusCode function_namespace0_generated_176_finish(UA_Server *server, UA_UInt16* ns) { |
| 72791 | return UA_Server_addNode_finish(server, |
| 72792 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14232LU) |
| 72793 | ); |
| 72794 | } |
| 72795 | |
| 72796 | /* ReaderGroupType - ns=0;i=17999 */ |
| 72797 | |
| 72798 | static UA_StatusCode function_namespace0_generated_177_begin(UA_Server *server, UA_UInt16* ns) { |
| 72799 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72800 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 72801 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReaderGroupType"); |
| 72802 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 72803 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17999LU), |
| 72804 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14232LU), |
| 72805 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 72806 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReaderGroupType"), |
| 72807 | typeDefinition: UA_NODEID_NULL, |
| 72808 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 72809 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72810 | return retVal; |
| 72811 | } |
| 72812 | |
| 72813 | static UA_StatusCode function_namespace0_generated_177_finish(UA_Server *server, UA_UInt16* ns) { |
| 72814 | return UA_Server_addNode_finish(server, |
| 72815 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17999LU) |
| 72816 | ); |
| 72817 | } |
| 72818 | |
| 72819 | /* RemoveDataSetReader - ns=0;i=21085 */ |
| 72820 | |
| 72821 | static UA_StatusCode function_namespace0_generated_178_begin(UA_Server *server, UA_UInt16* ns) { |
| 72822 | #ifdef UA_ENABLE_METHODCALLS |
| 72823 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72824 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 72825 | attr.executable = true; |
| 72826 | attr.userExecutable = true; |
| 72827 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveDataSetReader"); |
| 72828 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 72829 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21085LU), |
| 72830 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17999LU), |
| 72831 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 72832 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveDataSetReader"), |
| 72833 | typeDefinition: UA_NODEID_NULL, |
| 72834 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 72835 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72836 | return retVal; |
| 72837 | #else |
| 72838 | return UA_STATUSCODE_GOOD; |
| 72839 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72840 | } |
| 72841 | |
| 72842 | static UA_StatusCode function_namespace0_generated_178_finish(UA_Server *server, UA_UInt16* ns) { |
| 72843 | #ifdef UA_ENABLE_METHODCALLS |
| 72844 | return UA_Server_addMethodNode_finish(server, |
| 72845 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21085LU) |
| 72846 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 72847 | #else |
| 72848 | return UA_STATUSCODE_GOOD; |
| 72849 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72850 | } |
| 72851 | |
| 72852 | /* InputArguments - ns=0;i=21086 */ |
| 72853 | |
| 72854 | static UA_StatusCode function_namespace0_generated_179_begin(UA_Server *server, UA_UInt16* ns) { |
| 72855 | #ifdef UA_ENABLE_METHODCALLS |
| 72856 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72857 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72858 | attr.minimumSamplingInterval = 0.000000; |
| 72859 | attr.userAccessLevel = 1; |
| 72860 | attr.accessLevel = 1; |
| 72861 | attr.valueRank = 1; |
| 72862 | attr.arrayDimensionsSize = 1; |
| 72863 | UA_UInt32 arrayDimensions[1]; |
| 72864 | arrayDimensions[0] = 0; |
| 72865 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72866 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 72867 | UA_Argument variablenode_ns_0_i_21086_variant_DataContents[1]; |
| 72868 | |
| 72869 | UA_init(p: &variablenode_ns_0_i_21086_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72870 | variablenode_ns_0_i_21086_variant_DataContents[0].name = UA_STRING(chars: "DataSetReaderNodeId"); |
| 72871 | variablenode_ns_0_i_21086_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15623LU); |
| 72872 | variablenode_ns_0_i_21086_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 72873 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_21086_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72874 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 72875 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72876 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21086LU), |
| 72877 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21085LU), |
| 72878 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72879 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 72880 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72881 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72882 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72883 | |
| 72884 | return retVal; |
| 72885 | #else |
| 72886 | return UA_STATUSCODE_GOOD; |
| 72887 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72888 | } |
| 72889 | |
| 72890 | static UA_StatusCode function_namespace0_generated_179_finish(UA_Server *server, UA_UInt16* ns) { |
| 72891 | #ifdef UA_ENABLE_METHODCALLS |
| 72892 | return UA_Server_addNode_finish(server, |
| 72893 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21086LU) |
| 72894 | ); |
| 72895 | #else |
| 72896 | return UA_STATUSCODE_GOOD; |
| 72897 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72898 | } |
| 72899 | |
| 72900 | /* AddDataSetReader - ns=0;i=21082 */ |
| 72901 | |
| 72902 | static UA_StatusCode function_namespace0_generated_180_begin(UA_Server *server, UA_UInt16* ns) { |
| 72903 | #ifdef UA_ENABLE_METHODCALLS |
| 72904 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72905 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 72906 | attr.executable = true; |
| 72907 | attr.userExecutable = true; |
| 72908 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddDataSetReader"); |
| 72909 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 72910 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21082LU), |
| 72911 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17999LU), |
| 72912 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 72913 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddDataSetReader"), |
| 72914 | typeDefinition: UA_NODEID_NULL, |
| 72915 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 72916 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72917 | return retVal; |
| 72918 | #else |
| 72919 | return UA_STATUSCODE_GOOD; |
| 72920 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72921 | } |
| 72922 | |
| 72923 | static UA_StatusCode function_namespace0_generated_180_finish(UA_Server *server, UA_UInt16* ns) { |
| 72924 | #ifdef UA_ENABLE_METHODCALLS |
| 72925 | return UA_Server_addMethodNode_finish(server, |
| 72926 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21082LU) |
| 72927 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 72928 | #else |
| 72929 | return UA_STATUSCODE_GOOD; |
| 72930 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72931 | } |
| 72932 | |
| 72933 | /* OutputArguments - ns=0;i=21084 */ |
| 72934 | |
| 72935 | static UA_StatusCode function_namespace0_generated_181_begin(UA_Server *server, UA_UInt16* ns) { |
| 72936 | #ifdef UA_ENABLE_METHODCALLS |
| 72937 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72938 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72939 | attr.minimumSamplingInterval = 0.000000; |
| 72940 | attr.userAccessLevel = 1; |
| 72941 | attr.accessLevel = 1; |
| 72942 | attr.valueRank = 1; |
| 72943 | attr.arrayDimensionsSize = 1; |
| 72944 | UA_UInt32 arrayDimensions[1]; |
| 72945 | arrayDimensions[0] = 0; |
| 72946 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72947 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 72948 | UA_Argument variablenode_ns_0_i_21084_variant_DataContents[1]; |
| 72949 | |
| 72950 | UA_init(p: &variablenode_ns_0_i_21084_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72951 | variablenode_ns_0_i_21084_variant_DataContents[0].name = UA_STRING(chars: "DataSetReaderNodeId"); |
| 72952 | variablenode_ns_0_i_21084_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 72953 | variablenode_ns_0_i_21084_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 72954 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_21084_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72955 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 72956 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 72957 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21084LU), |
| 72958 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21082LU), |
| 72959 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 72960 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 72961 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 72962 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 72963 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 72964 | |
| 72965 | return retVal; |
| 72966 | #else |
| 72967 | return UA_STATUSCODE_GOOD; |
| 72968 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72969 | } |
| 72970 | |
| 72971 | static UA_StatusCode function_namespace0_generated_181_finish(UA_Server *server, UA_UInt16* ns) { |
| 72972 | #ifdef UA_ENABLE_METHODCALLS |
| 72973 | return UA_Server_addNode_finish(server, |
| 72974 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21084LU) |
| 72975 | ); |
| 72976 | #else |
| 72977 | return UA_STATUSCODE_GOOD; |
| 72978 | #endif /* UA_ENABLE_METHODCALLS */ |
| 72979 | } |
| 72980 | |
| 72981 | /* InputArguments - ns=0;i=21083 */ |
| 72982 | |
| 72983 | static UA_StatusCode function_namespace0_generated_182_begin(UA_Server *server, UA_UInt16* ns) { |
| 72984 | #ifdef UA_ENABLE_METHODCALLS |
| 72985 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 72986 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 72987 | attr.minimumSamplingInterval = 0.000000; |
| 72988 | attr.userAccessLevel = 1; |
| 72989 | attr.accessLevel = 1; |
| 72990 | attr.valueRank = 1; |
| 72991 | attr.arrayDimensionsSize = 1; |
| 72992 | UA_UInt32 arrayDimensions[1]; |
| 72993 | arrayDimensions[0] = 0; |
| 72994 | attr.arrayDimensions = &arrayDimensions[0]; |
| 72995 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 72996 | UA_Argument variablenode_ns_0_i_21083_variant_DataContents[1]; |
| 72997 | |
| 72998 | UA_init(p: &variablenode_ns_0_i_21083_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 72999 | variablenode_ns_0_i_21083_variant_DataContents[0].name = UA_STRING(chars: "Configuration"); |
| 73000 | variablenode_ns_0_i_21083_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15623LU); |
| 73001 | variablenode_ns_0_i_21083_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 73002 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_21083_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73003 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 73004 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73005 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21083LU), |
| 73006 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21082LU), |
| 73007 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73008 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 73009 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73010 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73011 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73012 | |
| 73013 | return retVal; |
| 73014 | #else |
| 73015 | return UA_STATUSCODE_GOOD; |
| 73016 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73017 | } |
| 73018 | |
| 73019 | static UA_StatusCode function_namespace0_generated_182_finish(UA_Server *server, UA_UInt16* ns) { |
| 73020 | #ifdef UA_ENABLE_METHODCALLS |
| 73021 | return UA_Server_addNode_finish(server, |
| 73022 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21083LU) |
| 73023 | ); |
| 73024 | #else |
| 73025 | return UA_STATUSCODE_GOOD; |
| 73026 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73027 | } |
| 73028 | |
| 73029 | /* <DataSetReaderName> - ns=0;i=18076 */ |
| 73030 | |
| 73031 | static UA_StatusCode function_namespace0_generated_183_begin(UA_Server *server, UA_UInt16* ns) { |
| 73032 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73033 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 73034 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "<DataSetReaderName>"); |
| 73035 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 73036 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 18076LU), |
| 73037 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17999LU), |
| 73038 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15297LU), |
| 73039 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "<DataSetReaderName>"), |
| 73040 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15306LU), |
| 73041 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 73042 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73043 | return retVal; |
| 73044 | } |
| 73045 | |
| 73046 | static UA_StatusCode function_namespace0_generated_183_finish(UA_Server *server, UA_UInt16* ns) { |
| 73047 | return UA_Server_addNode_finish(server, |
| 73048 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 18076LU) |
| 73049 | ); |
| 73050 | } |
| 73051 | |
| 73052 | /* WriterGroupType - ns=0;i=17725 */ |
| 73053 | |
| 73054 | static UA_StatusCode function_namespace0_generated_184_begin(UA_Server *server, UA_UInt16* ns) { |
| 73055 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73056 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 73057 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "WriterGroupType"); |
| 73058 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 73059 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU), |
| 73060 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14232LU), |
| 73061 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 73062 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "WriterGroupType"), |
| 73063 | typeDefinition: UA_NODEID_NULL, |
| 73064 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 73065 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73066 | return retVal; |
| 73067 | } |
| 73068 | |
| 73069 | static UA_StatusCode function_namespace0_generated_184_finish(UA_Server *server, UA_UInt16* ns) { |
| 73070 | return UA_Server_addNode_finish(server, |
| 73071 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU) |
| 73072 | ); |
| 73073 | } |
| 73074 | |
| 73075 | /* RemoveDataSetWriter - ns=0;i=17992 */ |
| 73076 | |
| 73077 | static UA_StatusCode function_namespace0_generated_185_begin(UA_Server *server, UA_UInt16* ns) { |
| 73078 | #ifdef UA_ENABLE_METHODCALLS |
| 73079 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73080 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 73081 | attr.executable = true; |
| 73082 | attr.userExecutable = true; |
| 73083 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveDataSetWriter"); |
| 73084 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 73085 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17992LU), |
| 73086 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU), |
| 73087 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 73088 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveDataSetWriter"), |
| 73089 | typeDefinition: UA_NODEID_NULL, |
| 73090 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 73091 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73092 | return retVal; |
| 73093 | #else |
| 73094 | return UA_STATUSCODE_GOOD; |
| 73095 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73096 | } |
| 73097 | |
| 73098 | static UA_StatusCode function_namespace0_generated_185_finish(UA_Server *server, UA_UInt16* ns) { |
| 73099 | #ifdef UA_ENABLE_METHODCALLS |
| 73100 | return UA_Server_addMethodNode_finish(server, |
| 73101 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17992LU) |
| 73102 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 73103 | #else |
| 73104 | return UA_STATUSCODE_GOOD; |
| 73105 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73106 | } |
| 73107 | |
| 73108 | /* InputArguments - ns=0;i=17993 */ |
| 73109 | |
| 73110 | static UA_StatusCode function_namespace0_generated_186_begin(UA_Server *server, UA_UInt16* ns) { |
| 73111 | #ifdef UA_ENABLE_METHODCALLS |
| 73112 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73113 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73114 | attr.minimumSamplingInterval = 0.000000; |
| 73115 | attr.userAccessLevel = 1; |
| 73116 | attr.accessLevel = 1; |
| 73117 | attr.valueRank = 1; |
| 73118 | attr.arrayDimensionsSize = 1; |
| 73119 | UA_UInt32 arrayDimensions[1]; |
| 73120 | arrayDimensions[0] = 0; |
| 73121 | attr.arrayDimensions = &arrayDimensions[0]; |
| 73122 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 73123 | UA_Argument variablenode_ns_0_i_17993_variant_DataContents[1]; |
| 73124 | |
| 73125 | UA_init(p: &variablenode_ns_0_i_17993_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73126 | variablenode_ns_0_i_17993_variant_DataContents[0].name = UA_STRING(chars: "DataSetWriterNodeId"); |
| 73127 | variablenode_ns_0_i_17993_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 73128 | variablenode_ns_0_i_17993_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 73129 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17993_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73130 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 73131 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73132 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17993LU), |
| 73133 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17992LU), |
| 73134 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73135 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 73136 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73137 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73138 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73139 | |
| 73140 | return retVal; |
| 73141 | #else |
| 73142 | return UA_STATUSCODE_GOOD; |
| 73143 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73144 | } |
| 73145 | |
| 73146 | static UA_StatusCode function_namespace0_generated_186_finish(UA_Server *server, UA_UInt16* ns) { |
| 73147 | #ifdef UA_ENABLE_METHODCALLS |
| 73148 | return UA_Server_addNode_finish(server, |
| 73149 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17993LU) |
| 73150 | ); |
| 73151 | #else |
| 73152 | return UA_STATUSCODE_GOOD; |
| 73153 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73154 | } |
| 73155 | |
| 73156 | /* AddDataSetWriter - ns=0;i=17969 */ |
| 73157 | |
| 73158 | static UA_StatusCode function_namespace0_generated_187_begin(UA_Server *server, UA_UInt16* ns) { |
| 73159 | #ifdef UA_ENABLE_METHODCALLS |
| 73160 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73161 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 73162 | attr.executable = true; |
| 73163 | attr.userExecutable = true; |
| 73164 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddDataSetWriter"); |
| 73165 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 73166 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17969LU), |
| 73167 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU), |
| 73168 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 73169 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddDataSetWriter"), |
| 73170 | typeDefinition: UA_NODEID_NULL, |
| 73171 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 73172 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73173 | return retVal; |
| 73174 | #else |
| 73175 | return UA_STATUSCODE_GOOD; |
| 73176 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73177 | } |
| 73178 | |
| 73179 | static UA_StatusCode function_namespace0_generated_187_finish(UA_Server *server, UA_UInt16* ns) { |
| 73180 | #ifdef UA_ENABLE_METHODCALLS |
| 73181 | return UA_Server_addMethodNode_finish(server, |
| 73182 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17969LU) |
| 73183 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 73184 | #else |
| 73185 | return UA_STATUSCODE_GOOD; |
| 73186 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73187 | } |
| 73188 | |
| 73189 | /* OutputArguments - ns=0;i=17987 */ |
| 73190 | |
| 73191 | static UA_StatusCode function_namespace0_generated_188_begin(UA_Server *server, UA_UInt16* ns) { |
| 73192 | #ifdef UA_ENABLE_METHODCALLS |
| 73193 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73194 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73195 | attr.minimumSamplingInterval = 0.000000; |
| 73196 | attr.userAccessLevel = 1; |
| 73197 | attr.accessLevel = 1; |
| 73198 | attr.valueRank = 1; |
| 73199 | attr.arrayDimensionsSize = 1; |
| 73200 | UA_UInt32 arrayDimensions[1]; |
| 73201 | arrayDimensions[0] = 0; |
| 73202 | attr.arrayDimensions = &arrayDimensions[0]; |
| 73203 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 73204 | UA_Argument variablenode_ns_0_i_17987_variant_DataContents[1]; |
| 73205 | |
| 73206 | UA_init(p: &variablenode_ns_0_i_17987_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73207 | variablenode_ns_0_i_17987_variant_DataContents[0].name = UA_STRING(chars: "DataSetWriterNodeId"); |
| 73208 | variablenode_ns_0_i_17987_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 73209 | variablenode_ns_0_i_17987_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 73210 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17987_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73211 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 73212 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73213 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17987LU), |
| 73214 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17969LU), |
| 73215 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73216 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 73217 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73218 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73219 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73220 | |
| 73221 | return retVal; |
| 73222 | #else |
| 73223 | return UA_STATUSCODE_GOOD; |
| 73224 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73225 | } |
| 73226 | |
| 73227 | static UA_StatusCode function_namespace0_generated_188_finish(UA_Server *server, UA_UInt16* ns) { |
| 73228 | #ifdef UA_ENABLE_METHODCALLS |
| 73229 | return UA_Server_addNode_finish(server, |
| 73230 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17987LU) |
| 73231 | ); |
| 73232 | #else |
| 73233 | return UA_STATUSCODE_GOOD; |
| 73234 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73235 | } |
| 73236 | |
| 73237 | /* InputArguments - ns=0;i=17976 */ |
| 73238 | |
| 73239 | static UA_StatusCode function_namespace0_generated_189_begin(UA_Server *server, UA_UInt16* ns) { |
| 73240 | #ifdef UA_ENABLE_METHODCALLS |
| 73241 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73242 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73243 | attr.minimumSamplingInterval = 0.000000; |
| 73244 | attr.userAccessLevel = 1; |
| 73245 | attr.accessLevel = 1; |
| 73246 | attr.valueRank = 1; |
| 73247 | attr.arrayDimensionsSize = 1; |
| 73248 | UA_UInt32 arrayDimensions[1]; |
| 73249 | arrayDimensions[0] = 0; |
| 73250 | attr.arrayDimensions = &arrayDimensions[0]; |
| 73251 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 73252 | UA_Argument variablenode_ns_0_i_17976_variant_DataContents[1]; |
| 73253 | |
| 73254 | UA_init(p: &variablenode_ns_0_i_17976_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73255 | variablenode_ns_0_i_17976_variant_DataContents[0].name = UA_STRING(chars: "Configuration"); |
| 73256 | variablenode_ns_0_i_17976_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15597LU); |
| 73257 | variablenode_ns_0_i_17976_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 73258 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17976_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73259 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 73260 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73261 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17976LU), |
| 73262 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17969LU), |
| 73263 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73264 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 73265 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73266 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73267 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73268 | |
| 73269 | return retVal; |
| 73270 | #else |
| 73271 | return UA_STATUSCODE_GOOD; |
| 73272 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73273 | } |
| 73274 | |
| 73275 | static UA_StatusCode function_namespace0_generated_189_finish(UA_Server *server, UA_UInt16* ns) { |
| 73276 | #ifdef UA_ENABLE_METHODCALLS |
| 73277 | return UA_Server_addNode_finish(server, |
| 73278 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17976LU) |
| 73279 | ); |
| 73280 | #else |
| 73281 | return UA_STATUSCODE_GOOD; |
| 73282 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73283 | } |
| 73284 | |
| 73285 | /* <DataSetWriterName> - ns=0;i=17743 */ |
| 73286 | |
| 73287 | static UA_StatusCode function_namespace0_generated_190_begin(UA_Server *server, UA_UInt16* ns) { |
| 73288 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73289 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 73290 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "<DataSetWriterName>"); |
| 73291 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 73292 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17743LU), |
| 73293 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU), |
| 73294 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15296LU), |
| 73295 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "<DataSetWriterName>"), |
| 73296 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15298LU), |
| 73297 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 73298 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73299 | return retVal; |
| 73300 | } |
| 73301 | |
| 73302 | static UA_StatusCode function_namespace0_generated_190_finish(UA_Server *server, UA_UInt16* ns) { |
| 73303 | return UA_Server_addNode_finish(server, |
| 73304 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17743LU) |
| 73305 | ); |
| 73306 | } |
| 73307 | |
| 73308 | /* Status - ns=0;i=17749 */ |
| 73309 | |
| 73310 | static UA_StatusCode function_namespace0_generated_191_begin(UA_Server *server, UA_UInt16* ns) { |
| 73311 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73312 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 73313 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Status"); |
| 73314 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 73315 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17749LU), |
| 73316 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17743LU), |
| 73317 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 73318 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Status"), |
| 73319 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14643LU), |
| 73320 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 73321 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73322 | return retVal; |
| 73323 | } |
| 73324 | |
| 73325 | static UA_StatusCode function_namespace0_generated_191_finish(UA_Server *server, UA_UInt16* ns) { |
| 73326 | return UA_Server_addNode_finish(server, |
| 73327 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17749LU) |
| 73328 | ); |
| 73329 | } |
| 73330 | |
| 73331 | /* State - ns=0;i=17750 */ |
| 73332 | |
| 73333 | static UA_StatusCode function_namespace0_generated_192_begin(UA_Server *server, UA_UInt16* ns) { |
| 73334 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73335 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73336 | attr.minimumSamplingInterval = 0.000000; |
| 73337 | attr.userAccessLevel = 1; |
| 73338 | attr.accessLevel = 1; |
| 73339 | /* Value rank inherited */ |
| 73340 | attr.valueRank = -2; |
| 73341 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14647LU); |
| 73342 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "State"); |
| 73343 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73344 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17750LU), |
| 73345 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17749LU), |
| 73346 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 73347 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "State"), |
| 73348 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 73349 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73350 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73351 | return retVal; |
| 73352 | } |
| 73353 | |
| 73354 | static UA_StatusCode function_namespace0_generated_192_finish(UA_Server *server, UA_UInt16* ns) { |
| 73355 | return UA_Server_addNode_finish(server, |
| 73356 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17750LU) |
| 73357 | ); |
| 73358 | } |
| 73359 | |
| 73360 | /* DataSetFieldContentMask - ns=0;i=17745 */ |
| 73361 | |
| 73362 | static UA_StatusCode function_namespace0_generated_193_begin(UA_Server *server, UA_UInt16* ns) { |
| 73363 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73364 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73365 | attr.minimumSamplingInterval = 0.000000; |
| 73366 | attr.userAccessLevel = 1; |
| 73367 | attr.accessLevel = 1; |
| 73368 | /* Value rank inherited */ |
| 73369 | attr.valueRank = -2; |
| 73370 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15583LU); |
| 73371 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetFieldContentMask"); |
| 73372 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73373 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17745LU), |
| 73374 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17743LU), |
| 73375 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73376 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetFieldContentMask"), |
| 73377 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73378 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73379 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73380 | return retVal; |
| 73381 | } |
| 73382 | |
| 73383 | static UA_StatusCode function_namespace0_generated_193_finish(UA_Server *server, UA_UInt16* ns) { |
| 73384 | return UA_Server_addNode_finish(server, |
| 73385 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17745LU) |
| 73386 | ); |
| 73387 | } |
| 73388 | |
| 73389 | /* DataSetWriterId - ns=0;i=17744 */ |
| 73390 | |
| 73391 | static UA_StatusCode function_namespace0_generated_194_begin(UA_Server *server, UA_UInt16* ns) { |
| 73392 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73393 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73394 | attr.minimumSamplingInterval = 0.000000; |
| 73395 | attr.userAccessLevel = 1; |
| 73396 | attr.accessLevel = 1; |
| 73397 | /* Value rank inherited */ |
| 73398 | attr.valueRank = -2; |
| 73399 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 73400 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetWriterId"); |
| 73401 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73402 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17744LU), |
| 73403 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17743LU), |
| 73404 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73405 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetWriterId"), |
| 73406 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73407 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73408 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73409 | return retVal; |
| 73410 | } |
| 73411 | |
| 73412 | static UA_StatusCode function_namespace0_generated_194_finish(UA_Server *server, UA_UInt16* ns) { |
| 73413 | return UA_Server_addNode_finish(server, |
| 73414 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17744LU) |
| 73415 | ); |
| 73416 | } |
| 73417 | |
| 73418 | /* DataSetWriterProperties - ns=0;i=17490 */ |
| 73419 | |
| 73420 | static UA_StatusCode function_namespace0_generated_195_begin(UA_Server *server, UA_UInt16* ns) { |
| 73421 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73422 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73423 | attr.minimumSamplingInterval = 0.000000; |
| 73424 | attr.userAccessLevel = 1; |
| 73425 | attr.accessLevel = 1; |
| 73426 | attr.valueRank = 1; |
| 73427 | attr.arrayDimensionsSize = 1; |
| 73428 | UA_UInt32 arrayDimensions[1]; |
| 73429 | arrayDimensions[0] = 0; |
| 73430 | attr.arrayDimensions = &arrayDimensions[0]; |
| 73431 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14533LU); |
| 73432 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetWriterProperties"); |
| 73433 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73434 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17490LU), |
| 73435 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17743LU), |
| 73436 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73437 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetWriterProperties"), |
| 73438 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73439 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73440 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73441 | return retVal; |
| 73442 | } |
| 73443 | |
| 73444 | static UA_StatusCode function_namespace0_generated_195_finish(UA_Server *server, UA_UInt16* ns) { |
| 73445 | return UA_Server_addNode_finish(server, |
| 73446 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17490LU) |
| 73447 | ); |
| 73448 | } |
| 73449 | |
| 73450 | /* LocaleIds - ns=0;i=17740 */ |
| 73451 | |
| 73452 | static UA_StatusCode function_namespace0_generated_196_begin(UA_Server *server, UA_UInt16* ns) { |
| 73453 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73454 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73455 | attr.minimumSamplingInterval = 0.000000; |
| 73456 | attr.userAccessLevel = 1; |
| 73457 | attr.accessLevel = 1; |
| 73458 | attr.valueRank = 1; |
| 73459 | attr.arrayDimensionsSize = 1; |
| 73460 | UA_UInt32 arrayDimensions[1]; |
| 73461 | arrayDimensions[0] = 0; |
| 73462 | attr.arrayDimensions = &arrayDimensions[0]; |
| 73463 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU); |
| 73464 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleIds"); |
| 73465 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73466 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17740LU), |
| 73467 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU), |
| 73468 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73469 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleIds"), |
| 73470 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73471 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73472 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73473 | return retVal; |
| 73474 | } |
| 73475 | |
| 73476 | static UA_StatusCode function_namespace0_generated_196_finish(UA_Server *server, UA_UInt16* ns) { |
| 73477 | return UA_Server_addNode_finish(server, |
| 73478 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17740LU) |
| 73479 | ); |
| 73480 | } |
| 73481 | |
| 73482 | /* Priority - ns=0;i=17739 */ |
| 73483 | |
| 73484 | static UA_StatusCode function_namespace0_generated_197_begin(UA_Server *server, UA_UInt16* ns) { |
| 73485 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73486 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73487 | attr.minimumSamplingInterval = 0.000000; |
| 73488 | attr.userAccessLevel = 1; |
| 73489 | attr.accessLevel = 1; |
| 73490 | /* Value rank inherited */ |
| 73491 | attr.valueRank = -2; |
| 73492 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU); |
| 73493 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Priority"); |
| 73494 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73495 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17739LU), |
| 73496 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU), |
| 73497 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73498 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Priority"), |
| 73499 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73500 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73501 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73502 | return retVal; |
| 73503 | } |
| 73504 | |
| 73505 | static UA_StatusCode function_namespace0_generated_197_finish(UA_Server *server, UA_UInt16* ns) { |
| 73506 | return UA_Server_addNode_finish(server, |
| 73507 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17739LU) |
| 73508 | ); |
| 73509 | } |
| 73510 | |
| 73511 | /* KeepAliveTime - ns=0;i=17738 */ |
| 73512 | |
| 73513 | static UA_StatusCode function_namespace0_generated_198_begin(UA_Server *server, UA_UInt16* ns) { |
| 73514 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73515 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73516 | attr.minimumSamplingInterval = 0.000000; |
| 73517 | attr.userAccessLevel = 1; |
| 73518 | attr.accessLevel = 1; |
| 73519 | /* Value rank inherited */ |
| 73520 | attr.valueRank = -2; |
| 73521 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 73522 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "KeepAliveTime"); |
| 73523 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73524 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17738LU), |
| 73525 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU), |
| 73526 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73527 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "KeepAliveTime"), |
| 73528 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73529 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73530 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73531 | return retVal; |
| 73532 | } |
| 73533 | |
| 73534 | static UA_StatusCode function_namespace0_generated_198_finish(UA_Server *server, UA_UInt16* ns) { |
| 73535 | return UA_Server_addNode_finish(server, |
| 73536 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17738LU) |
| 73537 | ); |
| 73538 | } |
| 73539 | |
| 73540 | /* PublishingInterval - ns=0;i=17737 */ |
| 73541 | |
| 73542 | static UA_StatusCode function_namespace0_generated_199_begin(UA_Server *server, UA_UInt16* ns) { |
| 73543 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73544 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73545 | attr.minimumSamplingInterval = 0.000000; |
| 73546 | attr.userAccessLevel = 1; |
| 73547 | attr.accessLevel = 1; |
| 73548 | /* Value rank inherited */ |
| 73549 | attr.valueRank = -2; |
| 73550 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 73551 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishingInterval"); |
| 73552 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73553 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17737LU), |
| 73554 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU), |
| 73555 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73556 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishingInterval"), |
| 73557 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73558 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73559 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73560 | return retVal; |
| 73561 | } |
| 73562 | |
| 73563 | static UA_StatusCode function_namespace0_generated_199_finish(UA_Server *server, UA_UInt16* ns) { |
| 73564 | return UA_Server_addNode_finish(server, |
| 73565 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17737LU) |
| 73566 | ); |
| 73567 | } |
| 73568 | |
| 73569 | /* WriterGroupId - ns=0;i=17736 */ |
| 73570 | |
| 73571 | static UA_StatusCode function_namespace0_generated_200_begin(UA_Server *server, UA_UInt16* ns) { |
| 73572 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73573 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73574 | attr.minimumSamplingInterval = 0.000000; |
| 73575 | attr.userAccessLevel = 1; |
| 73576 | attr.accessLevel = 1; |
| 73577 | /* Value rank inherited */ |
| 73578 | attr.valueRank = -2; |
| 73579 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 73580 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "WriterGroupId"); |
| 73581 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73582 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17736LU), |
| 73583 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU), |
| 73584 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73585 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "WriterGroupId"), |
| 73586 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73587 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73588 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73589 | return retVal; |
| 73590 | } |
| 73591 | |
| 73592 | static UA_StatusCode function_namespace0_generated_200_finish(UA_Server *server, UA_UInt16* ns) { |
| 73593 | return UA_Server_addNode_finish(server, |
| 73594 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17736LU) |
| 73595 | ); |
| 73596 | } |
| 73597 | |
| 73598 | /* MaxNetworkMessageSize - ns=0;i=17724 */ |
| 73599 | |
| 73600 | static UA_StatusCode function_namespace0_generated_201_begin(UA_Server *server, UA_UInt16* ns) { |
| 73601 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73602 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73603 | attr.minimumSamplingInterval = 0.000000; |
| 73604 | attr.userAccessLevel = 1; |
| 73605 | attr.accessLevel = 1; |
| 73606 | /* Value rank inherited */ |
| 73607 | attr.valueRank = -2; |
| 73608 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 73609 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNetworkMessageSize"); |
| 73610 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73611 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17724LU), |
| 73612 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14232LU), |
| 73613 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73614 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNetworkMessageSize"), |
| 73615 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73616 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73617 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73618 | return retVal; |
| 73619 | } |
| 73620 | |
| 73621 | static UA_StatusCode function_namespace0_generated_201_finish(UA_Server *server, UA_UInt16* ns) { |
| 73622 | return UA_Server_addNode_finish(server, |
| 73623 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17724LU) |
| 73624 | ); |
| 73625 | } |
| 73626 | |
| 73627 | /* SecurityGroupId - ns=0;i=15927 */ |
| 73628 | |
| 73629 | static UA_StatusCode function_namespace0_generated_202_begin(UA_Server *server, UA_UInt16* ns) { |
| 73630 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73631 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73632 | attr.minimumSamplingInterval = 0.000000; |
| 73633 | attr.userAccessLevel = 1; |
| 73634 | attr.accessLevel = 1; |
| 73635 | /* Value rank inherited */ |
| 73636 | attr.valueRank = -2; |
| 73637 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 73638 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityGroupId"); |
| 73639 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73640 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15927LU), |
| 73641 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14232LU), |
| 73642 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73643 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityGroupId"), |
| 73644 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73645 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73646 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73647 | return retVal; |
| 73648 | } |
| 73649 | |
| 73650 | static UA_StatusCode function_namespace0_generated_202_finish(UA_Server *server, UA_UInt16* ns) { |
| 73651 | return UA_Server_addNode_finish(server, |
| 73652 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15927LU) |
| 73653 | ); |
| 73654 | } |
| 73655 | |
| 73656 | /* ConnectionTransportType - ns=0;i=17721 */ |
| 73657 | |
| 73658 | static UA_StatusCode function_namespace0_generated_203_begin(UA_Server *server, UA_UInt16* ns) { |
| 73659 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73660 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 73661 | attr.isAbstract = true; |
| 73662 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConnectionTransportType"); |
| 73663 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 73664 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17721LU), |
| 73665 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 73666 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 73667 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConnectionTransportType"), |
| 73668 | typeDefinition: UA_NODEID_NULL, |
| 73669 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 73670 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73671 | return retVal; |
| 73672 | } |
| 73673 | |
| 73674 | static UA_StatusCode function_namespace0_generated_203_finish(UA_Server *server, UA_UInt16* ns) { |
| 73675 | return UA_Server_addNode_finish(server, |
| 73676 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17721LU) |
| 73677 | ); |
| 73678 | } |
| 73679 | |
| 73680 | /* NetworkAddressType - ns=0;i=21145 */ |
| 73681 | |
| 73682 | static UA_StatusCode function_namespace0_generated_204_begin(UA_Server *server, UA_UInt16* ns) { |
| 73683 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73684 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 73685 | attr.isAbstract = true; |
| 73686 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NetworkAddressType"); |
| 73687 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 73688 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21145LU), |
| 73689 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 73690 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 73691 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NetworkAddressType"), |
| 73692 | typeDefinition: UA_NODEID_NULL, |
| 73693 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 73694 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73695 | return retVal; |
| 73696 | } |
| 73697 | |
| 73698 | static UA_StatusCode function_namespace0_generated_204_finish(UA_Server *server, UA_UInt16* ns) { |
| 73699 | return UA_Server_addNode_finish(server, |
| 73700 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21145LU) |
| 73701 | ); |
| 73702 | } |
| 73703 | |
| 73704 | /* NetworkAddressUrlType - ns=0;i=21147 */ |
| 73705 | |
| 73706 | static UA_StatusCode function_namespace0_generated_205_begin(UA_Server *server, UA_UInt16* ns) { |
| 73707 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73708 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 73709 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NetworkAddressUrlType"); |
| 73710 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 73711 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21147LU), |
| 73712 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21145LU), |
| 73713 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 73714 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NetworkAddressUrlType"), |
| 73715 | typeDefinition: UA_NODEID_NULL, |
| 73716 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 73717 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73718 | return retVal; |
| 73719 | } |
| 73720 | |
| 73721 | static UA_StatusCode function_namespace0_generated_205_finish(UA_Server *server, UA_UInt16* ns) { |
| 73722 | return UA_Server_addNode_finish(server, |
| 73723 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21147LU) |
| 73724 | ); |
| 73725 | } |
| 73726 | |
| 73727 | /* Url - ns=0;i=21149 */ |
| 73728 | |
| 73729 | static UA_StatusCode function_namespace0_generated_206_begin(UA_Server *server, UA_UInt16* ns) { |
| 73730 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73731 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73732 | attr.minimumSamplingInterval = 0.000000; |
| 73733 | attr.userAccessLevel = 1; |
| 73734 | attr.accessLevel = 1; |
| 73735 | /* Value rank inherited */ |
| 73736 | attr.valueRank = -2; |
| 73737 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 73738 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Url"); |
| 73739 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73740 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21149LU), |
| 73741 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21147LU), |
| 73742 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 73743 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Url"), |
| 73744 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 73745 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73746 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73747 | return retVal; |
| 73748 | } |
| 73749 | |
| 73750 | static UA_StatusCode function_namespace0_generated_206_finish(UA_Server *server, UA_UInt16* ns) { |
| 73751 | return UA_Server_addNode_finish(server, |
| 73752 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21149LU) |
| 73753 | ); |
| 73754 | } |
| 73755 | |
| 73756 | /* NetworkInterface - ns=0;i=21146 */ |
| 73757 | |
| 73758 | static UA_StatusCode function_namespace0_generated_207_begin(UA_Server *server, UA_UInt16* ns) { |
| 73759 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73760 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73761 | attr.minimumSamplingInterval = 0.000000; |
| 73762 | attr.userAccessLevel = 1; |
| 73763 | attr.accessLevel = 1; |
| 73764 | /* Value rank inherited */ |
| 73765 | attr.valueRank = -2; |
| 73766 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 73767 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NetworkInterface"); |
| 73768 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73769 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21146LU), |
| 73770 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21145LU), |
| 73771 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 73772 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NetworkInterface"), |
| 73773 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 73774 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73775 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73776 | return retVal; |
| 73777 | } |
| 73778 | |
| 73779 | static UA_StatusCode function_namespace0_generated_207_finish(UA_Server *server, UA_UInt16* ns) { |
| 73780 | return UA_Server_addNode_finish(server, |
| 73781 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21146LU) |
| 73782 | ); |
| 73783 | } |
| 73784 | |
| 73785 | /* PubSubConnectionType - ns=0;i=14209 */ |
| 73786 | |
| 73787 | static UA_StatusCode function_namespace0_generated_208_begin(UA_Server *server, UA_UInt16* ns) { |
| 73788 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73789 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 73790 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PubSubConnectionType"); |
| 73791 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 73792 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 73793 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 73794 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 73795 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PubSubConnectionType"), |
| 73796 | typeDefinition: UA_NODEID_NULL, |
| 73797 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 73798 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73799 | return retVal; |
| 73800 | } |
| 73801 | |
| 73802 | static UA_StatusCode function_namespace0_generated_208_finish(UA_Server *server, UA_UInt16* ns) { |
| 73803 | return UA_Server_addNode_finish(server, |
| 73804 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU) |
| 73805 | ); |
| 73806 | } |
| 73807 | |
| 73808 | /* ConnectionProperties - ns=0;i=17485 */ |
| 73809 | |
| 73810 | static UA_StatusCode function_namespace0_generated_209_begin(UA_Server *server, UA_UInt16* ns) { |
| 73811 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73812 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73813 | attr.minimumSamplingInterval = 0.000000; |
| 73814 | attr.userAccessLevel = 1; |
| 73815 | attr.accessLevel = 1; |
| 73816 | attr.valueRank = 1; |
| 73817 | attr.arrayDimensionsSize = 1; |
| 73818 | UA_UInt32 arrayDimensions[1]; |
| 73819 | arrayDimensions[0] = 0; |
| 73820 | attr.arrayDimensions = &arrayDimensions[0]; |
| 73821 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14533LU); |
| 73822 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConnectionProperties"); |
| 73823 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73824 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17485LU), |
| 73825 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 73826 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73827 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConnectionProperties"), |
| 73828 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73829 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73830 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73831 | return retVal; |
| 73832 | } |
| 73833 | |
| 73834 | static UA_StatusCode function_namespace0_generated_209_finish(UA_Server *server, UA_UInt16* ns) { |
| 73835 | return UA_Server_addNode_finish(server, |
| 73836 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17485LU) |
| 73837 | ); |
| 73838 | } |
| 73839 | |
| 73840 | /* AddReaderGroup - ns=0;i=17465 */ |
| 73841 | |
| 73842 | static UA_StatusCode function_namespace0_generated_210_begin(UA_Server *server, UA_UInt16* ns) { |
| 73843 | #ifdef UA_ENABLE_METHODCALLS |
| 73844 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73845 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 73846 | attr.executable = true; |
| 73847 | attr.userExecutable = true; |
| 73848 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddReaderGroup"); |
| 73849 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 73850 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17465LU), |
| 73851 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 73852 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 73853 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddReaderGroup"), |
| 73854 | typeDefinition: UA_NODEID_NULL, |
| 73855 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 73856 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73857 | return retVal; |
| 73858 | #else |
| 73859 | return UA_STATUSCODE_GOOD; |
| 73860 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73861 | } |
| 73862 | |
| 73863 | static UA_StatusCode function_namespace0_generated_210_finish(UA_Server *server, UA_UInt16* ns) { |
| 73864 | #ifdef UA_ENABLE_METHODCALLS |
| 73865 | return UA_Server_addMethodNode_finish(server, |
| 73866 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17465LU) |
| 73867 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 73868 | #else |
| 73869 | return UA_STATUSCODE_GOOD; |
| 73870 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73871 | } |
| 73872 | |
| 73873 | /* OutputArguments - ns=0;i=17508 */ |
| 73874 | |
| 73875 | static UA_StatusCode function_namespace0_generated_211_begin(UA_Server *server, UA_UInt16* ns) { |
| 73876 | #ifdef UA_ENABLE_METHODCALLS |
| 73877 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73878 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73879 | attr.minimumSamplingInterval = 0.000000; |
| 73880 | attr.userAccessLevel = 1; |
| 73881 | attr.accessLevel = 1; |
| 73882 | attr.valueRank = 1; |
| 73883 | attr.arrayDimensionsSize = 1; |
| 73884 | UA_UInt32 arrayDimensions[1]; |
| 73885 | arrayDimensions[0] = 0; |
| 73886 | attr.arrayDimensions = &arrayDimensions[0]; |
| 73887 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 73888 | UA_Argument variablenode_ns_0_i_17508_variant_DataContents[1]; |
| 73889 | |
| 73890 | UA_init(p: &variablenode_ns_0_i_17508_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73891 | variablenode_ns_0_i_17508_variant_DataContents[0].name = UA_STRING(chars: "GroupId"); |
| 73892 | variablenode_ns_0_i_17508_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 73893 | variablenode_ns_0_i_17508_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 73894 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17508_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73895 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 73896 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73897 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17508LU), |
| 73898 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17465LU), |
| 73899 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73900 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 73901 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73902 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73903 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73904 | |
| 73905 | return retVal; |
| 73906 | #else |
| 73907 | return UA_STATUSCODE_GOOD; |
| 73908 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73909 | } |
| 73910 | |
| 73911 | static UA_StatusCode function_namespace0_generated_211_finish(UA_Server *server, UA_UInt16* ns) { |
| 73912 | #ifdef UA_ENABLE_METHODCALLS |
| 73913 | return UA_Server_addNode_finish(server, |
| 73914 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17508LU) |
| 73915 | ); |
| 73916 | #else |
| 73917 | return UA_STATUSCODE_GOOD; |
| 73918 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73919 | } |
| 73920 | |
| 73921 | /* InputArguments - ns=0;i=17507 */ |
| 73922 | |
| 73923 | static UA_StatusCode function_namespace0_generated_212_begin(UA_Server *server, UA_UInt16* ns) { |
| 73924 | #ifdef UA_ENABLE_METHODCALLS |
| 73925 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73926 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 73927 | attr.minimumSamplingInterval = 0.000000; |
| 73928 | attr.userAccessLevel = 1; |
| 73929 | attr.accessLevel = 1; |
| 73930 | attr.valueRank = 1; |
| 73931 | attr.arrayDimensionsSize = 1; |
| 73932 | UA_UInt32 arrayDimensions[1]; |
| 73933 | arrayDimensions[0] = 0; |
| 73934 | attr.arrayDimensions = &arrayDimensions[0]; |
| 73935 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 73936 | UA_Argument variablenode_ns_0_i_17507_variant_DataContents[1]; |
| 73937 | |
| 73938 | UA_init(p: &variablenode_ns_0_i_17507_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73939 | variablenode_ns_0_i_17507_variant_DataContents[0].name = UA_STRING(chars: "Configuration"); |
| 73940 | variablenode_ns_0_i_17507_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15520LU); |
| 73941 | variablenode_ns_0_i_17507_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 73942 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17507_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 73943 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 73944 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 73945 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17507LU), |
| 73946 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17465LU), |
| 73947 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 73948 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 73949 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 73950 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 73951 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73952 | |
| 73953 | return retVal; |
| 73954 | #else |
| 73955 | return UA_STATUSCODE_GOOD; |
| 73956 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73957 | } |
| 73958 | |
| 73959 | static UA_StatusCode function_namespace0_generated_212_finish(UA_Server *server, UA_UInt16* ns) { |
| 73960 | #ifdef UA_ENABLE_METHODCALLS |
| 73961 | return UA_Server_addNode_finish(server, |
| 73962 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17507LU) |
| 73963 | ); |
| 73964 | #else |
| 73965 | return UA_STATUSCODE_GOOD; |
| 73966 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73967 | } |
| 73968 | |
| 73969 | /* AddWriterGroup - ns=0;i=17427 */ |
| 73970 | |
| 73971 | static UA_StatusCode function_namespace0_generated_213_begin(UA_Server *server, UA_UInt16* ns) { |
| 73972 | #ifdef UA_ENABLE_METHODCALLS |
| 73973 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 73974 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 73975 | attr.executable = true; |
| 73976 | attr.userExecutable = true; |
| 73977 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddWriterGroup"); |
| 73978 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 73979 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17427LU), |
| 73980 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 73981 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 73982 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddWriterGroup"), |
| 73983 | typeDefinition: UA_NODEID_NULL, |
| 73984 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 73985 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 73986 | return retVal; |
| 73987 | #else |
| 73988 | return UA_STATUSCODE_GOOD; |
| 73989 | #endif /* UA_ENABLE_METHODCALLS */ |
| 73990 | } |
| 73991 | |
| 73992 | static UA_StatusCode function_namespace0_generated_213_finish(UA_Server *server, UA_UInt16* ns) { |
| 73993 | #ifdef UA_ENABLE_METHODCALLS |
| 73994 | return UA_Server_addMethodNode_finish(server, |
| 73995 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17427LU) |
| 73996 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 73997 | #else |
| 73998 | return UA_STATUSCODE_GOOD; |
| 73999 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74000 | } |
| 74001 | |
| 74002 | /* OutputArguments - ns=0;i=17456 */ |
| 74003 | |
| 74004 | static UA_StatusCode function_namespace0_generated_214_begin(UA_Server *server, UA_UInt16* ns) { |
| 74005 | #ifdef UA_ENABLE_METHODCALLS |
| 74006 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74007 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74008 | attr.minimumSamplingInterval = 0.000000; |
| 74009 | attr.userAccessLevel = 1; |
| 74010 | attr.accessLevel = 1; |
| 74011 | attr.valueRank = 1; |
| 74012 | attr.arrayDimensionsSize = 1; |
| 74013 | UA_UInt32 arrayDimensions[1]; |
| 74014 | arrayDimensions[0] = 0; |
| 74015 | attr.arrayDimensions = &arrayDimensions[0]; |
| 74016 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 74017 | UA_Argument variablenode_ns_0_i_17456_variant_DataContents[1]; |
| 74018 | |
| 74019 | UA_init(p: &variablenode_ns_0_i_17456_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74020 | variablenode_ns_0_i_17456_variant_DataContents[0].name = UA_STRING(chars: "GroupId"); |
| 74021 | variablenode_ns_0_i_17456_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 74022 | variablenode_ns_0_i_17456_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 74023 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17456_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74024 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 74025 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74026 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17456LU), |
| 74027 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17427LU), |
| 74028 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74029 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 74030 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74031 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74032 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74033 | |
| 74034 | return retVal; |
| 74035 | #else |
| 74036 | return UA_STATUSCODE_GOOD; |
| 74037 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74038 | } |
| 74039 | |
| 74040 | static UA_StatusCode function_namespace0_generated_214_finish(UA_Server *server, UA_UInt16* ns) { |
| 74041 | #ifdef UA_ENABLE_METHODCALLS |
| 74042 | return UA_Server_addNode_finish(server, |
| 74043 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17456LU) |
| 74044 | ); |
| 74045 | #else |
| 74046 | return UA_STATUSCODE_GOOD; |
| 74047 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74048 | } |
| 74049 | |
| 74050 | /* InputArguments - ns=0;i=17428 */ |
| 74051 | |
| 74052 | static UA_StatusCode function_namespace0_generated_215_begin(UA_Server *server, UA_UInt16* ns) { |
| 74053 | #ifdef UA_ENABLE_METHODCALLS |
| 74054 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74055 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74056 | attr.minimumSamplingInterval = 0.000000; |
| 74057 | attr.userAccessLevel = 1; |
| 74058 | attr.accessLevel = 1; |
| 74059 | attr.valueRank = 1; |
| 74060 | attr.arrayDimensionsSize = 1; |
| 74061 | UA_UInt32 arrayDimensions[1]; |
| 74062 | arrayDimensions[0] = 0; |
| 74063 | attr.arrayDimensions = &arrayDimensions[0]; |
| 74064 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 74065 | UA_Argument variablenode_ns_0_i_17428_variant_DataContents[1]; |
| 74066 | |
| 74067 | UA_init(p: &variablenode_ns_0_i_17428_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74068 | variablenode_ns_0_i_17428_variant_DataContents[0].name = UA_STRING(chars: "Configuration"); |
| 74069 | variablenode_ns_0_i_17428_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15480LU); |
| 74070 | variablenode_ns_0_i_17428_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 74071 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17428_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74072 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 74073 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74074 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17428LU), |
| 74075 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17427LU), |
| 74076 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74077 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 74078 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74079 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74080 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74081 | |
| 74082 | return retVal; |
| 74083 | #else |
| 74084 | return UA_STATUSCODE_GOOD; |
| 74085 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74086 | } |
| 74087 | |
| 74088 | static UA_StatusCode function_namespace0_generated_215_finish(UA_Server *server, UA_UInt16* ns) { |
| 74089 | #ifdef UA_ENABLE_METHODCALLS |
| 74090 | return UA_Server_addNode_finish(server, |
| 74091 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17428LU) |
| 74092 | ); |
| 74093 | #else |
| 74094 | return UA_STATUSCODE_GOOD; |
| 74095 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74096 | } |
| 74097 | |
| 74098 | /* <ReaderGroupName> - ns=0;i=17325 */ |
| 74099 | |
| 74100 | static UA_StatusCode function_namespace0_generated_216_begin(UA_Server *server, UA_UInt16* ns) { |
| 74101 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74102 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 74103 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "<ReaderGroupName>"); |
| 74104 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 74105 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17325LU), |
| 74106 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 74107 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74108 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "<ReaderGroupName>"), |
| 74109 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17999LU), |
| 74110 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 74111 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74112 | return retVal; |
| 74113 | } |
| 74114 | |
| 74115 | static UA_StatusCode function_namespace0_generated_216_finish(UA_Server *server, UA_UInt16* ns) { |
| 74116 | return UA_Server_addNode_finish(server, |
| 74117 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17325LU) |
| 74118 | ); |
| 74119 | } |
| 74120 | |
| 74121 | /* <WriterGroupName> - ns=0;i=17310 */ |
| 74122 | |
| 74123 | static UA_StatusCode function_namespace0_generated_217_begin(UA_Server *server, UA_UInt16* ns) { |
| 74124 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74125 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 74126 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "<WriterGroupName>"); |
| 74127 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 74128 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17310LU), |
| 74129 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 74130 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74131 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "<WriterGroupName>"), |
| 74132 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17725LU), |
| 74133 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 74134 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74135 | return retVal; |
| 74136 | } |
| 74137 | |
| 74138 | static UA_StatusCode function_namespace0_generated_217_finish(UA_Server *server, UA_UInt16* ns) { |
| 74139 | return UA_Server_addNode_finish(server, |
| 74140 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17310LU) |
| 74141 | ); |
| 74142 | } |
| 74143 | |
| 74144 | /* TransportProfileUri - ns=0;i=17306 */ |
| 74145 | |
| 74146 | static UA_StatusCode function_namespace0_generated_218_begin(UA_Server *server, UA_UInt16* ns) { |
| 74147 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74148 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74149 | attr.minimumSamplingInterval = 0.000000; |
| 74150 | attr.userAccessLevel = 1; |
| 74151 | attr.accessLevel = 1; |
| 74152 | /* Value rank inherited */ |
| 74153 | attr.valueRank = -2; |
| 74154 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 74155 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransportProfileUri"); |
| 74156 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74157 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17306LU), |
| 74158 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 74159 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74160 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransportProfileUri"), |
| 74161 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16309LU), |
| 74162 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74163 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74164 | return retVal; |
| 74165 | } |
| 74166 | |
| 74167 | static UA_StatusCode function_namespace0_generated_218_finish(UA_Server *server, UA_UInt16* ns) { |
| 74168 | return UA_Server_addNode_finish(server, |
| 74169 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17306LU) |
| 74170 | ); |
| 74171 | } |
| 74172 | |
| 74173 | /* Selections - ns=0;i=17710 */ |
| 74174 | |
| 74175 | static UA_StatusCode function_namespace0_generated_219_begin(UA_Server *server, UA_UInt16* ns) { |
| 74176 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74177 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74178 | attr.minimumSamplingInterval = 0.000000; |
| 74179 | attr.userAccessLevel = 1; |
| 74180 | attr.accessLevel = 1; |
| 74181 | attr.valueRank = 1; |
| 74182 | attr.arrayDimensionsSize = 1; |
| 74183 | UA_UInt32 arrayDimensions[1]; |
| 74184 | arrayDimensions[0] = 0; |
| 74185 | attr.arrayDimensions = &arrayDimensions[0]; |
| 74186 | /* DataType inherited */ |
| 74187 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 74188 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Selections"); |
| 74189 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74190 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17710LU), |
| 74191 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17306LU), |
| 74192 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74193 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Selections"), |
| 74194 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74195 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74196 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74197 | return retVal; |
| 74198 | } |
| 74199 | |
| 74200 | static UA_StatusCode function_namespace0_generated_219_finish(UA_Server *server, UA_UInt16* ns) { |
| 74201 | return UA_Server_addNode_finish(server, |
| 74202 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17710LU) |
| 74203 | ); |
| 74204 | } |
| 74205 | |
| 74206 | /* TransportSettings - ns=0;i=17203 */ |
| 74207 | |
| 74208 | static UA_StatusCode function_namespace0_generated_220_begin(UA_Server *server, UA_UInt16* ns) { |
| 74209 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74210 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 74211 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransportSettings"); |
| 74212 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 74213 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17203LU), |
| 74214 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 74215 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74216 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransportSettings"), |
| 74217 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17721LU), |
| 74218 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 74219 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74220 | return retVal; |
| 74221 | } |
| 74222 | |
| 74223 | static UA_StatusCode function_namespace0_generated_220_finish(UA_Server *server, UA_UInt16* ns) { |
| 74224 | return UA_Server_addNode_finish(server, |
| 74225 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17203LU) |
| 74226 | ); |
| 74227 | } |
| 74228 | |
| 74229 | /* Status - ns=0;i=14600 */ |
| 74230 | |
| 74231 | static UA_StatusCode function_namespace0_generated_221_begin(UA_Server *server, UA_UInt16* ns) { |
| 74232 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74233 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 74234 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Status"); |
| 74235 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 74236 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14600LU), |
| 74237 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 74238 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74239 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Status"), |
| 74240 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14643LU), |
| 74241 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 74242 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74243 | return retVal; |
| 74244 | } |
| 74245 | |
| 74246 | static UA_StatusCode function_namespace0_generated_221_finish(UA_Server *server, UA_UInt16* ns) { |
| 74247 | return UA_Server_addNode_finish(server, |
| 74248 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14600LU) |
| 74249 | ); |
| 74250 | } |
| 74251 | |
| 74252 | /* State - ns=0;i=14601 */ |
| 74253 | |
| 74254 | static UA_StatusCode function_namespace0_generated_222_begin(UA_Server *server, UA_UInt16* ns) { |
| 74255 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74256 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74257 | attr.minimumSamplingInterval = 0.000000; |
| 74258 | attr.userAccessLevel = 1; |
| 74259 | attr.accessLevel = 1; |
| 74260 | /* Value rank inherited */ |
| 74261 | attr.valueRank = -2; |
| 74262 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14647LU); |
| 74263 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "State"); |
| 74264 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74265 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14601LU), |
| 74266 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14600LU), |
| 74267 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74268 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "State"), |
| 74269 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 74270 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74271 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74272 | return retVal; |
| 74273 | } |
| 74274 | |
| 74275 | static UA_StatusCode function_namespace0_generated_222_finish(UA_Server *server, UA_UInt16* ns) { |
| 74276 | return UA_Server_addNode_finish(server, |
| 74277 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14601LU) |
| 74278 | ); |
| 74279 | } |
| 74280 | |
| 74281 | /* PublisherId - ns=0;i=14595 */ |
| 74282 | |
| 74283 | static UA_StatusCode function_namespace0_generated_223_begin(UA_Server *server, UA_UInt16* ns) { |
| 74284 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74285 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74286 | attr.minimumSamplingInterval = 0.000000; |
| 74287 | attr.userAccessLevel = 1; |
| 74288 | attr.accessLevel = 1; |
| 74289 | /* Value rank inherited */ |
| 74290 | attr.valueRank = -2; |
| 74291 | /* DataType inherited */ |
| 74292 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 74293 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublisherId"); |
| 74294 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74295 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14595LU), |
| 74296 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 74297 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74298 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublisherId"), |
| 74299 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74300 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74301 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74302 | return retVal; |
| 74303 | } |
| 74304 | |
| 74305 | static UA_StatusCode function_namespace0_generated_223_finish(UA_Server *server, UA_UInt16* ns) { |
| 74306 | return UA_Server_addNode_finish(server, |
| 74307 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14595LU) |
| 74308 | ); |
| 74309 | } |
| 74310 | |
| 74311 | /* RemoveGroup - ns=0;i=14225 */ |
| 74312 | |
| 74313 | static UA_StatusCode function_namespace0_generated_224_begin(UA_Server *server, UA_UInt16* ns) { |
| 74314 | #ifdef UA_ENABLE_METHODCALLS |
| 74315 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74316 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 74317 | attr.executable = true; |
| 74318 | attr.userExecutable = true; |
| 74319 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveGroup"); |
| 74320 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 74321 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14225LU), |
| 74322 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 74323 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74324 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveGroup"), |
| 74325 | typeDefinition: UA_NODEID_NULL, |
| 74326 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 74327 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74328 | return retVal; |
| 74329 | #else |
| 74330 | return UA_STATUSCODE_GOOD; |
| 74331 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74332 | } |
| 74333 | |
| 74334 | static UA_StatusCode function_namespace0_generated_224_finish(UA_Server *server, UA_UInt16* ns) { |
| 74335 | #ifdef UA_ENABLE_METHODCALLS |
| 74336 | return UA_Server_addMethodNode_finish(server, |
| 74337 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14225LU) |
| 74338 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 74339 | #else |
| 74340 | return UA_STATUSCODE_GOOD; |
| 74341 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74342 | } |
| 74343 | |
| 74344 | /* InputArguments - ns=0;i=14226 */ |
| 74345 | |
| 74346 | static UA_StatusCode function_namespace0_generated_225_begin(UA_Server *server, UA_UInt16* ns) { |
| 74347 | #ifdef UA_ENABLE_METHODCALLS |
| 74348 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74349 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74350 | attr.minimumSamplingInterval = 0.000000; |
| 74351 | attr.userAccessLevel = 1; |
| 74352 | attr.accessLevel = 1; |
| 74353 | attr.valueRank = 1; |
| 74354 | attr.arrayDimensionsSize = 1; |
| 74355 | UA_UInt32 arrayDimensions[1]; |
| 74356 | arrayDimensions[0] = 0; |
| 74357 | attr.arrayDimensions = &arrayDimensions[0]; |
| 74358 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 74359 | UA_Argument variablenode_ns_0_i_14226_variant_DataContents[1]; |
| 74360 | |
| 74361 | UA_init(p: &variablenode_ns_0_i_14226_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74362 | variablenode_ns_0_i_14226_variant_DataContents[0].name = UA_STRING(chars: "GroupId"); |
| 74363 | variablenode_ns_0_i_14226_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 74364 | variablenode_ns_0_i_14226_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 74365 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_14226_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74366 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 74367 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74368 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14226LU), |
| 74369 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14225LU), |
| 74370 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74371 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 74372 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74373 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74374 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74375 | |
| 74376 | return retVal; |
| 74377 | #else |
| 74378 | return UA_STATUSCODE_GOOD; |
| 74379 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74380 | } |
| 74381 | |
| 74382 | static UA_StatusCode function_namespace0_generated_225_finish(UA_Server *server, UA_UInt16* ns) { |
| 74383 | #ifdef UA_ENABLE_METHODCALLS |
| 74384 | return UA_Server_addNode_finish(server, |
| 74385 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14226LU) |
| 74386 | ); |
| 74387 | #else |
| 74388 | return UA_STATUSCODE_GOOD; |
| 74389 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74390 | } |
| 74391 | |
| 74392 | /* Address - ns=0;i=14221 */ |
| 74393 | |
| 74394 | static UA_StatusCode function_namespace0_generated_226_begin(UA_Server *server, UA_UInt16* ns) { |
| 74395 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74396 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 74397 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Address"); |
| 74398 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 74399 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14221LU), |
| 74400 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 74401 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74402 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Address"), |
| 74403 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21145LU), |
| 74404 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 74405 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74406 | return retVal; |
| 74407 | } |
| 74408 | |
| 74409 | static UA_StatusCode function_namespace0_generated_226_finish(UA_Server *server, UA_UInt16* ns) { |
| 74410 | return UA_Server_addNode_finish(server, |
| 74411 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14221LU) |
| 74412 | ); |
| 74413 | } |
| 74414 | |
| 74415 | /* NetworkInterface - ns=0;i=17202 */ |
| 74416 | |
| 74417 | static UA_StatusCode function_namespace0_generated_227_begin(UA_Server *server, UA_UInt16* ns) { |
| 74418 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74419 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74420 | attr.minimumSamplingInterval = 0.000000; |
| 74421 | attr.userAccessLevel = 1; |
| 74422 | attr.accessLevel = 1; |
| 74423 | /* Value rank inherited */ |
| 74424 | attr.valueRank = -2; |
| 74425 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 74426 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NetworkInterface"); |
| 74427 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74428 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17202LU), |
| 74429 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14221LU), |
| 74430 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74431 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NetworkInterface"), |
| 74432 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 74433 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74434 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74435 | return retVal; |
| 74436 | } |
| 74437 | |
| 74438 | static UA_StatusCode function_namespace0_generated_227_finish(UA_Server *server, UA_UInt16* ns) { |
| 74439 | return UA_Server_addNode_finish(server, |
| 74440 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17202LU) |
| 74441 | ); |
| 74442 | } |
| 74443 | |
| 74444 | /* PublishedDataSetType - ns=0;i=14509 */ |
| 74445 | |
| 74446 | static UA_StatusCode function_namespace0_generated_228_begin(UA_Server *server, UA_UInt16* ns) { |
| 74447 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74448 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 74449 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishedDataSetType"); |
| 74450 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 74451 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14509LU), |
| 74452 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 74453 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 74454 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishedDataSetType"), |
| 74455 | typeDefinition: UA_NODEID_NULL, |
| 74456 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 74457 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74458 | return retVal; |
| 74459 | } |
| 74460 | |
| 74461 | static UA_StatusCode function_namespace0_generated_228_finish(UA_Server *server, UA_UInt16* ns) { |
| 74462 | return UA_Server_addNode_finish(server, |
| 74463 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14509LU) |
| 74464 | ); |
| 74465 | } |
| 74466 | |
| 74467 | /* DataSetClassId - ns=0;i=16759 */ |
| 74468 | |
| 74469 | static UA_StatusCode function_namespace0_generated_229_begin(UA_Server *server, UA_UInt16* ns) { |
| 74470 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74471 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74472 | attr.minimumSamplingInterval = 0.000000; |
| 74473 | attr.userAccessLevel = 1; |
| 74474 | attr.accessLevel = 1; |
| 74475 | /* Value rank inherited */ |
| 74476 | attr.valueRank = -2; |
| 74477 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14LU); |
| 74478 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetClassId"); |
| 74479 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74480 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16759LU), |
| 74481 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14509LU), |
| 74482 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74483 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetClassId"), |
| 74484 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74485 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74486 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74487 | return retVal; |
| 74488 | } |
| 74489 | |
| 74490 | static UA_StatusCode function_namespace0_generated_229_finish(UA_Server *server, UA_UInt16* ns) { |
| 74491 | return UA_Server_addNode_finish(server, |
| 74492 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16759LU) |
| 74493 | ); |
| 74494 | } |
| 74495 | |
| 74496 | /* DataSetMetaData - ns=0;i=15229 */ |
| 74497 | |
| 74498 | static UA_StatusCode function_namespace0_generated_230_begin(UA_Server *server, UA_UInt16* ns) { |
| 74499 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74500 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74501 | attr.minimumSamplingInterval = 0.000000; |
| 74502 | attr.userAccessLevel = 1; |
| 74503 | attr.accessLevel = 1; |
| 74504 | /* Value rank inherited */ |
| 74505 | attr.valueRank = -2; |
| 74506 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14523LU); |
| 74507 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetMetaData"); |
| 74508 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74509 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15229LU), |
| 74510 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14509LU), |
| 74511 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74512 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetMetaData"), |
| 74513 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74514 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74515 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74516 | return retVal; |
| 74517 | } |
| 74518 | |
| 74519 | static UA_StatusCode function_namespace0_generated_230_finish(UA_Server *server, UA_UInt16* ns) { |
| 74520 | return UA_Server_addNode_finish(server, |
| 74521 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15229LU) |
| 74522 | ); |
| 74523 | } |
| 74524 | |
| 74525 | /* PublishedDataItemsType - ns=0;i=14534 */ |
| 74526 | |
| 74527 | static UA_StatusCode function_namespace0_generated_231_begin(UA_Server *server, UA_UInt16* ns) { |
| 74528 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74529 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 74530 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishedDataItemsType"); |
| 74531 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 74532 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14534LU), |
| 74533 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14509LU), |
| 74534 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 74535 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishedDataItemsType"), |
| 74536 | typeDefinition: UA_NODEID_NULL, |
| 74537 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 74538 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74539 | return retVal; |
| 74540 | } |
| 74541 | |
| 74542 | static UA_StatusCode function_namespace0_generated_231_finish(UA_Server *server, UA_UInt16* ns) { |
| 74543 | return UA_Server_addNode_finish(server, |
| 74544 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14534LU) |
| 74545 | ); |
| 74546 | } |
| 74547 | |
| 74548 | /* RemoveVariables - ns=0;i=14558 */ |
| 74549 | |
| 74550 | static UA_StatusCode function_namespace0_generated_232_begin(UA_Server *server, UA_UInt16* ns) { |
| 74551 | #ifdef UA_ENABLE_METHODCALLS |
| 74552 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74553 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 74554 | attr.executable = true; |
| 74555 | attr.userExecutable = true; |
| 74556 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveVariables"); |
| 74557 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 74558 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14558LU), |
| 74559 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14534LU), |
| 74560 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74561 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveVariables"), |
| 74562 | typeDefinition: UA_NODEID_NULL, |
| 74563 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 74564 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74565 | return retVal; |
| 74566 | #else |
| 74567 | return UA_STATUSCODE_GOOD; |
| 74568 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74569 | } |
| 74570 | |
| 74571 | static UA_StatusCode function_namespace0_generated_232_finish(UA_Server *server, UA_UInt16* ns) { |
| 74572 | #ifdef UA_ENABLE_METHODCALLS |
| 74573 | return UA_Server_addMethodNode_finish(server, |
| 74574 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14558LU) |
| 74575 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 74576 | #else |
| 74577 | return UA_STATUSCODE_GOOD; |
| 74578 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74579 | } |
| 74580 | |
| 74581 | /* OutputArguments - ns=0;i=14560 */ |
| 74582 | |
| 74583 | static UA_StatusCode function_namespace0_generated_233_begin(UA_Server *server, UA_UInt16* ns) { |
| 74584 | #ifdef UA_ENABLE_METHODCALLS |
| 74585 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74586 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74587 | attr.minimumSamplingInterval = 0.000000; |
| 74588 | attr.userAccessLevel = 1; |
| 74589 | attr.accessLevel = 1; |
| 74590 | attr.valueRank = 1; |
| 74591 | attr.arrayDimensionsSize = 1; |
| 74592 | UA_UInt32 arrayDimensions[1]; |
| 74593 | arrayDimensions[0] = 0; |
| 74594 | attr.arrayDimensions = &arrayDimensions[0]; |
| 74595 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 74596 | UA_Argument variablenode_ns_0_i_14560_variant_DataContents[2]; |
| 74597 | |
| 74598 | UA_init(p: &variablenode_ns_0_i_14560_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74599 | variablenode_ns_0_i_14560_variant_DataContents[0].name = UA_STRING(chars: "NewConfigurationVersion"); |
| 74600 | variablenode_ns_0_i_14560_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14593LU); |
| 74601 | variablenode_ns_0_i_14560_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 74602 | |
| 74603 | UA_init(p: &variablenode_ns_0_i_14560_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74604 | variablenode_ns_0_i_14560_variant_DataContents[1].name = UA_STRING(chars: "RemoveResults"); |
| 74605 | variablenode_ns_0_i_14560_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU); |
| 74606 | variablenode_ns_0_i_14560_variant_DataContents[1].valueRank = (UA_Int32) 1; |
| 74607 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_14560_variant_DataContents, arraySize: (UA_Int32) 2, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74608 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 74609 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74610 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14560LU), |
| 74611 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14558LU), |
| 74612 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74613 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 74614 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74615 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74616 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74617 | |
| 74618 | |
| 74619 | return retVal; |
| 74620 | #else |
| 74621 | return UA_STATUSCODE_GOOD; |
| 74622 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74623 | } |
| 74624 | |
| 74625 | static UA_StatusCode function_namespace0_generated_233_finish(UA_Server *server, UA_UInt16* ns) { |
| 74626 | #ifdef UA_ENABLE_METHODCALLS |
| 74627 | return UA_Server_addNode_finish(server, |
| 74628 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14560LU) |
| 74629 | ); |
| 74630 | #else |
| 74631 | return UA_STATUSCODE_GOOD; |
| 74632 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74633 | } |
| 74634 | |
| 74635 | /* InputArguments - ns=0;i=14559 */ |
| 74636 | |
| 74637 | static UA_StatusCode function_namespace0_generated_234_begin(UA_Server *server, UA_UInt16* ns) { |
| 74638 | #ifdef UA_ENABLE_METHODCALLS |
| 74639 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74640 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74641 | attr.minimumSamplingInterval = 0.000000; |
| 74642 | attr.userAccessLevel = 1; |
| 74643 | attr.accessLevel = 1; |
| 74644 | attr.valueRank = 1; |
| 74645 | attr.arrayDimensionsSize = 1; |
| 74646 | UA_UInt32 arrayDimensions[1]; |
| 74647 | arrayDimensions[0] = 0; |
| 74648 | attr.arrayDimensions = &arrayDimensions[0]; |
| 74649 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 74650 | UA_Argument variablenode_ns_0_i_14559_variant_DataContents[2]; |
| 74651 | |
| 74652 | UA_init(p: &variablenode_ns_0_i_14559_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74653 | variablenode_ns_0_i_14559_variant_DataContents[0].name = UA_STRING(chars: "ConfigurationVersion"); |
| 74654 | variablenode_ns_0_i_14559_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14593LU); |
| 74655 | variablenode_ns_0_i_14559_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 74656 | |
| 74657 | UA_init(p: &variablenode_ns_0_i_14559_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74658 | variablenode_ns_0_i_14559_variant_DataContents[1].name = UA_STRING(chars: "VariablesToRemove"); |
| 74659 | variablenode_ns_0_i_14559_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 74660 | variablenode_ns_0_i_14559_variant_DataContents[1].valueRank = (UA_Int32) 1; |
| 74661 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_14559_variant_DataContents, arraySize: (UA_Int32) 2, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74662 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 74663 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74664 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14559LU), |
| 74665 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14558LU), |
| 74666 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74667 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 74668 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74669 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74670 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74671 | |
| 74672 | |
| 74673 | return retVal; |
| 74674 | #else |
| 74675 | return UA_STATUSCODE_GOOD; |
| 74676 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74677 | } |
| 74678 | |
| 74679 | static UA_StatusCode function_namespace0_generated_234_finish(UA_Server *server, UA_UInt16* ns) { |
| 74680 | #ifdef UA_ENABLE_METHODCALLS |
| 74681 | return UA_Server_addNode_finish(server, |
| 74682 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14559LU) |
| 74683 | ); |
| 74684 | #else |
| 74685 | return UA_STATUSCODE_GOOD; |
| 74686 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74687 | } |
| 74688 | |
| 74689 | /* AddVariables - ns=0;i=14555 */ |
| 74690 | |
| 74691 | static UA_StatusCode function_namespace0_generated_235_begin(UA_Server *server, UA_UInt16* ns) { |
| 74692 | #ifdef UA_ENABLE_METHODCALLS |
| 74693 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74694 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 74695 | attr.executable = true; |
| 74696 | attr.userExecutable = true; |
| 74697 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddVariables"); |
| 74698 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 74699 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14555LU), |
| 74700 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14534LU), |
| 74701 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74702 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddVariables"), |
| 74703 | typeDefinition: UA_NODEID_NULL, |
| 74704 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 74705 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74706 | return retVal; |
| 74707 | #else |
| 74708 | return UA_STATUSCODE_GOOD; |
| 74709 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74710 | } |
| 74711 | |
| 74712 | static UA_StatusCode function_namespace0_generated_235_finish(UA_Server *server, UA_UInt16* ns) { |
| 74713 | #ifdef UA_ENABLE_METHODCALLS |
| 74714 | return UA_Server_addMethodNode_finish(server, |
| 74715 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14555LU) |
| 74716 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 74717 | #else |
| 74718 | return UA_STATUSCODE_GOOD; |
| 74719 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74720 | } |
| 74721 | |
| 74722 | /* OutputArguments - ns=0;i=14557 */ |
| 74723 | |
| 74724 | static UA_StatusCode function_namespace0_generated_236_begin(UA_Server *server, UA_UInt16* ns) { |
| 74725 | #ifdef UA_ENABLE_METHODCALLS |
| 74726 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74727 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74728 | attr.minimumSamplingInterval = 0.000000; |
| 74729 | attr.userAccessLevel = 1; |
| 74730 | attr.accessLevel = 1; |
| 74731 | attr.valueRank = 1; |
| 74732 | attr.arrayDimensionsSize = 1; |
| 74733 | UA_UInt32 arrayDimensions[1]; |
| 74734 | arrayDimensions[0] = 0; |
| 74735 | attr.arrayDimensions = &arrayDimensions[0]; |
| 74736 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 74737 | UA_Argument variablenode_ns_0_i_14557_variant_DataContents[2]; |
| 74738 | |
| 74739 | UA_init(p: &variablenode_ns_0_i_14557_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74740 | variablenode_ns_0_i_14557_variant_DataContents[0].name = UA_STRING(chars: "NewConfigurationVersion"); |
| 74741 | variablenode_ns_0_i_14557_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14593LU); |
| 74742 | variablenode_ns_0_i_14557_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 74743 | |
| 74744 | UA_init(p: &variablenode_ns_0_i_14557_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74745 | variablenode_ns_0_i_14557_variant_DataContents[1].name = UA_STRING(chars: "AddResults"); |
| 74746 | variablenode_ns_0_i_14557_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU); |
| 74747 | variablenode_ns_0_i_14557_variant_DataContents[1].valueRank = (UA_Int32) 1; |
| 74748 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_14557_variant_DataContents, arraySize: (UA_Int32) 2, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74749 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 74750 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74751 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14557LU), |
| 74752 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14555LU), |
| 74753 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74754 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 74755 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74756 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74757 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74758 | |
| 74759 | |
| 74760 | return retVal; |
| 74761 | #else |
| 74762 | return UA_STATUSCODE_GOOD; |
| 74763 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74764 | } |
| 74765 | |
| 74766 | static UA_StatusCode function_namespace0_generated_236_finish(UA_Server *server, UA_UInt16* ns) { |
| 74767 | #ifdef UA_ENABLE_METHODCALLS |
| 74768 | return UA_Server_addNode_finish(server, |
| 74769 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14557LU) |
| 74770 | ); |
| 74771 | #else |
| 74772 | return UA_STATUSCODE_GOOD; |
| 74773 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74774 | } |
| 74775 | |
| 74776 | /* InputArguments - ns=0;i=14556 */ |
| 74777 | |
| 74778 | static UA_StatusCode function_namespace0_generated_237_begin(UA_Server *server, UA_UInt16* ns) { |
| 74779 | #ifdef UA_ENABLE_METHODCALLS |
| 74780 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74781 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74782 | attr.minimumSamplingInterval = 0.000000; |
| 74783 | attr.userAccessLevel = 1; |
| 74784 | attr.accessLevel = 1; |
| 74785 | attr.valueRank = 1; |
| 74786 | attr.arrayDimensionsSize = 1; |
| 74787 | UA_UInt32 arrayDimensions[1]; |
| 74788 | arrayDimensions[0] = 0; |
| 74789 | attr.arrayDimensions = &arrayDimensions[0]; |
| 74790 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 74791 | UA_Argument variablenode_ns_0_i_14556_variant_DataContents[4]; |
| 74792 | |
| 74793 | UA_init(p: &variablenode_ns_0_i_14556_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74794 | variablenode_ns_0_i_14556_variant_DataContents[0].name = UA_STRING(chars: "ConfigurationVersion"); |
| 74795 | variablenode_ns_0_i_14556_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14593LU); |
| 74796 | variablenode_ns_0_i_14556_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 74797 | |
| 74798 | UA_init(p: &variablenode_ns_0_i_14556_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74799 | variablenode_ns_0_i_14556_variant_DataContents[1].name = UA_STRING(chars: "FieldNameAliases"); |
| 74800 | variablenode_ns_0_i_14556_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 74801 | variablenode_ns_0_i_14556_variant_DataContents[1].valueRank = (UA_Int32) 1; |
| 74802 | |
| 74803 | UA_init(p: &variablenode_ns_0_i_14556_variant_DataContents[2], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74804 | variablenode_ns_0_i_14556_variant_DataContents[2].name = UA_STRING(chars: "PromotedFields"); |
| 74805 | variablenode_ns_0_i_14556_variant_DataContents[2].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 74806 | variablenode_ns_0_i_14556_variant_DataContents[2].valueRank = (UA_Int32) 1; |
| 74807 | |
| 74808 | UA_init(p: &variablenode_ns_0_i_14556_variant_DataContents[3], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74809 | variablenode_ns_0_i_14556_variant_DataContents[3].name = UA_STRING(chars: "VariablesToAdd"); |
| 74810 | variablenode_ns_0_i_14556_variant_DataContents[3].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14273LU); |
| 74811 | variablenode_ns_0_i_14556_variant_DataContents[3].valueRank = (UA_Int32) 1; |
| 74812 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_14556_variant_DataContents, arraySize: (UA_Int32) 4, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74813 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 74814 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74815 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14556LU), |
| 74816 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14555LU), |
| 74817 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74818 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 74819 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74820 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74821 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74822 | |
| 74823 | |
| 74824 | |
| 74825 | |
| 74826 | return retVal; |
| 74827 | #else |
| 74828 | return UA_STATUSCODE_GOOD; |
| 74829 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74830 | } |
| 74831 | |
| 74832 | static UA_StatusCode function_namespace0_generated_237_finish(UA_Server *server, UA_UInt16* ns) { |
| 74833 | #ifdef UA_ENABLE_METHODCALLS |
| 74834 | return UA_Server_addNode_finish(server, |
| 74835 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14556LU) |
| 74836 | ); |
| 74837 | #else |
| 74838 | return UA_STATUSCODE_GOOD; |
| 74839 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74840 | } |
| 74841 | |
| 74842 | /* PublishedData - ns=0;i=14548 */ |
| 74843 | |
| 74844 | static UA_StatusCode function_namespace0_generated_238_begin(UA_Server *server, UA_UInt16* ns) { |
| 74845 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74846 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74847 | attr.minimumSamplingInterval = 0.000000; |
| 74848 | attr.userAccessLevel = 1; |
| 74849 | attr.accessLevel = 1; |
| 74850 | attr.valueRank = 1; |
| 74851 | attr.arrayDimensionsSize = 1; |
| 74852 | UA_UInt32 arrayDimensions[1]; |
| 74853 | arrayDimensions[0] = 0; |
| 74854 | attr.arrayDimensions = &arrayDimensions[0]; |
| 74855 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14273LU); |
| 74856 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishedData"); |
| 74857 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74858 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14548LU), |
| 74859 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14534LU), |
| 74860 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74861 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishedData"), |
| 74862 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74863 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74864 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74865 | return retVal; |
| 74866 | } |
| 74867 | |
| 74868 | static UA_StatusCode function_namespace0_generated_238_finish(UA_Server *server, UA_UInt16* ns) { |
| 74869 | return UA_Server_addNode_finish(server, |
| 74870 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14548LU) |
| 74871 | ); |
| 74872 | } |
| 74873 | |
| 74874 | /* ConfigurationVersion - ns=0;i=14519 */ |
| 74875 | |
| 74876 | static UA_StatusCode function_namespace0_generated_239_begin(UA_Server *server, UA_UInt16* ns) { |
| 74877 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74878 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74879 | attr.minimumSamplingInterval = 0.000000; |
| 74880 | attr.userAccessLevel = 1; |
| 74881 | attr.accessLevel = 1; |
| 74882 | /* Value rank inherited */ |
| 74883 | attr.valueRank = -2; |
| 74884 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14593LU); |
| 74885 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConfigurationVersion"); |
| 74886 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74887 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14519LU), |
| 74888 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14509LU), |
| 74889 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74890 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConfigurationVersion"), |
| 74891 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74892 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74893 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74894 | return retVal; |
| 74895 | } |
| 74896 | |
| 74897 | static UA_StatusCode function_namespace0_generated_239_finish(UA_Server *server, UA_UInt16* ns) { |
| 74898 | return UA_Server_addNode_finish(server, |
| 74899 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14519LU) |
| 74900 | ); |
| 74901 | } |
| 74902 | |
| 74903 | /* DataSetFolderType - ns=0;i=14477 */ |
| 74904 | |
| 74905 | static UA_StatusCode function_namespace0_generated_240_begin(UA_Server *server, UA_UInt16* ns) { |
| 74906 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74907 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 74908 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataSetFolderType"); |
| 74909 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 74910 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14477LU), |
| 74911 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU), |
| 74912 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 74913 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataSetFolderType"), |
| 74914 | typeDefinition: UA_NODEID_NULL, |
| 74915 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 74916 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74917 | return retVal; |
| 74918 | } |
| 74919 | |
| 74920 | static UA_StatusCode function_namespace0_generated_240_finish(UA_Server *server, UA_UInt16* ns) { |
| 74921 | return UA_Server_addNode_finish(server, |
| 74922 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14477LU) |
| 74923 | ); |
| 74924 | } |
| 74925 | |
| 74926 | /* RemoveDataSetFolder - ns=0;i=16997 */ |
| 74927 | |
| 74928 | static UA_StatusCode function_namespace0_generated_241_begin(UA_Server *server, UA_UInt16* ns) { |
| 74929 | #ifdef UA_ENABLE_METHODCALLS |
| 74930 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74931 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 74932 | attr.executable = true; |
| 74933 | attr.userExecutable = true; |
| 74934 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveDataSetFolder"); |
| 74935 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 74936 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16997LU), |
| 74937 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14477LU), |
| 74938 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 74939 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveDataSetFolder"), |
| 74940 | typeDefinition: UA_NODEID_NULL, |
| 74941 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 74942 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74943 | return retVal; |
| 74944 | #else |
| 74945 | return UA_STATUSCODE_GOOD; |
| 74946 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74947 | } |
| 74948 | |
| 74949 | static UA_StatusCode function_namespace0_generated_241_finish(UA_Server *server, UA_UInt16* ns) { |
| 74950 | #ifdef UA_ENABLE_METHODCALLS |
| 74951 | return UA_Server_addMethodNode_finish(server, |
| 74952 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16997LU) |
| 74953 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 74954 | #else |
| 74955 | return UA_STATUSCODE_GOOD; |
| 74956 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74957 | } |
| 74958 | |
| 74959 | /* InputArguments - ns=0;i=17007 */ |
| 74960 | |
| 74961 | static UA_StatusCode function_namespace0_generated_242_begin(UA_Server *server, UA_UInt16* ns) { |
| 74962 | #ifdef UA_ENABLE_METHODCALLS |
| 74963 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 74964 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 74965 | attr.minimumSamplingInterval = 0.000000; |
| 74966 | attr.userAccessLevel = 1; |
| 74967 | attr.accessLevel = 1; |
| 74968 | attr.valueRank = 1; |
| 74969 | attr.arrayDimensionsSize = 1; |
| 74970 | UA_UInt32 arrayDimensions[1]; |
| 74971 | arrayDimensions[0] = 0; |
| 74972 | attr.arrayDimensions = &arrayDimensions[0]; |
| 74973 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 74974 | UA_Argument variablenode_ns_0_i_17007_variant_DataContents[1]; |
| 74975 | |
| 74976 | UA_init(p: &variablenode_ns_0_i_17007_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74977 | variablenode_ns_0_i_17007_variant_DataContents[0].name = UA_STRING(chars: "DataSetFolderNodeId"); |
| 74978 | variablenode_ns_0_i_17007_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 74979 | variablenode_ns_0_i_17007_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 74980 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17007_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 74981 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 74982 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 74983 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17007LU), |
| 74984 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16997LU), |
| 74985 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 74986 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 74987 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 74988 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 74989 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 74990 | |
| 74991 | return retVal; |
| 74992 | #else |
| 74993 | return UA_STATUSCODE_GOOD; |
| 74994 | #endif /* UA_ENABLE_METHODCALLS */ |
| 74995 | } |
| 74996 | |
| 74997 | static UA_StatusCode function_namespace0_generated_242_finish(UA_Server *server, UA_UInt16* ns) { |
| 74998 | #ifdef UA_ENABLE_METHODCALLS |
| 74999 | return UA_Server_addNode_finish(server, |
| 75000 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17007LU) |
| 75001 | ); |
| 75002 | #else |
| 75003 | return UA_STATUSCODE_GOOD; |
| 75004 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75005 | } |
| 75006 | |
| 75007 | /* AddDataSetFolder - ns=0;i=16994 */ |
| 75008 | |
| 75009 | static UA_StatusCode function_namespace0_generated_243_begin(UA_Server *server, UA_UInt16* ns) { |
| 75010 | #ifdef UA_ENABLE_METHODCALLS |
| 75011 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75012 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 75013 | attr.executable = true; |
| 75014 | attr.userExecutable = true; |
| 75015 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddDataSetFolder"); |
| 75016 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 75017 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16994LU), |
| 75018 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14477LU), |
| 75019 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75020 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddDataSetFolder"), |
| 75021 | typeDefinition: UA_NODEID_NULL, |
| 75022 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 75023 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75024 | return retVal; |
| 75025 | #else |
| 75026 | return UA_STATUSCODE_GOOD; |
| 75027 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75028 | } |
| 75029 | |
| 75030 | static UA_StatusCode function_namespace0_generated_243_finish(UA_Server *server, UA_UInt16* ns) { |
| 75031 | #ifdef UA_ENABLE_METHODCALLS |
| 75032 | return UA_Server_addMethodNode_finish(server, |
| 75033 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16994LU) |
| 75034 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 75035 | #else |
| 75036 | return UA_STATUSCODE_GOOD; |
| 75037 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75038 | } |
| 75039 | |
| 75040 | /* OutputArguments - ns=0;i=16996 */ |
| 75041 | |
| 75042 | static UA_StatusCode function_namespace0_generated_244_begin(UA_Server *server, UA_UInt16* ns) { |
| 75043 | #ifdef UA_ENABLE_METHODCALLS |
| 75044 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75045 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75046 | attr.minimumSamplingInterval = 0.000000; |
| 75047 | attr.userAccessLevel = 1; |
| 75048 | attr.accessLevel = 1; |
| 75049 | attr.valueRank = 1; |
| 75050 | attr.arrayDimensionsSize = 1; |
| 75051 | UA_UInt32 arrayDimensions[1]; |
| 75052 | arrayDimensions[0] = 0; |
| 75053 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75054 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 75055 | UA_Argument variablenode_ns_0_i_16996_variant_DataContents[1]; |
| 75056 | |
| 75057 | UA_init(p: &variablenode_ns_0_i_16996_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75058 | variablenode_ns_0_i_16996_variant_DataContents[0].name = UA_STRING(chars: "DataSetFolderNodeId"); |
| 75059 | variablenode_ns_0_i_16996_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 75060 | variablenode_ns_0_i_16996_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 75061 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_16996_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75062 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 75063 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75064 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16996LU), |
| 75065 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16994LU), |
| 75066 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75067 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 75068 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75069 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75070 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75071 | |
| 75072 | return retVal; |
| 75073 | #else |
| 75074 | return UA_STATUSCODE_GOOD; |
| 75075 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75076 | } |
| 75077 | |
| 75078 | static UA_StatusCode function_namespace0_generated_244_finish(UA_Server *server, UA_UInt16* ns) { |
| 75079 | #ifdef UA_ENABLE_METHODCALLS |
| 75080 | return UA_Server_addNode_finish(server, |
| 75081 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16996LU) |
| 75082 | ); |
| 75083 | #else |
| 75084 | return UA_STATUSCODE_GOOD; |
| 75085 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75086 | } |
| 75087 | |
| 75088 | /* InputArguments - ns=0;i=16995 */ |
| 75089 | |
| 75090 | static UA_StatusCode function_namespace0_generated_245_begin(UA_Server *server, UA_UInt16* ns) { |
| 75091 | #ifdef UA_ENABLE_METHODCALLS |
| 75092 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75093 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75094 | attr.minimumSamplingInterval = 0.000000; |
| 75095 | attr.userAccessLevel = 1; |
| 75096 | attr.accessLevel = 1; |
| 75097 | attr.valueRank = 1; |
| 75098 | attr.arrayDimensionsSize = 1; |
| 75099 | UA_UInt32 arrayDimensions[1]; |
| 75100 | arrayDimensions[0] = 0; |
| 75101 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75102 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 75103 | UA_Argument variablenode_ns_0_i_16995_variant_DataContents[1]; |
| 75104 | |
| 75105 | UA_init(p: &variablenode_ns_0_i_16995_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75106 | variablenode_ns_0_i_16995_variant_DataContents[0].name = UA_STRING(chars: "Name"); |
| 75107 | variablenode_ns_0_i_16995_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 75108 | variablenode_ns_0_i_16995_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 75109 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_16995_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75110 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 75111 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75112 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16995LU), |
| 75113 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16994LU), |
| 75114 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75115 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 75116 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75117 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75118 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75119 | |
| 75120 | return retVal; |
| 75121 | #else |
| 75122 | return UA_STATUSCODE_GOOD; |
| 75123 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75124 | } |
| 75125 | |
| 75126 | static UA_StatusCode function_namespace0_generated_245_finish(UA_Server *server, UA_UInt16* ns) { |
| 75127 | #ifdef UA_ENABLE_METHODCALLS |
| 75128 | return UA_Server_addNode_finish(server, |
| 75129 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16995LU) |
| 75130 | ); |
| 75131 | #else |
| 75132 | return UA_STATUSCODE_GOOD; |
| 75133 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75134 | } |
| 75135 | |
| 75136 | /* RemovePublishedDataSet - ns=0;i=14499 */ |
| 75137 | |
| 75138 | static UA_StatusCode function_namespace0_generated_246_begin(UA_Server *server, UA_UInt16* ns) { |
| 75139 | #ifdef UA_ENABLE_METHODCALLS |
| 75140 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75141 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 75142 | attr.executable = true; |
| 75143 | attr.userExecutable = true; |
| 75144 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemovePublishedDataSet"); |
| 75145 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 75146 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14499LU), |
| 75147 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14477LU), |
| 75148 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75149 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemovePublishedDataSet"), |
| 75150 | typeDefinition: UA_NODEID_NULL, |
| 75151 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 75152 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75153 | return retVal; |
| 75154 | #else |
| 75155 | return UA_STATUSCODE_GOOD; |
| 75156 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75157 | } |
| 75158 | |
| 75159 | static UA_StatusCode function_namespace0_generated_246_finish(UA_Server *server, UA_UInt16* ns) { |
| 75160 | #ifdef UA_ENABLE_METHODCALLS |
| 75161 | return UA_Server_addMethodNode_finish(server, |
| 75162 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14499LU) |
| 75163 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 75164 | #else |
| 75165 | return UA_STATUSCODE_GOOD; |
| 75166 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75167 | } |
| 75168 | |
| 75169 | /* InputArguments - ns=0;i=14500 */ |
| 75170 | |
| 75171 | static UA_StatusCode function_namespace0_generated_247_begin(UA_Server *server, UA_UInt16* ns) { |
| 75172 | #ifdef UA_ENABLE_METHODCALLS |
| 75173 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75174 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75175 | attr.minimumSamplingInterval = 0.000000; |
| 75176 | attr.userAccessLevel = 1; |
| 75177 | attr.accessLevel = 1; |
| 75178 | attr.valueRank = 1; |
| 75179 | attr.arrayDimensionsSize = 1; |
| 75180 | UA_UInt32 arrayDimensions[1]; |
| 75181 | arrayDimensions[0] = 0; |
| 75182 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75183 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 75184 | UA_Argument variablenode_ns_0_i_14500_variant_DataContents[1]; |
| 75185 | |
| 75186 | UA_init(p: &variablenode_ns_0_i_14500_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75187 | variablenode_ns_0_i_14500_variant_DataContents[0].name = UA_STRING(chars: "DataSetNodeId"); |
| 75188 | variablenode_ns_0_i_14500_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 75189 | variablenode_ns_0_i_14500_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 75190 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_14500_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75191 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 75192 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75193 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14500LU), |
| 75194 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14499LU), |
| 75195 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75196 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 75197 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75198 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75199 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75200 | |
| 75201 | return retVal; |
| 75202 | #else |
| 75203 | return UA_STATUSCODE_GOOD; |
| 75204 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75205 | } |
| 75206 | |
| 75207 | static UA_StatusCode function_namespace0_generated_247_finish(UA_Server *server, UA_UInt16* ns) { |
| 75208 | #ifdef UA_ENABLE_METHODCALLS |
| 75209 | return UA_Server_addNode_finish(server, |
| 75210 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14500LU) |
| 75211 | ); |
| 75212 | #else |
| 75213 | return UA_STATUSCODE_GOOD; |
| 75214 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75215 | } |
| 75216 | |
| 75217 | /* AddPublishedDataItems - ns=0;i=14493 */ |
| 75218 | |
| 75219 | static UA_StatusCode function_namespace0_generated_248_begin(UA_Server *server, UA_UInt16* ns) { |
| 75220 | #ifdef UA_ENABLE_METHODCALLS |
| 75221 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75222 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 75223 | attr.executable = true; |
| 75224 | attr.userExecutable = true; |
| 75225 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddPublishedDataItems"); |
| 75226 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 75227 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14493LU), |
| 75228 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14477LU), |
| 75229 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75230 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddPublishedDataItems"), |
| 75231 | typeDefinition: UA_NODEID_NULL, |
| 75232 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 75233 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75234 | return retVal; |
| 75235 | #else |
| 75236 | return UA_STATUSCODE_GOOD; |
| 75237 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75238 | } |
| 75239 | |
| 75240 | static UA_StatusCode function_namespace0_generated_248_finish(UA_Server *server, UA_UInt16* ns) { |
| 75241 | #ifdef UA_ENABLE_METHODCALLS |
| 75242 | return UA_Server_addMethodNode_finish(server, |
| 75243 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14493LU) |
| 75244 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 75245 | #else |
| 75246 | return UA_STATUSCODE_GOOD; |
| 75247 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75248 | } |
| 75249 | |
| 75250 | /* OutputArguments - ns=0;i=14495 */ |
| 75251 | |
| 75252 | static UA_StatusCode function_namespace0_generated_249_begin(UA_Server *server, UA_UInt16* ns) { |
| 75253 | #ifdef UA_ENABLE_METHODCALLS |
| 75254 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75255 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75256 | attr.minimumSamplingInterval = 0.000000; |
| 75257 | attr.userAccessLevel = 1; |
| 75258 | attr.accessLevel = 1; |
| 75259 | attr.valueRank = 1; |
| 75260 | attr.arrayDimensionsSize = 1; |
| 75261 | UA_UInt32 arrayDimensions[1]; |
| 75262 | arrayDimensions[0] = 0; |
| 75263 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75264 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 75265 | UA_Argument variablenode_ns_0_i_14495_variant_DataContents[3]; |
| 75266 | |
| 75267 | UA_init(p: &variablenode_ns_0_i_14495_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75268 | variablenode_ns_0_i_14495_variant_DataContents[0].name = UA_STRING(chars: "DataSetNodeId"); |
| 75269 | variablenode_ns_0_i_14495_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 75270 | variablenode_ns_0_i_14495_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 75271 | |
| 75272 | UA_init(p: &variablenode_ns_0_i_14495_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75273 | variablenode_ns_0_i_14495_variant_DataContents[1].name = UA_STRING(chars: "ConfigurationVersion"); |
| 75274 | variablenode_ns_0_i_14495_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14593LU); |
| 75275 | variablenode_ns_0_i_14495_variant_DataContents[1].valueRank = (UA_Int32) -1; |
| 75276 | |
| 75277 | UA_init(p: &variablenode_ns_0_i_14495_variant_DataContents[2], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75278 | variablenode_ns_0_i_14495_variant_DataContents[2].name = UA_STRING(chars: "AddResults"); |
| 75279 | variablenode_ns_0_i_14495_variant_DataContents[2].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU); |
| 75280 | variablenode_ns_0_i_14495_variant_DataContents[2].valueRank = (UA_Int32) 1; |
| 75281 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_14495_variant_DataContents, arraySize: (UA_Int32) 3, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75282 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 75283 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75284 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14495LU), |
| 75285 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14493LU), |
| 75286 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75287 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 75288 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75289 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75290 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75291 | |
| 75292 | |
| 75293 | |
| 75294 | return retVal; |
| 75295 | #else |
| 75296 | return UA_STATUSCODE_GOOD; |
| 75297 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75298 | } |
| 75299 | |
| 75300 | static UA_StatusCode function_namespace0_generated_249_finish(UA_Server *server, UA_UInt16* ns) { |
| 75301 | #ifdef UA_ENABLE_METHODCALLS |
| 75302 | return UA_Server_addNode_finish(server, |
| 75303 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14495LU) |
| 75304 | ); |
| 75305 | #else |
| 75306 | return UA_STATUSCODE_GOOD; |
| 75307 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75308 | } |
| 75309 | |
| 75310 | /* InputArguments - ns=0;i=14494 */ |
| 75311 | |
| 75312 | static UA_StatusCode function_namespace0_generated_250_begin(UA_Server *server, UA_UInt16* ns) { |
| 75313 | #ifdef UA_ENABLE_METHODCALLS |
| 75314 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75315 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75316 | attr.minimumSamplingInterval = 0.000000; |
| 75317 | attr.userAccessLevel = 1; |
| 75318 | attr.accessLevel = 1; |
| 75319 | attr.valueRank = 1; |
| 75320 | attr.arrayDimensionsSize = 1; |
| 75321 | UA_UInt32 arrayDimensions[1]; |
| 75322 | arrayDimensions[0] = 0; |
| 75323 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75324 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 75325 | UA_Argument variablenode_ns_0_i_14494_variant_DataContents[4]; |
| 75326 | |
| 75327 | UA_init(p: &variablenode_ns_0_i_14494_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75328 | variablenode_ns_0_i_14494_variant_DataContents[0].name = UA_STRING(chars: "Name"); |
| 75329 | variablenode_ns_0_i_14494_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 75330 | variablenode_ns_0_i_14494_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 75331 | |
| 75332 | UA_init(p: &variablenode_ns_0_i_14494_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75333 | variablenode_ns_0_i_14494_variant_DataContents[1].name = UA_STRING(chars: "FieldNameAliases"); |
| 75334 | variablenode_ns_0_i_14494_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 75335 | variablenode_ns_0_i_14494_variant_DataContents[1].valueRank = (UA_Int32) 1; |
| 75336 | |
| 75337 | UA_init(p: &variablenode_ns_0_i_14494_variant_DataContents[2], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75338 | variablenode_ns_0_i_14494_variant_DataContents[2].name = UA_STRING(chars: "FieldFlags"); |
| 75339 | variablenode_ns_0_i_14494_variant_DataContents[2].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15904LU); |
| 75340 | variablenode_ns_0_i_14494_variant_DataContents[2].valueRank = (UA_Int32) 1; |
| 75341 | |
| 75342 | UA_init(p: &variablenode_ns_0_i_14494_variant_DataContents[3], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75343 | variablenode_ns_0_i_14494_variant_DataContents[3].name = UA_STRING(chars: "VariablesToAdd"); |
| 75344 | variablenode_ns_0_i_14494_variant_DataContents[3].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14273LU); |
| 75345 | variablenode_ns_0_i_14494_variant_DataContents[3].valueRank = (UA_Int32) 1; |
| 75346 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_14494_variant_DataContents, arraySize: (UA_Int32) 4, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75347 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 75348 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75349 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14494LU), |
| 75350 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14493LU), |
| 75351 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75352 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 75353 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75354 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75355 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75356 | |
| 75357 | |
| 75358 | |
| 75359 | |
| 75360 | return retVal; |
| 75361 | #else |
| 75362 | return UA_STATUSCODE_GOOD; |
| 75363 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75364 | } |
| 75365 | |
| 75366 | static UA_StatusCode function_namespace0_generated_250_finish(UA_Server *server, UA_UInt16* ns) { |
| 75367 | #ifdef UA_ENABLE_METHODCALLS |
| 75368 | return UA_Server_addNode_finish(server, |
| 75369 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14494LU) |
| 75370 | ); |
| 75371 | #else |
| 75372 | return UA_STATUSCODE_GOOD; |
| 75373 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75374 | } |
| 75375 | |
| 75376 | /* <DataSetFolderName> - ns=0;i=14478 */ |
| 75377 | |
| 75378 | static UA_StatusCode function_namespace0_generated_251_begin(UA_Server *server, UA_UInt16* ns) { |
| 75379 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75380 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 75381 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "<DataSetFolderName>"); |
| 75382 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 75383 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14478LU), |
| 75384 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14477LU), |
| 75385 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU), |
| 75386 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "<DataSetFolderName>"), |
| 75387 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14477LU), |
| 75388 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 75389 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75390 | return retVal; |
| 75391 | } |
| 75392 | |
| 75393 | static UA_StatusCode function_namespace0_generated_251_finish(UA_Server *server, UA_UInt16* ns) { |
| 75394 | return UA_Server_addNode_finish(server, |
| 75395 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14478LU) |
| 75396 | ); |
| 75397 | } |
| 75398 | |
| 75399 | /* PubSubKeyServiceType - ns=0;i=15906 */ |
| 75400 | |
| 75401 | static UA_StatusCode function_namespace0_generated_252_begin(UA_Server *server, UA_UInt16* ns) { |
| 75402 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75403 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 75404 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PubSubKeyServiceType"); |
| 75405 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 75406 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15906LU), |
| 75407 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 75408 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 75409 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PubSubKeyServiceType"), |
| 75410 | typeDefinition: UA_NODEID_NULL, |
| 75411 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 75412 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75413 | return retVal; |
| 75414 | } |
| 75415 | |
| 75416 | static UA_StatusCode function_namespace0_generated_252_finish(UA_Server *server, UA_UInt16* ns) { |
| 75417 | return UA_Server_addNode_finish(server, |
| 75418 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15906LU) |
| 75419 | ); |
| 75420 | } |
| 75421 | |
| 75422 | /* PublishSubscribeType - ns=0;i=14416 */ |
| 75423 | |
| 75424 | static UA_StatusCode function_namespace0_generated_253_begin(UA_Server *server, UA_UInt16* ns) { |
| 75425 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75426 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 75427 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishSubscribeType"); |
| 75428 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 75429 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU), |
| 75430 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15906LU), |
| 75431 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 75432 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishSubscribeType"), |
| 75433 | typeDefinition: UA_NODEID_NULL, |
| 75434 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 75435 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75436 | return retVal; |
| 75437 | } |
| 75438 | |
| 75439 | static UA_StatusCode function_namespace0_generated_253_finish(UA_Server *server, UA_UInt16* ns) { |
| 75440 | return UA_Server_addNode_finish(server, |
| 75441 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU) |
| 75442 | ); |
| 75443 | } |
| 75444 | |
| 75445 | /* DefaultDatagramPublisherId - ns=0;i=25432 */ |
| 75446 | |
| 75447 | static UA_StatusCode function_namespace0_generated_254_begin(UA_Server *server, UA_UInt16* ns) { |
| 75448 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75449 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75450 | attr.minimumSamplingInterval = 0.000000; |
| 75451 | attr.userAccessLevel = 1; |
| 75452 | attr.accessLevel = 1; |
| 75453 | /* Value rank inherited */ |
| 75454 | attr.valueRank = -2; |
| 75455 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9LU); |
| 75456 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DefaultDatagramPublisherId"); |
| 75457 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75458 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25432LU), |
| 75459 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU), |
| 75460 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75461 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DefaultDatagramPublisherId"), |
| 75462 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75463 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75464 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75465 | return retVal; |
| 75466 | } |
| 75467 | |
| 75468 | static UA_StatusCode function_namespace0_generated_254_finish(UA_Server *server, UA_UInt16* ns) { |
| 75469 | return UA_Server_addNode_finish(server, |
| 75470 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25432LU) |
| 75471 | ); |
| 75472 | } |
| 75473 | |
| 75474 | /* SubscribedDataSets - ns=0;i=23622 */ |
| 75475 | |
| 75476 | static UA_StatusCode function_namespace0_generated_255_begin(UA_Server *server, UA_UInt16* ns) { |
| 75477 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75478 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 75479 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscribedDataSets"); |
| 75480 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 75481 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23622LU), |
| 75482 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU), |
| 75483 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75484 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscribedDataSets"), |
| 75485 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU), |
| 75486 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 75487 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75488 | return retVal; |
| 75489 | } |
| 75490 | |
| 75491 | static UA_StatusCode function_namespace0_generated_255_finish(UA_Server *server, UA_UInt16* ns) { |
| 75492 | return UA_Server_addNode_finish(server, |
| 75493 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23622LU) |
| 75494 | ); |
| 75495 | } |
| 75496 | |
| 75497 | /* SupportedTransportProfiles - ns=0;i=17479 */ |
| 75498 | |
| 75499 | static UA_StatusCode function_namespace0_generated_256_begin(UA_Server *server, UA_UInt16* ns) { |
| 75500 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75501 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75502 | attr.minimumSamplingInterval = 0.000000; |
| 75503 | attr.userAccessLevel = 1; |
| 75504 | attr.accessLevel = 1; |
| 75505 | attr.valueRank = 1; |
| 75506 | attr.arrayDimensionsSize = 1; |
| 75507 | UA_UInt32 arrayDimensions[1]; |
| 75508 | arrayDimensions[0] = 0; |
| 75509 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75510 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 75511 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SupportedTransportProfiles"); |
| 75512 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75513 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17479LU), |
| 75514 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU), |
| 75515 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75516 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SupportedTransportProfiles"), |
| 75517 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75518 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75519 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75520 | return retVal; |
| 75521 | } |
| 75522 | |
| 75523 | static UA_StatusCode function_namespace0_generated_256_finish(UA_Server *server, UA_UInt16* ns) { |
| 75524 | return UA_Server_addNode_finish(server, |
| 75525 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17479LU) |
| 75526 | ); |
| 75527 | } |
| 75528 | |
| 75529 | /* AddConnection - ns=0;i=16598 */ |
| 75530 | |
| 75531 | static UA_StatusCode function_namespace0_generated_257_begin(UA_Server *server, UA_UInt16* ns) { |
| 75532 | #ifdef UA_ENABLE_METHODCALLS |
| 75533 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75534 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 75535 | attr.executable = true; |
| 75536 | attr.userExecutable = true; |
| 75537 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddConnection"); |
| 75538 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 75539 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16598LU), |
| 75540 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU), |
| 75541 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75542 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddConnection"), |
| 75543 | typeDefinition: UA_NODEID_NULL, |
| 75544 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 75545 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75546 | return retVal; |
| 75547 | #else |
| 75548 | return UA_STATUSCODE_GOOD; |
| 75549 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75550 | } |
| 75551 | |
| 75552 | static UA_StatusCode function_namespace0_generated_257_finish(UA_Server *server, UA_UInt16* ns) { |
| 75553 | #ifdef UA_ENABLE_METHODCALLS |
| 75554 | return UA_Server_addMethodNode_finish(server, |
| 75555 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16598LU) |
| 75556 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 75557 | #else |
| 75558 | return UA_STATUSCODE_GOOD; |
| 75559 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75560 | } |
| 75561 | |
| 75562 | /* OutputArguments - ns=0;i=16600 */ |
| 75563 | |
| 75564 | static UA_StatusCode function_namespace0_generated_258_begin(UA_Server *server, UA_UInt16* ns) { |
| 75565 | #ifdef UA_ENABLE_METHODCALLS |
| 75566 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75567 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75568 | attr.minimumSamplingInterval = 0.000000; |
| 75569 | attr.userAccessLevel = 1; |
| 75570 | attr.accessLevel = 1; |
| 75571 | attr.valueRank = 1; |
| 75572 | attr.arrayDimensionsSize = 1; |
| 75573 | UA_UInt32 arrayDimensions[1]; |
| 75574 | arrayDimensions[0] = 0; |
| 75575 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75576 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 75577 | UA_Argument variablenode_ns_0_i_16600_variant_DataContents[1]; |
| 75578 | |
| 75579 | UA_init(p: &variablenode_ns_0_i_16600_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75580 | variablenode_ns_0_i_16600_variant_DataContents[0].name = UA_STRING(chars: "ConnectionId"); |
| 75581 | variablenode_ns_0_i_16600_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 75582 | variablenode_ns_0_i_16600_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 75583 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_16600_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75584 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 75585 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75586 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16600LU), |
| 75587 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16598LU), |
| 75588 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75589 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 75590 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75591 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75592 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75593 | |
| 75594 | return retVal; |
| 75595 | #else |
| 75596 | return UA_STATUSCODE_GOOD; |
| 75597 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75598 | } |
| 75599 | |
| 75600 | static UA_StatusCode function_namespace0_generated_258_finish(UA_Server *server, UA_UInt16* ns) { |
| 75601 | #ifdef UA_ENABLE_METHODCALLS |
| 75602 | return UA_Server_addNode_finish(server, |
| 75603 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16600LU) |
| 75604 | ); |
| 75605 | #else |
| 75606 | return UA_STATUSCODE_GOOD; |
| 75607 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75608 | } |
| 75609 | |
| 75610 | /* InputArguments - ns=0;i=16599 */ |
| 75611 | |
| 75612 | static UA_StatusCode function_namespace0_generated_259_begin(UA_Server *server, UA_UInt16* ns) { |
| 75613 | #ifdef UA_ENABLE_METHODCALLS |
| 75614 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75615 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75616 | attr.minimumSamplingInterval = 0.000000; |
| 75617 | attr.userAccessLevel = 1; |
| 75618 | attr.accessLevel = 1; |
| 75619 | attr.valueRank = 1; |
| 75620 | attr.arrayDimensionsSize = 1; |
| 75621 | UA_UInt32 arrayDimensions[1]; |
| 75622 | arrayDimensions[0] = 0; |
| 75623 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75624 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 75625 | UA_Argument variablenode_ns_0_i_16599_variant_DataContents[1]; |
| 75626 | |
| 75627 | UA_init(p: &variablenode_ns_0_i_16599_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75628 | variablenode_ns_0_i_16599_variant_DataContents[0].name = UA_STRING(chars: "Configuration"); |
| 75629 | variablenode_ns_0_i_16599_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15617LU); |
| 75630 | variablenode_ns_0_i_16599_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 75631 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_16599_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75632 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 75633 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75634 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16599LU), |
| 75635 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16598LU), |
| 75636 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75637 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 75638 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75639 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75640 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75641 | |
| 75642 | return retVal; |
| 75643 | #else |
| 75644 | return UA_STATUSCODE_GOOD; |
| 75645 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75646 | } |
| 75647 | |
| 75648 | static UA_StatusCode function_namespace0_generated_259_finish(UA_Server *server, UA_UInt16* ns) { |
| 75649 | #ifdef UA_ENABLE_METHODCALLS |
| 75650 | return UA_Server_addNode_finish(server, |
| 75651 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16599LU) |
| 75652 | ); |
| 75653 | #else |
| 75654 | return UA_STATUSCODE_GOOD; |
| 75655 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75656 | } |
| 75657 | |
| 75658 | /* Status - ns=0;i=15844 */ |
| 75659 | |
| 75660 | static UA_StatusCode function_namespace0_generated_260_begin(UA_Server *server, UA_UInt16* ns) { |
| 75661 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75662 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 75663 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Status"); |
| 75664 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 75665 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15844LU), |
| 75666 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU), |
| 75667 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75668 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Status"), |
| 75669 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14643LU), |
| 75670 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 75671 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75672 | return retVal; |
| 75673 | } |
| 75674 | |
| 75675 | static UA_StatusCode function_namespace0_generated_260_finish(UA_Server *server, UA_UInt16* ns) { |
| 75676 | return UA_Server_addNode_finish(server, |
| 75677 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15844LU) |
| 75678 | ); |
| 75679 | } |
| 75680 | |
| 75681 | /* State - ns=0;i=15845 */ |
| 75682 | |
| 75683 | static UA_StatusCode function_namespace0_generated_261_begin(UA_Server *server, UA_UInt16* ns) { |
| 75684 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75685 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75686 | attr.minimumSamplingInterval = 0.000000; |
| 75687 | attr.userAccessLevel = 1; |
| 75688 | attr.accessLevel = 1; |
| 75689 | /* Value rank inherited */ |
| 75690 | attr.valueRank = -2; |
| 75691 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14647LU); |
| 75692 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "State"); |
| 75693 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75694 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15845LU), |
| 75695 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15844LU), |
| 75696 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75697 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "State"), |
| 75698 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 75699 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75700 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75701 | return retVal; |
| 75702 | } |
| 75703 | |
| 75704 | static UA_StatusCode function_namespace0_generated_261_finish(UA_Server *server, UA_UInt16* ns) { |
| 75705 | return UA_Server_addNode_finish(server, |
| 75706 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15845LU) |
| 75707 | ); |
| 75708 | } |
| 75709 | |
| 75710 | /* PublishedDataSets - ns=0;i=14434 */ |
| 75711 | |
| 75712 | static UA_StatusCode function_namespace0_generated_262_begin(UA_Server *server, UA_UInt16* ns) { |
| 75713 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75714 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 75715 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishedDataSets"); |
| 75716 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 75717 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14434LU), |
| 75718 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU), |
| 75719 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75720 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishedDataSets"), |
| 75721 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14477LU), |
| 75722 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 75723 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75724 | return retVal; |
| 75725 | } |
| 75726 | |
| 75727 | static UA_StatusCode function_namespace0_generated_262_finish(UA_Server *server, UA_UInt16* ns) { |
| 75728 | return UA_Server_addNode_finish(server, |
| 75729 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14434LU) |
| 75730 | ); |
| 75731 | } |
| 75732 | |
| 75733 | /* RemoveConnection - ns=0;i=14432 */ |
| 75734 | |
| 75735 | static UA_StatusCode function_namespace0_generated_263_begin(UA_Server *server, UA_UInt16* ns) { |
| 75736 | #ifdef UA_ENABLE_METHODCALLS |
| 75737 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75738 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 75739 | attr.executable = true; |
| 75740 | attr.userExecutable = true; |
| 75741 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveConnection"); |
| 75742 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 75743 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14432LU), |
| 75744 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU), |
| 75745 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75746 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveConnection"), |
| 75747 | typeDefinition: UA_NODEID_NULL, |
| 75748 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 75749 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75750 | return retVal; |
| 75751 | #else |
| 75752 | return UA_STATUSCODE_GOOD; |
| 75753 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75754 | } |
| 75755 | |
| 75756 | static UA_StatusCode function_namespace0_generated_263_finish(UA_Server *server, UA_UInt16* ns) { |
| 75757 | #ifdef UA_ENABLE_METHODCALLS |
| 75758 | return UA_Server_addMethodNode_finish(server, |
| 75759 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14432LU) |
| 75760 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 75761 | #else |
| 75762 | return UA_STATUSCODE_GOOD; |
| 75763 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75764 | } |
| 75765 | |
| 75766 | /* InputArguments - ns=0;i=14433 */ |
| 75767 | |
| 75768 | static UA_StatusCode function_namespace0_generated_264_begin(UA_Server *server, UA_UInt16* ns) { |
| 75769 | #ifdef UA_ENABLE_METHODCALLS |
| 75770 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75771 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75772 | attr.minimumSamplingInterval = 0.000000; |
| 75773 | attr.userAccessLevel = 1; |
| 75774 | attr.accessLevel = 1; |
| 75775 | attr.valueRank = 1; |
| 75776 | attr.arrayDimensionsSize = 1; |
| 75777 | UA_UInt32 arrayDimensions[1]; |
| 75778 | arrayDimensions[0] = 0; |
| 75779 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75780 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 75781 | UA_Argument variablenode_ns_0_i_14433_variant_DataContents[1]; |
| 75782 | |
| 75783 | UA_init(p: &variablenode_ns_0_i_14433_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75784 | variablenode_ns_0_i_14433_variant_DataContents[0].name = UA_STRING(chars: "ConnectionId"); |
| 75785 | variablenode_ns_0_i_14433_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 75786 | variablenode_ns_0_i_14433_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 75787 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_14433_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 75788 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 75789 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75790 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14433LU), |
| 75791 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14432LU), |
| 75792 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75793 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 75794 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75795 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75796 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75797 | |
| 75798 | return retVal; |
| 75799 | #else |
| 75800 | return UA_STATUSCODE_GOOD; |
| 75801 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75802 | } |
| 75803 | |
| 75804 | static UA_StatusCode function_namespace0_generated_264_finish(UA_Server *server, UA_UInt16* ns) { |
| 75805 | #ifdef UA_ENABLE_METHODCALLS |
| 75806 | return UA_Server_addNode_finish(server, |
| 75807 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14433LU) |
| 75808 | ); |
| 75809 | #else |
| 75810 | return UA_STATUSCODE_GOOD; |
| 75811 | #endif /* UA_ENABLE_METHODCALLS */ |
| 75812 | } |
| 75813 | |
| 75814 | /* <ConnectionName> - ns=0;i=14417 */ |
| 75815 | |
| 75816 | static UA_StatusCode function_namespace0_generated_265_begin(UA_Server *server, UA_UInt16* ns) { |
| 75817 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75818 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 75819 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "<ConnectionName>"); |
| 75820 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 75821 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14417LU), |
| 75822 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU), |
| 75823 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14476LU), |
| 75824 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "<ConnectionName>"), |
| 75825 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14209LU), |
| 75826 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 75827 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75828 | return retVal; |
| 75829 | } |
| 75830 | |
| 75831 | static UA_StatusCode function_namespace0_generated_265_finish(UA_Server *server, UA_UInt16* ns) { |
| 75832 | return UA_Server_addNode_finish(server, |
| 75833 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14417LU) |
| 75834 | ); |
| 75835 | } |
| 75836 | |
| 75837 | /* ConnectionProperties - ns=0;i=17478 */ |
| 75838 | |
| 75839 | static UA_StatusCode function_namespace0_generated_266_begin(UA_Server *server, UA_UInt16* ns) { |
| 75840 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75841 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75842 | attr.minimumSamplingInterval = 0.000000; |
| 75843 | attr.userAccessLevel = 1; |
| 75844 | attr.accessLevel = 1; |
| 75845 | attr.valueRank = 1; |
| 75846 | attr.arrayDimensionsSize = 1; |
| 75847 | UA_UInt32 arrayDimensions[1]; |
| 75848 | arrayDimensions[0] = 0; |
| 75849 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75850 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14533LU); |
| 75851 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConnectionProperties"); |
| 75852 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75853 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17478LU), |
| 75854 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14417LU), |
| 75855 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75856 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConnectionProperties"), |
| 75857 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75858 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75859 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75860 | return retVal; |
| 75861 | } |
| 75862 | |
| 75863 | static UA_StatusCode function_namespace0_generated_266_finish(UA_Server *server, UA_UInt16* ns) { |
| 75864 | return UA_Server_addNode_finish(server, |
| 75865 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17478LU) |
| 75866 | ); |
| 75867 | } |
| 75868 | |
| 75869 | /* TransportProfileUri - ns=0;i=17292 */ |
| 75870 | |
| 75871 | static UA_StatusCode function_namespace0_generated_267_begin(UA_Server *server, UA_UInt16* ns) { |
| 75872 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75873 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75874 | attr.minimumSamplingInterval = 0.000000; |
| 75875 | attr.userAccessLevel = 1; |
| 75876 | attr.accessLevel = 1; |
| 75877 | /* Value rank inherited */ |
| 75878 | attr.valueRank = -2; |
| 75879 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 75880 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransportProfileUri"); |
| 75881 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75882 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17292LU), |
| 75883 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14417LU), |
| 75884 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75885 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransportProfileUri"), |
| 75886 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 16309LU), |
| 75887 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75888 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75889 | return retVal; |
| 75890 | } |
| 75891 | |
| 75892 | static UA_StatusCode function_namespace0_generated_267_finish(UA_Server *server, UA_UInt16* ns) { |
| 75893 | return UA_Server_addNode_finish(server, |
| 75894 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17292LU) |
| 75895 | ); |
| 75896 | } |
| 75897 | |
| 75898 | /* Selections - ns=0;i=17706 */ |
| 75899 | |
| 75900 | static UA_StatusCode function_namespace0_generated_268_begin(UA_Server *server, UA_UInt16* ns) { |
| 75901 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75902 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75903 | attr.minimumSamplingInterval = 0.000000; |
| 75904 | attr.userAccessLevel = 1; |
| 75905 | attr.accessLevel = 1; |
| 75906 | attr.valueRank = 1; |
| 75907 | attr.arrayDimensionsSize = 1; |
| 75908 | UA_UInt32 arrayDimensions[1]; |
| 75909 | arrayDimensions[0] = 0; |
| 75910 | attr.arrayDimensions = &arrayDimensions[0]; |
| 75911 | /* DataType inherited */ |
| 75912 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 75913 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Selections"); |
| 75914 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75915 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17706LU), |
| 75916 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17292LU), |
| 75917 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 75918 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Selections"), |
| 75919 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 75920 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75921 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75922 | return retVal; |
| 75923 | } |
| 75924 | |
| 75925 | static UA_StatusCode function_namespace0_generated_268_finish(UA_Server *server, UA_UInt16* ns) { |
| 75926 | return UA_Server_addNode_finish(server, |
| 75927 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17706LU) |
| 75928 | ); |
| 75929 | } |
| 75930 | |
| 75931 | /* Address - ns=0;i=14423 */ |
| 75932 | |
| 75933 | static UA_StatusCode function_namespace0_generated_269_begin(UA_Server *server, UA_UInt16* ns) { |
| 75934 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75935 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 75936 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Address"); |
| 75937 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 75938 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14423LU), |
| 75939 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14417LU), |
| 75940 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75941 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Address"), |
| 75942 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21145LU), |
| 75943 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 75944 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75945 | return retVal; |
| 75946 | } |
| 75947 | |
| 75948 | static UA_StatusCode function_namespace0_generated_269_finish(UA_Server *server, UA_UInt16* ns) { |
| 75949 | return UA_Server_addNode_finish(server, |
| 75950 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14423LU) |
| 75951 | ); |
| 75952 | } |
| 75953 | |
| 75954 | /* NetworkInterface - ns=0;i=15533 */ |
| 75955 | |
| 75956 | static UA_StatusCode function_namespace0_generated_270_begin(UA_Server *server, UA_UInt16* ns) { |
| 75957 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75958 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75959 | attr.minimumSamplingInterval = 0.000000; |
| 75960 | attr.userAccessLevel = 1; |
| 75961 | attr.accessLevel = 1; |
| 75962 | /* Value rank inherited */ |
| 75963 | attr.valueRank = -2; |
| 75964 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 75965 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NetworkInterface"); |
| 75966 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75967 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15533LU), |
| 75968 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14423LU), |
| 75969 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 75970 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NetworkInterface"), |
| 75971 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 75972 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 75973 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 75974 | return retVal; |
| 75975 | } |
| 75976 | |
| 75977 | static UA_StatusCode function_namespace0_generated_270_finish(UA_Server *server, UA_UInt16* ns) { |
| 75978 | return UA_Server_addNode_finish(server, |
| 75979 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15533LU) |
| 75980 | ); |
| 75981 | } |
| 75982 | |
| 75983 | /* PublisherId - ns=0;i=14418 */ |
| 75984 | |
| 75985 | static UA_StatusCode function_namespace0_generated_271_begin(UA_Server *server, UA_UInt16* ns) { |
| 75986 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 75987 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 75988 | attr.minimumSamplingInterval = 0.000000; |
| 75989 | attr.userAccessLevel = 1; |
| 75990 | attr.accessLevel = 1; |
| 75991 | /* Value rank inherited */ |
| 75992 | attr.valueRank = -2; |
| 75993 | /* DataType inherited */ |
| 75994 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 75995 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublisherId"); |
| 75996 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 75997 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14418LU), |
| 75998 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14417LU), |
| 75999 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76000 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublisherId"), |
| 76001 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76002 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76003 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76004 | return retVal; |
| 76005 | } |
| 76006 | |
| 76007 | static UA_StatusCode function_namespace0_generated_271_finish(UA_Server *server, UA_UInt16* ns) { |
| 76008 | return UA_Server_addNode_finish(server, |
| 76009 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14418LU) |
| 76010 | ); |
| 76011 | } |
| 76012 | |
| 76013 | /* HistoryServerCapabilitiesType - ns=0;i=2330 */ |
| 76014 | |
| 76015 | static UA_StatusCode function_namespace0_generated_272_begin(UA_Server *server, UA_UInt16* ns) { |
| 76016 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76017 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 76018 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryServerCapabilitiesType"); |
| 76019 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 76020 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2330LU), |
| 76021 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 76022 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 76023 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryServerCapabilitiesType"), |
| 76024 | typeDefinition: UA_NODEID_NULL, |
| 76025 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 76026 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76027 | return retVal; |
| 76028 | } |
| 76029 | |
| 76030 | static UA_StatusCode function_namespace0_generated_272_finish(UA_Server *server, UA_UInt16* ns) { |
| 76031 | return UA_Server_addNode_finish(server, |
| 76032 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2330LU) |
| 76033 | ); |
| 76034 | } |
| 76035 | |
| 76036 | /* ConditionType - ns=0;i=2782 */ |
| 76037 | |
| 76038 | static UA_StatusCode function_namespace0_generated_273_begin(UA_Server *server, UA_UInt16* ns) { |
| 76039 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76040 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 76041 | attr.isAbstract = true; |
| 76042 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConditionType"); |
| 76043 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 76044 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76045 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 76046 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 76047 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConditionType"), |
| 76048 | typeDefinition: UA_NODEID_NULL, |
| 76049 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 76050 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76051 | return retVal; |
| 76052 | } |
| 76053 | |
| 76054 | static UA_StatusCode function_namespace0_generated_273_finish(UA_Server *server, UA_UInt16* ns) { |
| 76055 | return UA_Server_addNode_finish(server, |
| 76056 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU) |
| 76057 | ); |
| 76058 | } |
| 76059 | |
| 76060 | /* AddComment - ns=0;i=9029 */ |
| 76061 | |
| 76062 | static UA_StatusCode function_namespace0_generated_274_begin(UA_Server *server, UA_UInt16* ns) { |
| 76063 | #ifdef UA_ENABLE_METHODCALLS |
| 76064 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76065 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 76066 | attr.executable = true; |
| 76067 | attr.userExecutable = true; |
| 76068 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddComment"); |
| 76069 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 76070 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9029LU), |
| 76071 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76072 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 76073 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddComment"), |
| 76074 | typeDefinition: UA_NODEID_NULL, |
| 76075 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 76076 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76077 | return retVal; |
| 76078 | #else |
| 76079 | return UA_STATUSCODE_GOOD; |
| 76080 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76081 | } |
| 76082 | |
| 76083 | static UA_StatusCode function_namespace0_generated_274_finish(UA_Server *server, UA_UInt16* ns) { |
| 76084 | #ifdef UA_ENABLE_METHODCALLS |
| 76085 | return UA_Server_addMethodNode_finish(server, |
| 76086 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9029LU) |
| 76087 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 76088 | #else |
| 76089 | return UA_STATUSCODE_GOOD; |
| 76090 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76091 | } |
| 76092 | |
| 76093 | /* InputArguments - ns=0;i=9030 */ |
| 76094 | |
| 76095 | static UA_StatusCode function_namespace0_generated_275_begin(UA_Server *server, UA_UInt16* ns) { |
| 76096 | #ifdef UA_ENABLE_METHODCALLS |
| 76097 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76098 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76099 | attr.minimumSamplingInterval = 0.000000; |
| 76100 | attr.userAccessLevel = 1; |
| 76101 | attr.accessLevel = 1; |
| 76102 | attr.valueRank = 1; |
| 76103 | attr.arrayDimensionsSize = 1; |
| 76104 | UA_UInt32 arrayDimensions[1]; |
| 76105 | arrayDimensions[0] = 2; |
| 76106 | attr.arrayDimensions = &arrayDimensions[0]; |
| 76107 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 76108 | UA_Argument variablenode_ns_0_i_9030_variant_DataContents[2]; |
| 76109 | |
| 76110 | UA_init(p: &variablenode_ns_0_i_9030_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 76111 | variablenode_ns_0_i_9030_variant_DataContents[0].name = UA_STRING(chars: "EventId"); |
| 76112 | variablenode_ns_0_i_9030_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU); |
| 76113 | variablenode_ns_0_i_9030_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 76114 | variablenode_ns_0_i_9030_variant_DataContents[0].description = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 76115 | |
| 76116 | UA_init(p: &variablenode_ns_0_i_9030_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 76117 | variablenode_ns_0_i_9030_variant_DataContents[1].name = UA_STRING(chars: "Comment"); |
| 76118 | variablenode_ns_0_i_9030_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 76119 | variablenode_ns_0_i_9030_variant_DataContents[1].valueRank = (UA_Int32) -1; |
| 76120 | variablenode_ns_0_i_9030_variant_DataContents[1].description = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 76121 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_9030_variant_DataContents, arraySize: (UA_Int32) 2, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 76122 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 76123 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76124 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9030LU), |
| 76125 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9029LU), |
| 76126 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76127 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 76128 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76129 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76130 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76131 | |
| 76132 | |
| 76133 | return retVal; |
| 76134 | #else |
| 76135 | return UA_STATUSCODE_GOOD; |
| 76136 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76137 | } |
| 76138 | |
| 76139 | static UA_StatusCode function_namespace0_generated_275_finish(UA_Server *server, UA_UInt16* ns) { |
| 76140 | #ifdef UA_ENABLE_METHODCALLS |
| 76141 | return UA_Server_addNode_finish(server, |
| 76142 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9030LU) |
| 76143 | ); |
| 76144 | #else |
| 76145 | return UA_STATUSCODE_GOOD; |
| 76146 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76147 | } |
| 76148 | |
| 76149 | /* Disable - ns=0;i=9028 */ |
| 76150 | |
| 76151 | static UA_StatusCode function_namespace0_generated_276_begin(UA_Server *server, UA_UInt16* ns) { |
| 76152 | #ifdef UA_ENABLE_METHODCALLS |
| 76153 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76154 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 76155 | attr.executable = true; |
| 76156 | attr.userExecutable = true; |
| 76157 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Disable"); |
| 76158 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 76159 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9028LU), |
| 76160 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76161 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 76162 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Disable"), |
| 76163 | typeDefinition: UA_NODEID_NULL, |
| 76164 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 76165 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76166 | return retVal; |
| 76167 | #else |
| 76168 | return UA_STATUSCODE_GOOD; |
| 76169 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76170 | } |
| 76171 | |
| 76172 | static UA_StatusCode function_namespace0_generated_276_finish(UA_Server *server, UA_UInt16* ns) { |
| 76173 | #ifdef UA_ENABLE_METHODCALLS |
| 76174 | return UA_Server_addMethodNode_finish(server, |
| 76175 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9028LU) |
| 76176 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 76177 | #else |
| 76178 | return UA_STATUSCODE_GOOD; |
| 76179 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76180 | } |
| 76181 | |
| 76182 | /* Enable - ns=0;i=9027 */ |
| 76183 | |
| 76184 | static UA_StatusCode function_namespace0_generated_277_begin(UA_Server *server, UA_UInt16* ns) { |
| 76185 | #ifdef UA_ENABLE_METHODCALLS |
| 76186 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76187 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 76188 | attr.executable = true; |
| 76189 | attr.userExecutable = true; |
| 76190 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Enable"); |
| 76191 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 76192 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9027LU), |
| 76193 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76194 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 76195 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Enable"), |
| 76196 | typeDefinition: UA_NODEID_NULL, |
| 76197 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 76198 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76199 | return retVal; |
| 76200 | #else |
| 76201 | return UA_STATUSCODE_GOOD; |
| 76202 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76203 | } |
| 76204 | |
| 76205 | static UA_StatusCode function_namespace0_generated_277_finish(UA_Server *server, UA_UInt16* ns) { |
| 76206 | #ifdef UA_ENABLE_METHODCALLS |
| 76207 | return UA_Server_addMethodNode_finish(server, |
| 76208 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9027LU) |
| 76209 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 76210 | #else |
| 76211 | return UA_STATUSCODE_GOOD; |
| 76212 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76213 | } |
| 76214 | |
| 76215 | /* ClientUserId - ns=0;i=9026 */ |
| 76216 | |
| 76217 | static UA_StatusCode function_namespace0_generated_278_begin(UA_Server *server, UA_UInt16* ns) { |
| 76218 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76219 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76220 | attr.minimumSamplingInterval = 0.000000; |
| 76221 | attr.userAccessLevel = 1; |
| 76222 | attr.accessLevel = 1; |
| 76223 | /* Value rank inherited */ |
| 76224 | attr.valueRank = -2; |
| 76225 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 76226 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientUserId"); |
| 76227 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76228 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9026LU), |
| 76229 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76230 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76231 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientUserId"), |
| 76232 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76233 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76234 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76235 | return retVal; |
| 76236 | } |
| 76237 | |
| 76238 | static UA_StatusCode function_namespace0_generated_278_finish(UA_Server *server, UA_UInt16* ns) { |
| 76239 | return UA_Server_addNode_finish(server, |
| 76240 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9026LU) |
| 76241 | ); |
| 76242 | } |
| 76243 | |
| 76244 | /* BranchId - ns=0;i=9010 */ |
| 76245 | |
| 76246 | static UA_StatusCode function_namespace0_generated_279_begin(UA_Server *server, UA_UInt16* ns) { |
| 76247 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76248 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76249 | attr.minimumSamplingInterval = 0.000000; |
| 76250 | attr.userAccessLevel = 1; |
| 76251 | attr.accessLevel = 1; |
| 76252 | /* Value rank inherited */ |
| 76253 | attr.valueRank = -2; |
| 76254 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 76255 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BranchId"); |
| 76256 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76257 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9010LU), |
| 76258 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76259 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76260 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BranchId"), |
| 76261 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76262 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76263 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76264 | return retVal; |
| 76265 | } |
| 76266 | |
| 76267 | static UA_StatusCode function_namespace0_generated_279_finish(UA_Server *server, UA_UInt16* ns) { |
| 76268 | return UA_Server_addNode_finish(server, |
| 76269 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9010LU) |
| 76270 | ); |
| 76271 | } |
| 76272 | |
| 76273 | /* ConditionName - ns=0;i=9009 */ |
| 76274 | |
| 76275 | static UA_StatusCode function_namespace0_generated_280_begin(UA_Server *server, UA_UInt16* ns) { |
| 76276 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76277 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76278 | attr.minimumSamplingInterval = 0.000000; |
| 76279 | attr.userAccessLevel = 1; |
| 76280 | attr.accessLevel = 1; |
| 76281 | /* Value rank inherited */ |
| 76282 | attr.valueRank = -2; |
| 76283 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 76284 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConditionName"); |
| 76285 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76286 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9009LU), |
| 76287 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76288 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76289 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConditionName"), |
| 76290 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76291 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76292 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76293 | return retVal; |
| 76294 | } |
| 76295 | |
| 76296 | static UA_StatusCode function_namespace0_generated_280_finish(UA_Server *server, UA_UInt16* ns) { |
| 76297 | return UA_Server_addNode_finish(server, |
| 76298 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9009LU) |
| 76299 | ); |
| 76300 | } |
| 76301 | |
| 76302 | /* ConditionRefresh - ns=0;i=3875 */ |
| 76303 | |
| 76304 | static UA_StatusCode function_namespace0_generated_281_begin(UA_Server *server, UA_UInt16* ns) { |
| 76305 | #ifdef UA_ENABLE_METHODCALLS |
| 76306 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76307 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 76308 | attr.executable = true; |
| 76309 | attr.userExecutable = true; |
| 76310 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConditionRefresh"); |
| 76311 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 76312 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3875LU), |
| 76313 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76314 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 76315 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConditionRefresh"), |
| 76316 | typeDefinition: UA_NODEID_NULL, |
| 76317 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 76318 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76319 | return retVal; |
| 76320 | #else |
| 76321 | return UA_STATUSCODE_GOOD; |
| 76322 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76323 | } |
| 76324 | |
| 76325 | static UA_StatusCode function_namespace0_generated_281_finish(UA_Server *server, UA_UInt16* ns) { |
| 76326 | #ifdef UA_ENABLE_METHODCALLS |
| 76327 | return UA_Server_addMethodNode_finish(server, |
| 76328 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3875LU) |
| 76329 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 76330 | #else |
| 76331 | return UA_STATUSCODE_GOOD; |
| 76332 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76333 | } |
| 76334 | |
| 76335 | /* InputArguments - ns=0;i=3876 */ |
| 76336 | |
| 76337 | static UA_StatusCode function_namespace0_generated_282_begin(UA_Server *server, UA_UInt16* ns) { |
| 76338 | #ifdef UA_ENABLE_METHODCALLS |
| 76339 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76340 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76341 | attr.minimumSamplingInterval = 0.000000; |
| 76342 | attr.userAccessLevel = 1; |
| 76343 | attr.accessLevel = 1; |
| 76344 | attr.valueRank = 1; |
| 76345 | attr.arrayDimensionsSize = 1; |
| 76346 | UA_UInt32 arrayDimensions[1]; |
| 76347 | arrayDimensions[0] = 1; |
| 76348 | attr.arrayDimensions = &arrayDimensions[0]; |
| 76349 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 76350 | UA_Argument variablenode_ns_0_i_3876_variant_DataContents[1]; |
| 76351 | |
| 76352 | UA_init(p: &variablenode_ns_0_i_3876_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 76353 | variablenode_ns_0_i_3876_variant_DataContents[0].name = UA_STRING(chars: "SubscriptionId"); |
| 76354 | variablenode_ns_0_i_3876_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 288LU); |
| 76355 | variablenode_ns_0_i_3876_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 76356 | variablenode_ns_0_i_3876_variant_DataContents[0].description = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 76357 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_3876_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 76358 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 76359 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76360 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3876LU), |
| 76361 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3875LU), |
| 76362 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76363 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 76364 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76365 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76366 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76367 | |
| 76368 | return retVal; |
| 76369 | #else |
| 76370 | return UA_STATUSCODE_GOOD; |
| 76371 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76372 | } |
| 76373 | |
| 76374 | static UA_StatusCode function_namespace0_generated_282_finish(UA_Server *server, UA_UInt16* ns) { |
| 76375 | #ifdef UA_ENABLE_METHODCALLS |
| 76376 | return UA_Server_addNode_finish(server, |
| 76377 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3876LU) |
| 76378 | ); |
| 76379 | #else |
| 76380 | return UA_STATUSCODE_GOOD; |
| 76381 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76382 | } |
| 76383 | |
| 76384 | /* Retain - ns=0;i=3874 */ |
| 76385 | |
| 76386 | static UA_StatusCode function_namespace0_generated_283_begin(UA_Server *server, UA_UInt16* ns) { |
| 76387 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76388 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76389 | attr.minimumSamplingInterval = 0.000000; |
| 76390 | attr.userAccessLevel = 1; |
| 76391 | attr.accessLevel = 1; |
| 76392 | /* Value rank inherited */ |
| 76393 | attr.valueRank = -2; |
| 76394 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 76395 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Retain"); |
| 76396 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76397 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3874LU), |
| 76398 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76399 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76400 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Retain"), |
| 76401 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76402 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76403 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76404 | return retVal; |
| 76405 | } |
| 76406 | |
| 76407 | static UA_StatusCode function_namespace0_generated_283_finish(UA_Server *server, UA_UInt16* ns) { |
| 76408 | return UA_Server_addNode_finish(server, |
| 76409 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3874LU) |
| 76410 | ); |
| 76411 | } |
| 76412 | |
| 76413 | /* SupportsFilteredRetain - ns=0;i=32060 */ |
| 76414 | |
| 76415 | static UA_StatusCode function_namespace0_generated_284_begin(UA_Server *server, UA_UInt16* ns) { |
| 76416 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76417 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76418 | attr.minimumSamplingInterval = 0.000000; |
| 76419 | attr.userAccessLevel = 1; |
| 76420 | attr.accessLevel = 1; |
| 76421 | /* Value rank inherited */ |
| 76422 | attr.valueRank = -2; |
| 76423 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 76424 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SupportsFilteredRetain"); |
| 76425 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76426 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32060LU), |
| 76427 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76428 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76429 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SupportsFilteredRetain"), |
| 76430 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76431 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76432 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76433 | return retVal; |
| 76434 | } |
| 76435 | |
| 76436 | static UA_StatusCode function_namespace0_generated_284_finish(UA_Server *server, UA_UInt16* ns) { |
| 76437 | return UA_Server_addNode_finish(server, |
| 76438 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 32060LU) |
| 76439 | ); |
| 76440 | } |
| 76441 | |
| 76442 | /* ConditionRefresh2 - ns=0;i=12912 */ |
| 76443 | |
| 76444 | static UA_StatusCode function_namespace0_generated_285_begin(UA_Server *server, UA_UInt16* ns) { |
| 76445 | #ifdef UA_ENABLE_METHODCALLS |
| 76446 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76447 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 76448 | attr.executable = true; |
| 76449 | attr.userExecutable = true; |
| 76450 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConditionRefresh2"); |
| 76451 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 76452 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12912LU), |
| 76453 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76454 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 76455 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConditionRefresh2"), |
| 76456 | typeDefinition: UA_NODEID_NULL, |
| 76457 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 76458 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76459 | return retVal; |
| 76460 | #else |
| 76461 | return UA_STATUSCODE_GOOD; |
| 76462 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76463 | } |
| 76464 | |
| 76465 | static UA_StatusCode function_namespace0_generated_285_finish(UA_Server *server, UA_UInt16* ns) { |
| 76466 | #ifdef UA_ENABLE_METHODCALLS |
| 76467 | return UA_Server_addMethodNode_finish(server, |
| 76468 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12912LU) |
| 76469 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 76470 | #else |
| 76471 | return UA_STATUSCODE_GOOD; |
| 76472 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76473 | } |
| 76474 | |
| 76475 | /* InputArguments - ns=0;i=12913 */ |
| 76476 | |
| 76477 | static UA_StatusCode function_namespace0_generated_286_begin(UA_Server *server, UA_UInt16* ns) { |
| 76478 | #ifdef UA_ENABLE_METHODCALLS |
| 76479 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76480 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76481 | attr.minimumSamplingInterval = 0.000000; |
| 76482 | attr.userAccessLevel = 1; |
| 76483 | attr.accessLevel = 1; |
| 76484 | attr.valueRank = 1; |
| 76485 | attr.arrayDimensionsSize = 1; |
| 76486 | UA_UInt32 arrayDimensions[1]; |
| 76487 | arrayDimensions[0] = 2; |
| 76488 | attr.arrayDimensions = &arrayDimensions[0]; |
| 76489 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 76490 | UA_Argument variablenode_ns_0_i_12913_variant_DataContents[2]; |
| 76491 | |
| 76492 | UA_init(p: &variablenode_ns_0_i_12913_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 76493 | variablenode_ns_0_i_12913_variant_DataContents[0].name = UA_STRING(chars: "SubscriptionId"); |
| 76494 | variablenode_ns_0_i_12913_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 288LU); |
| 76495 | variablenode_ns_0_i_12913_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 76496 | variablenode_ns_0_i_12913_variant_DataContents[0].description = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 76497 | |
| 76498 | UA_init(p: &variablenode_ns_0_i_12913_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 76499 | variablenode_ns_0_i_12913_variant_DataContents[1].name = UA_STRING(chars: "MonitoredItemId"); |
| 76500 | variablenode_ns_0_i_12913_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 288LU); |
| 76501 | variablenode_ns_0_i_12913_variant_DataContents[1].valueRank = (UA_Int32) -1; |
| 76502 | variablenode_ns_0_i_12913_variant_DataContents[1].description = UA_LOCALIZEDTEXT(locale: "", text: ""); |
| 76503 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_12913_variant_DataContents, arraySize: (UA_Int32) 2, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 76504 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 76505 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76506 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12913LU), |
| 76507 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12912LU), |
| 76508 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76509 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 76510 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76511 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76512 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76513 | |
| 76514 | |
| 76515 | return retVal; |
| 76516 | #else |
| 76517 | return UA_STATUSCODE_GOOD; |
| 76518 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76519 | } |
| 76520 | |
| 76521 | static UA_StatusCode function_namespace0_generated_286_finish(UA_Server *server, UA_UInt16* ns) { |
| 76522 | #ifdef UA_ENABLE_METHODCALLS |
| 76523 | return UA_Server_addNode_finish(server, |
| 76524 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12913LU) |
| 76525 | ); |
| 76526 | #else |
| 76527 | return UA_STATUSCODE_GOOD; |
| 76528 | #endif /* UA_ENABLE_METHODCALLS */ |
| 76529 | } |
| 76530 | |
| 76531 | /* ConditionClassName - ns=0;i=11113 */ |
| 76532 | |
| 76533 | static UA_StatusCode function_namespace0_generated_287_begin(UA_Server *server, UA_UInt16* ns) { |
| 76534 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76535 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76536 | attr.minimumSamplingInterval = 0.000000; |
| 76537 | attr.userAccessLevel = 1; |
| 76538 | attr.accessLevel = 1; |
| 76539 | /* Value rank inherited */ |
| 76540 | attr.valueRank = -2; |
| 76541 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 76542 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConditionClassName"); |
| 76543 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76544 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11113LU), |
| 76545 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76546 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76547 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConditionClassName"), |
| 76548 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76549 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76550 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76551 | return retVal; |
| 76552 | } |
| 76553 | |
| 76554 | static UA_StatusCode function_namespace0_generated_287_finish(UA_Server *server, UA_UInt16* ns) { |
| 76555 | return UA_Server_addNode_finish(server, |
| 76556 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11113LU) |
| 76557 | ); |
| 76558 | } |
| 76559 | |
| 76560 | /* ConditionClassId - ns=0;i=11112 */ |
| 76561 | |
| 76562 | static UA_StatusCode function_namespace0_generated_288_begin(UA_Server *server, UA_UInt16* ns) { |
| 76563 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76564 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76565 | attr.minimumSamplingInterval = 0.000000; |
| 76566 | attr.userAccessLevel = 1; |
| 76567 | attr.accessLevel = 1; |
| 76568 | /* Value rank inherited */ |
| 76569 | attr.valueRank = -2; |
| 76570 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 76571 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConditionClassId"); |
| 76572 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76573 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11112LU), |
| 76574 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76575 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76576 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConditionClassId"), |
| 76577 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76578 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76579 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76580 | return retVal; |
| 76581 | } |
| 76582 | |
| 76583 | static UA_StatusCode function_namespace0_generated_288_finish(UA_Server *server, UA_UInt16* ns) { |
| 76584 | return UA_Server_addNode_finish(server, |
| 76585 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11112LU) |
| 76586 | ); |
| 76587 | } |
| 76588 | |
| 76589 | /* StateVariableType - ns=0;i=2755 */ |
| 76590 | |
| 76591 | static UA_StatusCode function_namespace0_generated_289_begin(UA_Server *server, UA_UInt16* ns) { |
| 76592 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76593 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 76594 | /* Value rank inherited */ |
| 76595 | attr.valueRank = -2; |
| 76596 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 76597 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "StateVariableType"); |
| 76598 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 76599 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2755LU), |
| 76600 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 76601 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 76602 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "StateVariableType"), |
| 76603 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 76604 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 76605 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76606 | return retVal; |
| 76607 | } |
| 76608 | |
| 76609 | static UA_StatusCode function_namespace0_generated_289_finish(UA_Server *server, UA_UInt16* ns) { |
| 76610 | return UA_Server_addNode_finish(server, |
| 76611 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2755LU) |
| 76612 | ); |
| 76613 | } |
| 76614 | |
| 76615 | /* TwoStateVariableType - ns=0;i=8995 */ |
| 76616 | |
| 76617 | static UA_StatusCode function_namespace0_generated_290_begin(UA_Server *server, UA_UInt16* ns) { |
| 76618 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76619 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 76620 | /* Value rank inherited */ |
| 76621 | attr.valueRank = -2; |
| 76622 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 76623 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TwoStateVariableType"); |
| 76624 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 76625 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8995LU), |
| 76626 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2755LU), |
| 76627 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 76628 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TwoStateVariableType"), |
| 76629 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 76630 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 76631 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76632 | return retVal; |
| 76633 | } |
| 76634 | |
| 76635 | static UA_StatusCode function_namespace0_generated_290_finish(UA_Server *server, UA_UInt16* ns) { |
| 76636 | return UA_Server_addNode_finish(server, |
| 76637 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8995LU) |
| 76638 | ); |
| 76639 | } |
| 76640 | |
| 76641 | /* EnabledState - ns=0;i=9011 */ |
| 76642 | |
| 76643 | static UA_StatusCode function_namespace0_generated_291_begin(UA_Server *server, UA_UInt16* ns) { |
| 76644 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76645 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76646 | attr.minimumSamplingInterval = 0.000000; |
| 76647 | attr.userAccessLevel = 1; |
| 76648 | attr.accessLevel = 1; |
| 76649 | /* Value rank inherited */ |
| 76650 | attr.valueRank = -2; |
| 76651 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 76652 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnabledState"); |
| 76653 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76654 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9011LU), |
| 76655 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 76656 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 76657 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnabledState"), |
| 76658 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8995LU), |
| 76659 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76660 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76661 | return retVal; |
| 76662 | } |
| 76663 | |
| 76664 | static UA_StatusCode function_namespace0_generated_291_finish(UA_Server *server, UA_UInt16* ns) { |
| 76665 | return UA_Server_addNode_finish(server, |
| 76666 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9011LU) |
| 76667 | ); |
| 76668 | } |
| 76669 | |
| 76670 | /* FalseState - ns=0;i=9019 */ |
| 76671 | |
| 76672 | static UA_StatusCode function_namespace0_generated_292_begin(UA_Server *server, UA_UInt16* ns) { |
| 76673 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76674 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76675 | attr.minimumSamplingInterval = 0.000000; |
| 76676 | attr.userAccessLevel = 1; |
| 76677 | attr.accessLevel = 1; |
| 76678 | /* Value rank inherited */ |
| 76679 | attr.valueRank = -2; |
| 76680 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 76681 | UA_LocalizedText *variablenode_ns_0_i_9019_variant_DataContents = UA_LocalizedText_new(); |
| 76682 | if (!variablenode_ns_0_i_9019_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 76683 | UA_LocalizedText_init(p: variablenode_ns_0_i_9019_variant_DataContents); |
| 76684 | *variablenode_ns_0_i_9019_variant_DataContents = UA_LOCALIZEDTEXT_ALLOC(locale: "en", text: ""); |
| 76685 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_9019_variant_DataContents, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 76686 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FalseState"); |
| 76687 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76688 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9019LU), |
| 76689 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9011LU), |
| 76690 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76691 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "FalseState"), |
| 76692 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76693 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76694 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76695 | UA_LocalizedText_delete(p: variablenode_ns_0_i_9019_variant_DataContents); |
| 76696 | return retVal; |
| 76697 | } |
| 76698 | |
| 76699 | static UA_StatusCode function_namespace0_generated_292_finish(UA_Server *server, UA_UInt16* ns) { |
| 76700 | return UA_Server_addNode_finish(server, |
| 76701 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9019LU) |
| 76702 | ); |
| 76703 | } |
| 76704 | |
| 76705 | /* TrueState - ns=0;i=9018 */ |
| 76706 | |
| 76707 | static UA_StatusCode function_namespace0_generated_293_begin(UA_Server *server, UA_UInt16* ns) { |
| 76708 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76709 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76710 | attr.minimumSamplingInterval = 0.000000; |
| 76711 | attr.userAccessLevel = 1; |
| 76712 | attr.accessLevel = 1; |
| 76713 | /* Value rank inherited */ |
| 76714 | attr.valueRank = -2; |
| 76715 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 76716 | UA_LocalizedText *variablenode_ns_0_i_9018_variant_DataContents = UA_LocalizedText_new(); |
| 76717 | if (!variablenode_ns_0_i_9018_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 76718 | UA_LocalizedText_init(p: variablenode_ns_0_i_9018_variant_DataContents); |
| 76719 | *variablenode_ns_0_i_9018_variant_DataContents = UA_LOCALIZEDTEXT_ALLOC(locale: "en", text: ""); |
| 76720 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_9018_variant_DataContents, type: &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]); |
| 76721 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TrueState"); |
| 76722 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76723 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9018LU), |
| 76724 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9011LU), |
| 76725 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76726 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TrueState"), |
| 76727 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76728 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76729 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76730 | UA_LocalizedText_delete(p: variablenode_ns_0_i_9018_variant_DataContents); |
| 76731 | return retVal; |
| 76732 | } |
| 76733 | |
| 76734 | static UA_StatusCode function_namespace0_generated_293_finish(UA_Server *server, UA_UInt16* ns) { |
| 76735 | return UA_Server_addNode_finish(server, |
| 76736 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9018LU) |
| 76737 | ); |
| 76738 | } |
| 76739 | |
| 76740 | /* EffectiveTransitionTime - ns=0;i=9017 */ |
| 76741 | |
| 76742 | static UA_StatusCode function_namespace0_generated_294_begin(UA_Server *server, UA_UInt16* ns) { |
| 76743 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76744 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76745 | attr.minimumSamplingInterval = 0.000000; |
| 76746 | attr.userAccessLevel = 1; |
| 76747 | attr.accessLevel = 1; |
| 76748 | /* Value rank inherited */ |
| 76749 | attr.valueRank = -2; |
| 76750 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 76751 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EffectiveTransitionTime"); |
| 76752 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76753 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9017LU), |
| 76754 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9011LU), |
| 76755 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76756 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EffectiveTransitionTime"), |
| 76757 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76758 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76759 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76760 | return retVal; |
| 76761 | } |
| 76762 | |
| 76763 | static UA_StatusCode function_namespace0_generated_294_finish(UA_Server *server, UA_UInt16* ns) { |
| 76764 | return UA_Server_addNode_finish(server, |
| 76765 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9017LU) |
| 76766 | ); |
| 76767 | } |
| 76768 | |
| 76769 | /* TransitionTime - ns=0;i=9016 */ |
| 76770 | |
| 76771 | static UA_StatusCode function_namespace0_generated_295_begin(UA_Server *server, UA_UInt16* ns) { |
| 76772 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76773 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76774 | attr.minimumSamplingInterval = 0.000000; |
| 76775 | attr.userAccessLevel = 1; |
| 76776 | attr.accessLevel = 1; |
| 76777 | /* Value rank inherited */ |
| 76778 | attr.valueRank = -2; |
| 76779 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 76780 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransitionTime"); |
| 76781 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76782 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9016LU), |
| 76783 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9011LU), |
| 76784 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76785 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransitionTime"), |
| 76786 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76787 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76788 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76789 | return retVal; |
| 76790 | } |
| 76791 | |
| 76792 | static UA_StatusCode function_namespace0_generated_295_finish(UA_Server *server, UA_UInt16* ns) { |
| 76793 | return UA_Server_addNode_finish(server, |
| 76794 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9016LU) |
| 76795 | ); |
| 76796 | } |
| 76797 | |
| 76798 | /* EffectiveDisplayName - ns=0;i=9015 */ |
| 76799 | |
| 76800 | static UA_StatusCode function_namespace0_generated_296_begin(UA_Server *server, UA_UInt16* ns) { |
| 76801 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76802 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76803 | attr.minimumSamplingInterval = 0.000000; |
| 76804 | attr.userAccessLevel = 1; |
| 76805 | attr.accessLevel = 1; |
| 76806 | /* Value rank inherited */ |
| 76807 | attr.valueRank = -2; |
| 76808 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 76809 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EffectiveDisplayName"); |
| 76810 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76811 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9015LU), |
| 76812 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9011LU), |
| 76813 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76814 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EffectiveDisplayName"), |
| 76815 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76816 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76817 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76818 | return retVal; |
| 76819 | } |
| 76820 | |
| 76821 | static UA_StatusCode function_namespace0_generated_296_finish(UA_Server *server, UA_UInt16* ns) { |
| 76822 | return UA_Server_addNode_finish(server, |
| 76823 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9015LU) |
| 76824 | ); |
| 76825 | } |
| 76826 | |
| 76827 | /* Id - ns=0;i=9012 */ |
| 76828 | |
| 76829 | static UA_StatusCode function_namespace0_generated_297_begin(UA_Server *server, UA_UInt16* ns) { |
| 76830 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76831 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76832 | attr.minimumSamplingInterval = 0.000000; |
| 76833 | attr.userAccessLevel = 1; |
| 76834 | attr.accessLevel = 1; |
| 76835 | /* Value rank inherited */ |
| 76836 | attr.valueRank = -2; |
| 76837 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 76838 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Id"); |
| 76839 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76840 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9012LU), |
| 76841 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9011LU), |
| 76842 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76843 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Id"), |
| 76844 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76845 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76846 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76847 | return retVal; |
| 76848 | } |
| 76849 | |
| 76850 | static UA_StatusCode function_namespace0_generated_297_finish(UA_Server *server, UA_UInt16* ns) { |
| 76851 | return UA_Server_addNode_finish(server, |
| 76852 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9012LU) |
| 76853 | ); |
| 76854 | } |
| 76855 | |
| 76856 | /* EffectiveTransitionTime - ns=0;i=9001 */ |
| 76857 | |
| 76858 | static UA_StatusCode function_namespace0_generated_298_begin(UA_Server *server, UA_UInt16* ns) { |
| 76859 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76860 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76861 | attr.minimumSamplingInterval = 0.000000; |
| 76862 | attr.userAccessLevel = 1; |
| 76863 | attr.accessLevel = 1; |
| 76864 | /* Value rank inherited */ |
| 76865 | attr.valueRank = -2; |
| 76866 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 76867 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EffectiveTransitionTime"); |
| 76868 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76869 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9001LU), |
| 76870 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8995LU), |
| 76871 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76872 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EffectiveTransitionTime"), |
| 76873 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76874 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76875 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76876 | return retVal; |
| 76877 | } |
| 76878 | |
| 76879 | static UA_StatusCode function_namespace0_generated_298_finish(UA_Server *server, UA_UInt16* ns) { |
| 76880 | return UA_Server_addNode_finish(server, |
| 76881 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9001LU) |
| 76882 | ); |
| 76883 | } |
| 76884 | |
| 76885 | /* TransitionTime - ns=0;i=9000 */ |
| 76886 | |
| 76887 | static UA_StatusCode function_namespace0_generated_299_begin(UA_Server *server, UA_UInt16* ns) { |
| 76888 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76889 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76890 | attr.minimumSamplingInterval = 0.000000; |
| 76891 | attr.userAccessLevel = 1; |
| 76892 | attr.accessLevel = 1; |
| 76893 | /* Value rank inherited */ |
| 76894 | attr.valueRank = -2; |
| 76895 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 76896 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransitionTime"); |
| 76897 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76898 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9000LU), |
| 76899 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8995LU), |
| 76900 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76901 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransitionTime"), |
| 76902 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76903 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76904 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76905 | return retVal; |
| 76906 | } |
| 76907 | |
| 76908 | static UA_StatusCode function_namespace0_generated_299_finish(UA_Server *server, UA_UInt16* ns) { |
| 76909 | return UA_Server_addNode_finish(server, |
| 76910 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9000LU) |
| 76911 | ); |
| 76912 | } |
| 76913 | |
| 76914 | /* Id - ns=0;i=8996 */ |
| 76915 | |
| 76916 | static UA_StatusCode function_namespace0_generated_300_begin(UA_Server *server, UA_UInt16* ns) { |
| 76917 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76918 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76919 | attr.minimumSamplingInterval = 0.000000; |
| 76920 | attr.userAccessLevel = 1; |
| 76921 | attr.accessLevel = 1; |
| 76922 | /* Value rank inherited */ |
| 76923 | attr.valueRank = -2; |
| 76924 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 76925 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Id"); |
| 76926 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76927 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8996LU), |
| 76928 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8995LU), |
| 76929 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76930 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Id"), |
| 76931 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76932 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76933 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76934 | return retVal; |
| 76935 | } |
| 76936 | |
| 76937 | static UA_StatusCode function_namespace0_generated_300_finish(UA_Server *server, UA_UInt16* ns) { |
| 76938 | return UA_Server_addNode_finish(server, |
| 76939 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8996LU) |
| 76940 | ); |
| 76941 | } |
| 76942 | |
| 76943 | /* FalseState - ns=0;i=11111 */ |
| 76944 | |
| 76945 | static UA_StatusCode function_namespace0_generated_301_begin(UA_Server *server, UA_UInt16* ns) { |
| 76946 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76947 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76948 | attr.minimumSamplingInterval = 0.000000; |
| 76949 | attr.userAccessLevel = 1; |
| 76950 | attr.accessLevel = 1; |
| 76951 | /* Value rank inherited */ |
| 76952 | attr.valueRank = -2; |
| 76953 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 76954 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "FalseState"); |
| 76955 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76956 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11111LU), |
| 76957 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8995LU), |
| 76958 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76959 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "FalseState"), |
| 76960 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76961 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76962 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76963 | return retVal; |
| 76964 | } |
| 76965 | |
| 76966 | static UA_StatusCode function_namespace0_generated_301_finish(UA_Server *server, UA_UInt16* ns) { |
| 76967 | return UA_Server_addNode_finish(server, |
| 76968 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11111LU) |
| 76969 | ); |
| 76970 | } |
| 76971 | |
| 76972 | /* TrueState - ns=0;i=11110 */ |
| 76973 | |
| 76974 | static UA_StatusCode function_namespace0_generated_302_begin(UA_Server *server, UA_UInt16* ns) { |
| 76975 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 76976 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 76977 | attr.minimumSamplingInterval = 0.000000; |
| 76978 | attr.userAccessLevel = 1; |
| 76979 | attr.accessLevel = 1; |
| 76980 | /* Value rank inherited */ |
| 76981 | attr.valueRank = -2; |
| 76982 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 76983 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TrueState"); |
| 76984 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 76985 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11110LU), |
| 76986 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8995LU), |
| 76987 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 76988 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TrueState"), |
| 76989 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 76990 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 76991 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 76992 | return retVal; |
| 76993 | } |
| 76994 | |
| 76995 | static UA_StatusCode function_namespace0_generated_302_finish(UA_Server *server, UA_UInt16* ns) { |
| 76996 | return UA_Server_addNode_finish(server, |
| 76997 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11110LU) |
| 76998 | ); |
| 76999 | } |
| 77000 | |
| 77001 | /* EffectiveDisplayName - ns=0;i=2759 */ |
| 77002 | |
| 77003 | static UA_StatusCode function_namespace0_generated_303_begin(UA_Server *server, UA_UInt16* ns) { |
| 77004 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77005 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77006 | attr.minimumSamplingInterval = 0.000000; |
| 77007 | attr.userAccessLevel = 1; |
| 77008 | attr.accessLevel = 1; |
| 77009 | /* Value rank inherited */ |
| 77010 | attr.valueRank = -2; |
| 77011 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 77012 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EffectiveDisplayName"); |
| 77013 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77014 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2759LU), |
| 77015 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2755LU), |
| 77016 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77017 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EffectiveDisplayName"), |
| 77018 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77019 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77020 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77021 | return retVal; |
| 77022 | } |
| 77023 | |
| 77024 | static UA_StatusCode function_namespace0_generated_303_finish(UA_Server *server, UA_UInt16* ns) { |
| 77025 | return UA_Server_addNode_finish(server, |
| 77026 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2759LU) |
| 77027 | ); |
| 77028 | } |
| 77029 | |
| 77030 | /* Number - ns=0;i=2758 */ |
| 77031 | |
| 77032 | static UA_StatusCode function_namespace0_generated_304_begin(UA_Server *server, UA_UInt16* ns) { |
| 77033 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77034 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77035 | attr.minimumSamplingInterval = 0.000000; |
| 77036 | attr.userAccessLevel = 1; |
| 77037 | attr.accessLevel = 1; |
| 77038 | /* Value rank inherited */ |
| 77039 | attr.valueRank = -2; |
| 77040 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 77041 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Number"); |
| 77042 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77043 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2758LU), |
| 77044 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2755LU), |
| 77045 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77046 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Number"), |
| 77047 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77048 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77049 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77050 | return retVal; |
| 77051 | } |
| 77052 | |
| 77053 | static UA_StatusCode function_namespace0_generated_304_finish(UA_Server *server, UA_UInt16* ns) { |
| 77054 | return UA_Server_addNode_finish(server, |
| 77055 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2758LU) |
| 77056 | ); |
| 77057 | } |
| 77058 | |
| 77059 | /* Name - ns=0;i=2757 */ |
| 77060 | |
| 77061 | static UA_StatusCode function_namespace0_generated_305_begin(UA_Server *server, UA_UInt16* ns) { |
| 77062 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77063 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77064 | attr.minimumSamplingInterval = 0.000000; |
| 77065 | attr.userAccessLevel = 1; |
| 77066 | attr.accessLevel = 1; |
| 77067 | /* Value rank inherited */ |
| 77068 | attr.valueRank = -2; |
| 77069 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 20LU); |
| 77070 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Name"); |
| 77071 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77072 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2757LU), |
| 77073 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2755LU), |
| 77074 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77075 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Name"), |
| 77076 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77077 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77078 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77079 | return retVal; |
| 77080 | } |
| 77081 | |
| 77082 | static UA_StatusCode function_namespace0_generated_305_finish(UA_Server *server, UA_UInt16* ns) { |
| 77083 | return UA_Server_addNode_finish(server, |
| 77084 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2757LU) |
| 77085 | ); |
| 77086 | } |
| 77087 | |
| 77088 | /* Id - ns=0;i=2756 */ |
| 77089 | |
| 77090 | static UA_StatusCode function_namespace0_generated_306_begin(UA_Server *server, UA_UInt16* ns) { |
| 77091 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77092 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77093 | attr.minimumSamplingInterval = 0.000000; |
| 77094 | attr.userAccessLevel = 1; |
| 77095 | attr.accessLevel = 1; |
| 77096 | /* Value rank inherited */ |
| 77097 | attr.valueRank = -2; |
| 77098 | /* DataType inherited */ |
| 77099 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 77100 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Id"); |
| 77101 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77102 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2756LU), |
| 77103 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2755LU), |
| 77104 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77105 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Id"), |
| 77106 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77107 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77108 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77109 | return retVal; |
| 77110 | } |
| 77111 | |
| 77112 | static UA_StatusCode function_namespace0_generated_306_finish(UA_Server *server, UA_UInt16* ns) { |
| 77113 | return UA_Server_addNode_finish(server, |
| 77114 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2756LU) |
| 77115 | ); |
| 77116 | } |
| 77117 | |
| 77118 | /* ConditionVariableType - ns=0;i=9002 */ |
| 77119 | |
| 77120 | static UA_StatusCode function_namespace0_generated_307_begin(UA_Server *server, UA_UInt16* ns) { |
| 77121 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77122 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 77123 | attr.valueRank = -2; |
| 77124 | /* DataType inherited */ |
| 77125 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 77126 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConditionVariableType"); |
| 77127 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 77128 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9002LU), |
| 77129 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 77130 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77131 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConditionVariableType"), |
| 77132 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 77133 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 77134 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77135 | return retVal; |
| 77136 | } |
| 77137 | |
| 77138 | static UA_StatusCode function_namespace0_generated_307_finish(UA_Server *server, UA_UInt16* ns) { |
| 77139 | return UA_Server_addNode_finish(server, |
| 77140 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9002LU) |
| 77141 | ); |
| 77142 | } |
| 77143 | |
| 77144 | /* Comment - ns=0;i=9024 */ |
| 77145 | |
| 77146 | static UA_StatusCode function_namespace0_generated_308_begin(UA_Server *server, UA_UInt16* ns) { |
| 77147 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77148 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77149 | attr.minimumSamplingInterval = 0.000000; |
| 77150 | attr.userAccessLevel = 1; |
| 77151 | attr.accessLevel = 1; |
| 77152 | /* Value rank inherited */ |
| 77153 | attr.valueRank = -2; |
| 77154 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 77155 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Comment"); |
| 77156 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77157 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9024LU), |
| 77158 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 77159 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 77160 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Comment"), |
| 77161 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9002LU), |
| 77162 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77163 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77164 | return retVal; |
| 77165 | } |
| 77166 | |
| 77167 | static UA_StatusCode function_namespace0_generated_308_finish(UA_Server *server, UA_UInt16* ns) { |
| 77168 | return UA_Server_addNode_finish(server, |
| 77169 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9024LU) |
| 77170 | ); |
| 77171 | } |
| 77172 | |
| 77173 | /* SourceTimestamp - ns=0;i=9025 */ |
| 77174 | |
| 77175 | static UA_StatusCode function_namespace0_generated_309_begin(UA_Server *server, UA_UInt16* ns) { |
| 77176 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77177 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77178 | attr.minimumSamplingInterval = 0.000000; |
| 77179 | attr.userAccessLevel = 1; |
| 77180 | attr.accessLevel = 1; |
| 77181 | /* Value rank inherited */ |
| 77182 | attr.valueRank = -2; |
| 77183 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 77184 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SourceTimestamp"); |
| 77185 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77186 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9025LU), |
| 77187 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9024LU), |
| 77188 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77189 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SourceTimestamp"), |
| 77190 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77191 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77192 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77193 | return retVal; |
| 77194 | } |
| 77195 | |
| 77196 | static UA_StatusCode function_namespace0_generated_309_finish(UA_Server *server, UA_UInt16* ns) { |
| 77197 | return UA_Server_addNode_finish(server, |
| 77198 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9025LU) |
| 77199 | ); |
| 77200 | } |
| 77201 | |
| 77202 | /* LastSeverity - ns=0;i=9022 */ |
| 77203 | |
| 77204 | static UA_StatusCode function_namespace0_generated_310_begin(UA_Server *server, UA_UInt16* ns) { |
| 77205 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77206 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77207 | attr.minimumSamplingInterval = 0.000000; |
| 77208 | attr.userAccessLevel = 1; |
| 77209 | attr.accessLevel = 1; |
| 77210 | /* Value rank inherited */ |
| 77211 | attr.valueRank = -2; |
| 77212 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 77213 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LastSeverity"); |
| 77214 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77215 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9022LU), |
| 77216 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 77217 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 77218 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LastSeverity"), |
| 77219 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9002LU), |
| 77220 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77221 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77222 | return retVal; |
| 77223 | } |
| 77224 | |
| 77225 | static UA_StatusCode function_namespace0_generated_310_finish(UA_Server *server, UA_UInt16* ns) { |
| 77226 | return UA_Server_addNode_finish(server, |
| 77227 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9022LU) |
| 77228 | ); |
| 77229 | } |
| 77230 | |
| 77231 | /* SourceTimestamp - ns=0;i=9023 */ |
| 77232 | |
| 77233 | static UA_StatusCode function_namespace0_generated_311_begin(UA_Server *server, UA_UInt16* ns) { |
| 77234 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77235 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77236 | attr.minimumSamplingInterval = 0.000000; |
| 77237 | attr.userAccessLevel = 1; |
| 77238 | attr.accessLevel = 1; |
| 77239 | /* Value rank inherited */ |
| 77240 | attr.valueRank = -2; |
| 77241 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 77242 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SourceTimestamp"); |
| 77243 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77244 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9023LU), |
| 77245 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9022LU), |
| 77246 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77247 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SourceTimestamp"), |
| 77248 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77249 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77250 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77251 | return retVal; |
| 77252 | } |
| 77253 | |
| 77254 | static UA_StatusCode function_namespace0_generated_311_finish(UA_Server *server, UA_UInt16* ns) { |
| 77255 | return UA_Server_addNode_finish(server, |
| 77256 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9023LU) |
| 77257 | ); |
| 77258 | } |
| 77259 | |
| 77260 | /* Quality - ns=0;i=9020 */ |
| 77261 | |
| 77262 | static UA_StatusCode function_namespace0_generated_312_begin(UA_Server *server, UA_UInt16* ns) { |
| 77263 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77264 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77265 | attr.minimumSamplingInterval = 0.000000; |
| 77266 | attr.userAccessLevel = 1; |
| 77267 | attr.accessLevel = 1; |
| 77268 | /* Value rank inherited */ |
| 77269 | attr.valueRank = -2; |
| 77270 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 19LU); |
| 77271 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Quality"); |
| 77272 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77273 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9020LU), |
| 77274 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2782LU), |
| 77275 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 77276 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Quality"), |
| 77277 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9002LU), |
| 77278 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77279 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77280 | return retVal; |
| 77281 | } |
| 77282 | |
| 77283 | static UA_StatusCode function_namespace0_generated_312_finish(UA_Server *server, UA_UInt16* ns) { |
| 77284 | return UA_Server_addNode_finish(server, |
| 77285 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9020LU) |
| 77286 | ); |
| 77287 | } |
| 77288 | |
| 77289 | /* SourceTimestamp - ns=0;i=9021 */ |
| 77290 | |
| 77291 | static UA_StatusCode function_namespace0_generated_313_begin(UA_Server *server, UA_UInt16* ns) { |
| 77292 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77293 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77294 | attr.minimumSamplingInterval = 0.000000; |
| 77295 | attr.userAccessLevel = 1; |
| 77296 | attr.accessLevel = 1; |
| 77297 | /* Value rank inherited */ |
| 77298 | attr.valueRank = -2; |
| 77299 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 77300 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SourceTimestamp"); |
| 77301 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77302 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9021LU), |
| 77303 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9020LU), |
| 77304 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77305 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SourceTimestamp"), |
| 77306 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77307 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77308 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77309 | return retVal; |
| 77310 | } |
| 77311 | |
| 77312 | static UA_StatusCode function_namespace0_generated_313_finish(UA_Server *server, UA_UInt16* ns) { |
| 77313 | return UA_Server_addNode_finish(server, |
| 77314 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9021LU) |
| 77315 | ); |
| 77316 | } |
| 77317 | |
| 77318 | /* SourceTimestamp - ns=0;i=9003 */ |
| 77319 | |
| 77320 | static UA_StatusCode function_namespace0_generated_314_begin(UA_Server *server, UA_UInt16* ns) { |
| 77321 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77322 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77323 | attr.minimumSamplingInterval = 0.000000; |
| 77324 | attr.userAccessLevel = 1; |
| 77325 | attr.accessLevel = 1; |
| 77326 | /* Value rank inherited */ |
| 77327 | attr.valueRank = -2; |
| 77328 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 77329 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SourceTimestamp"); |
| 77330 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77331 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9003LU), |
| 77332 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9002LU), |
| 77333 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77334 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SourceTimestamp"), |
| 77335 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77336 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77337 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77338 | return retVal; |
| 77339 | } |
| 77340 | |
| 77341 | static UA_StatusCode function_namespace0_generated_314_finish(UA_Server *server, UA_UInt16* ns) { |
| 77342 | return UA_Server_addNode_finish(server, |
| 77343 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9003LU) |
| 77344 | ); |
| 77345 | } |
| 77346 | |
| 77347 | /* AuditEventType - ns=0;i=2052 */ |
| 77348 | |
| 77349 | static UA_StatusCode function_namespace0_generated_315_begin(UA_Server *server, UA_UInt16* ns) { |
| 77350 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77351 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77352 | attr.isAbstract = true; |
| 77353 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AuditEventType"); |
| 77354 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77355 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2052LU), |
| 77356 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 77357 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77358 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AuditEventType"), |
| 77359 | typeDefinition: UA_NODEID_NULL, |
| 77360 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77361 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77362 | return retVal; |
| 77363 | } |
| 77364 | |
| 77365 | static UA_StatusCode function_namespace0_generated_315_finish(UA_Server *server, UA_UInt16* ns) { |
| 77366 | return UA_Server_addNode_finish(server, |
| 77367 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2052LU) |
| 77368 | ); |
| 77369 | } |
| 77370 | |
| 77371 | /* AuditUpdateMethodEventType - ns=0;i=2127 */ |
| 77372 | |
| 77373 | static UA_StatusCode function_namespace0_generated_316_begin(UA_Server *server, UA_UInt16* ns) { |
| 77374 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77375 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77376 | attr.isAbstract = true; |
| 77377 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AuditUpdateMethodEventType"); |
| 77378 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77379 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2127LU), |
| 77380 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2052LU), |
| 77381 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77382 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AuditUpdateMethodEventType"), |
| 77383 | typeDefinition: UA_NODEID_NULL, |
| 77384 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77385 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77386 | return retVal; |
| 77387 | } |
| 77388 | |
| 77389 | static UA_StatusCode function_namespace0_generated_316_finish(UA_Server *server, UA_UInt16* ns) { |
| 77390 | return UA_Server_addNode_finish(server, |
| 77391 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2127LU) |
| 77392 | ); |
| 77393 | } |
| 77394 | |
| 77395 | /* AuditConditionEventType - ns=0;i=2790 */ |
| 77396 | |
| 77397 | static UA_StatusCode function_namespace0_generated_317_begin(UA_Server *server, UA_UInt16* ns) { |
| 77398 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77399 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77400 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AuditConditionEventType"); |
| 77401 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77402 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2790LU), |
| 77403 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2127LU), |
| 77404 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77405 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AuditConditionEventType"), |
| 77406 | typeDefinition: UA_NODEID_NULL, |
| 77407 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77408 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77409 | return retVal; |
| 77410 | } |
| 77411 | |
| 77412 | static UA_StatusCode function_namespace0_generated_317_finish(UA_Server *server, UA_UInt16* ns) { |
| 77413 | return UA_Server_addNode_finish(server, |
| 77414 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2790LU) |
| 77415 | ); |
| 77416 | } |
| 77417 | |
| 77418 | /* AuditConditionCommentEventType - ns=0;i=2829 */ |
| 77419 | |
| 77420 | static UA_StatusCode function_namespace0_generated_318_begin(UA_Server *server, UA_UInt16* ns) { |
| 77421 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77422 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77423 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AuditConditionCommentEventType"); |
| 77424 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77425 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2829LU), |
| 77426 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2790LU), |
| 77427 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77428 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AuditConditionCommentEventType"), |
| 77429 | typeDefinition: UA_NODEID_NULL, |
| 77430 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77431 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77432 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2829LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3065LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9029LU), false); |
| 77433 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77434 | return retVal; |
| 77435 | } |
| 77436 | |
| 77437 | static UA_StatusCode function_namespace0_generated_318_finish(UA_Server *server, UA_UInt16* ns) { |
| 77438 | return UA_Server_addNode_finish(server, |
| 77439 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2829LU) |
| 77440 | ); |
| 77441 | } |
| 77442 | |
| 77443 | /* ConditionEventId - ns=0;i=17222 */ |
| 77444 | |
| 77445 | static UA_StatusCode function_namespace0_generated_319_begin(UA_Server *server, UA_UInt16* ns) { |
| 77446 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77447 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77448 | attr.minimumSamplingInterval = 0.000000; |
| 77449 | attr.userAccessLevel = 1; |
| 77450 | attr.accessLevel = 1; |
| 77451 | /* Value rank inherited */ |
| 77452 | attr.valueRank = -2; |
| 77453 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU); |
| 77454 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ConditionEventId"); |
| 77455 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77456 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17222LU), |
| 77457 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2829LU), |
| 77458 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77459 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ConditionEventId"), |
| 77460 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77461 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77462 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77463 | return retVal; |
| 77464 | } |
| 77465 | |
| 77466 | static UA_StatusCode function_namespace0_generated_319_finish(UA_Server *server, UA_UInt16* ns) { |
| 77467 | return UA_Server_addNode_finish(server, |
| 77468 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17222LU) |
| 77469 | ); |
| 77470 | } |
| 77471 | |
| 77472 | /* Comment - ns=0;i=11851 */ |
| 77473 | |
| 77474 | static UA_StatusCode function_namespace0_generated_320_begin(UA_Server *server, UA_UInt16* ns) { |
| 77475 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77476 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77477 | attr.minimumSamplingInterval = 0.000000; |
| 77478 | attr.userAccessLevel = 1; |
| 77479 | attr.accessLevel = 1; |
| 77480 | /* Value rank inherited */ |
| 77481 | attr.valueRank = -2; |
| 77482 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 77483 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Comment"); |
| 77484 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77485 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11851LU), |
| 77486 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2829LU), |
| 77487 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77488 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Comment"), |
| 77489 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77490 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77491 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77492 | return retVal; |
| 77493 | } |
| 77494 | |
| 77495 | static UA_StatusCode function_namespace0_generated_320_finish(UA_Server *server, UA_UInt16* ns) { |
| 77496 | return UA_Server_addNode_finish(server, |
| 77497 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11851LU) |
| 77498 | ); |
| 77499 | } |
| 77500 | |
| 77501 | /* AuditConditionEnableEventType - ns=0;i=2803 */ |
| 77502 | |
| 77503 | static UA_StatusCode function_namespace0_generated_321_begin(UA_Server *server, UA_UInt16* ns) { |
| 77504 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77505 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77506 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AuditConditionEnableEventType"); |
| 77507 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77508 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2803LU), |
| 77509 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2790LU), |
| 77510 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77511 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AuditConditionEnableEventType"), |
| 77512 | typeDefinition: UA_NODEID_NULL, |
| 77513 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77514 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77515 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2803LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3065LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9028LU), false); |
| 77516 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77517 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2803LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3065LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9027LU), false); |
| 77518 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77519 | return retVal; |
| 77520 | } |
| 77521 | |
| 77522 | static UA_StatusCode function_namespace0_generated_321_finish(UA_Server *server, UA_UInt16* ns) { |
| 77523 | return UA_Server_addNode_finish(server, |
| 77524 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2803LU) |
| 77525 | ); |
| 77526 | } |
| 77527 | |
| 77528 | /* InputArguments - ns=0;i=2129 */ |
| 77529 | |
| 77530 | static UA_StatusCode function_namespace0_generated_322_begin(UA_Server *server, UA_UInt16* ns) { |
| 77531 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77532 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77533 | attr.minimumSamplingInterval = 0.000000; |
| 77534 | attr.userAccessLevel = 1; |
| 77535 | attr.accessLevel = 1; |
| 77536 | attr.valueRank = 1; |
| 77537 | attr.arrayDimensionsSize = 1; |
| 77538 | UA_UInt32 arrayDimensions[1]; |
| 77539 | arrayDimensions[0] = 0; |
| 77540 | attr.arrayDimensions = &arrayDimensions[0]; |
| 77541 | /* DataType inherited */ |
| 77542 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 77543 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 77544 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77545 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2129LU), |
| 77546 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2127LU), |
| 77547 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77548 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 77549 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77550 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77551 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77552 | return retVal; |
| 77553 | } |
| 77554 | |
| 77555 | static UA_StatusCode function_namespace0_generated_322_finish(UA_Server *server, UA_UInt16* ns) { |
| 77556 | return UA_Server_addNode_finish(server, |
| 77557 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2129LU) |
| 77558 | ); |
| 77559 | } |
| 77560 | |
| 77561 | /* MethodId - ns=0;i=2128 */ |
| 77562 | |
| 77563 | static UA_StatusCode function_namespace0_generated_323_begin(UA_Server *server, UA_UInt16* ns) { |
| 77564 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77565 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77566 | attr.minimumSamplingInterval = 0.000000; |
| 77567 | attr.userAccessLevel = 1; |
| 77568 | attr.accessLevel = 1; |
| 77569 | /* Value rank inherited */ |
| 77570 | attr.valueRank = -2; |
| 77571 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 77572 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MethodId"); |
| 77573 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77574 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2128LU), |
| 77575 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2127LU), |
| 77576 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77577 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MethodId"), |
| 77578 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77579 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77580 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77581 | return retVal; |
| 77582 | } |
| 77583 | |
| 77584 | static UA_StatusCode function_namespace0_generated_323_finish(UA_Server *server, UA_UInt16* ns) { |
| 77585 | return UA_Server_addNode_finish(server, |
| 77586 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2128LU) |
| 77587 | ); |
| 77588 | } |
| 77589 | |
| 77590 | /* ClientUserId - ns=0;i=2057 */ |
| 77591 | |
| 77592 | static UA_StatusCode function_namespace0_generated_324_begin(UA_Server *server, UA_UInt16* ns) { |
| 77593 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77594 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77595 | attr.minimumSamplingInterval = 0.000000; |
| 77596 | attr.userAccessLevel = 1; |
| 77597 | attr.accessLevel = 1; |
| 77598 | /* Value rank inherited */ |
| 77599 | attr.valueRank = -2; |
| 77600 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 77601 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientUserId"); |
| 77602 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77603 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2057LU), |
| 77604 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2052LU), |
| 77605 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77606 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientUserId"), |
| 77607 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77608 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77609 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77610 | return retVal; |
| 77611 | } |
| 77612 | |
| 77613 | static UA_StatusCode function_namespace0_generated_324_finish(UA_Server *server, UA_UInt16* ns) { |
| 77614 | return UA_Server_addNode_finish(server, |
| 77615 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2057LU) |
| 77616 | ); |
| 77617 | } |
| 77618 | |
| 77619 | /* ClientAuditEntryId - ns=0;i=2056 */ |
| 77620 | |
| 77621 | static UA_StatusCode function_namespace0_generated_325_begin(UA_Server *server, UA_UInt16* ns) { |
| 77622 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77623 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77624 | attr.minimumSamplingInterval = 0.000000; |
| 77625 | attr.userAccessLevel = 1; |
| 77626 | attr.accessLevel = 1; |
| 77627 | /* Value rank inherited */ |
| 77628 | attr.valueRank = -2; |
| 77629 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 77630 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientAuditEntryId"); |
| 77631 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77632 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2056LU), |
| 77633 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2052LU), |
| 77634 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77635 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientAuditEntryId"), |
| 77636 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77637 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77638 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77639 | return retVal; |
| 77640 | } |
| 77641 | |
| 77642 | static UA_StatusCode function_namespace0_generated_325_finish(UA_Server *server, UA_UInt16* ns) { |
| 77643 | return UA_Server_addNode_finish(server, |
| 77644 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2056LU) |
| 77645 | ); |
| 77646 | } |
| 77647 | |
| 77648 | /* ServerId - ns=0;i=2055 */ |
| 77649 | |
| 77650 | static UA_StatusCode function_namespace0_generated_326_begin(UA_Server *server, UA_UInt16* ns) { |
| 77651 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77652 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77653 | attr.minimumSamplingInterval = 0.000000; |
| 77654 | attr.userAccessLevel = 1; |
| 77655 | attr.accessLevel = 1; |
| 77656 | /* Value rank inherited */ |
| 77657 | attr.valueRank = -2; |
| 77658 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 77659 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerId"); |
| 77660 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77661 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2055LU), |
| 77662 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2052LU), |
| 77663 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77664 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerId"), |
| 77665 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77666 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77667 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77668 | return retVal; |
| 77669 | } |
| 77670 | |
| 77671 | static UA_StatusCode function_namespace0_generated_326_finish(UA_Server *server, UA_UInt16* ns) { |
| 77672 | return UA_Server_addNode_finish(server, |
| 77673 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2055LU) |
| 77674 | ); |
| 77675 | } |
| 77676 | |
| 77677 | /* Status - ns=0;i=2054 */ |
| 77678 | |
| 77679 | static UA_StatusCode function_namespace0_generated_327_begin(UA_Server *server, UA_UInt16* ns) { |
| 77680 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77681 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77682 | attr.minimumSamplingInterval = 0.000000; |
| 77683 | attr.userAccessLevel = 1; |
| 77684 | attr.accessLevel = 1; |
| 77685 | /* Value rank inherited */ |
| 77686 | attr.valueRank = -2; |
| 77687 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 77688 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Status"); |
| 77689 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77690 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2054LU), |
| 77691 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2052LU), |
| 77692 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77693 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Status"), |
| 77694 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77695 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77696 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77697 | return retVal; |
| 77698 | } |
| 77699 | |
| 77700 | static UA_StatusCode function_namespace0_generated_327_finish(UA_Server *server, UA_UInt16* ns) { |
| 77701 | return UA_Server_addNode_finish(server, |
| 77702 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2054LU) |
| 77703 | ); |
| 77704 | } |
| 77705 | |
| 77706 | /* ActionTimeStamp - ns=0;i=2053 */ |
| 77707 | |
| 77708 | static UA_StatusCode function_namespace0_generated_328_begin(UA_Server *server, UA_UInt16* ns) { |
| 77709 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77710 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77711 | attr.minimumSamplingInterval = 0.000000; |
| 77712 | attr.userAccessLevel = 1; |
| 77713 | attr.accessLevel = 1; |
| 77714 | /* Value rank inherited */ |
| 77715 | attr.valueRank = -2; |
| 77716 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 77717 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ActionTimeStamp"); |
| 77718 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77719 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2053LU), |
| 77720 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2052LU), |
| 77721 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77722 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ActionTimeStamp"), |
| 77723 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77724 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77725 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77726 | return retVal; |
| 77727 | } |
| 77728 | |
| 77729 | static UA_StatusCode function_namespace0_generated_328_finish(UA_Server *server, UA_UInt16* ns) { |
| 77730 | return UA_Server_addNode_finish(server, |
| 77731 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2053LU) |
| 77732 | ); |
| 77733 | } |
| 77734 | |
| 77735 | /* SystemEventType - ns=0;i=2130 */ |
| 77736 | |
| 77737 | static UA_StatusCode function_namespace0_generated_329_begin(UA_Server *server, UA_UInt16* ns) { |
| 77738 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77739 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77740 | attr.isAbstract = true; |
| 77741 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SystemEventType"); |
| 77742 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77743 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2130LU), |
| 77744 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 77745 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77746 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SystemEventType"), |
| 77747 | typeDefinition: UA_NODEID_NULL, |
| 77748 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77749 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77750 | return retVal; |
| 77751 | } |
| 77752 | |
| 77753 | static UA_StatusCode function_namespace0_generated_329_finish(UA_Server *server, UA_UInt16* ns) { |
| 77754 | return UA_Server_addNode_finish(server, |
| 77755 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2130LU) |
| 77756 | ); |
| 77757 | } |
| 77758 | |
| 77759 | /* RefreshEndEventType - ns=0;i=2788 */ |
| 77760 | |
| 77761 | static UA_StatusCode function_namespace0_generated_330_begin(UA_Server *server, UA_UInt16* ns) { |
| 77762 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77763 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77764 | attr.isAbstract = true; |
| 77765 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RefreshEndEventType"); |
| 77766 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77767 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2788LU), |
| 77768 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2130LU), |
| 77769 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77770 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RefreshEndEventType"), |
| 77771 | typeDefinition: UA_NODEID_NULL, |
| 77772 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77773 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77774 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2788LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3065LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3875LU), false); |
| 77775 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77776 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2788LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3065LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12912LU), false); |
| 77777 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77778 | return retVal; |
| 77779 | } |
| 77780 | |
| 77781 | static UA_StatusCode function_namespace0_generated_330_finish(UA_Server *server, UA_UInt16* ns) { |
| 77782 | return UA_Server_addNode_finish(server, |
| 77783 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2788LU) |
| 77784 | ); |
| 77785 | } |
| 77786 | |
| 77787 | /* RefreshStartEventType - ns=0;i=2787 */ |
| 77788 | |
| 77789 | static UA_StatusCode function_namespace0_generated_331_begin(UA_Server *server, UA_UInt16* ns) { |
| 77790 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77791 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77792 | attr.isAbstract = true; |
| 77793 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RefreshStartEventType"); |
| 77794 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77795 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2787LU), |
| 77796 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2130LU), |
| 77797 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77798 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RefreshStartEventType"), |
| 77799 | typeDefinition: UA_NODEID_NULL, |
| 77800 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77801 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77802 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2787LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3065LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3875LU), false); |
| 77803 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77804 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2787LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3065LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12912LU), false); |
| 77805 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77806 | return retVal; |
| 77807 | } |
| 77808 | |
| 77809 | static UA_StatusCode function_namespace0_generated_331_finish(UA_Server *server, UA_UInt16* ns) { |
| 77810 | return UA_Server_addNode_finish(server, |
| 77811 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2787LU) |
| 77812 | ); |
| 77813 | } |
| 77814 | |
| 77815 | /* BaseModelChangeEventType - ns=0;i=2132 */ |
| 77816 | |
| 77817 | static UA_StatusCode function_namespace0_generated_332_begin(UA_Server *server, UA_UInt16* ns) { |
| 77818 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77819 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77820 | attr.isAbstract = true; |
| 77821 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseModelChangeEventType"); |
| 77822 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77823 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2132LU), |
| 77824 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 77825 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77826 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BaseModelChangeEventType"), |
| 77827 | typeDefinition: UA_NODEID_NULL, |
| 77828 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77829 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77830 | return retVal; |
| 77831 | } |
| 77832 | |
| 77833 | static UA_StatusCode function_namespace0_generated_332_finish(UA_Server *server, UA_UInt16* ns) { |
| 77834 | return UA_Server_addNode_finish(server, |
| 77835 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2132LU) |
| 77836 | ); |
| 77837 | } |
| 77838 | |
| 77839 | /* GeneralModelChangeEventType - ns=0;i=2133 */ |
| 77840 | |
| 77841 | static UA_StatusCode function_namespace0_generated_333_begin(UA_Server *server, UA_UInt16* ns) { |
| 77842 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77843 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77844 | attr.isAbstract = true; |
| 77845 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "GeneralModelChangeEventType"); |
| 77846 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77847 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2133LU), |
| 77848 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2132LU), |
| 77849 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77850 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "GeneralModelChangeEventType"), |
| 77851 | typeDefinition: UA_NODEID_NULL, |
| 77852 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77853 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77854 | return retVal; |
| 77855 | } |
| 77856 | |
| 77857 | static UA_StatusCode function_namespace0_generated_333_finish(UA_Server *server, UA_UInt16* ns) { |
| 77858 | return UA_Server_addNode_finish(server, |
| 77859 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2133LU) |
| 77860 | ); |
| 77861 | } |
| 77862 | |
| 77863 | /* Changes - ns=0;i=2134 */ |
| 77864 | |
| 77865 | static UA_StatusCode function_namespace0_generated_334_begin(UA_Server *server, UA_UInt16* ns) { |
| 77866 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77867 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77868 | attr.minimumSamplingInterval = 0.000000; |
| 77869 | attr.userAccessLevel = 1; |
| 77870 | attr.accessLevel = 1; |
| 77871 | attr.valueRank = 1; |
| 77872 | attr.arrayDimensionsSize = 1; |
| 77873 | UA_UInt32 arrayDimensions[1]; |
| 77874 | arrayDimensions[0] = 0; |
| 77875 | attr.arrayDimensions = &arrayDimensions[0]; |
| 77876 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 877LU); |
| 77877 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Changes"); |
| 77878 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77879 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2134LU), |
| 77880 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2133LU), |
| 77881 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77882 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Changes"), |
| 77883 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77884 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77885 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77886 | return retVal; |
| 77887 | } |
| 77888 | |
| 77889 | static UA_StatusCode function_namespace0_generated_334_finish(UA_Server *server, UA_UInt16* ns) { |
| 77890 | return UA_Server_addNode_finish(server, |
| 77891 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2134LU) |
| 77892 | ); |
| 77893 | } |
| 77894 | |
| 77895 | /* EventQueueOverflowEventType - ns=0;i=3035 */ |
| 77896 | |
| 77897 | static UA_StatusCode function_namespace0_generated_335_begin(UA_Server *server, UA_UInt16* ns) { |
| 77898 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77899 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 77900 | attr.isAbstract = true; |
| 77901 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventQueueOverflowEventType"); |
| 77902 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 77903 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3035LU), |
| 77904 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 77905 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 77906 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventQueueOverflowEventType"), |
| 77907 | typeDefinition: UA_NODEID_NULL, |
| 77908 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 77909 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77910 | return retVal; |
| 77911 | } |
| 77912 | |
| 77913 | static UA_StatusCode function_namespace0_generated_335_finish(UA_Server *server, UA_UInt16* ns) { |
| 77914 | return UA_Server_addNode_finish(server, |
| 77915 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3035LU) |
| 77916 | ); |
| 77917 | } |
| 77918 | |
| 77919 | /* Severity - ns=0;i=2051 */ |
| 77920 | |
| 77921 | static UA_StatusCode function_namespace0_generated_336_begin(UA_Server *server, UA_UInt16* ns) { |
| 77922 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77923 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77924 | attr.minimumSamplingInterval = 0.000000; |
| 77925 | attr.userAccessLevel = 1; |
| 77926 | attr.accessLevel = 1; |
| 77927 | /* Value rank inherited */ |
| 77928 | attr.valueRank = -2; |
| 77929 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 77930 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Severity"); |
| 77931 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 77932 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "Indicates how urgent an event is."); |
| 77933 | #endif |
| 77934 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77935 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2051LU), |
| 77936 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 77937 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77938 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Severity"), |
| 77939 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77940 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77941 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77942 | return retVal; |
| 77943 | } |
| 77944 | |
| 77945 | static UA_StatusCode function_namespace0_generated_336_finish(UA_Server *server, UA_UInt16* ns) { |
| 77946 | return UA_Server_addNode_finish(server, |
| 77947 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2051LU) |
| 77948 | ); |
| 77949 | } |
| 77950 | |
| 77951 | /* Message - ns=0;i=2050 */ |
| 77952 | |
| 77953 | static UA_StatusCode function_namespace0_generated_337_begin(UA_Server *server, UA_UInt16* ns) { |
| 77954 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77955 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77956 | attr.minimumSamplingInterval = 0.000000; |
| 77957 | attr.userAccessLevel = 1; |
| 77958 | attr.accessLevel = 1; |
| 77959 | /* Value rank inherited */ |
| 77960 | attr.valueRank = -2; |
| 77961 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 77962 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Message"); |
| 77963 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 77964 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A localized description of the event."); |
| 77965 | #endif |
| 77966 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77967 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2050LU), |
| 77968 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 77969 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 77970 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Message"), |
| 77971 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 77972 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 77973 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 77974 | return retVal; |
| 77975 | } |
| 77976 | |
| 77977 | static UA_StatusCode function_namespace0_generated_337_finish(UA_Server *server, UA_UInt16* ns) { |
| 77978 | return UA_Server_addNode_finish(server, |
| 77979 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2050LU) |
| 77980 | ); |
| 77981 | } |
| 77982 | |
| 77983 | /* LocalTime - ns=0;i=3190 */ |
| 77984 | |
| 77985 | static UA_StatusCode function_namespace0_generated_338_begin(UA_Server *server, UA_UInt16* ns) { |
| 77986 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 77987 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 77988 | attr.minimumSamplingInterval = 0.000000; |
| 77989 | attr.userAccessLevel = 1; |
| 77990 | attr.accessLevel = 1; |
| 77991 | /* Value rank inherited */ |
| 77992 | attr.valueRank = -2; |
| 77993 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8912LU); |
| 77994 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocalTime"); |
| 77995 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 77996 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "Information about the local time where the event originated."); |
| 77997 | #endif |
| 77998 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 77999 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3190LU), |
| 78000 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 78001 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 78002 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocalTime"), |
| 78003 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 78004 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78005 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78006 | return retVal; |
| 78007 | } |
| 78008 | |
| 78009 | static UA_StatusCode function_namespace0_generated_338_finish(UA_Server *server, UA_UInt16* ns) { |
| 78010 | return UA_Server_addNode_finish(server, |
| 78011 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3190LU) |
| 78012 | ); |
| 78013 | } |
| 78014 | |
| 78015 | /* ReceiveTime - ns=0;i=2047 */ |
| 78016 | |
| 78017 | static UA_StatusCode function_namespace0_generated_339_begin(UA_Server *server, UA_UInt16* ns) { |
| 78018 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78019 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78020 | attr.minimumSamplingInterval = 0.000000; |
| 78021 | attr.userAccessLevel = 1; |
| 78022 | attr.accessLevel = 1; |
| 78023 | /* Value rank inherited */ |
| 78024 | attr.valueRank = -2; |
| 78025 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 78026 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReceiveTime"); |
| 78027 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 78028 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "When the server received the event from the underlying system."); |
| 78029 | #endif |
| 78030 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78031 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2047LU), |
| 78032 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 78033 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 78034 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReceiveTime"), |
| 78035 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 78036 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78037 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78038 | return retVal; |
| 78039 | } |
| 78040 | |
| 78041 | static UA_StatusCode function_namespace0_generated_339_finish(UA_Server *server, UA_UInt16* ns) { |
| 78042 | return UA_Server_addNode_finish(server, |
| 78043 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2047LU) |
| 78044 | ); |
| 78045 | } |
| 78046 | |
| 78047 | /* Time - ns=0;i=2046 */ |
| 78048 | |
| 78049 | static UA_StatusCode function_namespace0_generated_340_begin(UA_Server *server, UA_UInt16* ns) { |
| 78050 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78051 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78052 | attr.minimumSamplingInterval = 0.000000; |
| 78053 | attr.userAccessLevel = 1; |
| 78054 | attr.accessLevel = 1; |
| 78055 | /* Value rank inherited */ |
| 78056 | attr.valueRank = -2; |
| 78057 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 78058 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Time"); |
| 78059 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 78060 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "When the event occurred."); |
| 78061 | #endif |
| 78062 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78063 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2046LU), |
| 78064 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 78065 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 78066 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Time"), |
| 78067 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 78068 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78069 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78070 | return retVal; |
| 78071 | } |
| 78072 | |
| 78073 | static UA_StatusCode function_namespace0_generated_340_finish(UA_Server *server, UA_UInt16* ns) { |
| 78074 | return UA_Server_addNode_finish(server, |
| 78075 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2046LU) |
| 78076 | ); |
| 78077 | } |
| 78078 | |
| 78079 | /* SourceName - ns=0;i=2045 */ |
| 78080 | |
| 78081 | static UA_StatusCode function_namespace0_generated_341_begin(UA_Server *server, UA_UInt16* ns) { |
| 78082 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78083 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78084 | attr.minimumSamplingInterval = 0.000000; |
| 78085 | attr.userAccessLevel = 1; |
| 78086 | attr.accessLevel = 1; |
| 78087 | /* Value rank inherited */ |
| 78088 | attr.valueRank = -2; |
| 78089 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 78090 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SourceName"); |
| 78091 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 78092 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A description of the source of the event."); |
| 78093 | #endif |
| 78094 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78095 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2045LU), |
| 78096 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 78097 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 78098 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SourceName"), |
| 78099 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 78100 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78101 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78102 | return retVal; |
| 78103 | } |
| 78104 | |
| 78105 | static UA_StatusCode function_namespace0_generated_341_finish(UA_Server *server, UA_UInt16* ns) { |
| 78106 | return UA_Server_addNode_finish(server, |
| 78107 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2045LU) |
| 78108 | ); |
| 78109 | } |
| 78110 | |
| 78111 | /* SourceNode - ns=0;i=2044 */ |
| 78112 | |
| 78113 | static UA_StatusCode function_namespace0_generated_342_begin(UA_Server *server, UA_UInt16* ns) { |
| 78114 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78115 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78116 | attr.minimumSamplingInterval = 0.000000; |
| 78117 | attr.userAccessLevel = 1; |
| 78118 | attr.accessLevel = 1; |
| 78119 | /* Value rank inherited */ |
| 78120 | attr.valueRank = -2; |
| 78121 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 78122 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SourceNode"); |
| 78123 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 78124 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "The source of the event."); |
| 78125 | #endif |
| 78126 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78127 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2044LU), |
| 78128 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 78129 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 78130 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SourceNode"), |
| 78131 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 78132 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78133 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78134 | return retVal; |
| 78135 | } |
| 78136 | |
| 78137 | static UA_StatusCode function_namespace0_generated_342_finish(UA_Server *server, UA_UInt16* ns) { |
| 78138 | return UA_Server_addNode_finish(server, |
| 78139 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2044LU) |
| 78140 | ); |
| 78141 | } |
| 78142 | |
| 78143 | /* EventType - ns=0;i=2043 */ |
| 78144 | |
| 78145 | static UA_StatusCode function_namespace0_generated_343_begin(UA_Server *server, UA_UInt16* ns) { |
| 78146 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78147 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78148 | attr.minimumSamplingInterval = 0.000000; |
| 78149 | attr.userAccessLevel = 1; |
| 78150 | attr.accessLevel = 1; |
| 78151 | /* Value rank inherited */ |
| 78152 | attr.valueRank = -2; |
| 78153 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 78154 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventType"); |
| 78155 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 78156 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "The identifier for the event type."); |
| 78157 | #endif |
| 78158 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78159 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2043LU), |
| 78160 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 78161 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 78162 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventType"), |
| 78163 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 78164 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78165 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78166 | return retVal; |
| 78167 | } |
| 78168 | |
| 78169 | static UA_StatusCode function_namespace0_generated_343_finish(UA_Server *server, UA_UInt16* ns) { |
| 78170 | return UA_Server_addNode_finish(server, |
| 78171 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2043LU) |
| 78172 | ); |
| 78173 | } |
| 78174 | |
| 78175 | /* EventId - ns=0;i=2042 */ |
| 78176 | |
| 78177 | static UA_StatusCode function_namespace0_generated_344_begin(UA_Server *server, UA_UInt16* ns) { |
| 78178 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78179 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78180 | attr.minimumSamplingInterval = 0.000000; |
| 78181 | attr.userAccessLevel = 1; |
| 78182 | attr.accessLevel = 1; |
| 78183 | /* Value rank inherited */ |
| 78184 | attr.valueRank = -2; |
| 78185 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU); |
| 78186 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventId"); |
| 78187 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 78188 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A globally unique identifier for the event."); |
| 78189 | #endif |
| 78190 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78191 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2042LU), |
| 78192 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2041LU), |
| 78193 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 78194 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventId"), |
| 78195 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 78196 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78197 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78198 | return retVal; |
| 78199 | } |
| 78200 | |
| 78201 | static UA_StatusCode function_namespace0_generated_344_finish(UA_Server *server, UA_UInt16* ns) { |
| 78202 | return UA_Server_addNode_finish(server, |
| 78203 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2042LU) |
| 78204 | ); |
| 78205 | } |
| 78206 | |
| 78207 | /* SessionDiagnosticsVariableType - ns=0;i=2197 */ |
| 78208 | |
| 78209 | static UA_StatusCode function_namespace0_generated_345_begin(UA_Server *server, UA_UInt16* ns) { |
| 78210 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78211 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 78212 | /* Value rank inherited */ |
| 78213 | attr.valueRank = -2; |
| 78214 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 865LU); |
| 78215 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionDiagnosticsVariableType"); |
| 78216 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 78217 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78218 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78219 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 78220 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionDiagnosticsVariableType"), |
| 78221 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 78222 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 78223 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78224 | return retVal; |
| 78225 | } |
| 78226 | |
| 78227 | static UA_StatusCode function_namespace0_generated_345_finish(UA_Server *server, UA_UInt16* ns) { |
| 78228 | return UA_Server_addNode_finish(server, |
| 78229 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU) |
| 78230 | ); |
| 78231 | } |
| 78232 | |
| 78233 | /* TotalRequestCount - ns=0;i=8900 */ |
| 78234 | |
| 78235 | static UA_StatusCode function_namespace0_generated_346_begin(UA_Server *server, UA_UInt16* ns) { |
| 78236 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78237 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78238 | attr.minimumSamplingInterval = 0.000000; |
| 78239 | attr.userAccessLevel = 1; |
| 78240 | attr.accessLevel = 1; |
| 78241 | /* Value rank inherited */ |
| 78242 | attr.valueRank = -2; |
| 78243 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78244 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TotalRequestCount"); |
| 78245 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78246 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8900LU), |
| 78247 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78248 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78249 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TotalRequestCount"), |
| 78250 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78251 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78252 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78253 | return retVal; |
| 78254 | } |
| 78255 | |
| 78256 | static UA_StatusCode function_namespace0_generated_346_finish(UA_Server *server, UA_UInt16* ns) { |
| 78257 | return UA_Server_addNode_finish(server, |
| 78258 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8900LU) |
| 78259 | ); |
| 78260 | } |
| 78261 | |
| 78262 | /* MaxResponseMessageSize - ns=0;i=3050 */ |
| 78263 | |
| 78264 | static UA_StatusCode function_namespace0_generated_347_begin(UA_Server *server, UA_UInt16* ns) { |
| 78265 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78266 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78267 | attr.minimumSamplingInterval = 0.000000; |
| 78268 | attr.userAccessLevel = 1; |
| 78269 | attr.accessLevel = 1; |
| 78270 | /* Value rank inherited */ |
| 78271 | attr.valueRank = -2; |
| 78272 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 78273 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxResponseMessageSize"); |
| 78274 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78275 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3050LU), |
| 78276 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78277 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78278 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxResponseMessageSize"), |
| 78279 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78280 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78281 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78282 | return retVal; |
| 78283 | } |
| 78284 | |
| 78285 | static UA_StatusCode function_namespace0_generated_347_finish(UA_Server *server, UA_UInt16* ns) { |
| 78286 | return UA_Server_addNode_finish(server, |
| 78287 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3050LU) |
| 78288 | ); |
| 78289 | } |
| 78290 | |
| 78291 | /* UnregisterNodesCount - ns=0;i=2731 */ |
| 78292 | |
| 78293 | static UA_StatusCode function_namespace0_generated_348_begin(UA_Server *server, UA_UInt16* ns) { |
| 78294 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78295 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78296 | attr.minimumSamplingInterval = 0.000000; |
| 78297 | attr.userAccessLevel = 1; |
| 78298 | attr.accessLevel = 1; |
| 78299 | /* Value rank inherited */ |
| 78300 | attr.valueRank = -2; |
| 78301 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78302 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UnregisterNodesCount"); |
| 78303 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78304 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2731LU), |
| 78305 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78306 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78307 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UnregisterNodesCount"), |
| 78308 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78309 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78310 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78311 | return retVal; |
| 78312 | } |
| 78313 | |
| 78314 | static UA_StatusCode function_namespace0_generated_348_finish(UA_Server *server, UA_UInt16* ns) { |
| 78315 | return UA_Server_addNode_finish(server, |
| 78316 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2731LU) |
| 78317 | ); |
| 78318 | } |
| 78319 | |
| 78320 | /* RegisterNodesCount - ns=0;i=2730 */ |
| 78321 | |
| 78322 | static UA_StatusCode function_namespace0_generated_349_begin(UA_Server *server, UA_UInt16* ns) { |
| 78323 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78324 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78325 | attr.minimumSamplingInterval = 0.000000; |
| 78326 | attr.userAccessLevel = 1; |
| 78327 | attr.accessLevel = 1; |
| 78328 | /* Value rank inherited */ |
| 78329 | attr.valueRank = -2; |
| 78330 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78331 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RegisterNodesCount"); |
| 78332 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78333 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2730LU), |
| 78334 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78335 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78336 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RegisterNodesCount"), |
| 78337 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78338 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78339 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78340 | return retVal; |
| 78341 | } |
| 78342 | |
| 78343 | static UA_StatusCode function_namespace0_generated_349_finish(UA_Server *server, UA_UInt16* ns) { |
| 78344 | return UA_Server_addNode_finish(server, |
| 78345 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2730LU) |
| 78346 | ); |
| 78347 | } |
| 78348 | |
| 78349 | /* QueryNextCount - ns=0;i=2242 */ |
| 78350 | |
| 78351 | static UA_StatusCode function_namespace0_generated_350_begin(UA_Server *server, UA_UInt16* ns) { |
| 78352 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78353 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78354 | attr.minimumSamplingInterval = 0.000000; |
| 78355 | attr.userAccessLevel = 1; |
| 78356 | attr.accessLevel = 1; |
| 78357 | /* Value rank inherited */ |
| 78358 | attr.valueRank = -2; |
| 78359 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78360 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QueryNextCount"); |
| 78361 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78362 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2242LU), |
| 78363 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78364 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78365 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QueryNextCount"), |
| 78366 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78367 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78368 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78369 | return retVal; |
| 78370 | } |
| 78371 | |
| 78372 | static UA_StatusCode function_namespace0_generated_350_finish(UA_Server *server, UA_UInt16* ns) { |
| 78373 | return UA_Server_addNode_finish(server, |
| 78374 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2242LU) |
| 78375 | ); |
| 78376 | } |
| 78377 | |
| 78378 | /* QueryFirstCount - ns=0;i=2241 */ |
| 78379 | |
| 78380 | static UA_StatusCode function_namespace0_generated_351_begin(UA_Server *server, UA_UInt16* ns) { |
| 78381 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78382 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78383 | attr.minimumSamplingInterval = 0.000000; |
| 78384 | attr.userAccessLevel = 1; |
| 78385 | attr.accessLevel = 1; |
| 78386 | /* Value rank inherited */ |
| 78387 | attr.valueRank = -2; |
| 78388 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78389 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QueryFirstCount"); |
| 78390 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78391 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2241LU), |
| 78392 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78393 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78394 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QueryFirstCount"), |
| 78395 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78396 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78397 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78398 | return retVal; |
| 78399 | } |
| 78400 | |
| 78401 | static UA_StatusCode function_namespace0_generated_351_finish(UA_Server *server, UA_UInt16* ns) { |
| 78402 | return UA_Server_addNode_finish(server, |
| 78403 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2241LU) |
| 78404 | ); |
| 78405 | } |
| 78406 | |
| 78407 | /* TranslateBrowsePathsToNodeIdsCount - ns=0;i=2240 */ |
| 78408 | |
| 78409 | static UA_StatusCode function_namespace0_generated_352_begin(UA_Server *server, UA_UInt16* ns) { |
| 78410 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78411 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78412 | attr.minimumSamplingInterval = 0.000000; |
| 78413 | attr.userAccessLevel = 1; |
| 78414 | attr.accessLevel = 1; |
| 78415 | /* Value rank inherited */ |
| 78416 | attr.valueRank = -2; |
| 78417 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78418 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TranslateBrowsePathsToNodeIdsCount"); |
| 78419 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78420 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2240LU), |
| 78421 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78422 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78423 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TranslateBrowsePathsToNodeIdsCount"), |
| 78424 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78425 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78426 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78427 | return retVal; |
| 78428 | } |
| 78429 | |
| 78430 | static UA_StatusCode function_namespace0_generated_352_finish(UA_Server *server, UA_UInt16* ns) { |
| 78431 | return UA_Server_addNode_finish(server, |
| 78432 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2240LU) |
| 78433 | ); |
| 78434 | } |
| 78435 | |
| 78436 | /* BrowseNextCount - ns=0;i=2239 */ |
| 78437 | |
| 78438 | static UA_StatusCode function_namespace0_generated_353_begin(UA_Server *server, UA_UInt16* ns) { |
| 78439 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78440 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78441 | attr.minimumSamplingInterval = 0.000000; |
| 78442 | attr.userAccessLevel = 1; |
| 78443 | attr.accessLevel = 1; |
| 78444 | /* Value rank inherited */ |
| 78445 | attr.valueRank = -2; |
| 78446 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78447 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BrowseNextCount"); |
| 78448 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78449 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2239LU), |
| 78450 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78451 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78452 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BrowseNextCount"), |
| 78453 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78454 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78455 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78456 | return retVal; |
| 78457 | } |
| 78458 | |
| 78459 | static UA_StatusCode function_namespace0_generated_353_finish(UA_Server *server, UA_UInt16* ns) { |
| 78460 | return UA_Server_addNode_finish(server, |
| 78461 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2239LU) |
| 78462 | ); |
| 78463 | } |
| 78464 | |
| 78465 | /* BrowseCount - ns=0;i=2238 */ |
| 78466 | |
| 78467 | static UA_StatusCode function_namespace0_generated_354_begin(UA_Server *server, UA_UInt16* ns) { |
| 78468 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78469 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78470 | attr.minimumSamplingInterval = 0.000000; |
| 78471 | attr.userAccessLevel = 1; |
| 78472 | attr.accessLevel = 1; |
| 78473 | /* Value rank inherited */ |
| 78474 | attr.valueRank = -2; |
| 78475 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78476 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BrowseCount"); |
| 78477 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78478 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2238LU), |
| 78479 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78480 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78481 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BrowseCount"), |
| 78482 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78483 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78484 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78485 | return retVal; |
| 78486 | } |
| 78487 | |
| 78488 | static UA_StatusCode function_namespace0_generated_354_finish(UA_Server *server, UA_UInt16* ns) { |
| 78489 | return UA_Server_addNode_finish(server, |
| 78490 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2238LU) |
| 78491 | ); |
| 78492 | } |
| 78493 | |
| 78494 | /* DeleteReferencesCount - ns=0;i=2237 */ |
| 78495 | |
| 78496 | static UA_StatusCode function_namespace0_generated_355_begin(UA_Server *server, UA_UInt16* ns) { |
| 78497 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78498 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78499 | attr.minimumSamplingInterval = 0.000000; |
| 78500 | attr.userAccessLevel = 1; |
| 78501 | attr.accessLevel = 1; |
| 78502 | /* Value rank inherited */ |
| 78503 | attr.valueRank = -2; |
| 78504 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78505 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteReferencesCount"); |
| 78506 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78507 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2237LU), |
| 78508 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78509 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78510 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteReferencesCount"), |
| 78511 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78512 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78513 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78514 | return retVal; |
| 78515 | } |
| 78516 | |
| 78517 | static UA_StatusCode function_namespace0_generated_355_finish(UA_Server *server, UA_UInt16* ns) { |
| 78518 | return UA_Server_addNode_finish(server, |
| 78519 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2237LU) |
| 78520 | ); |
| 78521 | } |
| 78522 | |
| 78523 | /* DeleteNodesCount - ns=0;i=2236 */ |
| 78524 | |
| 78525 | static UA_StatusCode function_namespace0_generated_356_begin(UA_Server *server, UA_UInt16* ns) { |
| 78526 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78527 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78528 | attr.minimumSamplingInterval = 0.000000; |
| 78529 | attr.userAccessLevel = 1; |
| 78530 | attr.accessLevel = 1; |
| 78531 | /* Value rank inherited */ |
| 78532 | attr.valueRank = -2; |
| 78533 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78534 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteNodesCount"); |
| 78535 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78536 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2236LU), |
| 78537 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78538 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78539 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteNodesCount"), |
| 78540 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78541 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78542 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78543 | return retVal; |
| 78544 | } |
| 78545 | |
| 78546 | static UA_StatusCode function_namespace0_generated_356_finish(UA_Server *server, UA_UInt16* ns) { |
| 78547 | return UA_Server_addNode_finish(server, |
| 78548 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2236LU) |
| 78549 | ); |
| 78550 | } |
| 78551 | |
| 78552 | /* AddReferencesCount - ns=0;i=2235 */ |
| 78553 | |
| 78554 | static UA_StatusCode function_namespace0_generated_357_begin(UA_Server *server, UA_UInt16* ns) { |
| 78555 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78556 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78557 | attr.minimumSamplingInterval = 0.000000; |
| 78558 | attr.userAccessLevel = 1; |
| 78559 | attr.accessLevel = 1; |
| 78560 | /* Value rank inherited */ |
| 78561 | attr.valueRank = -2; |
| 78562 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78563 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddReferencesCount"); |
| 78564 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78565 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2235LU), |
| 78566 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78567 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78568 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddReferencesCount"), |
| 78569 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78570 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78571 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78572 | return retVal; |
| 78573 | } |
| 78574 | |
| 78575 | static UA_StatusCode function_namespace0_generated_357_finish(UA_Server *server, UA_UInt16* ns) { |
| 78576 | return UA_Server_addNode_finish(server, |
| 78577 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2235LU) |
| 78578 | ); |
| 78579 | } |
| 78580 | |
| 78581 | /* AddNodesCount - ns=0;i=2234 */ |
| 78582 | |
| 78583 | static UA_StatusCode function_namespace0_generated_358_begin(UA_Server *server, UA_UInt16* ns) { |
| 78584 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78585 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78586 | attr.minimumSamplingInterval = 0.000000; |
| 78587 | attr.userAccessLevel = 1; |
| 78588 | attr.accessLevel = 1; |
| 78589 | /* Value rank inherited */ |
| 78590 | attr.valueRank = -2; |
| 78591 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78592 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddNodesCount"); |
| 78593 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78594 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2234LU), |
| 78595 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78596 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78597 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddNodesCount"), |
| 78598 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78599 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78600 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78601 | return retVal; |
| 78602 | } |
| 78603 | |
| 78604 | static UA_StatusCode function_namespace0_generated_358_finish(UA_Server *server, UA_UInt16* ns) { |
| 78605 | return UA_Server_addNode_finish(server, |
| 78606 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2234LU) |
| 78607 | ); |
| 78608 | } |
| 78609 | |
| 78610 | /* DeleteSubscriptionsCount - ns=0;i=2233 */ |
| 78611 | |
| 78612 | static UA_StatusCode function_namespace0_generated_359_begin(UA_Server *server, UA_UInt16* ns) { |
| 78613 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78614 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78615 | attr.minimumSamplingInterval = 0.000000; |
| 78616 | attr.userAccessLevel = 1; |
| 78617 | attr.accessLevel = 1; |
| 78618 | /* Value rank inherited */ |
| 78619 | attr.valueRank = -2; |
| 78620 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78621 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteSubscriptionsCount"); |
| 78622 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78623 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2233LU), |
| 78624 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78625 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78626 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteSubscriptionsCount"), |
| 78627 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78628 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78629 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78630 | return retVal; |
| 78631 | } |
| 78632 | |
| 78633 | static UA_StatusCode function_namespace0_generated_359_finish(UA_Server *server, UA_UInt16* ns) { |
| 78634 | return UA_Server_addNode_finish(server, |
| 78635 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2233LU) |
| 78636 | ); |
| 78637 | } |
| 78638 | |
| 78639 | /* TransferSubscriptionsCount - ns=0;i=2232 */ |
| 78640 | |
| 78641 | static UA_StatusCode function_namespace0_generated_360_begin(UA_Server *server, UA_UInt16* ns) { |
| 78642 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78643 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78644 | attr.minimumSamplingInterval = 0.000000; |
| 78645 | attr.userAccessLevel = 1; |
| 78646 | attr.accessLevel = 1; |
| 78647 | /* Value rank inherited */ |
| 78648 | attr.valueRank = -2; |
| 78649 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78650 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransferSubscriptionsCount"); |
| 78651 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78652 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2232LU), |
| 78653 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78654 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78655 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransferSubscriptionsCount"), |
| 78656 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78657 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78658 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78659 | return retVal; |
| 78660 | } |
| 78661 | |
| 78662 | static UA_StatusCode function_namespace0_generated_360_finish(UA_Server *server, UA_UInt16* ns) { |
| 78663 | return UA_Server_addNode_finish(server, |
| 78664 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2232LU) |
| 78665 | ); |
| 78666 | } |
| 78667 | |
| 78668 | /* RepublishCount - ns=0;i=2231 */ |
| 78669 | |
| 78670 | static UA_StatusCode function_namespace0_generated_361_begin(UA_Server *server, UA_UInt16* ns) { |
| 78671 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78672 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78673 | attr.minimumSamplingInterval = 0.000000; |
| 78674 | attr.userAccessLevel = 1; |
| 78675 | attr.accessLevel = 1; |
| 78676 | /* Value rank inherited */ |
| 78677 | attr.valueRank = -2; |
| 78678 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78679 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RepublishCount"); |
| 78680 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78681 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2231LU), |
| 78682 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78683 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78684 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RepublishCount"), |
| 78685 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78686 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78687 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78688 | return retVal; |
| 78689 | } |
| 78690 | |
| 78691 | static UA_StatusCode function_namespace0_generated_361_finish(UA_Server *server, UA_UInt16* ns) { |
| 78692 | return UA_Server_addNode_finish(server, |
| 78693 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2231LU) |
| 78694 | ); |
| 78695 | } |
| 78696 | |
| 78697 | /* PublishCount - ns=0;i=2230 */ |
| 78698 | |
| 78699 | static UA_StatusCode function_namespace0_generated_362_begin(UA_Server *server, UA_UInt16* ns) { |
| 78700 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78701 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78702 | attr.minimumSamplingInterval = 0.000000; |
| 78703 | attr.userAccessLevel = 1; |
| 78704 | attr.accessLevel = 1; |
| 78705 | /* Value rank inherited */ |
| 78706 | attr.valueRank = -2; |
| 78707 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78708 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishCount"); |
| 78709 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78710 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2230LU), |
| 78711 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78712 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78713 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishCount"), |
| 78714 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78715 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78716 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78717 | return retVal; |
| 78718 | } |
| 78719 | |
| 78720 | static UA_StatusCode function_namespace0_generated_362_finish(UA_Server *server, UA_UInt16* ns) { |
| 78721 | return UA_Server_addNode_finish(server, |
| 78722 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2230LU) |
| 78723 | ); |
| 78724 | } |
| 78725 | |
| 78726 | /* SetPublishingModeCount - ns=0;i=2229 */ |
| 78727 | |
| 78728 | static UA_StatusCode function_namespace0_generated_363_begin(UA_Server *server, UA_UInt16* ns) { |
| 78729 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78730 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78731 | attr.minimumSamplingInterval = 0.000000; |
| 78732 | attr.userAccessLevel = 1; |
| 78733 | attr.accessLevel = 1; |
| 78734 | /* Value rank inherited */ |
| 78735 | attr.valueRank = -2; |
| 78736 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78737 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetPublishingModeCount"); |
| 78738 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78739 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2229LU), |
| 78740 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78741 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78742 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetPublishingModeCount"), |
| 78743 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78744 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78745 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78746 | return retVal; |
| 78747 | } |
| 78748 | |
| 78749 | static UA_StatusCode function_namespace0_generated_363_finish(UA_Server *server, UA_UInt16* ns) { |
| 78750 | return UA_Server_addNode_finish(server, |
| 78751 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2229LU) |
| 78752 | ); |
| 78753 | } |
| 78754 | |
| 78755 | /* ModifySubscriptionCount - ns=0;i=2228 */ |
| 78756 | |
| 78757 | static UA_StatusCode function_namespace0_generated_364_begin(UA_Server *server, UA_UInt16* ns) { |
| 78758 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78759 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78760 | attr.minimumSamplingInterval = 0.000000; |
| 78761 | attr.userAccessLevel = 1; |
| 78762 | attr.accessLevel = 1; |
| 78763 | /* Value rank inherited */ |
| 78764 | attr.valueRank = -2; |
| 78765 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78766 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModifySubscriptionCount"); |
| 78767 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78768 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2228LU), |
| 78769 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78770 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78771 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModifySubscriptionCount"), |
| 78772 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78773 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78774 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78775 | return retVal; |
| 78776 | } |
| 78777 | |
| 78778 | static UA_StatusCode function_namespace0_generated_364_finish(UA_Server *server, UA_UInt16* ns) { |
| 78779 | return UA_Server_addNode_finish(server, |
| 78780 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2228LU) |
| 78781 | ); |
| 78782 | } |
| 78783 | |
| 78784 | /* CreateSubscriptionCount - ns=0;i=2227 */ |
| 78785 | |
| 78786 | static UA_StatusCode function_namespace0_generated_365_begin(UA_Server *server, UA_UInt16* ns) { |
| 78787 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78788 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78789 | attr.minimumSamplingInterval = 0.000000; |
| 78790 | attr.userAccessLevel = 1; |
| 78791 | attr.accessLevel = 1; |
| 78792 | /* Value rank inherited */ |
| 78793 | attr.valueRank = -2; |
| 78794 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78795 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CreateSubscriptionCount"); |
| 78796 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78797 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2227LU), |
| 78798 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78799 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78800 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CreateSubscriptionCount"), |
| 78801 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78802 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78803 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78804 | return retVal; |
| 78805 | } |
| 78806 | |
| 78807 | static UA_StatusCode function_namespace0_generated_365_finish(UA_Server *server, UA_UInt16* ns) { |
| 78808 | return UA_Server_addNode_finish(server, |
| 78809 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2227LU) |
| 78810 | ); |
| 78811 | } |
| 78812 | |
| 78813 | /* DeleteMonitoredItemsCount - ns=0;i=2226 */ |
| 78814 | |
| 78815 | static UA_StatusCode function_namespace0_generated_366_begin(UA_Server *server, UA_UInt16* ns) { |
| 78816 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78817 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78818 | attr.minimumSamplingInterval = 0.000000; |
| 78819 | attr.userAccessLevel = 1; |
| 78820 | attr.accessLevel = 1; |
| 78821 | /* Value rank inherited */ |
| 78822 | attr.valueRank = -2; |
| 78823 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78824 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteMonitoredItemsCount"); |
| 78825 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78826 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2226LU), |
| 78827 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78828 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78829 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteMonitoredItemsCount"), |
| 78830 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78831 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78832 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78833 | return retVal; |
| 78834 | } |
| 78835 | |
| 78836 | static UA_StatusCode function_namespace0_generated_366_finish(UA_Server *server, UA_UInt16* ns) { |
| 78837 | return UA_Server_addNode_finish(server, |
| 78838 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2226LU) |
| 78839 | ); |
| 78840 | } |
| 78841 | |
| 78842 | /* SetTriggeringCount - ns=0;i=2225 */ |
| 78843 | |
| 78844 | static UA_StatusCode function_namespace0_generated_367_begin(UA_Server *server, UA_UInt16* ns) { |
| 78845 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78846 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78847 | attr.minimumSamplingInterval = 0.000000; |
| 78848 | attr.userAccessLevel = 1; |
| 78849 | attr.accessLevel = 1; |
| 78850 | /* Value rank inherited */ |
| 78851 | attr.valueRank = -2; |
| 78852 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78853 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetTriggeringCount"); |
| 78854 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78855 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2225LU), |
| 78856 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78857 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78858 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetTriggeringCount"), |
| 78859 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78860 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78861 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78862 | return retVal; |
| 78863 | } |
| 78864 | |
| 78865 | static UA_StatusCode function_namespace0_generated_367_finish(UA_Server *server, UA_UInt16* ns) { |
| 78866 | return UA_Server_addNode_finish(server, |
| 78867 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2225LU) |
| 78868 | ); |
| 78869 | } |
| 78870 | |
| 78871 | /* SetMonitoringModeCount - ns=0;i=2224 */ |
| 78872 | |
| 78873 | static UA_StatusCode function_namespace0_generated_368_begin(UA_Server *server, UA_UInt16* ns) { |
| 78874 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78875 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78876 | attr.minimumSamplingInterval = 0.000000; |
| 78877 | attr.userAccessLevel = 1; |
| 78878 | attr.accessLevel = 1; |
| 78879 | /* Value rank inherited */ |
| 78880 | attr.valueRank = -2; |
| 78881 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78882 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetMonitoringModeCount"); |
| 78883 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78884 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2224LU), |
| 78885 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78886 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78887 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetMonitoringModeCount"), |
| 78888 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78889 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78890 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78891 | return retVal; |
| 78892 | } |
| 78893 | |
| 78894 | static UA_StatusCode function_namespace0_generated_368_finish(UA_Server *server, UA_UInt16* ns) { |
| 78895 | return UA_Server_addNode_finish(server, |
| 78896 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2224LU) |
| 78897 | ); |
| 78898 | } |
| 78899 | |
| 78900 | /* ModifyMonitoredItemsCount - ns=0;i=2223 */ |
| 78901 | |
| 78902 | static UA_StatusCode function_namespace0_generated_369_begin(UA_Server *server, UA_UInt16* ns) { |
| 78903 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78904 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78905 | attr.minimumSamplingInterval = 0.000000; |
| 78906 | attr.userAccessLevel = 1; |
| 78907 | attr.accessLevel = 1; |
| 78908 | /* Value rank inherited */ |
| 78909 | attr.valueRank = -2; |
| 78910 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78911 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModifyMonitoredItemsCount"); |
| 78912 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78913 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2223LU), |
| 78914 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78915 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78916 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModifyMonitoredItemsCount"), |
| 78917 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78918 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78919 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78920 | return retVal; |
| 78921 | } |
| 78922 | |
| 78923 | static UA_StatusCode function_namespace0_generated_369_finish(UA_Server *server, UA_UInt16* ns) { |
| 78924 | return UA_Server_addNode_finish(server, |
| 78925 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2223LU) |
| 78926 | ); |
| 78927 | } |
| 78928 | |
| 78929 | /* CreateMonitoredItemsCount - ns=0;i=2222 */ |
| 78930 | |
| 78931 | static UA_StatusCode function_namespace0_generated_370_begin(UA_Server *server, UA_UInt16* ns) { |
| 78932 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78933 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78934 | attr.minimumSamplingInterval = 0.000000; |
| 78935 | attr.userAccessLevel = 1; |
| 78936 | attr.accessLevel = 1; |
| 78937 | /* Value rank inherited */ |
| 78938 | attr.valueRank = -2; |
| 78939 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78940 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CreateMonitoredItemsCount"); |
| 78941 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78942 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2222LU), |
| 78943 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78944 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78945 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CreateMonitoredItemsCount"), |
| 78946 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78947 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78948 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78949 | return retVal; |
| 78950 | } |
| 78951 | |
| 78952 | static UA_StatusCode function_namespace0_generated_370_finish(UA_Server *server, UA_UInt16* ns) { |
| 78953 | return UA_Server_addNode_finish(server, |
| 78954 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2222LU) |
| 78955 | ); |
| 78956 | } |
| 78957 | |
| 78958 | /* CallCount - ns=0;i=2221 */ |
| 78959 | |
| 78960 | static UA_StatusCode function_namespace0_generated_371_begin(UA_Server *server, UA_UInt16* ns) { |
| 78961 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78962 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78963 | attr.minimumSamplingInterval = 0.000000; |
| 78964 | attr.userAccessLevel = 1; |
| 78965 | attr.accessLevel = 1; |
| 78966 | /* Value rank inherited */ |
| 78967 | attr.valueRank = -2; |
| 78968 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78969 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CallCount"); |
| 78970 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 78971 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2221LU), |
| 78972 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 78973 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 78974 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CallCount"), |
| 78975 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 78976 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 78977 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 78978 | return retVal; |
| 78979 | } |
| 78980 | |
| 78981 | static UA_StatusCode function_namespace0_generated_371_finish(UA_Server *server, UA_UInt16* ns) { |
| 78982 | return UA_Server_addNode_finish(server, |
| 78983 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2221LU) |
| 78984 | ); |
| 78985 | } |
| 78986 | |
| 78987 | /* HistoryUpdateCount - ns=0;i=2220 */ |
| 78988 | |
| 78989 | static UA_StatusCode function_namespace0_generated_372_begin(UA_Server *server, UA_UInt16* ns) { |
| 78990 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 78991 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 78992 | attr.minimumSamplingInterval = 0.000000; |
| 78993 | attr.userAccessLevel = 1; |
| 78994 | attr.accessLevel = 1; |
| 78995 | /* Value rank inherited */ |
| 78996 | attr.valueRank = -2; |
| 78997 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 78998 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryUpdateCount"); |
| 78999 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79000 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2220LU), |
| 79001 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79002 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79003 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryUpdateCount"), |
| 79004 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79005 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79006 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79007 | return retVal; |
| 79008 | } |
| 79009 | |
| 79010 | static UA_StatusCode function_namespace0_generated_372_finish(UA_Server *server, UA_UInt16* ns) { |
| 79011 | return UA_Server_addNode_finish(server, |
| 79012 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2220LU) |
| 79013 | ); |
| 79014 | } |
| 79015 | |
| 79016 | /* WriteCount - ns=0;i=2219 */ |
| 79017 | |
| 79018 | static UA_StatusCode function_namespace0_generated_373_begin(UA_Server *server, UA_UInt16* ns) { |
| 79019 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79020 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79021 | attr.minimumSamplingInterval = 0.000000; |
| 79022 | attr.userAccessLevel = 1; |
| 79023 | attr.accessLevel = 1; |
| 79024 | /* Value rank inherited */ |
| 79025 | attr.valueRank = -2; |
| 79026 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 79027 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "WriteCount"); |
| 79028 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79029 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2219LU), |
| 79030 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79031 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79032 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "WriteCount"), |
| 79033 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79034 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79035 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79036 | return retVal; |
| 79037 | } |
| 79038 | |
| 79039 | static UA_StatusCode function_namespace0_generated_373_finish(UA_Server *server, UA_UInt16* ns) { |
| 79040 | return UA_Server_addNode_finish(server, |
| 79041 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2219LU) |
| 79042 | ); |
| 79043 | } |
| 79044 | |
| 79045 | /* HistoryReadCount - ns=0;i=2218 */ |
| 79046 | |
| 79047 | static UA_StatusCode function_namespace0_generated_374_begin(UA_Server *server, UA_UInt16* ns) { |
| 79048 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79049 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79050 | attr.minimumSamplingInterval = 0.000000; |
| 79051 | attr.userAccessLevel = 1; |
| 79052 | attr.accessLevel = 1; |
| 79053 | /* Value rank inherited */ |
| 79054 | attr.valueRank = -2; |
| 79055 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 79056 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryReadCount"); |
| 79057 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79058 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2218LU), |
| 79059 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79060 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79061 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryReadCount"), |
| 79062 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79063 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79064 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79065 | return retVal; |
| 79066 | } |
| 79067 | |
| 79068 | static UA_StatusCode function_namespace0_generated_374_finish(UA_Server *server, UA_UInt16* ns) { |
| 79069 | return UA_Server_addNode_finish(server, |
| 79070 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2218LU) |
| 79071 | ); |
| 79072 | } |
| 79073 | |
| 79074 | /* ReadCount - ns=0;i=2217 */ |
| 79075 | |
| 79076 | static UA_StatusCode function_namespace0_generated_375_begin(UA_Server *server, UA_UInt16* ns) { |
| 79077 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79078 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79079 | attr.minimumSamplingInterval = 0.000000; |
| 79080 | attr.userAccessLevel = 1; |
| 79081 | attr.accessLevel = 1; |
| 79082 | /* Value rank inherited */ |
| 79083 | attr.valueRank = -2; |
| 79084 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 79085 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReadCount"); |
| 79086 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79087 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2217LU), |
| 79088 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79089 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79090 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReadCount"), |
| 79091 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79092 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79093 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79094 | return retVal; |
| 79095 | } |
| 79096 | |
| 79097 | static UA_StatusCode function_namespace0_generated_375_finish(UA_Server *server, UA_UInt16* ns) { |
| 79098 | return UA_Server_addNode_finish(server, |
| 79099 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2217LU) |
| 79100 | ); |
| 79101 | } |
| 79102 | |
| 79103 | /* CurrentPublishRequestsInQueue - ns=0;i=2209 */ |
| 79104 | |
| 79105 | static UA_StatusCode function_namespace0_generated_376_begin(UA_Server *server, UA_UInt16* ns) { |
| 79106 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79107 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79108 | attr.minimumSamplingInterval = 0.000000; |
| 79109 | attr.userAccessLevel = 1; |
| 79110 | attr.accessLevel = 1; |
| 79111 | /* Value rank inherited */ |
| 79112 | attr.valueRank = -2; |
| 79113 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79114 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentPublishRequestsInQueue"); |
| 79115 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79116 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2209LU), |
| 79117 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79118 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79119 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentPublishRequestsInQueue"), |
| 79120 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79121 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79122 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79123 | return retVal; |
| 79124 | } |
| 79125 | |
| 79126 | static UA_StatusCode function_namespace0_generated_376_finish(UA_Server *server, UA_UInt16* ns) { |
| 79127 | return UA_Server_addNode_finish(server, |
| 79128 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2209LU) |
| 79129 | ); |
| 79130 | } |
| 79131 | |
| 79132 | /* CurrentMonitoredItemsCount - ns=0;i=2208 */ |
| 79133 | |
| 79134 | static UA_StatusCode function_namespace0_generated_377_begin(UA_Server *server, UA_UInt16* ns) { |
| 79135 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79136 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79137 | attr.minimumSamplingInterval = 0.000000; |
| 79138 | attr.userAccessLevel = 1; |
| 79139 | attr.accessLevel = 1; |
| 79140 | /* Value rank inherited */ |
| 79141 | attr.valueRank = -2; |
| 79142 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79143 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentMonitoredItemsCount"); |
| 79144 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79145 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2208LU), |
| 79146 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79147 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79148 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentMonitoredItemsCount"), |
| 79149 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79150 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79151 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79152 | return retVal; |
| 79153 | } |
| 79154 | |
| 79155 | static UA_StatusCode function_namespace0_generated_377_finish(UA_Server *server, UA_UInt16* ns) { |
| 79156 | return UA_Server_addNode_finish(server, |
| 79157 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2208LU) |
| 79158 | ); |
| 79159 | } |
| 79160 | |
| 79161 | /* CurrentSubscriptionsCount - ns=0;i=2207 */ |
| 79162 | |
| 79163 | static UA_StatusCode function_namespace0_generated_378_begin(UA_Server *server, UA_UInt16* ns) { |
| 79164 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79165 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79166 | attr.minimumSamplingInterval = 0.000000; |
| 79167 | attr.userAccessLevel = 1; |
| 79168 | attr.accessLevel = 1; |
| 79169 | /* Value rank inherited */ |
| 79170 | attr.valueRank = -2; |
| 79171 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79172 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentSubscriptionsCount"); |
| 79173 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79174 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2207LU), |
| 79175 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79176 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79177 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentSubscriptionsCount"), |
| 79178 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79179 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79180 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79181 | return retVal; |
| 79182 | } |
| 79183 | |
| 79184 | static UA_StatusCode function_namespace0_generated_378_finish(UA_Server *server, UA_UInt16* ns) { |
| 79185 | return UA_Server_addNode_finish(server, |
| 79186 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2207LU) |
| 79187 | ); |
| 79188 | } |
| 79189 | |
| 79190 | /* ClientLastContactTime - ns=0;i=2206 */ |
| 79191 | |
| 79192 | static UA_StatusCode function_namespace0_generated_379_begin(UA_Server *server, UA_UInt16* ns) { |
| 79193 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79194 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79195 | attr.minimumSamplingInterval = 0.000000; |
| 79196 | attr.userAccessLevel = 1; |
| 79197 | attr.accessLevel = 1; |
| 79198 | /* Value rank inherited */ |
| 79199 | attr.valueRank = -2; |
| 79200 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 79201 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientLastContactTime"); |
| 79202 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79203 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2206LU), |
| 79204 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79205 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79206 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientLastContactTime"), |
| 79207 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79208 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79209 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79210 | return retVal; |
| 79211 | } |
| 79212 | |
| 79213 | static UA_StatusCode function_namespace0_generated_379_finish(UA_Server *server, UA_UInt16* ns) { |
| 79214 | return UA_Server_addNode_finish(server, |
| 79215 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2206LU) |
| 79216 | ); |
| 79217 | } |
| 79218 | |
| 79219 | /* ClientConnectionTime - ns=0;i=2205 */ |
| 79220 | |
| 79221 | static UA_StatusCode function_namespace0_generated_380_begin(UA_Server *server, UA_UInt16* ns) { |
| 79222 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79223 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79224 | attr.minimumSamplingInterval = 0.000000; |
| 79225 | attr.userAccessLevel = 1; |
| 79226 | attr.accessLevel = 1; |
| 79227 | /* Value rank inherited */ |
| 79228 | attr.valueRank = -2; |
| 79229 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 79230 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientConnectionTime"); |
| 79231 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79232 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2205LU), |
| 79233 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79234 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79235 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientConnectionTime"), |
| 79236 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79237 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79238 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79239 | return retVal; |
| 79240 | } |
| 79241 | |
| 79242 | static UA_StatusCode function_namespace0_generated_380_finish(UA_Server *server, UA_UInt16* ns) { |
| 79243 | return UA_Server_addNode_finish(server, |
| 79244 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2205LU) |
| 79245 | ); |
| 79246 | } |
| 79247 | |
| 79248 | /* ActualSessionTimeout - ns=0;i=2204 */ |
| 79249 | |
| 79250 | static UA_StatusCode function_namespace0_generated_381_begin(UA_Server *server, UA_UInt16* ns) { |
| 79251 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79252 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79253 | attr.minimumSamplingInterval = 0.000000; |
| 79254 | attr.userAccessLevel = 1; |
| 79255 | attr.accessLevel = 1; |
| 79256 | /* Value rank inherited */ |
| 79257 | attr.valueRank = -2; |
| 79258 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 79259 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ActualSessionTimeout"); |
| 79260 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79261 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2204LU), |
| 79262 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79263 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79264 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ActualSessionTimeout"), |
| 79265 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79266 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79267 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79268 | return retVal; |
| 79269 | } |
| 79270 | |
| 79271 | static UA_StatusCode function_namespace0_generated_381_finish(UA_Server *server, UA_UInt16* ns) { |
| 79272 | return UA_Server_addNode_finish(server, |
| 79273 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2204LU) |
| 79274 | ); |
| 79275 | } |
| 79276 | |
| 79277 | /* LocaleIds - ns=0;i=2203 */ |
| 79278 | |
| 79279 | static UA_StatusCode function_namespace0_generated_382_begin(UA_Server *server, UA_UInt16* ns) { |
| 79280 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79281 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79282 | attr.minimumSamplingInterval = 0.000000; |
| 79283 | attr.userAccessLevel = 1; |
| 79284 | attr.accessLevel = 1; |
| 79285 | attr.valueRank = 1; |
| 79286 | attr.arrayDimensionsSize = 1; |
| 79287 | UA_UInt32 arrayDimensions[1]; |
| 79288 | arrayDimensions[0] = 0; |
| 79289 | attr.arrayDimensions = &arrayDimensions[0]; |
| 79290 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU); |
| 79291 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleIds"); |
| 79292 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79293 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2203LU), |
| 79294 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79295 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79296 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleIds"), |
| 79297 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79298 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79299 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79300 | return retVal; |
| 79301 | } |
| 79302 | |
| 79303 | static UA_StatusCode function_namespace0_generated_382_finish(UA_Server *server, UA_UInt16* ns) { |
| 79304 | return UA_Server_addNode_finish(server, |
| 79305 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2203LU) |
| 79306 | ); |
| 79307 | } |
| 79308 | |
| 79309 | /* EndpointUrl - ns=0;i=2202 */ |
| 79310 | |
| 79311 | static UA_StatusCode function_namespace0_generated_383_begin(UA_Server *server, UA_UInt16* ns) { |
| 79312 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79313 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79314 | attr.minimumSamplingInterval = 0.000000; |
| 79315 | attr.userAccessLevel = 1; |
| 79316 | attr.accessLevel = 1; |
| 79317 | /* Value rank inherited */ |
| 79318 | attr.valueRank = -2; |
| 79319 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 79320 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EndpointUrl"); |
| 79321 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79322 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2202LU), |
| 79323 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79324 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79325 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EndpointUrl"), |
| 79326 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79327 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79328 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79329 | return retVal; |
| 79330 | } |
| 79331 | |
| 79332 | static UA_StatusCode function_namespace0_generated_383_finish(UA_Server *server, UA_UInt16* ns) { |
| 79333 | return UA_Server_addNode_finish(server, |
| 79334 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2202LU) |
| 79335 | ); |
| 79336 | } |
| 79337 | |
| 79338 | /* ServerUri - ns=0;i=2201 */ |
| 79339 | |
| 79340 | static UA_StatusCode function_namespace0_generated_384_begin(UA_Server *server, UA_UInt16* ns) { |
| 79341 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79342 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79343 | attr.minimumSamplingInterval = 0.000000; |
| 79344 | attr.userAccessLevel = 1; |
| 79345 | attr.accessLevel = 1; |
| 79346 | /* Value rank inherited */ |
| 79347 | attr.valueRank = -2; |
| 79348 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 79349 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerUri"); |
| 79350 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79351 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2201LU), |
| 79352 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79353 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79354 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerUri"), |
| 79355 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79356 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79357 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79358 | return retVal; |
| 79359 | } |
| 79360 | |
| 79361 | static UA_StatusCode function_namespace0_generated_384_finish(UA_Server *server, UA_UInt16* ns) { |
| 79362 | return UA_Server_addNode_finish(server, |
| 79363 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2201LU) |
| 79364 | ); |
| 79365 | } |
| 79366 | |
| 79367 | /* ClientDescription - ns=0;i=2200 */ |
| 79368 | |
| 79369 | static UA_StatusCode function_namespace0_generated_385_begin(UA_Server *server, UA_UInt16* ns) { |
| 79370 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79371 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79372 | attr.minimumSamplingInterval = 0.000000; |
| 79373 | attr.userAccessLevel = 1; |
| 79374 | attr.accessLevel = 1; |
| 79375 | /* Value rank inherited */ |
| 79376 | attr.valueRank = -2; |
| 79377 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 308LU); |
| 79378 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientDescription"); |
| 79379 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79380 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2200LU), |
| 79381 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79382 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79383 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientDescription"), |
| 79384 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79385 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79386 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79387 | return retVal; |
| 79388 | } |
| 79389 | |
| 79390 | static UA_StatusCode function_namespace0_generated_385_finish(UA_Server *server, UA_UInt16* ns) { |
| 79391 | return UA_Server_addNode_finish(server, |
| 79392 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2200LU) |
| 79393 | ); |
| 79394 | } |
| 79395 | |
| 79396 | /* SessionName - ns=0;i=2199 */ |
| 79397 | |
| 79398 | static UA_StatusCode function_namespace0_generated_386_begin(UA_Server *server, UA_UInt16* ns) { |
| 79399 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79400 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79401 | attr.minimumSamplingInterval = 0.000000; |
| 79402 | attr.userAccessLevel = 1; |
| 79403 | attr.accessLevel = 1; |
| 79404 | /* Value rank inherited */ |
| 79405 | attr.valueRank = -2; |
| 79406 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 79407 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionName"); |
| 79408 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79409 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2199LU), |
| 79410 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79411 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79412 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionName"), |
| 79413 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79414 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79415 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79416 | return retVal; |
| 79417 | } |
| 79418 | |
| 79419 | static UA_StatusCode function_namespace0_generated_386_finish(UA_Server *server, UA_UInt16* ns) { |
| 79420 | return UA_Server_addNode_finish(server, |
| 79421 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2199LU) |
| 79422 | ); |
| 79423 | } |
| 79424 | |
| 79425 | /* SessionId - ns=0;i=2198 */ |
| 79426 | |
| 79427 | static UA_StatusCode function_namespace0_generated_387_begin(UA_Server *server, UA_UInt16* ns) { |
| 79428 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79429 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79430 | attr.minimumSamplingInterval = 0.000000; |
| 79431 | attr.userAccessLevel = 1; |
| 79432 | attr.accessLevel = 1; |
| 79433 | /* Value rank inherited */ |
| 79434 | attr.valueRank = -2; |
| 79435 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 79436 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionId"); |
| 79437 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79438 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2198LU), |
| 79439 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79440 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79441 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionId"), |
| 79442 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79443 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79444 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79445 | return retVal; |
| 79446 | } |
| 79447 | |
| 79448 | static UA_StatusCode function_namespace0_generated_387_finish(UA_Server *server, UA_UInt16* ns) { |
| 79449 | return UA_Server_addNode_finish(server, |
| 79450 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2198LU) |
| 79451 | ); |
| 79452 | } |
| 79453 | |
| 79454 | /* UnauthorizedRequestCount - ns=0;i=11892 */ |
| 79455 | |
| 79456 | static UA_StatusCode function_namespace0_generated_388_begin(UA_Server *server, UA_UInt16* ns) { |
| 79457 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79458 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79459 | attr.minimumSamplingInterval = 0.000000; |
| 79460 | attr.userAccessLevel = 1; |
| 79461 | attr.accessLevel = 1; |
| 79462 | /* Value rank inherited */ |
| 79463 | attr.valueRank = -2; |
| 79464 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79465 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UnauthorizedRequestCount"); |
| 79466 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79467 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11892LU), |
| 79468 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 79469 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79470 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UnauthorizedRequestCount"), |
| 79471 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79472 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79473 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79474 | return retVal; |
| 79475 | } |
| 79476 | |
| 79477 | static UA_StatusCode function_namespace0_generated_388_finish(UA_Server *server, UA_UInt16* ns) { |
| 79478 | return UA_Server_addNode_finish(server, |
| 79479 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11892LU) |
| 79480 | ); |
| 79481 | } |
| 79482 | |
| 79483 | /* SubscriptionDiagnosticsType - ns=0;i=2172 */ |
| 79484 | |
| 79485 | static UA_StatusCode function_namespace0_generated_389_begin(UA_Server *server, UA_UInt16* ns) { |
| 79486 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79487 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 79488 | /* Value rank inherited */ |
| 79489 | attr.valueRank = -2; |
| 79490 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 874LU); |
| 79491 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscriptionDiagnosticsType"); |
| 79492 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 79493 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79494 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79495 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 79496 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscriptionDiagnosticsType"), |
| 79497 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 79498 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 79499 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79500 | return retVal; |
| 79501 | } |
| 79502 | |
| 79503 | static UA_StatusCode function_namespace0_generated_389_finish(UA_Server *server, UA_UInt16* ns) { |
| 79504 | return UA_Server_addNode_finish(server, |
| 79505 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU) |
| 79506 | ); |
| 79507 | } |
| 79508 | |
| 79509 | /* EventQueueOverflowCount - ns=0;i=8902 */ |
| 79510 | |
| 79511 | static UA_StatusCode function_namespace0_generated_390_begin(UA_Server *server, UA_UInt16* ns) { |
| 79512 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79513 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79514 | attr.minimumSamplingInterval = 0.000000; |
| 79515 | attr.userAccessLevel = 1; |
| 79516 | attr.accessLevel = 1; |
| 79517 | /* Value rank inherited */ |
| 79518 | attr.valueRank = -2; |
| 79519 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79520 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventQueueOverflowCount"); |
| 79521 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79522 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8902LU), |
| 79523 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79524 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79525 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventQueueOverflowCount"), |
| 79526 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79527 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79528 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79529 | return retVal; |
| 79530 | } |
| 79531 | |
| 79532 | static UA_StatusCode function_namespace0_generated_390_finish(UA_Server *server, UA_UInt16* ns) { |
| 79533 | return UA_Server_addNode_finish(server, |
| 79534 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8902LU) |
| 79535 | ); |
| 79536 | } |
| 79537 | |
| 79538 | /* NextSequenceNumber - ns=0;i=8897 */ |
| 79539 | |
| 79540 | static UA_StatusCode function_namespace0_generated_391_begin(UA_Server *server, UA_UInt16* ns) { |
| 79541 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79542 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79543 | attr.minimumSamplingInterval = 0.000000; |
| 79544 | attr.userAccessLevel = 1; |
| 79545 | attr.accessLevel = 1; |
| 79546 | /* Value rank inherited */ |
| 79547 | attr.valueRank = -2; |
| 79548 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79549 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NextSequenceNumber"); |
| 79550 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79551 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8897LU), |
| 79552 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79553 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79554 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NextSequenceNumber"), |
| 79555 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79556 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79557 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79558 | return retVal; |
| 79559 | } |
| 79560 | |
| 79561 | static UA_StatusCode function_namespace0_generated_391_finish(UA_Server *server, UA_UInt16* ns) { |
| 79562 | return UA_Server_addNode_finish(server, |
| 79563 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8897LU) |
| 79564 | ); |
| 79565 | } |
| 79566 | |
| 79567 | /* MonitoringQueueOverflowCount - ns=0;i=8896 */ |
| 79568 | |
| 79569 | static UA_StatusCode function_namespace0_generated_392_begin(UA_Server *server, UA_UInt16* ns) { |
| 79570 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79571 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79572 | attr.minimumSamplingInterval = 0.000000; |
| 79573 | attr.userAccessLevel = 1; |
| 79574 | attr.accessLevel = 1; |
| 79575 | /* Value rank inherited */ |
| 79576 | attr.valueRank = -2; |
| 79577 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79578 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MonitoringQueueOverflowCount"); |
| 79579 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79580 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8896LU), |
| 79581 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79582 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79583 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MonitoringQueueOverflowCount"), |
| 79584 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79585 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79586 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79587 | return retVal; |
| 79588 | } |
| 79589 | |
| 79590 | static UA_StatusCode function_namespace0_generated_392_finish(UA_Server *server, UA_UInt16* ns) { |
| 79591 | return UA_Server_addNode_finish(server, |
| 79592 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8896LU) |
| 79593 | ); |
| 79594 | } |
| 79595 | |
| 79596 | /* DisabledMonitoredItemCount - ns=0;i=8895 */ |
| 79597 | |
| 79598 | static UA_StatusCode function_namespace0_generated_393_begin(UA_Server *server, UA_UInt16* ns) { |
| 79599 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79600 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79601 | attr.minimumSamplingInterval = 0.000000; |
| 79602 | attr.userAccessLevel = 1; |
| 79603 | attr.accessLevel = 1; |
| 79604 | /* Value rank inherited */ |
| 79605 | attr.valueRank = -2; |
| 79606 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79607 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DisabledMonitoredItemCount"); |
| 79608 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79609 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8895LU), |
| 79610 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79611 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79612 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DisabledMonitoredItemCount"), |
| 79613 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79614 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79615 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79616 | return retVal; |
| 79617 | } |
| 79618 | |
| 79619 | static UA_StatusCode function_namespace0_generated_393_finish(UA_Server *server, UA_UInt16* ns) { |
| 79620 | return UA_Server_addNode_finish(server, |
| 79621 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8895LU) |
| 79622 | ); |
| 79623 | } |
| 79624 | |
| 79625 | /* MonitoredItemCount - ns=0;i=8894 */ |
| 79626 | |
| 79627 | static UA_StatusCode function_namespace0_generated_394_begin(UA_Server *server, UA_UInt16* ns) { |
| 79628 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79629 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79630 | attr.minimumSamplingInterval = 0.000000; |
| 79631 | attr.userAccessLevel = 1; |
| 79632 | attr.accessLevel = 1; |
| 79633 | /* Value rank inherited */ |
| 79634 | attr.valueRank = -2; |
| 79635 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79636 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MonitoredItemCount"); |
| 79637 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79638 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8894LU), |
| 79639 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79640 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79641 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MonitoredItemCount"), |
| 79642 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79643 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79644 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79645 | return retVal; |
| 79646 | } |
| 79647 | |
| 79648 | static UA_StatusCode function_namespace0_generated_394_finish(UA_Server *server, UA_UInt16* ns) { |
| 79649 | return UA_Server_addNode_finish(server, |
| 79650 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8894LU) |
| 79651 | ); |
| 79652 | } |
| 79653 | |
| 79654 | /* DiscardedMessageCount - ns=0;i=8893 */ |
| 79655 | |
| 79656 | static UA_StatusCode function_namespace0_generated_395_begin(UA_Server *server, UA_UInt16* ns) { |
| 79657 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79658 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79659 | attr.minimumSamplingInterval = 0.000000; |
| 79660 | attr.userAccessLevel = 1; |
| 79661 | attr.accessLevel = 1; |
| 79662 | /* Value rank inherited */ |
| 79663 | attr.valueRank = -2; |
| 79664 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79665 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DiscardedMessageCount"); |
| 79666 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79667 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8893LU), |
| 79668 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79669 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79670 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DiscardedMessageCount"), |
| 79671 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79672 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79673 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79674 | return retVal; |
| 79675 | } |
| 79676 | |
| 79677 | static UA_StatusCode function_namespace0_generated_395_finish(UA_Server *server, UA_UInt16* ns) { |
| 79678 | return UA_Server_addNode_finish(server, |
| 79679 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8893LU) |
| 79680 | ); |
| 79681 | } |
| 79682 | |
| 79683 | /* UnacknowledgedMessageCount - ns=0;i=8892 */ |
| 79684 | |
| 79685 | static UA_StatusCode function_namespace0_generated_396_begin(UA_Server *server, UA_UInt16* ns) { |
| 79686 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79687 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79688 | attr.minimumSamplingInterval = 0.000000; |
| 79689 | attr.userAccessLevel = 1; |
| 79690 | attr.accessLevel = 1; |
| 79691 | /* Value rank inherited */ |
| 79692 | attr.valueRank = -2; |
| 79693 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79694 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UnacknowledgedMessageCount"); |
| 79695 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79696 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8892LU), |
| 79697 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79698 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79699 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UnacknowledgedMessageCount"), |
| 79700 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79701 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79702 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79703 | return retVal; |
| 79704 | } |
| 79705 | |
| 79706 | static UA_StatusCode function_namespace0_generated_396_finish(UA_Server *server, UA_UInt16* ns) { |
| 79707 | return UA_Server_addNode_finish(server, |
| 79708 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8892LU) |
| 79709 | ); |
| 79710 | } |
| 79711 | |
| 79712 | /* CurrentLifetimeCount - ns=0;i=8891 */ |
| 79713 | |
| 79714 | static UA_StatusCode function_namespace0_generated_397_begin(UA_Server *server, UA_UInt16* ns) { |
| 79715 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79716 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79717 | attr.minimumSamplingInterval = 0.000000; |
| 79718 | attr.userAccessLevel = 1; |
| 79719 | attr.accessLevel = 1; |
| 79720 | /* Value rank inherited */ |
| 79721 | attr.valueRank = -2; |
| 79722 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79723 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentLifetimeCount"); |
| 79724 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79725 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8891LU), |
| 79726 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79727 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79728 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentLifetimeCount"), |
| 79729 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79730 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79731 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79732 | return retVal; |
| 79733 | } |
| 79734 | |
| 79735 | static UA_StatusCode function_namespace0_generated_397_finish(UA_Server *server, UA_UInt16* ns) { |
| 79736 | return UA_Server_addNode_finish(server, |
| 79737 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8891LU) |
| 79738 | ); |
| 79739 | } |
| 79740 | |
| 79741 | /* CurrentKeepAliveCount - ns=0;i=8890 */ |
| 79742 | |
| 79743 | static UA_StatusCode function_namespace0_generated_398_begin(UA_Server *server, UA_UInt16* ns) { |
| 79744 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79745 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79746 | attr.minimumSamplingInterval = 0.000000; |
| 79747 | attr.userAccessLevel = 1; |
| 79748 | attr.accessLevel = 1; |
| 79749 | /* Value rank inherited */ |
| 79750 | attr.valueRank = -2; |
| 79751 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79752 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentKeepAliveCount"); |
| 79753 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79754 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8890LU), |
| 79755 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79756 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79757 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentKeepAliveCount"), |
| 79758 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79759 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79760 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79761 | return retVal; |
| 79762 | } |
| 79763 | |
| 79764 | static UA_StatusCode function_namespace0_generated_398_finish(UA_Server *server, UA_UInt16* ns) { |
| 79765 | return UA_Server_addNode_finish(server, |
| 79766 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8890LU) |
| 79767 | ); |
| 79768 | } |
| 79769 | |
| 79770 | /* LatePublishRequestCount - ns=0;i=8889 */ |
| 79771 | |
| 79772 | static UA_StatusCode function_namespace0_generated_399_begin(UA_Server *server, UA_UInt16* ns) { |
| 79773 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79774 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79775 | attr.minimumSamplingInterval = 0.000000; |
| 79776 | attr.userAccessLevel = 1; |
| 79777 | attr.accessLevel = 1; |
| 79778 | /* Value rank inherited */ |
| 79779 | attr.valueRank = -2; |
| 79780 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79781 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LatePublishRequestCount"); |
| 79782 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79783 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8889LU), |
| 79784 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79785 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79786 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LatePublishRequestCount"), |
| 79787 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79788 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79789 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79790 | return retVal; |
| 79791 | } |
| 79792 | |
| 79793 | static UA_StatusCode function_namespace0_generated_399_finish(UA_Server *server, UA_UInt16* ns) { |
| 79794 | return UA_Server_addNode_finish(server, |
| 79795 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8889LU) |
| 79796 | ); |
| 79797 | } |
| 79798 | |
| 79799 | /* MaxLifetimeCount - ns=0;i=8888 */ |
| 79800 | |
| 79801 | static UA_StatusCode function_namespace0_generated_400_begin(UA_Server *server, UA_UInt16* ns) { |
| 79802 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79803 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79804 | attr.minimumSamplingInterval = 0.000000; |
| 79805 | attr.userAccessLevel = 1; |
| 79806 | attr.accessLevel = 1; |
| 79807 | /* Value rank inherited */ |
| 79808 | attr.valueRank = -2; |
| 79809 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79810 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxLifetimeCount"); |
| 79811 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79812 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8888LU), |
| 79813 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79814 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79815 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxLifetimeCount"), |
| 79816 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79817 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79818 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79819 | return retVal; |
| 79820 | } |
| 79821 | |
| 79822 | static UA_StatusCode function_namespace0_generated_400_finish(UA_Server *server, UA_UInt16* ns) { |
| 79823 | return UA_Server_addNode_finish(server, |
| 79824 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8888LU) |
| 79825 | ); |
| 79826 | } |
| 79827 | |
| 79828 | /* EventNotificationsCount - ns=0;i=2998 */ |
| 79829 | |
| 79830 | static UA_StatusCode function_namespace0_generated_401_begin(UA_Server *server, UA_UInt16* ns) { |
| 79831 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79832 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79833 | attr.minimumSamplingInterval = 0.000000; |
| 79834 | attr.userAccessLevel = 1; |
| 79835 | attr.accessLevel = 1; |
| 79836 | /* Value rank inherited */ |
| 79837 | attr.valueRank = -2; |
| 79838 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79839 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventNotificationsCount"); |
| 79840 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79841 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2998LU), |
| 79842 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79843 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79844 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventNotificationsCount"), |
| 79845 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79846 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79847 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79848 | return retVal; |
| 79849 | } |
| 79850 | |
| 79851 | static UA_StatusCode function_namespace0_generated_401_finish(UA_Server *server, UA_UInt16* ns) { |
| 79852 | return UA_Server_addNode_finish(server, |
| 79853 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2998LU) |
| 79854 | ); |
| 79855 | } |
| 79856 | |
| 79857 | /* NotificationsCount - ns=0;i=2193 */ |
| 79858 | |
| 79859 | static UA_StatusCode function_namespace0_generated_402_begin(UA_Server *server, UA_UInt16* ns) { |
| 79860 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79861 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79862 | attr.minimumSamplingInterval = 0.000000; |
| 79863 | attr.userAccessLevel = 1; |
| 79864 | attr.accessLevel = 1; |
| 79865 | /* Value rank inherited */ |
| 79866 | attr.valueRank = -2; |
| 79867 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79868 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NotificationsCount"); |
| 79869 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79870 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2193LU), |
| 79871 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79872 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79873 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NotificationsCount"), |
| 79874 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79875 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79876 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79877 | return retVal; |
| 79878 | } |
| 79879 | |
| 79880 | static UA_StatusCode function_namespace0_generated_402_finish(UA_Server *server, UA_UInt16* ns) { |
| 79881 | return UA_Server_addNode_finish(server, |
| 79882 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2193LU) |
| 79883 | ); |
| 79884 | } |
| 79885 | |
| 79886 | /* DataChangeNotificationsCount - ns=0;i=2191 */ |
| 79887 | |
| 79888 | static UA_StatusCode function_namespace0_generated_403_begin(UA_Server *server, UA_UInt16* ns) { |
| 79889 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79890 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79891 | attr.minimumSamplingInterval = 0.000000; |
| 79892 | attr.userAccessLevel = 1; |
| 79893 | attr.accessLevel = 1; |
| 79894 | /* Value rank inherited */ |
| 79895 | attr.valueRank = -2; |
| 79896 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79897 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataChangeNotificationsCount"); |
| 79898 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79899 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2191LU), |
| 79900 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79901 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79902 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataChangeNotificationsCount"), |
| 79903 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79904 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79905 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79906 | return retVal; |
| 79907 | } |
| 79908 | |
| 79909 | static UA_StatusCode function_namespace0_generated_403_finish(UA_Server *server, UA_UInt16* ns) { |
| 79910 | return UA_Server_addNode_finish(server, |
| 79911 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2191LU) |
| 79912 | ); |
| 79913 | } |
| 79914 | |
| 79915 | /* PublishRequestCount - ns=0;i=2190 */ |
| 79916 | |
| 79917 | static UA_StatusCode function_namespace0_generated_404_begin(UA_Server *server, UA_UInt16* ns) { |
| 79918 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79919 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79920 | attr.minimumSamplingInterval = 0.000000; |
| 79921 | attr.userAccessLevel = 1; |
| 79922 | attr.accessLevel = 1; |
| 79923 | /* Value rank inherited */ |
| 79924 | attr.valueRank = -2; |
| 79925 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79926 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishRequestCount"); |
| 79927 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79928 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2190LU), |
| 79929 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79930 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79931 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishRequestCount"), |
| 79932 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79933 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79934 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79935 | return retVal; |
| 79936 | } |
| 79937 | |
| 79938 | static UA_StatusCode function_namespace0_generated_404_finish(UA_Server *server, UA_UInt16* ns) { |
| 79939 | return UA_Server_addNode_finish(server, |
| 79940 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2190LU) |
| 79941 | ); |
| 79942 | } |
| 79943 | |
| 79944 | /* TransferredToSameClientCount - ns=0;i=2189 */ |
| 79945 | |
| 79946 | static UA_StatusCode function_namespace0_generated_405_begin(UA_Server *server, UA_UInt16* ns) { |
| 79947 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79948 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79949 | attr.minimumSamplingInterval = 0.000000; |
| 79950 | attr.userAccessLevel = 1; |
| 79951 | attr.accessLevel = 1; |
| 79952 | /* Value rank inherited */ |
| 79953 | attr.valueRank = -2; |
| 79954 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79955 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransferredToSameClientCount"); |
| 79956 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79957 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2189LU), |
| 79958 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79959 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79960 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransferredToSameClientCount"), |
| 79961 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79962 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79963 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79964 | return retVal; |
| 79965 | } |
| 79966 | |
| 79967 | static UA_StatusCode function_namespace0_generated_405_finish(UA_Server *server, UA_UInt16* ns) { |
| 79968 | return UA_Server_addNode_finish(server, |
| 79969 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2189LU) |
| 79970 | ); |
| 79971 | } |
| 79972 | |
| 79973 | /* TransferredToAltClientCount - ns=0;i=2188 */ |
| 79974 | |
| 79975 | static UA_StatusCode function_namespace0_generated_406_begin(UA_Server *server, UA_UInt16* ns) { |
| 79976 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 79977 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 79978 | attr.minimumSamplingInterval = 0.000000; |
| 79979 | attr.userAccessLevel = 1; |
| 79980 | attr.accessLevel = 1; |
| 79981 | /* Value rank inherited */ |
| 79982 | attr.valueRank = -2; |
| 79983 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 79984 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransferredToAltClientCount"); |
| 79985 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 79986 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2188LU), |
| 79987 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 79988 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 79989 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransferredToAltClientCount"), |
| 79990 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 79991 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 79992 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 79993 | return retVal; |
| 79994 | } |
| 79995 | |
| 79996 | static UA_StatusCode function_namespace0_generated_406_finish(UA_Server *server, UA_UInt16* ns) { |
| 79997 | return UA_Server_addNode_finish(server, |
| 79998 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2188LU) |
| 79999 | ); |
| 80000 | } |
| 80001 | |
| 80002 | /* TransferRequestCount - ns=0;i=2187 */ |
| 80003 | |
| 80004 | static UA_StatusCode function_namespace0_generated_407_begin(UA_Server *server, UA_UInt16* ns) { |
| 80005 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80006 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80007 | attr.minimumSamplingInterval = 0.000000; |
| 80008 | attr.userAccessLevel = 1; |
| 80009 | attr.accessLevel = 1; |
| 80010 | /* Value rank inherited */ |
| 80011 | attr.valueRank = -2; |
| 80012 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80013 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransferRequestCount"); |
| 80014 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80015 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2187LU), |
| 80016 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80017 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80018 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransferRequestCount"), |
| 80019 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80020 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80021 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80022 | return retVal; |
| 80023 | } |
| 80024 | |
| 80025 | static UA_StatusCode function_namespace0_generated_407_finish(UA_Server *server, UA_UInt16* ns) { |
| 80026 | return UA_Server_addNode_finish(server, |
| 80027 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2187LU) |
| 80028 | ); |
| 80029 | } |
| 80030 | |
| 80031 | /* RepublishMessageCount - ns=0;i=2186 */ |
| 80032 | |
| 80033 | static UA_StatusCode function_namespace0_generated_408_begin(UA_Server *server, UA_UInt16* ns) { |
| 80034 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80035 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80036 | attr.minimumSamplingInterval = 0.000000; |
| 80037 | attr.userAccessLevel = 1; |
| 80038 | attr.accessLevel = 1; |
| 80039 | /* Value rank inherited */ |
| 80040 | attr.valueRank = -2; |
| 80041 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80042 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RepublishMessageCount"); |
| 80043 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80044 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2186LU), |
| 80045 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80046 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80047 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RepublishMessageCount"), |
| 80048 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80049 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80050 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80051 | return retVal; |
| 80052 | } |
| 80053 | |
| 80054 | static UA_StatusCode function_namespace0_generated_408_finish(UA_Server *server, UA_UInt16* ns) { |
| 80055 | return UA_Server_addNode_finish(server, |
| 80056 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2186LU) |
| 80057 | ); |
| 80058 | } |
| 80059 | |
| 80060 | /* RepublishMessageRequestCount - ns=0;i=2185 */ |
| 80061 | |
| 80062 | static UA_StatusCode function_namespace0_generated_409_begin(UA_Server *server, UA_UInt16* ns) { |
| 80063 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80064 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80065 | attr.minimumSamplingInterval = 0.000000; |
| 80066 | attr.userAccessLevel = 1; |
| 80067 | attr.accessLevel = 1; |
| 80068 | /* Value rank inherited */ |
| 80069 | attr.valueRank = -2; |
| 80070 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80071 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RepublishMessageRequestCount"); |
| 80072 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80073 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2185LU), |
| 80074 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80075 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80076 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RepublishMessageRequestCount"), |
| 80077 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80078 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80079 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80080 | return retVal; |
| 80081 | } |
| 80082 | |
| 80083 | static UA_StatusCode function_namespace0_generated_409_finish(UA_Server *server, UA_UInt16* ns) { |
| 80084 | return UA_Server_addNode_finish(server, |
| 80085 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2185LU) |
| 80086 | ); |
| 80087 | } |
| 80088 | |
| 80089 | /* RepublishRequestCount - ns=0;i=2184 */ |
| 80090 | |
| 80091 | static UA_StatusCode function_namespace0_generated_410_begin(UA_Server *server, UA_UInt16* ns) { |
| 80092 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80093 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80094 | attr.minimumSamplingInterval = 0.000000; |
| 80095 | attr.userAccessLevel = 1; |
| 80096 | attr.accessLevel = 1; |
| 80097 | /* Value rank inherited */ |
| 80098 | attr.valueRank = -2; |
| 80099 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80100 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RepublishRequestCount"); |
| 80101 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80102 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2184LU), |
| 80103 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80104 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80105 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RepublishRequestCount"), |
| 80106 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80107 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80108 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80109 | return retVal; |
| 80110 | } |
| 80111 | |
| 80112 | static UA_StatusCode function_namespace0_generated_410_finish(UA_Server *server, UA_UInt16* ns) { |
| 80113 | return UA_Server_addNode_finish(server, |
| 80114 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2184LU) |
| 80115 | ); |
| 80116 | } |
| 80117 | |
| 80118 | /* DisableCount - ns=0;i=2183 */ |
| 80119 | |
| 80120 | static UA_StatusCode function_namespace0_generated_411_begin(UA_Server *server, UA_UInt16* ns) { |
| 80121 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80122 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80123 | attr.minimumSamplingInterval = 0.000000; |
| 80124 | attr.userAccessLevel = 1; |
| 80125 | attr.accessLevel = 1; |
| 80126 | /* Value rank inherited */ |
| 80127 | attr.valueRank = -2; |
| 80128 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80129 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DisableCount"); |
| 80130 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80131 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2183LU), |
| 80132 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80133 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80134 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DisableCount"), |
| 80135 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80136 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80137 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80138 | return retVal; |
| 80139 | } |
| 80140 | |
| 80141 | static UA_StatusCode function_namespace0_generated_411_finish(UA_Server *server, UA_UInt16* ns) { |
| 80142 | return UA_Server_addNode_finish(server, |
| 80143 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2183LU) |
| 80144 | ); |
| 80145 | } |
| 80146 | |
| 80147 | /* EnableCount - ns=0;i=2182 */ |
| 80148 | |
| 80149 | static UA_StatusCode function_namespace0_generated_412_begin(UA_Server *server, UA_UInt16* ns) { |
| 80150 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80151 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80152 | attr.minimumSamplingInterval = 0.000000; |
| 80153 | attr.userAccessLevel = 1; |
| 80154 | attr.accessLevel = 1; |
| 80155 | /* Value rank inherited */ |
| 80156 | attr.valueRank = -2; |
| 80157 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80158 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnableCount"); |
| 80159 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80160 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2182LU), |
| 80161 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80162 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80163 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnableCount"), |
| 80164 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80165 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80166 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80167 | return retVal; |
| 80168 | } |
| 80169 | |
| 80170 | static UA_StatusCode function_namespace0_generated_412_finish(UA_Server *server, UA_UInt16* ns) { |
| 80171 | return UA_Server_addNode_finish(server, |
| 80172 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2182LU) |
| 80173 | ); |
| 80174 | } |
| 80175 | |
| 80176 | /* ModifyCount - ns=0;i=2181 */ |
| 80177 | |
| 80178 | static UA_StatusCode function_namespace0_generated_413_begin(UA_Server *server, UA_UInt16* ns) { |
| 80179 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80180 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80181 | attr.minimumSamplingInterval = 0.000000; |
| 80182 | attr.userAccessLevel = 1; |
| 80183 | attr.accessLevel = 1; |
| 80184 | /* Value rank inherited */ |
| 80185 | attr.valueRank = -2; |
| 80186 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80187 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModifyCount"); |
| 80188 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80189 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2181LU), |
| 80190 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80191 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80192 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModifyCount"), |
| 80193 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80194 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80195 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80196 | return retVal; |
| 80197 | } |
| 80198 | |
| 80199 | static UA_StatusCode function_namespace0_generated_413_finish(UA_Server *server, UA_UInt16* ns) { |
| 80200 | return UA_Server_addNode_finish(server, |
| 80201 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2181LU) |
| 80202 | ); |
| 80203 | } |
| 80204 | |
| 80205 | /* PublishingEnabled - ns=0;i=2180 */ |
| 80206 | |
| 80207 | static UA_StatusCode function_namespace0_generated_414_begin(UA_Server *server, UA_UInt16* ns) { |
| 80208 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80209 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80210 | attr.minimumSamplingInterval = 0.000000; |
| 80211 | attr.userAccessLevel = 1; |
| 80212 | attr.accessLevel = 1; |
| 80213 | /* Value rank inherited */ |
| 80214 | attr.valueRank = -2; |
| 80215 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 80216 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishingEnabled"); |
| 80217 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80218 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2180LU), |
| 80219 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80220 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80221 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishingEnabled"), |
| 80222 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80223 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80224 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80225 | return retVal; |
| 80226 | } |
| 80227 | |
| 80228 | static UA_StatusCode function_namespace0_generated_414_finish(UA_Server *server, UA_UInt16* ns) { |
| 80229 | return UA_Server_addNode_finish(server, |
| 80230 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2180LU) |
| 80231 | ); |
| 80232 | } |
| 80233 | |
| 80234 | /* MaxNotificationsPerPublish - ns=0;i=2179 */ |
| 80235 | |
| 80236 | static UA_StatusCode function_namespace0_generated_415_begin(UA_Server *server, UA_UInt16* ns) { |
| 80237 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80238 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80239 | attr.minimumSamplingInterval = 0.000000; |
| 80240 | attr.userAccessLevel = 1; |
| 80241 | attr.accessLevel = 1; |
| 80242 | /* Value rank inherited */ |
| 80243 | attr.valueRank = -2; |
| 80244 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80245 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNotificationsPerPublish"); |
| 80246 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80247 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2179LU), |
| 80248 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80249 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80250 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNotificationsPerPublish"), |
| 80251 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80252 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80253 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80254 | return retVal; |
| 80255 | } |
| 80256 | |
| 80257 | static UA_StatusCode function_namespace0_generated_415_finish(UA_Server *server, UA_UInt16* ns) { |
| 80258 | return UA_Server_addNode_finish(server, |
| 80259 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2179LU) |
| 80260 | ); |
| 80261 | } |
| 80262 | |
| 80263 | /* MaxKeepAliveCount - ns=0;i=2177 */ |
| 80264 | |
| 80265 | static UA_StatusCode function_namespace0_generated_416_begin(UA_Server *server, UA_UInt16* ns) { |
| 80266 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80267 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80268 | attr.minimumSamplingInterval = 0.000000; |
| 80269 | attr.userAccessLevel = 1; |
| 80270 | attr.accessLevel = 1; |
| 80271 | /* Value rank inherited */ |
| 80272 | attr.valueRank = -2; |
| 80273 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80274 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxKeepAliveCount"); |
| 80275 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80276 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2177LU), |
| 80277 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80278 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80279 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxKeepAliveCount"), |
| 80280 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80281 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80282 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80283 | return retVal; |
| 80284 | } |
| 80285 | |
| 80286 | static UA_StatusCode function_namespace0_generated_416_finish(UA_Server *server, UA_UInt16* ns) { |
| 80287 | return UA_Server_addNode_finish(server, |
| 80288 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2177LU) |
| 80289 | ); |
| 80290 | } |
| 80291 | |
| 80292 | /* PublishingInterval - ns=0;i=2176 */ |
| 80293 | |
| 80294 | static UA_StatusCode function_namespace0_generated_417_begin(UA_Server *server, UA_UInt16* ns) { |
| 80295 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80296 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80297 | attr.minimumSamplingInterval = 0.000000; |
| 80298 | attr.userAccessLevel = 1; |
| 80299 | attr.accessLevel = 1; |
| 80300 | /* Value rank inherited */ |
| 80301 | attr.valueRank = -2; |
| 80302 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 80303 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishingInterval"); |
| 80304 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80305 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2176LU), |
| 80306 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80307 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80308 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishingInterval"), |
| 80309 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80310 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80311 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80312 | return retVal; |
| 80313 | } |
| 80314 | |
| 80315 | static UA_StatusCode function_namespace0_generated_417_finish(UA_Server *server, UA_UInt16* ns) { |
| 80316 | return UA_Server_addNode_finish(server, |
| 80317 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2176LU) |
| 80318 | ); |
| 80319 | } |
| 80320 | |
| 80321 | /* Priority - ns=0;i=2175 */ |
| 80322 | |
| 80323 | static UA_StatusCode function_namespace0_generated_418_begin(UA_Server *server, UA_UInt16* ns) { |
| 80324 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80325 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80326 | attr.minimumSamplingInterval = 0.000000; |
| 80327 | attr.userAccessLevel = 1; |
| 80328 | attr.accessLevel = 1; |
| 80329 | /* Value rank inherited */ |
| 80330 | attr.valueRank = -2; |
| 80331 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU); |
| 80332 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Priority"); |
| 80333 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80334 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2175LU), |
| 80335 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80336 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80337 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Priority"), |
| 80338 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80339 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80340 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80341 | return retVal; |
| 80342 | } |
| 80343 | |
| 80344 | static UA_StatusCode function_namespace0_generated_418_finish(UA_Server *server, UA_UInt16* ns) { |
| 80345 | return UA_Server_addNode_finish(server, |
| 80346 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2175LU) |
| 80347 | ); |
| 80348 | } |
| 80349 | |
| 80350 | /* SubscriptionId - ns=0;i=2174 */ |
| 80351 | |
| 80352 | static UA_StatusCode function_namespace0_generated_419_begin(UA_Server *server, UA_UInt16* ns) { |
| 80353 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80354 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80355 | attr.minimumSamplingInterval = 0.000000; |
| 80356 | attr.userAccessLevel = 1; |
| 80357 | attr.accessLevel = 1; |
| 80358 | /* Value rank inherited */ |
| 80359 | attr.valueRank = -2; |
| 80360 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80361 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscriptionId"); |
| 80362 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80363 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2174LU), |
| 80364 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80365 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80366 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscriptionId"), |
| 80367 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80368 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80369 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80370 | return retVal; |
| 80371 | } |
| 80372 | |
| 80373 | static UA_StatusCode function_namespace0_generated_419_finish(UA_Server *server, UA_UInt16* ns) { |
| 80374 | return UA_Server_addNode_finish(server, |
| 80375 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2174LU) |
| 80376 | ); |
| 80377 | } |
| 80378 | |
| 80379 | /* SessionId - ns=0;i=2173 */ |
| 80380 | |
| 80381 | static UA_StatusCode function_namespace0_generated_420_begin(UA_Server *server, UA_UInt16* ns) { |
| 80382 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80383 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80384 | attr.minimumSamplingInterval = 0.000000; |
| 80385 | attr.userAccessLevel = 1; |
| 80386 | attr.accessLevel = 1; |
| 80387 | /* Value rank inherited */ |
| 80388 | attr.valueRank = -2; |
| 80389 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 80390 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionId"); |
| 80391 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80392 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2173LU), |
| 80393 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80394 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80395 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionId"), |
| 80396 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80397 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80398 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80399 | return retVal; |
| 80400 | } |
| 80401 | |
| 80402 | static UA_StatusCode function_namespace0_generated_420_finish(UA_Server *server, UA_UInt16* ns) { |
| 80403 | return UA_Server_addNode_finish(server, |
| 80404 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2173LU) |
| 80405 | ); |
| 80406 | } |
| 80407 | |
| 80408 | /* SubscriptionDiagnosticsArrayType - ns=0;i=2171 */ |
| 80409 | |
| 80410 | static UA_StatusCode function_namespace0_generated_421_begin(UA_Server *server, UA_UInt16* ns) { |
| 80411 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80412 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 80413 | attr.valueRank = 1; |
| 80414 | attr.arrayDimensionsSize = 1; |
| 80415 | UA_UInt32 arrayDimensions[1]; |
| 80416 | arrayDimensions[0] = 0; |
| 80417 | attr.arrayDimensions = &arrayDimensions[0]; |
| 80418 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 874LU); |
| 80419 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscriptionDiagnosticsArrayType"); |
| 80420 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 80421 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2171LU), |
| 80422 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80423 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 80424 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscriptionDiagnosticsArrayType"), |
| 80425 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 80426 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 80427 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80428 | return retVal; |
| 80429 | } |
| 80430 | |
| 80431 | static UA_StatusCode function_namespace0_generated_421_finish(UA_Server *server, UA_UInt16* ns) { |
| 80432 | return UA_Server_addNode_finish(server, |
| 80433 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2171LU) |
| 80434 | ); |
| 80435 | } |
| 80436 | |
| 80437 | /* SubscriptionDiagnostics - ns=0;i=12784 */ |
| 80438 | |
| 80439 | static UA_StatusCode function_namespace0_generated_422_begin(UA_Server *server, UA_UInt16* ns) { |
| 80440 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80441 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80442 | attr.minimumSamplingInterval = 0.000000; |
| 80443 | attr.userAccessLevel = 1; |
| 80444 | attr.accessLevel = 1; |
| 80445 | /* Value rank inherited */ |
| 80446 | attr.valueRank = -2; |
| 80447 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 874LU); |
| 80448 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscriptionDiagnostics"); |
| 80449 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80450 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80451 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2171LU), |
| 80452 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80453 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscriptionDiagnostics"), |
| 80454 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2172LU), |
| 80455 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80456 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80457 | return retVal; |
| 80458 | } |
| 80459 | |
| 80460 | static UA_StatusCode function_namespace0_generated_422_finish(UA_Server *server, UA_UInt16* ns) { |
| 80461 | return UA_Server_addNode_finish(server, |
| 80462 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU) |
| 80463 | ); |
| 80464 | } |
| 80465 | |
| 80466 | /* EventQueueOverflowCount - ns=0;i=12815 */ |
| 80467 | |
| 80468 | static UA_StatusCode function_namespace0_generated_423_begin(UA_Server *server, UA_UInt16* ns) { |
| 80469 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80470 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80471 | attr.minimumSamplingInterval = 0.000000; |
| 80472 | attr.userAccessLevel = 1; |
| 80473 | attr.accessLevel = 1; |
| 80474 | /* Value rank inherited */ |
| 80475 | attr.valueRank = -2; |
| 80476 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80477 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventQueueOverflowCount"); |
| 80478 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80479 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12815LU), |
| 80480 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80481 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80482 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventQueueOverflowCount"), |
| 80483 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80484 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80485 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80486 | return retVal; |
| 80487 | } |
| 80488 | |
| 80489 | static UA_StatusCode function_namespace0_generated_423_finish(UA_Server *server, UA_UInt16* ns) { |
| 80490 | return UA_Server_addNode_finish(server, |
| 80491 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12815LU) |
| 80492 | ); |
| 80493 | } |
| 80494 | |
| 80495 | /* NextSequenceNumber - ns=0;i=12814 */ |
| 80496 | |
| 80497 | static UA_StatusCode function_namespace0_generated_424_begin(UA_Server *server, UA_UInt16* ns) { |
| 80498 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80499 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80500 | attr.minimumSamplingInterval = 0.000000; |
| 80501 | attr.userAccessLevel = 1; |
| 80502 | attr.accessLevel = 1; |
| 80503 | /* Value rank inherited */ |
| 80504 | attr.valueRank = -2; |
| 80505 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80506 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NextSequenceNumber"); |
| 80507 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80508 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12814LU), |
| 80509 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80510 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80511 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NextSequenceNumber"), |
| 80512 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80513 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80514 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80515 | return retVal; |
| 80516 | } |
| 80517 | |
| 80518 | static UA_StatusCode function_namespace0_generated_424_finish(UA_Server *server, UA_UInt16* ns) { |
| 80519 | return UA_Server_addNode_finish(server, |
| 80520 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12814LU) |
| 80521 | ); |
| 80522 | } |
| 80523 | |
| 80524 | /* MonitoringQueueOverflowCount - ns=0;i=12813 */ |
| 80525 | |
| 80526 | static UA_StatusCode function_namespace0_generated_425_begin(UA_Server *server, UA_UInt16* ns) { |
| 80527 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80528 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80529 | attr.minimumSamplingInterval = 0.000000; |
| 80530 | attr.userAccessLevel = 1; |
| 80531 | attr.accessLevel = 1; |
| 80532 | /* Value rank inherited */ |
| 80533 | attr.valueRank = -2; |
| 80534 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80535 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MonitoringQueueOverflowCount"); |
| 80536 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80537 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12813LU), |
| 80538 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80539 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80540 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MonitoringQueueOverflowCount"), |
| 80541 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80542 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80543 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80544 | return retVal; |
| 80545 | } |
| 80546 | |
| 80547 | static UA_StatusCode function_namespace0_generated_425_finish(UA_Server *server, UA_UInt16* ns) { |
| 80548 | return UA_Server_addNode_finish(server, |
| 80549 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12813LU) |
| 80550 | ); |
| 80551 | } |
| 80552 | |
| 80553 | /* DisabledMonitoredItemCount - ns=0;i=12812 */ |
| 80554 | |
| 80555 | static UA_StatusCode function_namespace0_generated_426_begin(UA_Server *server, UA_UInt16* ns) { |
| 80556 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80557 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80558 | attr.minimumSamplingInterval = 0.000000; |
| 80559 | attr.userAccessLevel = 1; |
| 80560 | attr.accessLevel = 1; |
| 80561 | /* Value rank inherited */ |
| 80562 | attr.valueRank = -2; |
| 80563 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80564 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DisabledMonitoredItemCount"); |
| 80565 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80566 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12812LU), |
| 80567 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80568 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80569 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DisabledMonitoredItemCount"), |
| 80570 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80571 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80572 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80573 | return retVal; |
| 80574 | } |
| 80575 | |
| 80576 | static UA_StatusCode function_namespace0_generated_426_finish(UA_Server *server, UA_UInt16* ns) { |
| 80577 | return UA_Server_addNode_finish(server, |
| 80578 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12812LU) |
| 80579 | ); |
| 80580 | } |
| 80581 | |
| 80582 | /* MonitoredItemCount - ns=0;i=12811 */ |
| 80583 | |
| 80584 | static UA_StatusCode function_namespace0_generated_427_begin(UA_Server *server, UA_UInt16* ns) { |
| 80585 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80586 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80587 | attr.minimumSamplingInterval = 0.000000; |
| 80588 | attr.userAccessLevel = 1; |
| 80589 | attr.accessLevel = 1; |
| 80590 | /* Value rank inherited */ |
| 80591 | attr.valueRank = -2; |
| 80592 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80593 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MonitoredItemCount"); |
| 80594 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80595 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12811LU), |
| 80596 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80597 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80598 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MonitoredItemCount"), |
| 80599 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80600 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80601 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80602 | return retVal; |
| 80603 | } |
| 80604 | |
| 80605 | static UA_StatusCode function_namespace0_generated_427_finish(UA_Server *server, UA_UInt16* ns) { |
| 80606 | return UA_Server_addNode_finish(server, |
| 80607 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12811LU) |
| 80608 | ); |
| 80609 | } |
| 80610 | |
| 80611 | /* DiscardedMessageCount - ns=0;i=12810 */ |
| 80612 | |
| 80613 | static UA_StatusCode function_namespace0_generated_428_begin(UA_Server *server, UA_UInt16* ns) { |
| 80614 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80615 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80616 | attr.minimumSamplingInterval = 0.000000; |
| 80617 | attr.userAccessLevel = 1; |
| 80618 | attr.accessLevel = 1; |
| 80619 | /* Value rank inherited */ |
| 80620 | attr.valueRank = -2; |
| 80621 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80622 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DiscardedMessageCount"); |
| 80623 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80624 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12810LU), |
| 80625 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80626 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80627 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DiscardedMessageCount"), |
| 80628 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80629 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80630 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80631 | return retVal; |
| 80632 | } |
| 80633 | |
| 80634 | static UA_StatusCode function_namespace0_generated_428_finish(UA_Server *server, UA_UInt16* ns) { |
| 80635 | return UA_Server_addNode_finish(server, |
| 80636 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12810LU) |
| 80637 | ); |
| 80638 | } |
| 80639 | |
| 80640 | /* UnacknowledgedMessageCount - ns=0;i=12809 */ |
| 80641 | |
| 80642 | static UA_StatusCode function_namespace0_generated_429_begin(UA_Server *server, UA_UInt16* ns) { |
| 80643 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80644 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80645 | attr.minimumSamplingInterval = 0.000000; |
| 80646 | attr.userAccessLevel = 1; |
| 80647 | attr.accessLevel = 1; |
| 80648 | /* Value rank inherited */ |
| 80649 | attr.valueRank = -2; |
| 80650 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80651 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UnacknowledgedMessageCount"); |
| 80652 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80653 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12809LU), |
| 80654 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80655 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80656 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UnacknowledgedMessageCount"), |
| 80657 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80658 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80659 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80660 | return retVal; |
| 80661 | } |
| 80662 | |
| 80663 | static UA_StatusCode function_namespace0_generated_429_finish(UA_Server *server, UA_UInt16* ns) { |
| 80664 | return UA_Server_addNode_finish(server, |
| 80665 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12809LU) |
| 80666 | ); |
| 80667 | } |
| 80668 | |
| 80669 | /* CurrentLifetimeCount - ns=0;i=12808 */ |
| 80670 | |
| 80671 | static UA_StatusCode function_namespace0_generated_430_begin(UA_Server *server, UA_UInt16* ns) { |
| 80672 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80673 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80674 | attr.minimumSamplingInterval = 0.000000; |
| 80675 | attr.userAccessLevel = 1; |
| 80676 | attr.accessLevel = 1; |
| 80677 | /* Value rank inherited */ |
| 80678 | attr.valueRank = -2; |
| 80679 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80680 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentLifetimeCount"); |
| 80681 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80682 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12808LU), |
| 80683 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80684 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80685 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentLifetimeCount"), |
| 80686 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80687 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80688 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80689 | return retVal; |
| 80690 | } |
| 80691 | |
| 80692 | static UA_StatusCode function_namespace0_generated_430_finish(UA_Server *server, UA_UInt16* ns) { |
| 80693 | return UA_Server_addNode_finish(server, |
| 80694 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12808LU) |
| 80695 | ); |
| 80696 | } |
| 80697 | |
| 80698 | /* CurrentKeepAliveCount - ns=0;i=12807 */ |
| 80699 | |
| 80700 | static UA_StatusCode function_namespace0_generated_431_begin(UA_Server *server, UA_UInt16* ns) { |
| 80701 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80702 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80703 | attr.minimumSamplingInterval = 0.000000; |
| 80704 | attr.userAccessLevel = 1; |
| 80705 | attr.accessLevel = 1; |
| 80706 | /* Value rank inherited */ |
| 80707 | attr.valueRank = -2; |
| 80708 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80709 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentKeepAliveCount"); |
| 80710 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80711 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12807LU), |
| 80712 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80713 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80714 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentKeepAliveCount"), |
| 80715 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80716 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80717 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80718 | return retVal; |
| 80719 | } |
| 80720 | |
| 80721 | static UA_StatusCode function_namespace0_generated_431_finish(UA_Server *server, UA_UInt16* ns) { |
| 80722 | return UA_Server_addNode_finish(server, |
| 80723 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12807LU) |
| 80724 | ); |
| 80725 | } |
| 80726 | |
| 80727 | /* LatePublishRequestCount - ns=0;i=12806 */ |
| 80728 | |
| 80729 | static UA_StatusCode function_namespace0_generated_432_begin(UA_Server *server, UA_UInt16* ns) { |
| 80730 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80731 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80732 | attr.minimumSamplingInterval = 0.000000; |
| 80733 | attr.userAccessLevel = 1; |
| 80734 | attr.accessLevel = 1; |
| 80735 | /* Value rank inherited */ |
| 80736 | attr.valueRank = -2; |
| 80737 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80738 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LatePublishRequestCount"); |
| 80739 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80740 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12806LU), |
| 80741 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80742 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80743 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LatePublishRequestCount"), |
| 80744 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80745 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80746 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80747 | return retVal; |
| 80748 | } |
| 80749 | |
| 80750 | static UA_StatusCode function_namespace0_generated_432_finish(UA_Server *server, UA_UInt16* ns) { |
| 80751 | return UA_Server_addNode_finish(server, |
| 80752 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12806LU) |
| 80753 | ); |
| 80754 | } |
| 80755 | |
| 80756 | /* NotificationsCount - ns=0;i=12805 */ |
| 80757 | |
| 80758 | static UA_StatusCode function_namespace0_generated_433_begin(UA_Server *server, UA_UInt16* ns) { |
| 80759 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80760 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80761 | attr.minimumSamplingInterval = 0.000000; |
| 80762 | attr.userAccessLevel = 1; |
| 80763 | attr.accessLevel = 1; |
| 80764 | /* Value rank inherited */ |
| 80765 | attr.valueRank = -2; |
| 80766 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80767 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NotificationsCount"); |
| 80768 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80769 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12805LU), |
| 80770 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80771 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80772 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NotificationsCount"), |
| 80773 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80774 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80775 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80776 | return retVal; |
| 80777 | } |
| 80778 | |
| 80779 | static UA_StatusCode function_namespace0_generated_433_finish(UA_Server *server, UA_UInt16* ns) { |
| 80780 | return UA_Server_addNode_finish(server, |
| 80781 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12805LU) |
| 80782 | ); |
| 80783 | } |
| 80784 | |
| 80785 | /* EventNotificationsCount - ns=0;i=12804 */ |
| 80786 | |
| 80787 | static UA_StatusCode function_namespace0_generated_434_begin(UA_Server *server, UA_UInt16* ns) { |
| 80788 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80789 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80790 | attr.minimumSamplingInterval = 0.000000; |
| 80791 | attr.userAccessLevel = 1; |
| 80792 | attr.accessLevel = 1; |
| 80793 | /* Value rank inherited */ |
| 80794 | attr.valueRank = -2; |
| 80795 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80796 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EventNotificationsCount"); |
| 80797 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80798 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12804LU), |
| 80799 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80800 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80801 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EventNotificationsCount"), |
| 80802 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80803 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80804 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80805 | return retVal; |
| 80806 | } |
| 80807 | |
| 80808 | static UA_StatusCode function_namespace0_generated_434_finish(UA_Server *server, UA_UInt16* ns) { |
| 80809 | return UA_Server_addNode_finish(server, |
| 80810 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12804LU) |
| 80811 | ); |
| 80812 | } |
| 80813 | |
| 80814 | /* DataChangeNotificationsCount - ns=0;i=12803 */ |
| 80815 | |
| 80816 | static UA_StatusCode function_namespace0_generated_435_begin(UA_Server *server, UA_UInt16* ns) { |
| 80817 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80818 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80819 | attr.minimumSamplingInterval = 0.000000; |
| 80820 | attr.userAccessLevel = 1; |
| 80821 | attr.accessLevel = 1; |
| 80822 | /* Value rank inherited */ |
| 80823 | attr.valueRank = -2; |
| 80824 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80825 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataChangeNotificationsCount"); |
| 80826 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80827 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12803LU), |
| 80828 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80829 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80830 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataChangeNotificationsCount"), |
| 80831 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80832 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80833 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80834 | return retVal; |
| 80835 | } |
| 80836 | |
| 80837 | static UA_StatusCode function_namespace0_generated_435_finish(UA_Server *server, UA_UInt16* ns) { |
| 80838 | return UA_Server_addNode_finish(server, |
| 80839 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12803LU) |
| 80840 | ); |
| 80841 | } |
| 80842 | |
| 80843 | /* PublishRequestCount - ns=0;i=12802 */ |
| 80844 | |
| 80845 | static UA_StatusCode function_namespace0_generated_436_begin(UA_Server *server, UA_UInt16* ns) { |
| 80846 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80847 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80848 | attr.minimumSamplingInterval = 0.000000; |
| 80849 | attr.userAccessLevel = 1; |
| 80850 | attr.accessLevel = 1; |
| 80851 | /* Value rank inherited */ |
| 80852 | attr.valueRank = -2; |
| 80853 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80854 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishRequestCount"); |
| 80855 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80856 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12802LU), |
| 80857 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80858 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80859 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishRequestCount"), |
| 80860 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80861 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80862 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80863 | return retVal; |
| 80864 | } |
| 80865 | |
| 80866 | static UA_StatusCode function_namespace0_generated_436_finish(UA_Server *server, UA_UInt16* ns) { |
| 80867 | return UA_Server_addNode_finish(server, |
| 80868 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12802LU) |
| 80869 | ); |
| 80870 | } |
| 80871 | |
| 80872 | /* TransferredToSameClientCount - ns=0;i=12801 */ |
| 80873 | |
| 80874 | static UA_StatusCode function_namespace0_generated_437_begin(UA_Server *server, UA_UInt16* ns) { |
| 80875 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80876 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80877 | attr.minimumSamplingInterval = 0.000000; |
| 80878 | attr.userAccessLevel = 1; |
| 80879 | attr.accessLevel = 1; |
| 80880 | /* Value rank inherited */ |
| 80881 | attr.valueRank = -2; |
| 80882 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80883 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransferredToSameClientCount"); |
| 80884 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80885 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12801LU), |
| 80886 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80887 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80888 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransferredToSameClientCount"), |
| 80889 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80890 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80891 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80892 | return retVal; |
| 80893 | } |
| 80894 | |
| 80895 | static UA_StatusCode function_namespace0_generated_437_finish(UA_Server *server, UA_UInt16* ns) { |
| 80896 | return UA_Server_addNode_finish(server, |
| 80897 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12801LU) |
| 80898 | ); |
| 80899 | } |
| 80900 | |
| 80901 | /* TransferredToAltClientCount - ns=0;i=12800 */ |
| 80902 | |
| 80903 | static UA_StatusCode function_namespace0_generated_438_begin(UA_Server *server, UA_UInt16* ns) { |
| 80904 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80905 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80906 | attr.minimumSamplingInterval = 0.000000; |
| 80907 | attr.userAccessLevel = 1; |
| 80908 | attr.accessLevel = 1; |
| 80909 | /* Value rank inherited */ |
| 80910 | attr.valueRank = -2; |
| 80911 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80912 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransferredToAltClientCount"); |
| 80913 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80914 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12800LU), |
| 80915 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80916 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80917 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransferredToAltClientCount"), |
| 80918 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80919 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80920 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80921 | return retVal; |
| 80922 | } |
| 80923 | |
| 80924 | static UA_StatusCode function_namespace0_generated_438_finish(UA_Server *server, UA_UInt16* ns) { |
| 80925 | return UA_Server_addNode_finish(server, |
| 80926 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12800LU) |
| 80927 | ); |
| 80928 | } |
| 80929 | |
| 80930 | /* TransferRequestCount - ns=0;i=12799 */ |
| 80931 | |
| 80932 | static UA_StatusCode function_namespace0_generated_439_begin(UA_Server *server, UA_UInt16* ns) { |
| 80933 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80934 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80935 | attr.minimumSamplingInterval = 0.000000; |
| 80936 | attr.userAccessLevel = 1; |
| 80937 | attr.accessLevel = 1; |
| 80938 | /* Value rank inherited */ |
| 80939 | attr.valueRank = -2; |
| 80940 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80941 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransferRequestCount"); |
| 80942 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80943 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12799LU), |
| 80944 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80945 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80946 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransferRequestCount"), |
| 80947 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80948 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80949 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80950 | return retVal; |
| 80951 | } |
| 80952 | |
| 80953 | static UA_StatusCode function_namespace0_generated_439_finish(UA_Server *server, UA_UInt16* ns) { |
| 80954 | return UA_Server_addNode_finish(server, |
| 80955 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12799LU) |
| 80956 | ); |
| 80957 | } |
| 80958 | |
| 80959 | /* RepublishMessageCount - ns=0;i=12798 */ |
| 80960 | |
| 80961 | static UA_StatusCode function_namespace0_generated_440_begin(UA_Server *server, UA_UInt16* ns) { |
| 80962 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80963 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80964 | attr.minimumSamplingInterval = 0.000000; |
| 80965 | attr.userAccessLevel = 1; |
| 80966 | attr.accessLevel = 1; |
| 80967 | /* Value rank inherited */ |
| 80968 | attr.valueRank = -2; |
| 80969 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80970 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RepublishMessageCount"); |
| 80971 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 80972 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12798LU), |
| 80973 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 80974 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 80975 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RepublishMessageCount"), |
| 80976 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 80977 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 80978 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 80979 | return retVal; |
| 80980 | } |
| 80981 | |
| 80982 | static UA_StatusCode function_namespace0_generated_440_finish(UA_Server *server, UA_UInt16* ns) { |
| 80983 | return UA_Server_addNode_finish(server, |
| 80984 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12798LU) |
| 80985 | ); |
| 80986 | } |
| 80987 | |
| 80988 | /* RepublishMessageRequestCount - ns=0;i=12797 */ |
| 80989 | |
| 80990 | static UA_StatusCode function_namespace0_generated_441_begin(UA_Server *server, UA_UInt16* ns) { |
| 80991 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 80992 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 80993 | attr.minimumSamplingInterval = 0.000000; |
| 80994 | attr.userAccessLevel = 1; |
| 80995 | attr.accessLevel = 1; |
| 80996 | /* Value rank inherited */ |
| 80997 | attr.valueRank = -2; |
| 80998 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 80999 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RepublishMessageRequestCount"); |
| 81000 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81001 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12797LU), |
| 81002 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81003 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81004 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RepublishMessageRequestCount"), |
| 81005 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81006 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81007 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81008 | return retVal; |
| 81009 | } |
| 81010 | |
| 81011 | static UA_StatusCode function_namespace0_generated_441_finish(UA_Server *server, UA_UInt16* ns) { |
| 81012 | return UA_Server_addNode_finish(server, |
| 81013 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12797LU) |
| 81014 | ); |
| 81015 | } |
| 81016 | |
| 81017 | /* RepublishRequestCount - ns=0;i=12796 */ |
| 81018 | |
| 81019 | static UA_StatusCode function_namespace0_generated_442_begin(UA_Server *server, UA_UInt16* ns) { |
| 81020 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81021 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81022 | attr.minimumSamplingInterval = 0.000000; |
| 81023 | attr.userAccessLevel = 1; |
| 81024 | attr.accessLevel = 1; |
| 81025 | /* Value rank inherited */ |
| 81026 | attr.valueRank = -2; |
| 81027 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 81028 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RepublishRequestCount"); |
| 81029 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81030 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12796LU), |
| 81031 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81032 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81033 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RepublishRequestCount"), |
| 81034 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81035 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81036 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81037 | return retVal; |
| 81038 | } |
| 81039 | |
| 81040 | static UA_StatusCode function_namespace0_generated_442_finish(UA_Server *server, UA_UInt16* ns) { |
| 81041 | return UA_Server_addNode_finish(server, |
| 81042 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12796LU) |
| 81043 | ); |
| 81044 | } |
| 81045 | |
| 81046 | /* DisableCount - ns=0;i=12795 */ |
| 81047 | |
| 81048 | static UA_StatusCode function_namespace0_generated_443_begin(UA_Server *server, UA_UInt16* ns) { |
| 81049 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81050 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81051 | attr.minimumSamplingInterval = 0.000000; |
| 81052 | attr.userAccessLevel = 1; |
| 81053 | attr.accessLevel = 1; |
| 81054 | /* Value rank inherited */ |
| 81055 | attr.valueRank = -2; |
| 81056 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 81057 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DisableCount"); |
| 81058 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81059 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12795LU), |
| 81060 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81061 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81062 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DisableCount"), |
| 81063 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81064 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81065 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81066 | return retVal; |
| 81067 | } |
| 81068 | |
| 81069 | static UA_StatusCode function_namespace0_generated_443_finish(UA_Server *server, UA_UInt16* ns) { |
| 81070 | return UA_Server_addNode_finish(server, |
| 81071 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12795LU) |
| 81072 | ); |
| 81073 | } |
| 81074 | |
| 81075 | /* EnableCount - ns=0;i=12794 */ |
| 81076 | |
| 81077 | static UA_StatusCode function_namespace0_generated_444_begin(UA_Server *server, UA_UInt16* ns) { |
| 81078 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81079 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81080 | attr.minimumSamplingInterval = 0.000000; |
| 81081 | attr.userAccessLevel = 1; |
| 81082 | attr.accessLevel = 1; |
| 81083 | /* Value rank inherited */ |
| 81084 | attr.valueRank = -2; |
| 81085 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 81086 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnableCount"); |
| 81087 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81088 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12794LU), |
| 81089 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81090 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81091 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnableCount"), |
| 81092 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81093 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81094 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81095 | return retVal; |
| 81096 | } |
| 81097 | |
| 81098 | static UA_StatusCode function_namespace0_generated_444_finish(UA_Server *server, UA_UInt16* ns) { |
| 81099 | return UA_Server_addNode_finish(server, |
| 81100 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12794LU) |
| 81101 | ); |
| 81102 | } |
| 81103 | |
| 81104 | /* ModifyCount - ns=0;i=12793 */ |
| 81105 | |
| 81106 | static UA_StatusCode function_namespace0_generated_445_begin(UA_Server *server, UA_UInt16* ns) { |
| 81107 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81108 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81109 | attr.minimumSamplingInterval = 0.000000; |
| 81110 | attr.userAccessLevel = 1; |
| 81111 | attr.accessLevel = 1; |
| 81112 | /* Value rank inherited */ |
| 81113 | attr.valueRank = -2; |
| 81114 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 81115 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModifyCount"); |
| 81116 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81117 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12793LU), |
| 81118 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81119 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81120 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModifyCount"), |
| 81121 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81122 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81123 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81124 | return retVal; |
| 81125 | } |
| 81126 | |
| 81127 | static UA_StatusCode function_namespace0_generated_445_finish(UA_Server *server, UA_UInt16* ns) { |
| 81128 | return UA_Server_addNode_finish(server, |
| 81129 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12793LU) |
| 81130 | ); |
| 81131 | } |
| 81132 | |
| 81133 | /* PublishingEnabled - ns=0;i=12792 */ |
| 81134 | |
| 81135 | static UA_StatusCode function_namespace0_generated_446_begin(UA_Server *server, UA_UInt16* ns) { |
| 81136 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81137 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81138 | attr.minimumSamplingInterval = 0.000000; |
| 81139 | attr.userAccessLevel = 1; |
| 81140 | attr.accessLevel = 1; |
| 81141 | /* Value rank inherited */ |
| 81142 | attr.valueRank = -2; |
| 81143 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 81144 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishingEnabled"); |
| 81145 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81146 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12792LU), |
| 81147 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81148 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81149 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishingEnabled"), |
| 81150 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81151 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81152 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81153 | return retVal; |
| 81154 | } |
| 81155 | |
| 81156 | static UA_StatusCode function_namespace0_generated_446_finish(UA_Server *server, UA_UInt16* ns) { |
| 81157 | return UA_Server_addNode_finish(server, |
| 81158 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12792LU) |
| 81159 | ); |
| 81160 | } |
| 81161 | |
| 81162 | /* MaxNotificationsPerPublish - ns=0;i=12791 */ |
| 81163 | |
| 81164 | static UA_StatusCode function_namespace0_generated_447_begin(UA_Server *server, UA_UInt16* ns) { |
| 81165 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81166 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81167 | attr.minimumSamplingInterval = 0.000000; |
| 81168 | attr.userAccessLevel = 1; |
| 81169 | attr.accessLevel = 1; |
| 81170 | /* Value rank inherited */ |
| 81171 | attr.valueRank = -2; |
| 81172 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 81173 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNotificationsPerPublish"); |
| 81174 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81175 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12791LU), |
| 81176 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81177 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81178 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNotificationsPerPublish"), |
| 81179 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81180 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81181 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81182 | return retVal; |
| 81183 | } |
| 81184 | |
| 81185 | static UA_StatusCode function_namespace0_generated_447_finish(UA_Server *server, UA_UInt16* ns) { |
| 81186 | return UA_Server_addNode_finish(server, |
| 81187 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12791LU) |
| 81188 | ); |
| 81189 | } |
| 81190 | |
| 81191 | /* MaxLifetimeCount - ns=0;i=12790 */ |
| 81192 | |
| 81193 | static UA_StatusCode function_namespace0_generated_448_begin(UA_Server *server, UA_UInt16* ns) { |
| 81194 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81195 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81196 | attr.minimumSamplingInterval = 0.000000; |
| 81197 | attr.userAccessLevel = 1; |
| 81198 | attr.accessLevel = 1; |
| 81199 | /* Value rank inherited */ |
| 81200 | attr.valueRank = -2; |
| 81201 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 81202 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxLifetimeCount"); |
| 81203 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81204 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12790LU), |
| 81205 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81206 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81207 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxLifetimeCount"), |
| 81208 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81209 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81210 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81211 | return retVal; |
| 81212 | } |
| 81213 | |
| 81214 | static UA_StatusCode function_namespace0_generated_448_finish(UA_Server *server, UA_UInt16* ns) { |
| 81215 | return UA_Server_addNode_finish(server, |
| 81216 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12790LU) |
| 81217 | ); |
| 81218 | } |
| 81219 | |
| 81220 | /* MaxKeepAliveCount - ns=0;i=12789 */ |
| 81221 | |
| 81222 | static UA_StatusCode function_namespace0_generated_449_begin(UA_Server *server, UA_UInt16* ns) { |
| 81223 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81224 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81225 | attr.minimumSamplingInterval = 0.000000; |
| 81226 | attr.userAccessLevel = 1; |
| 81227 | attr.accessLevel = 1; |
| 81228 | /* Value rank inherited */ |
| 81229 | attr.valueRank = -2; |
| 81230 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 81231 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxKeepAliveCount"); |
| 81232 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81233 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12789LU), |
| 81234 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81235 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81236 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxKeepAliveCount"), |
| 81237 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81238 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81239 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81240 | return retVal; |
| 81241 | } |
| 81242 | |
| 81243 | static UA_StatusCode function_namespace0_generated_449_finish(UA_Server *server, UA_UInt16* ns) { |
| 81244 | return UA_Server_addNode_finish(server, |
| 81245 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12789LU) |
| 81246 | ); |
| 81247 | } |
| 81248 | |
| 81249 | /* PublishingInterval - ns=0;i=12788 */ |
| 81250 | |
| 81251 | static UA_StatusCode function_namespace0_generated_450_begin(UA_Server *server, UA_UInt16* ns) { |
| 81252 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81253 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81254 | attr.minimumSamplingInterval = 0.000000; |
| 81255 | attr.userAccessLevel = 1; |
| 81256 | attr.accessLevel = 1; |
| 81257 | /* Value rank inherited */ |
| 81258 | attr.valueRank = -2; |
| 81259 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 81260 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishingInterval"); |
| 81261 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81262 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12788LU), |
| 81263 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81264 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81265 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishingInterval"), |
| 81266 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81267 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81268 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81269 | return retVal; |
| 81270 | } |
| 81271 | |
| 81272 | static UA_StatusCode function_namespace0_generated_450_finish(UA_Server *server, UA_UInt16* ns) { |
| 81273 | return UA_Server_addNode_finish(server, |
| 81274 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12788LU) |
| 81275 | ); |
| 81276 | } |
| 81277 | |
| 81278 | /* Priority - ns=0;i=12787 */ |
| 81279 | |
| 81280 | static UA_StatusCode function_namespace0_generated_451_begin(UA_Server *server, UA_UInt16* ns) { |
| 81281 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81282 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81283 | attr.minimumSamplingInterval = 0.000000; |
| 81284 | attr.userAccessLevel = 1; |
| 81285 | attr.accessLevel = 1; |
| 81286 | /* Value rank inherited */ |
| 81287 | attr.valueRank = -2; |
| 81288 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU); |
| 81289 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Priority"); |
| 81290 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81291 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12787LU), |
| 81292 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81293 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81294 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Priority"), |
| 81295 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81296 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81297 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81298 | return retVal; |
| 81299 | } |
| 81300 | |
| 81301 | static UA_StatusCode function_namespace0_generated_451_finish(UA_Server *server, UA_UInt16* ns) { |
| 81302 | return UA_Server_addNode_finish(server, |
| 81303 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12787LU) |
| 81304 | ); |
| 81305 | } |
| 81306 | |
| 81307 | /* SubscriptionId - ns=0;i=12786 */ |
| 81308 | |
| 81309 | static UA_StatusCode function_namespace0_generated_452_begin(UA_Server *server, UA_UInt16* ns) { |
| 81310 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81311 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81312 | attr.minimumSamplingInterval = 0.000000; |
| 81313 | attr.userAccessLevel = 1; |
| 81314 | attr.accessLevel = 1; |
| 81315 | /* Value rank inherited */ |
| 81316 | attr.valueRank = -2; |
| 81317 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 81318 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscriptionId"); |
| 81319 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81320 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12786LU), |
| 81321 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81322 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81323 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscriptionId"), |
| 81324 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81325 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81326 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81327 | return retVal; |
| 81328 | } |
| 81329 | |
| 81330 | static UA_StatusCode function_namespace0_generated_452_finish(UA_Server *server, UA_UInt16* ns) { |
| 81331 | return UA_Server_addNode_finish(server, |
| 81332 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12786LU) |
| 81333 | ); |
| 81334 | } |
| 81335 | |
| 81336 | /* SessionId - ns=0;i=12785 */ |
| 81337 | |
| 81338 | static UA_StatusCode function_namespace0_generated_453_begin(UA_Server *server, UA_UInt16* ns) { |
| 81339 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81340 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81341 | attr.minimumSamplingInterval = 0.000000; |
| 81342 | attr.userAccessLevel = 1; |
| 81343 | attr.accessLevel = 1; |
| 81344 | /* Value rank inherited */ |
| 81345 | attr.valueRank = -2; |
| 81346 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 81347 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionId"); |
| 81348 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81349 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12785LU), |
| 81350 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), |
| 81351 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81352 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionId"), |
| 81353 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81354 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81355 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81356 | return retVal; |
| 81357 | } |
| 81358 | |
| 81359 | static UA_StatusCode function_namespace0_generated_453_finish(UA_Server *server, UA_UInt16* ns) { |
| 81360 | return UA_Server_addNode_finish(server, |
| 81361 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12785LU) |
| 81362 | ); |
| 81363 | } |
| 81364 | |
| 81365 | /* SessionSecurityDiagnosticsType - ns=0;i=2244 */ |
| 81366 | |
| 81367 | static UA_StatusCode function_namespace0_generated_454_begin(UA_Server *server, UA_UInt16* ns) { |
| 81368 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81369 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 81370 | /* Value rank inherited */ |
| 81371 | attr.valueRank = -2; |
| 81372 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 868LU); |
| 81373 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionSecurityDiagnosticsType"); |
| 81374 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 81375 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81376 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81377 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 81378 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionSecurityDiagnosticsType"), |
| 81379 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 81380 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 81381 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81382 | return retVal; |
| 81383 | } |
| 81384 | |
| 81385 | static UA_StatusCode function_namespace0_generated_454_finish(UA_Server *server, UA_UInt16* ns) { |
| 81386 | return UA_Server_addNode_finish(server, |
| 81387 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU) |
| 81388 | ); |
| 81389 | } |
| 81390 | |
| 81391 | /* ClientCertificate - ns=0;i=3058 */ |
| 81392 | |
| 81393 | static UA_StatusCode function_namespace0_generated_455_begin(UA_Server *server, UA_UInt16* ns) { |
| 81394 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81395 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81396 | attr.minimumSamplingInterval = 0.000000; |
| 81397 | attr.userAccessLevel = 1; |
| 81398 | attr.accessLevel = 1; |
| 81399 | /* Value rank inherited */ |
| 81400 | attr.valueRank = -2; |
| 81401 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU); |
| 81402 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientCertificate"); |
| 81403 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81404 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3058LU), |
| 81405 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81406 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81407 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientCertificate"), |
| 81408 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81409 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81410 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81411 | return retVal; |
| 81412 | } |
| 81413 | |
| 81414 | static UA_StatusCode function_namespace0_generated_455_finish(UA_Server *server, UA_UInt16* ns) { |
| 81415 | return UA_Server_addNode_finish(server, |
| 81416 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3058LU) |
| 81417 | ); |
| 81418 | } |
| 81419 | |
| 81420 | /* SecurityPolicyUri - ns=0;i=2252 */ |
| 81421 | |
| 81422 | static UA_StatusCode function_namespace0_generated_456_begin(UA_Server *server, UA_UInt16* ns) { |
| 81423 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81424 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81425 | attr.minimumSamplingInterval = 0.000000; |
| 81426 | attr.userAccessLevel = 1; |
| 81427 | attr.accessLevel = 1; |
| 81428 | /* Value rank inherited */ |
| 81429 | attr.valueRank = -2; |
| 81430 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81431 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityPolicyUri"); |
| 81432 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81433 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2252LU), |
| 81434 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81435 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81436 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityPolicyUri"), |
| 81437 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81438 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81439 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81440 | return retVal; |
| 81441 | } |
| 81442 | |
| 81443 | static UA_StatusCode function_namespace0_generated_456_finish(UA_Server *server, UA_UInt16* ns) { |
| 81444 | return UA_Server_addNode_finish(server, |
| 81445 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2252LU) |
| 81446 | ); |
| 81447 | } |
| 81448 | |
| 81449 | /* SecurityMode - ns=0;i=2251 */ |
| 81450 | |
| 81451 | static UA_StatusCode function_namespace0_generated_457_begin(UA_Server *server, UA_UInt16* ns) { |
| 81452 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81453 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81454 | attr.minimumSamplingInterval = 0.000000; |
| 81455 | attr.userAccessLevel = 1; |
| 81456 | attr.accessLevel = 1; |
| 81457 | /* Value rank inherited */ |
| 81458 | attr.valueRank = -2; |
| 81459 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 302LU); |
| 81460 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityMode"); |
| 81461 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81462 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2251LU), |
| 81463 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81464 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81465 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityMode"), |
| 81466 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81467 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81468 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81469 | return retVal; |
| 81470 | } |
| 81471 | |
| 81472 | static UA_StatusCode function_namespace0_generated_457_finish(UA_Server *server, UA_UInt16* ns) { |
| 81473 | return UA_Server_addNode_finish(server, |
| 81474 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2251LU) |
| 81475 | ); |
| 81476 | } |
| 81477 | |
| 81478 | /* TransportProtocol - ns=0;i=2250 */ |
| 81479 | |
| 81480 | static UA_StatusCode function_namespace0_generated_458_begin(UA_Server *server, UA_UInt16* ns) { |
| 81481 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81482 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81483 | attr.minimumSamplingInterval = 0.000000; |
| 81484 | attr.userAccessLevel = 1; |
| 81485 | attr.accessLevel = 1; |
| 81486 | /* Value rank inherited */ |
| 81487 | attr.valueRank = -2; |
| 81488 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81489 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransportProtocol"); |
| 81490 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81491 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2250LU), |
| 81492 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81493 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81494 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransportProtocol"), |
| 81495 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81496 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81497 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81498 | return retVal; |
| 81499 | } |
| 81500 | |
| 81501 | static UA_StatusCode function_namespace0_generated_458_finish(UA_Server *server, UA_UInt16* ns) { |
| 81502 | return UA_Server_addNode_finish(server, |
| 81503 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2250LU) |
| 81504 | ); |
| 81505 | } |
| 81506 | |
| 81507 | /* Encoding - ns=0;i=2249 */ |
| 81508 | |
| 81509 | static UA_StatusCode function_namespace0_generated_459_begin(UA_Server *server, UA_UInt16* ns) { |
| 81510 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81511 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81512 | attr.minimumSamplingInterval = 0.000000; |
| 81513 | attr.userAccessLevel = 1; |
| 81514 | attr.accessLevel = 1; |
| 81515 | /* Value rank inherited */ |
| 81516 | attr.valueRank = -2; |
| 81517 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81518 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Encoding"); |
| 81519 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81520 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2249LU), |
| 81521 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81522 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81523 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Encoding"), |
| 81524 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81525 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81526 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81527 | return retVal; |
| 81528 | } |
| 81529 | |
| 81530 | static UA_StatusCode function_namespace0_generated_459_finish(UA_Server *server, UA_UInt16* ns) { |
| 81531 | return UA_Server_addNode_finish(server, |
| 81532 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2249LU) |
| 81533 | ); |
| 81534 | } |
| 81535 | |
| 81536 | /* AuthenticationMechanism - ns=0;i=2248 */ |
| 81537 | |
| 81538 | static UA_StatusCode function_namespace0_generated_460_begin(UA_Server *server, UA_UInt16* ns) { |
| 81539 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81540 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81541 | attr.minimumSamplingInterval = 0.000000; |
| 81542 | attr.userAccessLevel = 1; |
| 81543 | attr.accessLevel = 1; |
| 81544 | /* Value rank inherited */ |
| 81545 | attr.valueRank = -2; |
| 81546 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81547 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AuthenticationMechanism"); |
| 81548 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81549 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2248LU), |
| 81550 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81551 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81552 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AuthenticationMechanism"), |
| 81553 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81554 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81555 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81556 | return retVal; |
| 81557 | } |
| 81558 | |
| 81559 | static UA_StatusCode function_namespace0_generated_460_finish(UA_Server *server, UA_UInt16* ns) { |
| 81560 | return UA_Server_addNode_finish(server, |
| 81561 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2248LU) |
| 81562 | ); |
| 81563 | } |
| 81564 | |
| 81565 | /* ClientUserIdHistory - ns=0;i=2247 */ |
| 81566 | |
| 81567 | static UA_StatusCode function_namespace0_generated_461_begin(UA_Server *server, UA_UInt16* ns) { |
| 81568 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81569 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81570 | attr.minimumSamplingInterval = 0.000000; |
| 81571 | attr.userAccessLevel = 1; |
| 81572 | attr.accessLevel = 1; |
| 81573 | attr.valueRank = 1; |
| 81574 | attr.arrayDimensionsSize = 1; |
| 81575 | UA_UInt32 arrayDimensions[1]; |
| 81576 | arrayDimensions[0] = 0; |
| 81577 | attr.arrayDimensions = &arrayDimensions[0]; |
| 81578 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81579 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientUserIdHistory"); |
| 81580 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81581 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2247LU), |
| 81582 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81583 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81584 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientUserIdHistory"), |
| 81585 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81586 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81587 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81588 | return retVal; |
| 81589 | } |
| 81590 | |
| 81591 | static UA_StatusCode function_namespace0_generated_461_finish(UA_Server *server, UA_UInt16* ns) { |
| 81592 | return UA_Server_addNode_finish(server, |
| 81593 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2247LU) |
| 81594 | ); |
| 81595 | } |
| 81596 | |
| 81597 | /* ClientUserIdOfSession - ns=0;i=2246 */ |
| 81598 | |
| 81599 | static UA_StatusCode function_namespace0_generated_462_begin(UA_Server *server, UA_UInt16* ns) { |
| 81600 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81601 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81602 | attr.minimumSamplingInterval = 0.000000; |
| 81603 | attr.userAccessLevel = 1; |
| 81604 | attr.accessLevel = 1; |
| 81605 | /* Value rank inherited */ |
| 81606 | attr.valueRank = -2; |
| 81607 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81608 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientUserIdOfSession"); |
| 81609 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81610 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2246LU), |
| 81611 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81612 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81613 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientUserIdOfSession"), |
| 81614 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81615 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81616 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81617 | return retVal; |
| 81618 | } |
| 81619 | |
| 81620 | static UA_StatusCode function_namespace0_generated_462_finish(UA_Server *server, UA_UInt16* ns) { |
| 81621 | return UA_Server_addNode_finish(server, |
| 81622 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2246LU) |
| 81623 | ); |
| 81624 | } |
| 81625 | |
| 81626 | /* SessionId - ns=0;i=2245 */ |
| 81627 | |
| 81628 | static UA_StatusCode function_namespace0_generated_463_begin(UA_Server *server, UA_UInt16* ns) { |
| 81629 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81630 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81631 | attr.minimumSamplingInterval = 0.000000; |
| 81632 | attr.userAccessLevel = 1; |
| 81633 | attr.accessLevel = 1; |
| 81634 | /* Value rank inherited */ |
| 81635 | attr.valueRank = -2; |
| 81636 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 81637 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionId"); |
| 81638 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81639 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2245LU), |
| 81640 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81641 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81642 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionId"), |
| 81643 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81644 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81645 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81646 | return retVal; |
| 81647 | } |
| 81648 | |
| 81649 | static UA_StatusCode function_namespace0_generated_463_finish(UA_Server *server, UA_UInt16* ns) { |
| 81650 | return UA_Server_addNode_finish(server, |
| 81651 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2245LU) |
| 81652 | ); |
| 81653 | } |
| 81654 | |
| 81655 | /* SessionDiagnosticsObjectType - ns=0;i=2029 */ |
| 81656 | |
| 81657 | static UA_StatusCode function_namespace0_generated_464_begin(UA_Server *server, UA_UInt16* ns) { |
| 81658 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81659 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 81660 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionDiagnosticsObjectType"); |
| 81661 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 81662 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2029LU), |
| 81663 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 81664 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 81665 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionDiagnosticsObjectType"), |
| 81666 | typeDefinition: UA_NODEID_NULL, |
| 81667 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 81668 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81669 | return retVal; |
| 81670 | } |
| 81671 | |
| 81672 | static UA_StatusCode function_namespace0_generated_464_finish(UA_Server *server, UA_UInt16* ns) { |
| 81673 | return UA_Server_addNode_finish(server, |
| 81674 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2029LU) |
| 81675 | ); |
| 81676 | } |
| 81677 | |
| 81678 | /* SubscriptionDiagnosticsArray - ns=0;i=2032 */ |
| 81679 | |
| 81680 | static UA_StatusCode function_namespace0_generated_465_begin(UA_Server *server, UA_UInt16* ns) { |
| 81681 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81682 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81683 | attr.minimumSamplingInterval = 0.000000; |
| 81684 | attr.userAccessLevel = 1; |
| 81685 | attr.accessLevel = 1; |
| 81686 | attr.valueRank = 1; |
| 81687 | attr.arrayDimensionsSize = 1; |
| 81688 | UA_UInt32 arrayDimensions[1]; |
| 81689 | arrayDimensions[0] = 0; |
| 81690 | attr.arrayDimensions = &arrayDimensions[0]; |
| 81691 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 874LU); |
| 81692 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscriptionDiagnosticsArray"); |
| 81693 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81694 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2032LU), |
| 81695 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2029LU), |
| 81696 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81697 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscriptionDiagnosticsArray"), |
| 81698 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2171LU), |
| 81699 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81700 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81701 | return retVal; |
| 81702 | } |
| 81703 | |
| 81704 | static UA_StatusCode function_namespace0_generated_465_finish(UA_Server *server, UA_UInt16* ns) { |
| 81705 | return UA_Server_addNode_finish(server, |
| 81706 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2032LU) |
| 81707 | ); |
| 81708 | } |
| 81709 | |
| 81710 | /* SessionSecurityDiagnostics - ns=0;i=2031 */ |
| 81711 | |
| 81712 | static UA_StatusCode function_namespace0_generated_466_begin(UA_Server *server, UA_UInt16* ns) { |
| 81713 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81714 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81715 | attr.minimumSamplingInterval = 0.000000; |
| 81716 | attr.userAccessLevel = 1; |
| 81717 | attr.accessLevel = 1; |
| 81718 | /* Value rank inherited */ |
| 81719 | attr.valueRank = -2; |
| 81720 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 868LU); |
| 81721 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionSecurityDiagnostics"); |
| 81722 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81723 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), |
| 81724 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2029LU), |
| 81725 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81726 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionSecurityDiagnostics"), |
| 81727 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 81728 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81729 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81730 | return retVal; |
| 81731 | } |
| 81732 | |
| 81733 | static UA_StatusCode function_namespace0_generated_466_finish(UA_Server *server, UA_UInt16* ns) { |
| 81734 | return UA_Server_addNode_finish(server, |
| 81735 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU) |
| 81736 | ); |
| 81737 | } |
| 81738 | |
| 81739 | /* ClientCertificate - ns=0;i=3187 */ |
| 81740 | |
| 81741 | static UA_StatusCode function_namespace0_generated_467_begin(UA_Server *server, UA_UInt16* ns) { |
| 81742 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81743 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81744 | attr.minimumSamplingInterval = 0.000000; |
| 81745 | attr.userAccessLevel = 1; |
| 81746 | attr.accessLevel = 1; |
| 81747 | /* Value rank inherited */ |
| 81748 | attr.valueRank = -2; |
| 81749 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU); |
| 81750 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientCertificate"); |
| 81751 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81752 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3187LU), |
| 81753 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), |
| 81754 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81755 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientCertificate"), |
| 81756 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81757 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81758 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81759 | return retVal; |
| 81760 | } |
| 81761 | |
| 81762 | static UA_StatusCode function_namespace0_generated_467_finish(UA_Server *server, UA_UInt16* ns) { |
| 81763 | return UA_Server_addNode_finish(server, |
| 81764 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3187LU) |
| 81765 | ); |
| 81766 | } |
| 81767 | |
| 81768 | /* SecurityPolicyUri - ns=0;i=3186 */ |
| 81769 | |
| 81770 | static UA_StatusCode function_namespace0_generated_468_begin(UA_Server *server, UA_UInt16* ns) { |
| 81771 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81772 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81773 | attr.minimumSamplingInterval = 0.000000; |
| 81774 | attr.userAccessLevel = 1; |
| 81775 | attr.accessLevel = 1; |
| 81776 | /* Value rank inherited */ |
| 81777 | attr.valueRank = -2; |
| 81778 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81779 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityPolicyUri"); |
| 81780 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81781 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3186LU), |
| 81782 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), |
| 81783 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81784 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityPolicyUri"), |
| 81785 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81786 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81787 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81788 | return retVal; |
| 81789 | } |
| 81790 | |
| 81791 | static UA_StatusCode function_namespace0_generated_468_finish(UA_Server *server, UA_UInt16* ns) { |
| 81792 | return UA_Server_addNode_finish(server, |
| 81793 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3186LU) |
| 81794 | ); |
| 81795 | } |
| 81796 | |
| 81797 | /* SecurityMode - ns=0;i=3185 */ |
| 81798 | |
| 81799 | static UA_StatusCode function_namespace0_generated_469_begin(UA_Server *server, UA_UInt16* ns) { |
| 81800 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81801 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81802 | attr.minimumSamplingInterval = 0.000000; |
| 81803 | attr.userAccessLevel = 1; |
| 81804 | attr.accessLevel = 1; |
| 81805 | /* Value rank inherited */ |
| 81806 | attr.valueRank = -2; |
| 81807 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 302LU); |
| 81808 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityMode"); |
| 81809 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81810 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3185LU), |
| 81811 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), |
| 81812 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81813 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityMode"), |
| 81814 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81815 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81816 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81817 | return retVal; |
| 81818 | } |
| 81819 | |
| 81820 | static UA_StatusCode function_namespace0_generated_469_finish(UA_Server *server, UA_UInt16* ns) { |
| 81821 | return UA_Server_addNode_finish(server, |
| 81822 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3185LU) |
| 81823 | ); |
| 81824 | } |
| 81825 | |
| 81826 | /* TransportProtocol - ns=0;i=3184 */ |
| 81827 | |
| 81828 | static UA_StatusCode function_namespace0_generated_470_begin(UA_Server *server, UA_UInt16* ns) { |
| 81829 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81830 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81831 | attr.minimumSamplingInterval = 0.000000; |
| 81832 | attr.userAccessLevel = 1; |
| 81833 | attr.accessLevel = 1; |
| 81834 | /* Value rank inherited */ |
| 81835 | attr.valueRank = -2; |
| 81836 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81837 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransportProtocol"); |
| 81838 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81839 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3184LU), |
| 81840 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), |
| 81841 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81842 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransportProtocol"), |
| 81843 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81844 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81845 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81846 | return retVal; |
| 81847 | } |
| 81848 | |
| 81849 | static UA_StatusCode function_namespace0_generated_470_finish(UA_Server *server, UA_UInt16* ns) { |
| 81850 | return UA_Server_addNode_finish(server, |
| 81851 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3184LU) |
| 81852 | ); |
| 81853 | } |
| 81854 | |
| 81855 | /* Encoding - ns=0;i=3183 */ |
| 81856 | |
| 81857 | static UA_StatusCode function_namespace0_generated_471_begin(UA_Server *server, UA_UInt16* ns) { |
| 81858 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81859 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81860 | attr.minimumSamplingInterval = 0.000000; |
| 81861 | attr.userAccessLevel = 1; |
| 81862 | attr.accessLevel = 1; |
| 81863 | /* Value rank inherited */ |
| 81864 | attr.valueRank = -2; |
| 81865 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81866 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Encoding"); |
| 81867 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81868 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3183LU), |
| 81869 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), |
| 81870 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81871 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Encoding"), |
| 81872 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81873 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81874 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81875 | return retVal; |
| 81876 | } |
| 81877 | |
| 81878 | static UA_StatusCode function_namespace0_generated_471_finish(UA_Server *server, UA_UInt16* ns) { |
| 81879 | return UA_Server_addNode_finish(server, |
| 81880 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3183LU) |
| 81881 | ); |
| 81882 | } |
| 81883 | |
| 81884 | /* AuthenticationMechanism - ns=0;i=3182 */ |
| 81885 | |
| 81886 | static UA_StatusCode function_namespace0_generated_472_begin(UA_Server *server, UA_UInt16* ns) { |
| 81887 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81888 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81889 | attr.minimumSamplingInterval = 0.000000; |
| 81890 | attr.userAccessLevel = 1; |
| 81891 | attr.accessLevel = 1; |
| 81892 | /* Value rank inherited */ |
| 81893 | attr.valueRank = -2; |
| 81894 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81895 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AuthenticationMechanism"); |
| 81896 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81897 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3182LU), |
| 81898 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), |
| 81899 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81900 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AuthenticationMechanism"), |
| 81901 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81902 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81903 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81904 | return retVal; |
| 81905 | } |
| 81906 | |
| 81907 | static UA_StatusCode function_namespace0_generated_472_finish(UA_Server *server, UA_UInt16* ns) { |
| 81908 | return UA_Server_addNode_finish(server, |
| 81909 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3182LU) |
| 81910 | ); |
| 81911 | } |
| 81912 | |
| 81913 | /* ClientUserIdHistory - ns=0;i=3181 */ |
| 81914 | |
| 81915 | static UA_StatusCode function_namespace0_generated_473_begin(UA_Server *server, UA_UInt16* ns) { |
| 81916 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81917 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81918 | attr.minimumSamplingInterval = 0.000000; |
| 81919 | attr.userAccessLevel = 1; |
| 81920 | attr.accessLevel = 1; |
| 81921 | attr.valueRank = 1; |
| 81922 | attr.arrayDimensionsSize = 1; |
| 81923 | UA_UInt32 arrayDimensions[1]; |
| 81924 | arrayDimensions[0] = 0; |
| 81925 | attr.arrayDimensions = &arrayDimensions[0]; |
| 81926 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81927 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientUserIdHistory"); |
| 81928 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81929 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3181LU), |
| 81930 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), |
| 81931 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81932 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientUserIdHistory"), |
| 81933 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81934 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81935 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81936 | return retVal; |
| 81937 | } |
| 81938 | |
| 81939 | static UA_StatusCode function_namespace0_generated_473_finish(UA_Server *server, UA_UInt16* ns) { |
| 81940 | return UA_Server_addNode_finish(server, |
| 81941 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3181LU) |
| 81942 | ); |
| 81943 | } |
| 81944 | |
| 81945 | /* ClientUserIdOfSession - ns=0;i=3180 */ |
| 81946 | |
| 81947 | static UA_StatusCode function_namespace0_generated_474_begin(UA_Server *server, UA_UInt16* ns) { |
| 81948 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81949 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81950 | attr.minimumSamplingInterval = 0.000000; |
| 81951 | attr.userAccessLevel = 1; |
| 81952 | attr.accessLevel = 1; |
| 81953 | /* Value rank inherited */ |
| 81954 | attr.valueRank = -2; |
| 81955 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 81956 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientUserIdOfSession"); |
| 81957 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81958 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3180LU), |
| 81959 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), |
| 81960 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81961 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientUserIdOfSession"), |
| 81962 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81963 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81964 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81965 | return retVal; |
| 81966 | } |
| 81967 | |
| 81968 | static UA_StatusCode function_namespace0_generated_474_finish(UA_Server *server, UA_UInt16* ns) { |
| 81969 | return UA_Server_addNode_finish(server, |
| 81970 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3180LU) |
| 81971 | ); |
| 81972 | } |
| 81973 | |
| 81974 | /* SessionId - ns=0;i=3179 */ |
| 81975 | |
| 81976 | static UA_StatusCode function_namespace0_generated_475_begin(UA_Server *server, UA_UInt16* ns) { |
| 81977 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 81978 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 81979 | attr.minimumSamplingInterval = 0.000000; |
| 81980 | attr.userAccessLevel = 1; |
| 81981 | attr.accessLevel = 1; |
| 81982 | /* Value rank inherited */ |
| 81983 | attr.valueRank = -2; |
| 81984 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 81985 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionId"); |
| 81986 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 81987 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3179LU), |
| 81988 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), |
| 81989 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 81990 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionId"), |
| 81991 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 81992 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 81993 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 81994 | return retVal; |
| 81995 | } |
| 81996 | |
| 81997 | static UA_StatusCode function_namespace0_generated_475_finish(UA_Server *server, UA_UInt16* ns) { |
| 81998 | return UA_Server_addNode_finish(server, |
| 81999 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3179LU) |
| 82000 | ); |
| 82001 | } |
| 82002 | |
| 82003 | /* SessionDiagnostics - ns=0;i=2030 */ |
| 82004 | |
| 82005 | static UA_StatusCode function_namespace0_generated_476_begin(UA_Server *server, UA_UInt16* ns) { |
| 82006 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82007 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82008 | attr.minimumSamplingInterval = 0.000000; |
| 82009 | attr.userAccessLevel = 1; |
| 82010 | attr.accessLevel = 1; |
| 82011 | /* Value rank inherited */ |
| 82012 | attr.valueRank = -2; |
| 82013 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 865LU); |
| 82014 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionDiagnostics"); |
| 82015 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82016 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82017 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2029LU), |
| 82018 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82019 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionDiagnostics"), |
| 82020 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 82021 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82022 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82023 | return retVal; |
| 82024 | } |
| 82025 | |
| 82026 | static UA_StatusCode function_namespace0_generated_476_finish(UA_Server *server, UA_UInt16* ns) { |
| 82027 | return UA_Server_addNode_finish(server, |
| 82028 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU) |
| 82029 | ); |
| 82030 | } |
| 82031 | |
| 82032 | /* TotalRequestCount - ns=0;i=8898 */ |
| 82033 | |
| 82034 | static UA_StatusCode function_namespace0_generated_477_begin(UA_Server *server, UA_UInt16* ns) { |
| 82035 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82036 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82037 | attr.minimumSamplingInterval = 0.000000; |
| 82038 | attr.userAccessLevel = 1; |
| 82039 | attr.accessLevel = 1; |
| 82040 | /* Value rank inherited */ |
| 82041 | attr.valueRank = -2; |
| 82042 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82043 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TotalRequestCount"); |
| 82044 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82045 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8898LU), |
| 82046 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82047 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82048 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TotalRequestCount"), |
| 82049 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82050 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82051 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82052 | return retVal; |
| 82053 | } |
| 82054 | |
| 82055 | static UA_StatusCode function_namespace0_generated_477_finish(UA_Server *server, UA_UInt16* ns) { |
| 82056 | return UA_Server_addNode_finish(server, |
| 82057 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8898LU) |
| 82058 | ); |
| 82059 | } |
| 82060 | |
| 82061 | /* UnregisterNodesCount - ns=0;i=3178 */ |
| 82062 | |
| 82063 | static UA_StatusCode function_namespace0_generated_478_begin(UA_Server *server, UA_UInt16* ns) { |
| 82064 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82065 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82066 | attr.minimumSamplingInterval = 0.000000; |
| 82067 | attr.userAccessLevel = 1; |
| 82068 | attr.accessLevel = 1; |
| 82069 | /* Value rank inherited */ |
| 82070 | attr.valueRank = -2; |
| 82071 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82072 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UnregisterNodesCount"); |
| 82073 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82074 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3178LU), |
| 82075 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82076 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82077 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UnregisterNodesCount"), |
| 82078 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82079 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82080 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82081 | return retVal; |
| 82082 | } |
| 82083 | |
| 82084 | static UA_StatusCode function_namespace0_generated_478_finish(UA_Server *server, UA_UInt16* ns) { |
| 82085 | return UA_Server_addNode_finish(server, |
| 82086 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3178LU) |
| 82087 | ); |
| 82088 | } |
| 82089 | |
| 82090 | /* RegisterNodesCount - ns=0;i=3177 */ |
| 82091 | |
| 82092 | static UA_StatusCode function_namespace0_generated_479_begin(UA_Server *server, UA_UInt16* ns) { |
| 82093 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82094 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82095 | attr.minimumSamplingInterval = 0.000000; |
| 82096 | attr.userAccessLevel = 1; |
| 82097 | attr.accessLevel = 1; |
| 82098 | /* Value rank inherited */ |
| 82099 | attr.valueRank = -2; |
| 82100 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82101 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RegisterNodesCount"); |
| 82102 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82103 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3177LU), |
| 82104 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82105 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82106 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RegisterNodesCount"), |
| 82107 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82108 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82109 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82110 | return retVal; |
| 82111 | } |
| 82112 | |
| 82113 | static UA_StatusCode function_namespace0_generated_479_finish(UA_Server *server, UA_UInt16* ns) { |
| 82114 | return UA_Server_addNode_finish(server, |
| 82115 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3177LU) |
| 82116 | ); |
| 82117 | } |
| 82118 | |
| 82119 | /* QueryNextCount - ns=0;i=3176 */ |
| 82120 | |
| 82121 | static UA_StatusCode function_namespace0_generated_480_begin(UA_Server *server, UA_UInt16* ns) { |
| 82122 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82123 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82124 | attr.minimumSamplingInterval = 0.000000; |
| 82125 | attr.userAccessLevel = 1; |
| 82126 | attr.accessLevel = 1; |
| 82127 | /* Value rank inherited */ |
| 82128 | attr.valueRank = -2; |
| 82129 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82130 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QueryNextCount"); |
| 82131 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82132 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3176LU), |
| 82133 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82134 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82135 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QueryNextCount"), |
| 82136 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82137 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82138 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82139 | return retVal; |
| 82140 | } |
| 82141 | |
| 82142 | static UA_StatusCode function_namespace0_generated_480_finish(UA_Server *server, UA_UInt16* ns) { |
| 82143 | return UA_Server_addNode_finish(server, |
| 82144 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3176LU) |
| 82145 | ); |
| 82146 | } |
| 82147 | |
| 82148 | /* QueryFirstCount - ns=0;i=3175 */ |
| 82149 | |
| 82150 | static UA_StatusCode function_namespace0_generated_481_begin(UA_Server *server, UA_UInt16* ns) { |
| 82151 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82152 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82153 | attr.minimumSamplingInterval = 0.000000; |
| 82154 | attr.userAccessLevel = 1; |
| 82155 | attr.accessLevel = 1; |
| 82156 | /* Value rank inherited */ |
| 82157 | attr.valueRank = -2; |
| 82158 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82159 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QueryFirstCount"); |
| 82160 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82161 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3175LU), |
| 82162 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82163 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82164 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QueryFirstCount"), |
| 82165 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82166 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82167 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82168 | return retVal; |
| 82169 | } |
| 82170 | |
| 82171 | static UA_StatusCode function_namespace0_generated_481_finish(UA_Server *server, UA_UInt16* ns) { |
| 82172 | return UA_Server_addNode_finish(server, |
| 82173 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3175LU) |
| 82174 | ); |
| 82175 | } |
| 82176 | |
| 82177 | /* TranslateBrowsePathsToNodeIdsCount - ns=0;i=3174 */ |
| 82178 | |
| 82179 | static UA_StatusCode function_namespace0_generated_482_begin(UA_Server *server, UA_UInt16* ns) { |
| 82180 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82181 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82182 | attr.minimumSamplingInterval = 0.000000; |
| 82183 | attr.userAccessLevel = 1; |
| 82184 | attr.accessLevel = 1; |
| 82185 | /* Value rank inherited */ |
| 82186 | attr.valueRank = -2; |
| 82187 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82188 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TranslateBrowsePathsToNodeIdsCount"); |
| 82189 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82190 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3174LU), |
| 82191 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82192 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82193 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TranslateBrowsePathsToNodeIdsCount"), |
| 82194 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82195 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82196 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82197 | return retVal; |
| 82198 | } |
| 82199 | |
| 82200 | static UA_StatusCode function_namespace0_generated_482_finish(UA_Server *server, UA_UInt16* ns) { |
| 82201 | return UA_Server_addNode_finish(server, |
| 82202 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3174LU) |
| 82203 | ); |
| 82204 | } |
| 82205 | |
| 82206 | /* BrowseNextCount - ns=0;i=3173 */ |
| 82207 | |
| 82208 | static UA_StatusCode function_namespace0_generated_483_begin(UA_Server *server, UA_UInt16* ns) { |
| 82209 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82210 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82211 | attr.minimumSamplingInterval = 0.000000; |
| 82212 | attr.userAccessLevel = 1; |
| 82213 | attr.accessLevel = 1; |
| 82214 | /* Value rank inherited */ |
| 82215 | attr.valueRank = -2; |
| 82216 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82217 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BrowseNextCount"); |
| 82218 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82219 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3173LU), |
| 82220 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82221 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82222 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BrowseNextCount"), |
| 82223 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82224 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82225 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82226 | return retVal; |
| 82227 | } |
| 82228 | |
| 82229 | static UA_StatusCode function_namespace0_generated_483_finish(UA_Server *server, UA_UInt16* ns) { |
| 82230 | return UA_Server_addNode_finish(server, |
| 82231 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3173LU) |
| 82232 | ); |
| 82233 | } |
| 82234 | |
| 82235 | /* BrowseCount - ns=0;i=3172 */ |
| 82236 | |
| 82237 | static UA_StatusCode function_namespace0_generated_484_begin(UA_Server *server, UA_UInt16* ns) { |
| 82238 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82239 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82240 | attr.minimumSamplingInterval = 0.000000; |
| 82241 | attr.userAccessLevel = 1; |
| 82242 | attr.accessLevel = 1; |
| 82243 | /* Value rank inherited */ |
| 82244 | attr.valueRank = -2; |
| 82245 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82246 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BrowseCount"); |
| 82247 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82248 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3172LU), |
| 82249 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82250 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82251 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BrowseCount"), |
| 82252 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82253 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82254 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82255 | return retVal; |
| 82256 | } |
| 82257 | |
| 82258 | static UA_StatusCode function_namespace0_generated_484_finish(UA_Server *server, UA_UInt16* ns) { |
| 82259 | return UA_Server_addNode_finish(server, |
| 82260 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3172LU) |
| 82261 | ); |
| 82262 | } |
| 82263 | |
| 82264 | /* DeleteReferencesCount - ns=0;i=3171 */ |
| 82265 | |
| 82266 | static UA_StatusCode function_namespace0_generated_485_begin(UA_Server *server, UA_UInt16* ns) { |
| 82267 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82268 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82269 | attr.minimumSamplingInterval = 0.000000; |
| 82270 | attr.userAccessLevel = 1; |
| 82271 | attr.accessLevel = 1; |
| 82272 | /* Value rank inherited */ |
| 82273 | attr.valueRank = -2; |
| 82274 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82275 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteReferencesCount"); |
| 82276 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82277 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3171LU), |
| 82278 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82279 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82280 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteReferencesCount"), |
| 82281 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82282 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82283 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82284 | return retVal; |
| 82285 | } |
| 82286 | |
| 82287 | static UA_StatusCode function_namespace0_generated_485_finish(UA_Server *server, UA_UInt16* ns) { |
| 82288 | return UA_Server_addNode_finish(server, |
| 82289 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3171LU) |
| 82290 | ); |
| 82291 | } |
| 82292 | |
| 82293 | /* DeleteNodesCount - ns=0;i=3170 */ |
| 82294 | |
| 82295 | static UA_StatusCode function_namespace0_generated_486_begin(UA_Server *server, UA_UInt16* ns) { |
| 82296 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82297 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82298 | attr.minimumSamplingInterval = 0.000000; |
| 82299 | attr.userAccessLevel = 1; |
| 82300 | attr.accessLevel = 1; |
| 82301 | /* Value rank inherited */ |
| 82302 | attr.valueRank = -2; |
| 82303 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82304 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteNodesCount"); |
| 82305 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82306 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3170LU), |
| 82307 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82308 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82309 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteNodesCount"), |
| 82310 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82311 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82312 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82313 | return retVal; |
| 82314 | } |
| 82315 | |
| 82316 | static UA_StatusCode function_namespace0_generated_486_finish(UA_Server *server, UA_UInt16* ns) { |
| 82317 | return UA_Server_addNode_finish(server, |
| 82318 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3170LU) |
| 82319 | ); |
| 82320 | } |
| 82321 | |
| 82322 | /* AddReferencesCount - ns=0;i=3169 */ |
| 82323 | |
| 82324 | static UA_StatusCode function_namespace0_generated_487_begin(UA_Server *server, UA_UInt16* ns) { |
| 82325 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82326 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82327 | attr.minimumSamplingInterval = 0.000000; |
| 82328 | attr.userAccessLevel = 1; |
| 82329 | attr.accessLevel = 1; |
| 82330 | /* Value rank inherited */ |
| 82331 | attr.valueRank = -2; |
| 82332 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82333 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddReferencesCount"); |
| 82334 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82335 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3169LU), |
| 82336 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82337 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82338 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddReferencesCount"), |
| 82339 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82340 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82341 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82342 | return retVal; |
| 82343 | } |
| 82344 | |
| 82345 | static UA_StatusCode function_namespace0_generated_487_finish(UA_Server *server, UA_UInt16* ns) { |
| 82346 | return UA_Server_addNode_finish(server, |
| 82347 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3169LU) |
| 82348 | ); |
| 82349 | } |
| 82350 | |
| 82351 | /* AddNodesCount - ns=0;i=3168 */ |
| 82352 | |
| 82353 | static UA_StatusCode function_namespace0_generated_488_begin(UA_Server *server, UA_UInt16* ns) { |
| 82354 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82355 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82356 | attr.minimumSamplingInterval = 0.000000; |
| 82357 | attr.userAccessLevel = 1; |
| 82358 | attr.accessLevel = 1; |
| 82359 | /* Value rank inherited */ |
| 82360 | attr.valueRank = -2; |
| 82361 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82362 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddNodesCount"); |
| 82363 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82364 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3168LU), |
| 82365 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82366 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82367 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddNodesCount"), |
| 82368 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82369 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82370 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82371 | return retVal; |
| 82372 | } |
| 82373 | |
| 82374 | static UA_StatusCode function_namespace0_generated_488_finish(UA_Server *server, UA_UInt16* ns) { |
| 82375 | return UA_Server_addNode_finish(server, |
| 82376 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3168LU) |
| 82377 | ); |
| 82378 | } |
| 82379 | |
| 82380 | /* DeleteSubscriptionsCount - ns=0;i=3167 */ |
| 82381 | |
| 82382 | static UA_StatusCode function_namespace0_generated_489_begin(UA_Server *server, UA_UInt16* ns) { |
| 82383 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82384 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82385 | attr.minimumSamplingInterval = 0.000000; |
| 82386 | attr.userAccessLevel = 1; |
| 82387 | attr.accessLevel = 1; |
| 82388 | /* Value rank inherited */ |
| 82389 | attr.valueRank = -2; |
| 82390 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82391 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteSubscriptionsCount"); |
| 82392 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82393 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3167LU), |
| 82394 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82395 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82396 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteSubscriptionsCount"), |
| 82397 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82398 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82399 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82400 | return retVal; |
| 82401 | } |
| 82402 | |
| 82403 | static UA_StatusCode function_namespace0_generated_489_finish(UA_Server *server, UA_UInt16* ns) { |
| 82404 | return UA_Server_addNode_finish(server, |
| 82405 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3167LU) |
| 82406 | ); |
| 82407 | } |
| 82408 | |
| 82409 | /* TransferSubscriptionsCount - ns=0;i=3166 */ |
| 82410 | |
| 82411 | static UA_StatusCode function_namespace0_generated_490_begin(UA_Server *server, UA_UInt16* ns) { |
| 82412 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82413 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82414 | attr.minimumSamplingInterval = 0.000000; |
| 82415 | attr.userAccessLevel = 1; |
| 82416 | attr.accessLevel = 1; |
| 82417 | /* Value rank inherited */ |
| 82418 | attr.valueRank = -2; |
| 82419 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82420 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransferSubscriptionsCount"); |
| 82421 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82422 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3166LU), |
| 82423 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82424 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82425 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransferSubscriptionsCount"), |
| 82426 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82427 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82428 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82429 | return retVal; |
| 82430 | } |
| 82431 | |
| 82432 | static UA_StatusCode function_namespace0_generated_490_finish(UA_Server *server, UA_UInt16* ns) { |
| 82433 | return UA_Server_addNode_finish(server, |
| 82434 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3166LU) |
| 82435 | ); |
| 82436 | } |
| 82437 | |
| 82438 | /* RepublishCount - ns=0;i=3165 */ |
| 82439 | |
| 82440 | static UA_StatusCode function_namespace0_generated_491_begin(UA_Server *server, UA_UInt16* ns) { |
| 82441 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82442 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82443 | attr.minimumSamplingInterval = 0.000000; |
| 82444 | attr.userAccessLevel = 1; |
| 82445 | attr.accessLevel = 1; |
| 82446 | /* Value rank inherited */ |
| 82447 | attr.valueRank = -2; |
| 82448 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82449 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RepublishCount"); |
| 82450 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82451 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3165LU), |
| 82452 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82453 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82454 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RepublishCount"), |
| 82455 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82456 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82457 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82458 | return retVal; |
| 82459 | } |
| 82460 | |
| 82461 | static UA_StatusCode function_namespace0_generated_491_finish(UA_Server *server, UA_UInt16* ns) { |
| 82462 | return UA_Server_addNode_finish(server, |
| 82463 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3165LU) |
| 82464 | ); |
| 82465 | } |
| 82466 | |
| 82467 | /* PublishCount - ns=0;i=3164 */ |
| 82468 | |
| 82469 | static UA_StatusCode function_namespace0_generated_492_begin(UA_Server *server, UA_UInt16* ns) { |
| 82470 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82471 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82472 | attr.minimumSamplingInterval = 0.000000; |
| 82473 | attr.userAccessLevel = 1; |
| 82474 | attr.accessLevel = 1; |
| 82475 | /* Value rank inherited */ |
| 82476 | attr.valueRank = -2; |
| 82477 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82478 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishCount"); |
| 82479 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82480 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3164LU), |
| 82481 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82482 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82483 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishCount"), |
| 82484 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82485 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82486 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82487 | return retVal; |
| 82488 | } |
| 82489 | |
| 82490 | static UA_StatusCode function_namespace0_generated_492_finish(UA_Server *server, UA_UInt16* ns) { |
| 82491 | return UA_Server_addNode_finish(server, |
| 82492 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3164LU) |
| 82493 | ); |
| 82494 | } |
| 82495 | |
| 82496 | /* SetPublishingModeCount - ns=0;i=3163 */ |
| 82497 | |
| 82498 | static UA_StatusCode function_namespace0_generated_493_begin(UA_Server *server, UA_UInt16* ns) { |
| 82499 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82500 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82501 | attr.minimumSamplingInterval = 0.000000; |
| 82502 | attr.userAccessLevel = 1; |
| 82503 | attr.accessLevel = 1; |
| 82504 | /* Value rank inherited */ |
| 82505 | attr.valueRank = -2; |
| 82506 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82507 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetPublishingModeCount"); |
| 82508 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82509 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3163LU), |
| 82510 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82511 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82512 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetPublishingModeCount"), |
| 82513 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82514 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82515 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82516 | return retVal; |
| 82517 | } |
| 82518 | |
| 82519 | static UA_StatusCode function_namespace0_generated_493_finish(UA_Server *server, UA_UInt16* ns) { |
| 82520 | return UA_Server_addNode_finish(server, |
| 82521 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3163LU) |
| 82522 | ); |
| 82523 | } |
| 82524 | |
| 82525 | /* ModifySubscriptionCount - ns=0;i=3162 */ |
| 82526 | |
| 82527 | static UA_StatusCode function_namespace0_generated_494_begin(UA_Server *server, UA_UInt16* ns) { |
| 82528 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82529 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82530 | attr.minimumSamplingInterval = 0.000000; |
| 82531 | attr.userAccessLevel = 1; |
| 82532 | attr.accessLevel = 1; |
| 82533 | /* Value rank inherited */ |
| 82534 | attr.valueRank = -2; |
| 82535 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82536 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModifySubscriptionCount"); |
| 82537 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82538 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3162LU), |
| 82539 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82540 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82541 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModifySubscriptionCount"), |
| 82542 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82543 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82544 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82545 | return retVal; |
| 82546 | } |
| 82547 | |
| 82548 | static UA_StatusCode function_namespace0_generated_494_finish(UA_Server *server, UA_UInt16* ns) { |
| 82549 | return UA_Server_addNode_finish(server, |
| 82550 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3162LU) |
| 82551 | ); |
| 82552 | } |
| 82553 | |
| 82554 | /* CreateSubscriptionCount - ns=0;i=3161 */ |
| 82555 | |
| 82556 | static UA_StatusCode function_namespace0_generated_495_begin(UA_Server *server, UA_UInt16* ns) { |
| 82557 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82558 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82559 | attr.minimumSamplingInterval = 0.000000; |
| 82560 | attr.userAccessLevel = 1; |
| 82561 | attr.accessLevel = 1; |
| 82562 | /* Value rank inherited */ |
| 82563 | attr.valueRank = -2; |
| 82564 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82565 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CreateSubscriptionCount"); |
| 82566 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82567 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3161LU), |
| 82568 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82569 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82570 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CreateSubscriptionCount"), |
| 82571 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82572 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82573 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82574 | return retVal; |
| 82575 | } |
| 82576 | |
| 82577 | static UA_StatusCode function_namespace0_generated_495_finish(UA_Server *server, UA_UInt16* ns) { |
| 82578 | return UA_Server_addNode_finish(server, |
| 82579 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3161LU) |
| 82580 | ); |
| 82581 | } |
| 82582 | |
| 82583 | /* DeleteMonitoredItemsCount - ns=0;i=3160 */ |
| 82584 | |
| 82585 | static UA_StatusCode function_namespace0_generated_496_begin(UA_Server *server, UA_UInt16* ns) { |
| 82586 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82587 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82588 | attr.minimumSamplingInterval = 0.000000; |
| 82589 | attr.userAccessLevel = 1; |
| 82590 | attr.accessLevel = 1; |
| 82591 | /* Value rank inherited */ |
| 82592 | attr.valueRank = -2; |
| 82593 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82594 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteMonitoredItemsCount"); |
| 82595 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82596 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3160LU), |
| 82597 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82598 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82599 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteMonitoredItemsCount"), |
| 82600 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82601 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82602 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82603 | return retVal; |
| 82604 | } |
| 82605 | |
| 82606 | static UA_StatusCode function_namespace0_generated_496_finish(UA_Server *server, UA_UInt16* ns) { |
| 82607 | return UA_Server_addNode_finish(server, |
| 82608 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3160LU) |
| 82609 | ); |
| 82610 | } |
| 82611 | |
| 82612 | /* SetTriggeringCount - ns=0;i=3159 */ |
| 82613 | |
| 82614 | static UA_StatusCode function_namespace0_generated_497_begin(UA_Server *server, UA_UInt16* ns) { |
| 82615 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82616 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82617 | attr.minimumSamplingInterval = 0.000000; |
| 82618 | attr.userAccessLevel = 1; |
| 82619 | attr.accessLevel = 1; |
| 82620 | /* Value rank inherited */ |
| 82621 | attr.valueRank = -2; |
| 82622 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82623 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetTriggeringCount"); |
| 82624 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82625 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3159LU), |
| 82626 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82627 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82628 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetTriggeringCount"), |
| 82629 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82630 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82631 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82632 | return retVal; |
| 82633 | } |
| 82634 | |
| 82635 | static UA_StatusCode function_namespace0_generated_497_finish(UA_Server *server, UA_UInt16* ns) { |
| 82636 | return UA_Server_addNode_finish(server, |
| 82637 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3159LU) |
| 82638 | ); |
| 82639 | } |
| 82640 | |
| 82641 | /* SetMonitoringModeCount - ns=0;i=3158 */ |
| 82642 | |
| 82643 | static UA_StatusCode function_namespace0_generated_498_begin(UA_Server *server, UA_UInt16* ns) { |
| 82644 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82645 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82646 | attr.minimumSamplingInterval = 0.000000; |
| 82647 | attr.userAccessLevel = 1; |
| 82648 | attr.accessLevel = 1; |
| 82649 | /* Value rank inherited */ |
| 82650 | attr.valueRank = -2; |
| 82651 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82652 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetMonitoringModeCount"); |
| 82653 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82654 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3158LU), |
| 82655 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82656 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82657 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetMonitoringModeCount"), |
| 82658 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82659 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82660 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82661 | return retVal; |
| 82662 | } |
| 82663 | |
| 82664 | static UA_StatusCode function_namespace0_generated_498_finish(UA_Server *server, UA_UInt16* ns) { |
| 82665 | return UA_Server_addNode_finish(server, |
| 82666 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3158LU) |
| 82667 | ); |
| 82668 | } |
| 82669 | |
| 82670 | /* ModifyMonitoredItemsCount - ns=0;i=3157 */ |
| 82671 | |
| 82672 | static UA_StatusCode function_namespace0_generated_499_begin(UA_Server *server, UA_UInt16* ns) { |
| 82673 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82674 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82675 | attr.minimumSamplingInterval = 0.000000; |
| 82676 | attr.userAccessLevel = 1; |
| 82677 | attr.accessLevel = 1; |
| 82678 | /* Value rank inherited */ |
| 82679 | attr.valueRank = -2; |
| 82680 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82681 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModifyMonitoredItemsCount"); |
| 82682 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82683 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3157LU), |
| 82684 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82685 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82686 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModifyMonitoredItemsCount"), |
| 82687 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82688 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82689 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82690 | return retVal; |
| 82691 | } |
| 82692 | |
| 82693 | static UA_StatusCode function_namespace0_generated_499_finish(UA_Server *server, UA_UInt16* ns) { |
| 82694 | return UA_Server_addNode_finish(server, |
| 82695 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3157LU) |
| 82696 | ); |
| 82697 | } |
| 82698 | |
| 82699 | /* CreateMonitoredItemsCount - ns=0;i=3156 */ |
| 82700 | |
| 82701 | static UA_StatusCode function_namespace0_generated_500_begin(UA_Server *server, UA_UInt16* ns) { |
| 82702 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82703 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82704 | attr.minimumSamplingInterval = 0.000000; |
| 82705 | attr.userAccessLevel = 1; |
| 82706 | attr.accessLevel = 1; |
| 82707 | /* Value rank inherited */ |
| 82708 | attr.valueRank = -2; |
| 82709 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82710 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CreateMonitoredItemsCount"); |
| 82711 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82712 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3156LU), |
| 82713 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82714 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82715 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CreateMonitoredItemsCount"), |
| 82716 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82717 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82718 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82719 | return retVal; |
| 82720 | } |
| 82721 | |
| 82722 | static UA_StatusCode function_namespace0_generated_500_finish(UA_Server *server, UA_UInt16* ns) { |
| 82723 | return UA_Server_addNode_finish(server, |
| 82724 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3156LU) |
| 82725 | ); |
| 82726 | } |
| 82727 | |
| 82728 | /* CallCount - ns=0;i=3155 */ |
| 82729 | |
| 82730 | static UA_StatusCode function_namespace0_generated_501_begin(UA_Server *server, UA_UInt16* ns) { |
| 82731 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82732 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82733 | attr.minimumSamplingInterval = 0.000000; |
| 82734 | attr.userAccessLevel = 1; |
| 82735 | attr.accessLevel = 1; |
| 82736 | /* Value rank inherited */ |
| 82737 | attr.valueRank = -2; |
| 82738 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82739 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CallCount"); |
| 82740 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82741 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3155LU), |
| 82742 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82743 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82744 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CallCount"), |
| 82745 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82746 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82747 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82748 | return retVal; |
| 82749 | } |
| 82750 | |
| 82751 | static UA_StatusCode function_namespace0_generated_501_finish(UA_Server *server, UA_UInt16* ns) { |
| 82752 | return UA_Server_addNode_finish(server, |
| 82753 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3155LU) |
| 82754 | ); |
| 82755 | } |
| 82756 | |
| 82757 | /* HistoryUpdateCount - ns=0;i=3154 */ |
| 82758 | |
| 82759 | static UA_StatusCode function_namespace0_generated_502_begin(UA_Server *server, UA_UInt16* ns) { |
| 82760 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82761 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82762 | attr.minimumSamplingInterval = 0.000000; |
| 82763 | attr.userAccessLevel = 1; |
| 82764 | attr.accessLevel = 1; |
| 82765 | /* Value rank inherited */ |
| 82766 | attr.valueRank = -2; |
| 82767 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82768 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryUpdateCount"); |
| 82769 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82770 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3154LU), |
| 82771 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82772 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82773 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryUpdateCount"), |
| 82774 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82775 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82776 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82777 | return retVal; |
| 82778 | } |
| 82779 | |
| 82780 | static UA_StatusCode function_namespace0_generated_502_finish(UA_Server *server, UA_UInt16* ns) { |
| 82781 | return UA_Server_addNode_finish(server, |
| 82782 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3154LU) |
| 82783 | ); |
| 82784 | } |
| 82785 | |
| 82786 | /* WriteCount - ns=0;i=3153 */ |
| 82787 | |
| 82788 | static UA_StatusCode function_namespace0_generated_503_begin(UA_Server *server, UA_UInt16* ns) { |
| 82789 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82790 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82791 | attr.minimumSamplingInterval = 0.000000; |
| 82792 | attr.userAccessLevel = 1; |
| 82793 | attr.accessLevel = 1; |
| 82794 | /* Value rank inherited */ |
| 82795 | attr.valueRank = -2; |
| 82796 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82797 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "WriteCount"); |
| 82798 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82799 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3153LU), |
| 82800 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82801 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82802 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "WriteCount"), |
| 82803 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82804 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82805 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82806 | return retVal; |
| 82807 | } |
| 82808 | |
| 82809 | static UA_StatusCode function_namespace0_generated_503_finish(UA_Server *server, UA_UInt16* ns) { |
| 82810 | return UA_Server_addNode_finish(server, |
| 82811 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3153LU) |
| 82812 | ); |
| 82813 | } |
| 82814 | |
| 82815 | /* HistoryReadCount - ns=0;i=3152 */ |
| 82816 | |
| 82817 | static UA_StatusCode function_namespace0_generated_504_begin(UA_Server *server, UA_UInt16* ns) { |
| 82818 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82819 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82820 | attr.minimumSamplingInterval = 0.000000; |
| 82821 | attr.userAccessLevel = 1; |
| 82822 | attr.accessLevel = 1; |
| 82823 | /* Value rank inherited */ |
| 82824 | attr.valueRank = -2; |
| 82825 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82826 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryReadCount"); |
| 82827 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82828 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3152LU), |
| 82829 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82830 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82831 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryReadCount"), |
| 82832 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82833 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82834 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82835 | return retVal; |
| 82836 | } |
| 82837 | |
| 82838 | static UA_StatusCode function_namespace0_generated_504_finish(UA_Server *server, UA_UInt16* ns) { |
| 82839 | return UA_Server_addNode_finish(server, |
| 82840 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3152LU) |
| 82841 | ); |
| 82842 | } |
| 82843 | |
| 82844 | /* ReadCount - ns=0;i=3151 */ |
| 82845 | |
| 82846 | static UA_StatusCode function_namespace0_generated_505_begin(UA_Server *server, UA_UInt16* ns) { |
| 82847 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82848 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82849 | attr.minimumSamplingInterval = 0.000000; |
| 82850 | attr.userAccessLevel = 1; |
| 82851 | attr.accessLevel = 1; |
| 82852 | /* Value rank inherited */ |
| 82853 | attr.valueRank = -2; |
| 82854 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 82855 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReadCount"); |
| 82856 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82857 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3151LU), |
| 82858 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82859 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82860 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReadCount"), |
| 82861 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82862 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82863 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82864 | return retVal; |
| 82865 | } |
| 82866 | |
| 82867 | static UA_StatusCode function_namespace0_generated_505_finish(UA_Server *server, UA_UInt16* ns) { |
| 82868 | return UA_Server_addNode_finish(server, |
| 82869 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3151LU) |
| 82870 | ); |
| 82871 | } |
| 82872 | |
| 82873 | /* CurrentPublishRequestsInQueue - ns=0;i=3143 */ |
| 82874 | |
| 82875 | static UA_StatusCode function_namespace0_generated_506_begin(UA_Server *server, UA_UInt16* ns) { |
| 82876 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82877 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82878 | attr.minimumSamplingInterval = 0.000000; |
| 82879 | attr.userAccessLevel = 1; |
| 82880 | attr.accessLevel = 1; |
| 82881 | /* Value rank inherited */ |
| 82882 | attr.valueRank = -2; |
| 82883 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 82884 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentPublishRequestsInQueue"); |
| 82885 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82886 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3143LU), |
| 82887 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82888 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82889 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentPublishRequestsInQueue"), |
| 82890 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82891 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82892 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82893 | return retVal; |
| 82894 | } |
| 82895 | |
| 82896 | static UA_StatusCode function_namespace0_generated_506_finish(UA_Server *server, UA_UInt16* ns) { |
| 82897 | return UA_Server_addNode_finish(server, |
| 82898 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3143LU) |
| 82899 | ); |
| 82900 | } |
| 82901 | |
| 82902 | /* CurrentMonitoredItemsCount - ns=0;i=3142 */ |
| 82903 | |
| 82904 | static UA_StatusCode function_namespace0_generated_507_begin(UA_Server *server, UA_UInt16* ns) { |
| 82905 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82906 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82907 | attr.minimumSamplingInterval = 0.000000; |
| 82908 | attr.userAccessLevel = 1; |
| 82909 | attr.accessLevel = 1; |
| 82910 | /* Value rank inherited */ |
| 82911 | attr.valueRank = -2; |
| 82912 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 82913 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentMonitoredItemsCount"); |
| 82914 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82915 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3142LU), |
| 82916 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82917 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82918 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentMonitoredItemsCount"), |
| 82919 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82920 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82921 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82922 | return retVal; |
| 82923 | } |
| 82924 | |
| 82925 | static UA_StatusCode function_namespace0_generated_507_finish(UA_Server *server, UA_UInt16* ns) { |
| 82926 | return UA_Server_addNode_finish(server, |
| 82927 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3142LU) |
| 82928 | ); |
| 82929 | } |
| 82930 | |
| 82931 | /* CurrentSubscriptionsCount - ns=0;i=3141 */ |
| 82932 | |
| 82933 | static UA_StatusCode function_namespace0_generated_508_begin(UA_Server *server, UA_UInt16* ns) { |
| 82934 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82935 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82936 | attr.minimumSamplingInterval = 0.000000; |
| 82937 | attr.userAccessLevel = 1; |
| 82938 | attr.accessLevel = 1; |
| 82939 | /* Value rank inherited */ |
| 82940 | attr.valueRank = -2; |
| 82941 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 82942 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentSubscriptionsCount"); |
| 82943 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82944 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3141LU), |
| 82945 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82946 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82947 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentSubscriptionsCount"), |
| 82948 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82949 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82950 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82951 | return retVal; |
| 82952 | } |
| 82953 | |
| 82954 | static UA_StatusCode function_namespace0_generated_508_finish(UA_Server *server, UA_UInt16* ns) { |
| 82955 | return UA_Server_addNode_finish(server, |
| 82956 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3141LU) |
| 82957 | ); |
| 82958 | } |
| 82959 | |
| 82960 | /* ClientLastContactTime - ns=0;i=3140 */ |
| 82961 | |
| 82962 | static UA_StatusCode function_namespace0_generated_509_begin(UA_Server *server, UA_UInt16* ns) { |
| 82963 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82964 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82965 | attr.minimumSamplingInterval = 0.000000; |
| 82966 | attr.userAccessLevel = 1; |
| 82967 | attr.accessLevel = 1; |
| 82968 | /* Value rank inherited */ |
| 82969 | attr.valueRank = -2; |
| 82970 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 82971 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientLastContactTime"); |
| 82972 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 82973 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3140LU), |
| 82974 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 82975 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 82976 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientLastContactTime"), |
| 82977 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 82978 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 82979 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 82980 | return retVal; |
| 82981 | } |
| 82982 | |
| 82983 | static UA_StatusCode function_namespace0_generated_509_finish(UA_Server *server, UA_UInt16* ns) { |
| 82984 | return UA_Server_addNode_finish(server, |
| 82985 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3140LU) |
| 82986 | ); |
| 82987 | } |
| 82988 | |
| 82989 | /* ClientConnectionTime - ns=0;i=3139 */ |
| 82990 | |
| 82991 | static UA_StatusCode function_namespace0_generated_510_begin(UA_Server *server, UA_UInt16* ns) { |
| 82992 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 82993 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 82994 | attr.minimumSamplingInterval = 0.000000; |
| 82995 | attr.userAccessLevel = 1; |
| 82996 | attr.accessLevel = 1; |
| 82997 | /* Value rank inherited */ |
| 82998 | attr.valueRank = -2; |
| 82999 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 83000 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientConnectionTime"); |
| 83001 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83002 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3139LU), |
| 83003 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 83004 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83005 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientConnectionTime"), |
| 83006 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83007 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83008 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83009 | return retVal; |
| 83010 | } |
| 83011 | |
| 83012 | static UA_StatusCode function_namespace0_generated_510_finish(UA_Server *server, UA_UInt16* ns) { |
| 83013 | return UA_Server_addNode_finish(server, |
| 83014 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3139LU) |
| 83015 | ); |
| 83016 | } |
| 83017 | |
| 83018 | /* MaxResponseMessageSize - ns=0;i=3138 */ |
| 83019 | |
| 83020 | static UA_StatusCode function_namespace0_generated_511_begin(UA_Server *server, UA_UInt16* ns) { |
| 83021 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83022 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83023 | attr.minimumSamplingInterval = 0.000000; |
| 83024 | attr.userAccessLevel = 1; |
| 83025 | attr.accessLevel = 1; |
| 83026 | /* Value rank inherited */ |
| 83027 | attr.valueRank = -2; |
| 83028 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83029 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxResponseMessageSize"); |
| 83030 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83031 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3138LU), |
| 83032 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 83033 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83034 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxResponseMessageSize"), |
| 83035 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83036 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83037 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83038 | return retVal; |
| 83039 | } |
| 83040 | |
| 83041 | static UA_StatusCode function_namespace0_generated_511_finish(UA_Server *server, UA_UInt16* ns) { |
| 83042 | return UA_Server_addNode_finish(server, |
| 83043 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3138LU) |
| 83044 | ); |
| 83045 | } |
| 83046 | |
| 83047 | /* ActualSessionTimeout - ns=0;i=3137 */ |
| 83048 | |
| 83049 | static UA_StatusCode function_namespace0_generated_512_begin(UA_Server *server, UA_UInt16* ns) { |
| 83050 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83051 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83052 | attr.minimumSamplingInterval = 0.000000; |
| 83053 | attr.userAccessLevel = 1; |
| 83054 | attr.accessLevel = 1; |
| 83055 | /* Value rank inherited */ |
| 83056 | attr.valueRank = -2; |
| 83057 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 83058 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ActualSessionTimeout"); |
| 83059 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83060 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3137LU), |
| 83061 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 83062 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83063 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ActualSessionTimeout"), |
| 83064 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83065 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83066 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83067 | return retVal; |
| 83068 | } |
| 83069 | |
| 83070 | static UA_StatusCode function_namespace0_generated_512_finish(UA_Server *server, UA_UInt16* ns) { |
| 83071 | return UA_Server_addNode_finish(server, |
| 83072 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3137LU) |
| 83073 | ); |
| 83074 | } |
| 83075 | |
| 83076 | /* LocaleIds - ns=0;i=3136 */ |
| 83077 | |
| 83078 | static UA_StatusCode function_namespace0_generated_513_begin(UA_Server *server, UA_UInt16* ns) { |
| 83079 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83080 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83081 | attr.minimumSamplingInterval = 0.000000; |
| 83082 | attr.userAccessLevel = 1; |
| 83083 | attr.accessLevel = 1; |
| 83084 | attr.valueRank = 1; |
| 83085 | attr.arrayDimensionsSize = 1; |
| 83086 | UA_UInt32 arrayDimensions[1]; |
| 83087 | arrayDimensions[0] = 0; |
| 83088 | attr.arrayDimensions = &arrayDimensions[0]; |
| 83089 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU); |
| 83090 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleIds"); |
| 83091 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83092 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3136LU), |
| 83093 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 83094 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83095 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleIds"), |
| 83096 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83097 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83098 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83099 | return retVal; |
| 83100 | } |
| 83101 | |
| 83102 | static UA_StatusCode function_namespace0_generated_513_finish(UA_Server *server, UA_UInt16* ns) { |
| 83103 | return UA_Server_addNode_finish(server, |
| 83104 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3136LU) |
| 83105 | ); |
| 83106 | } |
| 83107 | |
| 83108 | /* EndpointUrl - ns=0;i=3135 */ |
| 83109 | |
| 83110 | static UA_StatusCode function_namespace0_generated_514_begin(UA_Server *server, UA_UInt16* ns) { |
| 83111 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83112 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83113 | attr.minimumSamplingInterval = 0.000000; |
| 83114 | attr.userAccessLevel = 1; |
| 83115 | attr.accessLevel = 1; |
| 83116 | /* Value rank inherited */ |
| 83117 | attr.valueRank = -2; |
| 83118 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 83119 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EndpointUrl"); |
| 83120 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83121 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3135LU), |
| 83122 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 83123 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83124 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EndpointUrl"), |
| 83125 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83126 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83127 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83128 | return retVal; |
| 83129 | } |
| 83130 | |
| 83131 | static UA_StatusCode function_namespace0_generated_514_finish(UA_Server *server, UA_UInt16* ns) { |
| 83132 | return UA_Server_addNode_finish(server, |
| 83133 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3135LU) |
| 83134 | ); |
| 83135 | } |
| 83136 | |
| 83137 | /* ServerUri - ns=0;i=3134 */ |
| 83138 | |
| 83139 | static UA_StatusCode function_namespace0_generated_515_begin(UA_Server *server, UA_UInt16* ns) { |
| 83140 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83141 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83142 | attr.minimumSamplingInterval = 0.000000; |
| 83143 | attr.userAccessLevel = 1; |
| 83144 | attr.accessLevel = 1; |
| 83145 | /* Value rank inherited */ |
| 83146 | attr.valueRank = -2; |
| 83147 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 83148 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerUri"); |
| 83149 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83150 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3134LU), |
| 83151 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 83152 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83153 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerUri"), |
| 83154 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83155 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83156 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83157 | return retVal; |
| 83158 | } |
| 83159 | |
| 83160 | static UA_StatusCode function_namespace0_generated_515_finish(UA_Server *server, UA_UInt16* ns) { |
| 83161 | return UA_Server_addNode_finish(server, |
| 83162 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3134LU) |
| 83163 | ); |
| 83164 | } |
| 83165 | |
| 83166 | /* ClientDescription - ns=0;i=3133 */ |
| 83167 | |
| 83168 | static UA_StatusCode function_namespace0_generated_516_begin(UA_Server *server, UA_UInt16* ns) { |
| 83169 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83170 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83171 | attr.minimumSamplingInterval = 0.000000; |
| 83172 | attr.userAccessLevel = 1; |
| 83173 | attr.accessLevel = 1; |
| 83174 | /* Value rank inherited */ |
| 83175 | attr.valueRank = -2; |
| 83176 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 308LU); |
| 83177 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientDescription"); |
| 83178 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83179 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3133LU), |
| 83180 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 83181 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83182 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientDescription"), |
| 83183 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83184 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83185 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83186 | return retVal; |
| 83187 | } |
| 83188 | |
| 83189 | static UA_StatusCode function_namespace0_generated_516_finish(UA_Server *server, UA_UInt16* ns) { |
| 83190 | return UA_Server_addNode_finish(server, |
| 83191 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3133LU) |
| 83192 | ); |
| 83193 | } |
| 83194 | |
| 83195 | /* SessionName - ns=0;i=3132 */ |
| 83196 | |
| 83197 | static UA_StatusCode function_namespace0_generated_517_begin(UA_Server *server, UA_UInt16* ns) { |
| 83198 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83199 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83200 | attr.minimumSamplingInterval = 0.000000; |
| 83201 | attr.userAccessLevel = 1; |
| 83202 | attr.accessLevel = 1; |
| 83203 | /* Value rank inherited */ |
| 83204 | attr.valueRank = -2; |
| 83205 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 83206 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionName"); |
| 83207 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83208 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3132LU), |
| 83209 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 83210 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83211 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionName"), |
| 83212 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83213 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83214 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83215 | return retVal; |
| 83216 | } |
| 83217 | |
| 83218 | static UA_StatusCode function_namespace0_generated_517_finish(UA_Server *server, UA_UInt16* ns) { |
| 83219 | return UA_Server_addNode_finish(server, |
| 83220 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3132LU) |
| 83221 | ); |
| 83222 | } |
| 83223 | |
| 83224 | /* SessionId - ns=0;i=3131 */ |
| 83225 | |
| 83226 | static UA_StatusCode function_namespace0_generated_518_begin(UA_Server *server, UA_UInt16* ns) { |
| 83227 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83228 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83229 | attr.minimumSamplingInterval = 0.000000; |
| 83230 | attr.userAccessLevel = 1; |
| 83231 | attr.accessLevel = 1; |
| 83232 | /* Value rank inherited */ |
| 83233 | attr.valueRank = -2; |
| 83234 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 83235 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionId"); |
| 83236 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83237 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3131LU), |
| 83238 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 83239 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83240 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionId"), |
| 83241 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83242 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83243 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83244 | return retVal; |
| 83245 | } |
| 83246 | |
| 83247 | static UA_StatusCode function_namespace0_generated_518_finish(UA_Server *server, UA_UInt16* ns) { |
| 83248 | return UA_Server_addNode_finish(server, |
| 83249 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3131LU) |
| 83250 | ); |
| 83251 | } |
| 83252 | |
| 83253 | /* UnauthorizedRequestCount - ns=0;i=11891 */ |
| 83254 | |
| 83255 | static UA_StatusCode function_namespace0_generated_519_begin(UA_Server *server, UA_UInt16* ns) { |
| 83256 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83257 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83258 | attr.minimumSamplingInterval = 0.000000; |
| 83259 | attr.userAccessLevel = 1; |
| 83260 | attr.accessLevel = 1; |
| 83261 | /* Value rank inherited */ |
| 83262 | attr.valueRank = -2; |
| 83263 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83264 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UnauthorizedRequestCount"); |
| 83265 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83266 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11891LU), |
| 83267 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), |
| 83268 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83269 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UnauthorizedRequestCount"), |
| 83270 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83271 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83272 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83273 | return retVal; |
| 83274 | } |
| 83275 | |
| 83276 | static UA_StatusCode function_namespace0_generated_519_finish(UA_Server *server, UA_UInt16* ns) { |
| 83277 | return UA_Server_addNode_finish(server, |
| 83278 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11891LU) |
| 83279 | ); |
| 83280 | } |
| 83281 | |
| 83282 | /* ServerDiagnosticsSummaryType - ns=0;i=2150 */ |
| 83283 | |
| 83284 | static UA_StatusCode function_namespace0_generated_520_begin(UA_Server *server, UA_UInt16* ns) { |
| 83285 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83286 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 83287 | /* Value rank inherited */ |
| 83288 | attr.valueRank = -2; |
| 83289 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 859LU); |
| 83290 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerDiagnosticsSummaryType"); |
| 83291 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 83292 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83293 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83294 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 83295 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerDiagnosticsSummaryType"), |
| 83296 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 83297 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 83298 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83299 | return retVal; |
| 83300 | } |
| 83301 | |
| 83302 | static UA_StatusCode function_namespace0_generated_520_finish(UA_Server *server, UA_UInt16* ns) { |
| 83303 | return UA_Server_addNode_finish(server, |
| 83304 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU) |
| 83305 | ); |
| 83306 | } |
| 83307 | |
| 83308 | /* RejectedRequestsCount - ns=0;i=2163 */ |
| 83309 | |
| 83310 | static UA_StatusCode function_namespace0_generated_521_begin(UA_Server *server, UA_UInt16* ns) { |
| 83311 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83312 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83313 | attr.minimumSamplingInterval = 0.000000; |
| 83314 | attr.userAccessLevel = 1; |
| 83315 | attr.accessLevel = 1; |
| 83316 | /* Value rank inherited */ |
| 83317 | attr.valueRank = -2; |
| 83318 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83319 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RejectedRequestsCount"); |
| 83320 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83321 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2163LU), |
| 83322 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83323 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83324 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RejectedRequestsCount"), |
| 83325 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83326 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83327 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83328 | return retVal; |
| 83329 | } |
| 83330 | |
| 83331 | static UA_StatusCode function_namespace0_generated_521_finish(UA_Server *server, UA_UInt16* ns) { |
| 83332 | return UA_Server_addNode_finish(server, |
| 83333 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2163LU) |
| 83334 | ); |
| 83335 | } |
| 83336 | |
| 83337 | /* SecurityRejectedRequestsCount - ns=0;i=2162 */ |
| 83338 | |
| 83339 | static UA_StatusCode function_namespace0_generated_522_begin(UA_Server *server, UA_UInt16* ns) { |
| 83340 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83341 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83342 | attr.minimumSamplingInterval = 0.000000; |
| 83343 | attr.userAccessLevel = 1; |
| 83344 | attr.accessLevel = 1; |
| 83345 | /* Value rank inherited */ |
| 83346 | attr.valueRank = -2; |
| 83347 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83348 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityRejectedRequestsCount"); |
| 83349 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83350 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2162LU), |
| 83351 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83352 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83353 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityRejectedRequestsCount"), |
| 83354 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83355 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83356 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83357 | return retVal; |
| 83358 | } |
| 83359 | |
| 83360 | static UA_StatusCode function_namespace0_generated_522_finish(UA_Server *server, UA_UInt16* ns) { |
| 83361 | return UA_Server_addNode_finish(server, |
| 83362 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2162LU) |
| 83363 | ); |
| 83364 | } |
| 83365 | |
| 83366 | /* CumulatedSubscriptionCount - ns=0;i=2161 */ |
| 83367 | |
| 83368 | static UA_StatusCode function_namespace0_generated_523_begin(UA_Server *server, UA_UInt16* ns) { |
| 83369 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83370 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83371 | attr.minimumSamplingInterval = 0.000000; |
| 83372 | attr.userAccessLevel = 1; |
| 83373 | attr.accessLevel = 1; |
| 83374 | /* Value rank inherited */ |
| 83375 | attr.valueRank = -2; |
| 83376 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83377 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CumulatedSubscriptionCount"); |
| 83378 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83379 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2161LU), |
| 83380 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83381 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83382 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CumulatedSubscriptionCount"), |
| 83383 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83384 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83385 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83386 | return retVal; |
| 83387 | } |
| 83388 | |
| 83389 | static UA_StatusCode function_namespace0_generated_523_finish(UA_Server *server, UA_UInt16* ns) { |
| 83390 | return UA_Server_addNode_finish(server, |
| 83391 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2161LU) |
| 83392 | ); |
| 83393 | } |
| 83394 | |
| 83395 | /* CurrentSubscriptionCount - ns=0;i=2160 */ |
| 83396 | |
| 83397 | static UA_StatusCode function_namespace0_generated_524_begin(UA_Server *server, UA_UInt16* ns) { |
| 83398 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83399 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83400 | attr.minimumSamplingInterval = 0.000000; |
| 83401 | attr.userAccessLevel = 1; |
| 83402 | attr.accessLevel = 1; |
| 83403 | /* Value rank inherited */ |
| 83404 | attr.valueRank = -2; |
| 83405 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83406 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentSubscriptionCount"); |
| 83407 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83408 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2160LU), |
| 83409 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83410 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83411 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentSubscriptionCount"), |
| 83412 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83413 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83414 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83415 | return retVal; |
| 83416 | } |
| 83417 | |
| 83418 | static UA_StatusCode function_namespace0_generated_524_finish(UA_Server *server, UA_UInt16* ns) { |
| 83419 | return UA_Server_addNode_finish(server, |
| 83420 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2160LU) |
| 83421 | ); |
| 83422 | } |
| 83423 | |
| 83424 | /* PublishingIntervalCount - ns=0;i=2159 */ |
| 83425 | |
| 83426 | static UA_StatusCode function_namespace0_generated_525_begin(UA_Server *server, UA_UInt16* ns) { |
| 83427 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83428 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83429 | attr.minimumSamplingInterval = 0.000000; |
| 83430 | attr.userAccessLevel = 1; |
| 83431 | attr.accessLevel = 1; |
| 83432 | /* Value rank inherited */ |
| 83433 | attr.valueRank = -2; |
| 83434 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83435 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishingIntervalCount"); |
| 83436 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83437 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2159LU), |
| 83438 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83439 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83440 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishingIntervalCount"), |
| 83441 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83442 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83443 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83444 | return retVal; |
| 83445 | } |
| 83446 | |
| 83447 | static UA_StatusCode function_namespace0_generated_525_finish(UA_Server *server, UA_UInt16* ns) { |
| 83448 | return UA_Server_addNode_finish(server, |
| 83449 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2159LU) |
| 83450 | ); |
| 83451 | } |
| 83452 | |
| 83453 | /* SessionAbortCount - ns=0;i=2157 */ |
| 83454 | |
| 83455 | static UA_StatusCode function_namespace0_generated_526_begin(UA_Server *server, UA_UInt16* ns) { |
| 83456 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83457 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83458 | attr.minimumSamplingInterval = 0.000000; |
| 83459 | attr.userAccessLevel = 1; |
| 83460 | attr.accessLevel = 1; |
| 83461 | /* Value rank inherited */ |
| 83462 | attr.valueRank = -2; |
| 83463 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83464 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionAbortCount"); |
| 83465 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83466 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2157LU), |
| 83467 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83468 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83469 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionAbortCount"), |
| 83470 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83471 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83472 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83473 | return retVal; |
| 83474 | } |
| 83475 | |
| 83476 | static UA_StatusCode function_namespace0_generated_526_finish(UA_Server *server, UA_UInt16* ns) { |
| 83477 | return UA_Server_addNode_finish(server, |
| 83478 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2157LU) |
| 83479 | ); |
| 83480 | } |
| 83481 | |
| 83482 | /* SessionTimeoutCount - ns=0;i=2156 */ |
| 83483 | |
| 83484 | static UA_StatusCode function_namespace0_generated_527_begin(UA_Server *server, UA_UInt16* ns) { |
| 83485 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83486 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83487 | attr.minimumSamplingInterval = 0.000000; |
| 83488 | attr.userAccessLevel = 1; |
| 83489 | attr.accessLevel = 1; |
| 83490 | /* Value rank inherited */ |
| 83491 | attr.valueRank = -2; |
| 83492 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83493 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionTimeoutCount"); |
| 83494 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83495 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2156LU), |
| 83496 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83497 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83498 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionTimeoutCount"), |
| 83499 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83500 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83501 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83502 | return retVal; |
| 83503 | } |
| 83504 | |
| 83505 | static UA_StatusCode function_namespace0_generated_527_finish(UA_Server *server, UA_UInt16* ns) { |
| 83506 | return UA_Server_addNode_finish(server, |
| 83507 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2156LU) |
| 83508 | ); |
| 83509 | } |
| 83510 | |
| 83511 | /* RejectedSessionCount - ns=0;i=2155 */ |
| 83512 | |
| 83513 | static UA_StatusCode function_namespace0_generated_528_begin(UA_Server *server, UA_UInt16* ns) { |
| 83514 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83515 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83516 | attr.minimumSamplingInterval = 0.000000; |
| 83517 | attr.userAccessLevel = 1; |
| 83518 | attr.accessLevel = 1; |
| 83519 | /* Value rank inherited */ |
| 83520 | attr.valueRank = -2; |
| 83521 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83522 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RejectedSessionCount"); |
| 83523 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83524 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2155LU), |
| 83525 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83526 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83527 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RejectedSessionCount"), |
| 83528 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83529 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83530 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83531 | return retVal; |
| 83532 | } |
| 83533 | |
| 83534 | static UA_StatusCode function_namespace0_generated_528_finish(UA_Server *server, UA_UInt16* ns) { |
| 83535 | return UA_Server_addNode_finish(server, |
| 83536 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2155LU) |
| 83537 | ); |
| 83538 | } |
| 83539 | |
| 83540 | /* SecurityRejectedSessionCount - ns=0;i=2154 */ |
| 83541 | |
| 83542 | static UA_StatusCode function_namespace0_generated_529_begin(UA_Server *server, UA_UInt16* ns) { |
| 83543 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83544 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83545 | attr.minimumSamplingInterval = 0.000000; |
| 83546 | attr.userAccessLevel = 1; |
| 83547 | attr.accessLevel = 1; |
| 83548 | /* Value rank inherited */ |
| 83549 | attr.valueRank = -2; |
| 83550 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83551 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityRejectedSessionCount"); |
| 83552 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83553 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2154LU), |
| 83554 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83555 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83556 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityRejectedSessionCount"), |
| 83557 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83558 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83559 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83560 | return retVal; |
| 83561 | } |
| 83562 | |
| 83563 | static UA_StatusCode function_namespace0_generated_529_finish(UA_Server *server, UA_UInt16* ns) { |
| 83564 | return UA_Server_addNode_finish(server, |
| 83565 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2154LU) |
| 83566 | ); |
| 83567 | } |
| 83568 | |
| 83569 | /* CumulatedSessionCount - ns=0;i=2153 */ |
| 83570 | |
| 83571 | static UA_StatusCode function_namespace0_generated_530_begin(UA_Server *server, UA_UInt16* ns) { |
| 83572 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83573 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83574 | attr.minimumSamplingInterval = 0.000000; |
| 83575 | attr.userAccessLevel = 1; |
| 83576 | attr.accessLevel = 1; |
| 83577 | /* Value rank inherited */ |
| 83578 | attr.valueRank = -2; |
| 83579 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83580 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CumulatedSessionCount"); |
| 83581 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83582 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2153LU), |
| 83583 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83584 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83585 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CumulatedSessionCount"), |
| 83586 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83587 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83588 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83589 | return retVal; |
| 83590 | } |
| 83591 | |
| 83592 | static UA_StatusCode function_namespace0_generated_530_finish(UA_Server *server, UA_UInt16* ns) { |
| 83593 | return UA_Server_addNode_finish(server, |
| 83594 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2153LU) |
| 83595 | ); |
| 83596 | } |
| 83597 | |
| 83598 | /* CurrentSessionCount - ns=0;i=2152 */ |
| 83599 | |
| 83600 | static UA_StatusCode function_namespace0_generated_531_begin(UA_Server *server, UA_UInt16* ns) { |
| 83601 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83602 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83603 | attr.minimumSamplingInterval = 0.000000; |
| 83604 | attr.userAccessLevel = 1; |
| 83605 | attr.accessLevel = 1; |
| 83606 | /* Value rank inherited */ |
| 83607 | attr.valueRank = -2; |
| 83608 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83609 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentSessionCount"); |
| 83610 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83611 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2152LU), |
| 83612 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83613 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83614 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentSessionCount"), |
| 83615 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83616 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83617 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83618 | return retVal; |
| 83619 | } |
| 83620 | |
| 83621 | static UA_StatusCode function_namespace0_generated_531_finish(UA_Server *server, UA_UInt16* ns) { |
| 83622 | return UA_Server_addNode_finish(server, |
| 83623 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2152LU) |
| 83624 | ); |
| 83625 | } |
| 83626 | |
| 83627 | /* ServerViewCount - ns=0;i=2151 */ |
| 83628 | |
| 83629 | static UA_StatusCode function_namespace0_generated_532_begin(UA_Server *server, UA_UInt16* ns) { |
| 83630 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83631 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83632 | attr.minimumSamplingInterval = 0.000000; |
| 83633 | attr.userAccessLevel = 1; |
| 83634 | attr.accessLevel = 1; |
| 83635 | /* Value rank inherited */ |
| 83636 | attr.valueRank = -2; |
| 83637 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83638 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerViewCount"); |
| 83639 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83640 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2151LU), |
| 83641 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 83642 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83643 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerViewCount"), |
| 83644 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83645 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83646 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83647 | return retVal; |
| 83648 | } |
| 83649 | |
| 83650 | static UA_StatusCode function_namespace0_generated_532_finish(UA_Server *server, UA_UInt16* ns) { |
| 83651 | return UA_Server_addNode_finish(server, |
| 83652 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2151LU) |
| 83653 | ); |
| 83654 | } |
| 83655 | |
| 83656 | /* SamplingIntervalDiagnosticsType - ns=0;i=2165 */ |
| 83657 | |
| 83658 | static UA_StatusCode function_namespace0_generated_533_begin(UA_Server *server, UA_UInt16* ns) { |
| 83659 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83660 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 83661 | /* Value rank inherited */ |
| 83662 | attr.valueRank = -2; |
| 83663 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 856LU); |
| 83664 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SamplingIntervalDiagnosticsType"); |
| 83665 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 83666 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2165LU), |
| 83667 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83668 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 83669 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SamplingIntervalDiagnosticsType"), |
| 83670 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 83671 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 83672 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83673 | return retVal; |
| 83674 | } |
| 83675 | |
| 83676 | static UA_StatusCode function_namespace0_generated_533_finish(UA_Server *server, UA_UInt16* ns) { |
| 83677 | return UA_Server_addNode_finish(server, |
| 83678 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2165LU) |
| 83679 | ); |
| 83680 | } |
| 83681 | |
| 83682 | /* SamplingInterval - ns=0;i=2166 */ |
| 83683 | |
| 83684 | static UA_StatusCode function_namespace0_generated_534_begin(UA_Server *server, UA_UInt16* ns) { |
| 83685 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83686 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83687 | attr.minimumSamplingInterval = 0.000000; |
| 83688 | attr.userAccessLevel = 1; |
| 83689 | attr.accessLevel = 1; |
| 83690 | /* Value rank inherited */ |
| 83691 | attr.valueRank = -2; |
| 83692 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 83693 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SamplingInterval"); |
| 83694 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83695 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2166LU), |
| 83696 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2165LU), |
| 83697 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83698 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SamplingInterval"), |
| 83699 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83700 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83701 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83702 | return retVal; |
| 83703 | } |
| 83704 | |
| 83705 | static UA_StatusCode function_namespace0_generated_534_finish(UA_Server *server, UA_UInt16* ns) { |
| 83706 | return UA_Server_addNode_finish(server, |
| 83707 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2166LU) |
| 83708 | ); |
| 83709 | } |
| 83710 | |
| 83711 | /* DisabledMonitoredItemsSamplingCount - ns=0;i=11699 */ |
| 83712 | |
| 83713 | static UA_StatusCode function_namespace0_generated_535_begin(UA_Server *server, UA_UInt16* ns) { |
| 83714 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83715 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83716 | attr.minimumSamplingInterval = 0.000000; |
| 83717 | attr.userAccessLevel = 1; |
| 83718 | attr.accessLevel = 1; |
| 83719 | /* Value rank inherited */ |
| 83720 | attr.valueRank = -2; |
| 83721 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83722 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DisabledMonitoredItemsSamplingCount"); |
| 83723 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83724 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11699LU), |
| 83725 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2165LU), |
| 83726 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83727 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DisabledMonitoredItemsSamplingCount"), |
| 83728 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83729 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83730 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83731 | return retVal; |
| 83732 | } |
| 83733 | |
| 83734 | static UA_StatusCode function_namespace0_generated_535_finish(UA_Server *server, UA_UInt16* ns) { |
| 83735 | return UA_Server_addNode_finish(server, |
| 83736 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11699LU) |
| 83737 | ); |
| 83738 | } |
| 83739 | |
| 83740 | /* MaxSampledMonitoredItemsCount - ns=0;i=11698 */ |
| 83741 | |
| 83742 | static UA_StatusCode function_namespace0_generated_536_begin(UA_Server *server, UA_UInt16* ns) { |
| 83743 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83744 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83745 | attr.minimumSamplingInterval = 0.000000; |
| 83746 | attr.userAccessLevel = 1; |
| 83747 | attr.accessLevel = 1; |
| 83748 | /* Value rank inherited */ |
| 83749 | attr.valueRank = -2; |
| 83750 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83751 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxSampledMonitoredItemsCount"); |
| 83752 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83753 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11698LU), |
| 83754 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2165LU), |
| 83755 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83756 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxSampledMonitoredItemsCount"), |
| 83757 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83758 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83759 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83760 | return retVal; |
| 83761 | } |
| 83762 | |
| 83763 | static UA_StatusCode function_namespace0_generated_536_finish(UA_Server *server, UA_UInt16* ns) { |
| 83764 | return UA_Server_addNode_finish(server, |
| 83765 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11698LU) |
| 83766 | ); |
| 83767 | } |
| 83768 | |
| 83769 | /* SampledMonitoredItemsCount - ns=0;i=11697 */ |
| 83770 | |
| 83771 | static UA_StatusCode function_namespace0_generated_537_begin(UA_Server *server, UA_UInt16* ns) { |
| 83772 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83773 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83774 | attr.minimumSamplingInterval = 0.000000; |
| 83775 | attr.userAccessLevel = 1; |
| 83776 | attr.accessLevel = 1; |
| 83777 | /* Value rank inherited */ |
| 83778 | attr.valueRank = -2; |
| 83779 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83780 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SampledMonitoredItemsCount"); |
| 83781 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83782 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11697LU), |
| 83783 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2165LU), |
| 83784 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83785 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SampledMonitoredItemsCount"), |
| 83786 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83787 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83788 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83789 | return retVal; |
| 83790 | } |
| 83791 | |
| 83792 | static UA_StatusCode function_namespace0_generated_537_finish(UA_Server *server, UA_UInt16* ns) { |
| 83793 | return UA_Server_addNode_finish(server, |
| 83794 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11697LU) |
| 83795 | ); |
| 83796 | } |
| 83797 | |
| 83798 | /* SamplingIntervalDiagnosticsArrayType - ns=0;i=2164 */ |
| 83799 | |
| 83800 | static UA_StatusCode function_namespace0_generated_538_begin(UA_Server *server, UA_UInt16* ns) { |
| 83801 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83802 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 83803 | attr.valueRank = 1; |
| 83804 | attr.arrayDimensionsSize = 1; |
| 83805 | UA_UInt32 arrayDimensions[1]; |
| 83806 | arrayDimensions[0] = 0; |
| 83807 | attr.arrayDimensions = &arrayDimensions[0]; |
| 83808 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 856LU); |
| 83809 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SamplingIntervalDiagnosticsArrayType"); |
| 83810 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 83811 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2164LU), |
| 83812 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83813 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 83814 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SamplingIntervalDiagnosticsArrayType"), |
| 83815 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 83816 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 83817 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83818 | return retVal; |
| 83819 | } |
| 83820 | |
| 83821 | static UA_StatusCode function_namespace0_generated_538_finish(UA_Server *server, UA_UInt16* ns) { |
| 83822 | return UA_Server_addNode_finish(server, |
| 83823 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2164LU) |
| 83824 | ); |
| 83825 | } |
| 83826 | |
| 83827 | /* SamplingIntervalDiagnostics - ns=0;i=12779 */ |
| 83828 | |
| 83829 | static UA_StatusCode function_namespace0_generated_539_begin(UA_Server *server, UA_UInt16* ns) { |
| 83830 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83831 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83832 | attr.minimumSamplingInterval = 0.000000; |
| 83833 | attr.userAccessLevel = 1; |
| 83834 | attr.accessLevel = 1; |
| 83835 | /* Value rank inherited */ |
| 83836 | attr.valueRank = -2; |
| 83837 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 856LU); |
| 83838 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SamplingIntervalDiagnostics"); |
| 83839 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83840 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12779LU), |
| 83841 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2164LU), |
| 83842 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83843 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SamplingIntervalDiagnostics"), |
| 83844 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2165LU), |
| 83845 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83846 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83847 | return retVal; |
| 83848 | } |
| 83849 | |
| 83850 | static UA_StatusCode function_namespace0_generated_539_finish(UA_Server *server, UA_UInt16* ns) { |
| 83851 | return UA_Server_addNode_finish(server, |
| 83852 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12779LU) |
| 83853 | ); |
| 83854 | } |
| 83855 | |
| 83856 | /* DisabledMonitoredItemsSamplingCount - ns=0;i=12783 */ |
| 83857 | |
| 83858 | static UA_StatusCode function_namespace0_generated_540_begin(UA_Server *server, UA_UInt16* ns) { |
| 83859 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83860 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83861 | attr.minimumSamplingInterval = 0.000000; |
| 83862 | attr.userAccessLevel = 1; |
| 83863 | attr.accessLevel = 1; |
| 83864 | /* Value rank inherited */ |
| 83865 | attr.valueRank = -2; |
| 83866 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83867 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DisabledMonitoredItemsSamplingCount"); |
| 83868 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83869 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12783LU), |
| 83870 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12779LU), |
| 83871 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83872 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DisabledMonitoredItemsSamplingCount"), |
| 83873 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83874 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83875 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83876 | return retVal; |
| 83877 | } |
| 83878 | |
| 83879 | static UA_StatusCode function_namespace0_generated_540_finish(UA_Server *server, UA_UInt16* ns) { |
| 83880 | return UA_Server_addNode_finish(server, |
| 83881 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12783LU) |
| 83882 | ); |
| 83883 | } |
| 83884 | |
| 83885 | /* MaxSampledMonitoredItemsCount - ns=0;i=12782 */ |
| 83886 | |
| 83887 | static UA_StatusCode function_namespace0_generated_541_begin(UA_Server *server, UA_UInt16* ns) { |
| 83888 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83889 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83890 | attr.minimumSamplingInterval = 0.000000; |
| 83891 | attr.userAccessLevel = 1; |
| 83892 | attr.accessLevel = 1; |
| 83893 | /* Value rank inherited */ |
| 83894 | attr.valueRank = -2; |
| 83895 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83896 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxSampledMonitoredItemsCount"); |
| 83897 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83898 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12782LU), |
| 83899 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12779LU), |
| 83900 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83901 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxSampledMonitoredItemsCount"), |
| 83902 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83903 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83904 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83905 | return retVal; |
| 83906 | } |
| 83907 | |
| 83908 | static UA_StatusCode function_namespace0_generated_541_finish(UA_Server *server, UA_UInt16* ns) { |
| 83909 | return UA_Server_addNode_finish(server, |
| 83910 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12782LU) |
| 83911 | ); |
| 83912 | } |
| 83913 | |
| 83914 | /* SampledMonitoredItemsCount - ns=0;i=12781 */ |
| 83915 | |
| 83916 | static UA_StatusCode function_namespace0_generated_542_begin(UA_Server *server, UA_UInt16* ns) { |
| 83917 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83918 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83919 | attr.minimumSamplingInterval = 0.000000; |
| 83920 | attr.userAccessLevel = 1; |
| 83921 | attr.accessLevel = 1; |
| 83922 | /* Value rank inherited */ |
| 83923 | attr.valueRank = -2; |
| 83924 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 83925 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SampledMonitoredItemsCount"); |
| 83926 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83927 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12781LU), |
| 83928 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12779LU), |
| 83929 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83930 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SampledMonitoredItemsCount"), |
| 83931 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83932 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83933 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83934 | return retVal; |
| 83935 | } |
| 83936 | |
| 83937 | static UA_StatusCode function_namespace0_generated_542_finish(UA_Server *server, UA_UInt16* ns) { |
| 83938 | return UA_Server_addNode_finish(server, |
| 83939 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12781LU) |
| 83940 | ); |
| 83941 | } |
| 83942 | |
| 83943 | /* SamplingInterval - ns=0;i=12780 */ |
| 83944 | |
| 83945 | static UA_StatusCode function_namespace0_generated_543_begin(UA_Server *server, UA_UInt16* ns) { |
| 83946 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83947 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 83948 | attr.minimumSamplingInterval = 0.000000; |
| 83949 | attr.userAccessLevel = 1; |
| 83950 | attr.accessLevel = 1; |
| 83951 | /* Value rank inherited */ |
| 83952 | attr.valueRank = -2; |
| 83953 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 83954 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SamplingInterval"); |
| 83955 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 83956 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12780LU), |
| 83957 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12779LU), |
| 83958 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 83959 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SamplingInterval"), |
| 83960 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83961 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 83962 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83963 | return retVal; |
| 83964 | } |
| 83965 | |
| 83966 | static UA_StatusCode function_namespace0_generated_543_finish(UA_Server *server, UA_UInt16* ns) { |
| 83967 | return UA_Server_addNode_finish(server, |
| 83968 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12780LU) |
| 83969 | ); |
| 83970 | } |
| 83971 | |
| 83972 | /* SessionDiagnosticsArrayType - ns=0;i=2196 */ |
| 83973 | |
| 83974 | static UA_StatusCode function_namespace0_generated_544_begin(UA_Server *server, UA_UInt16* ns) { |
| 83975 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 83976 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 83977 | attr.valueRank = 1; |
| 83978 | attr.arrayDimensionsSize = 1; |
| 83979 | UA_UInt32 arrayDimensions[1]; |
| 83980 | arrayDimensions[0] = 0; |
| 83981 | attr.arrayDimensions = &arrayDimensions[0]; |
| 83982 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 865LU); |
| 83983 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionDiagnosticsArrayType"); |
| 83984 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 83985 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2196LU), |
| 83986 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 83987 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 83988 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionDiagnosticsArrayType"), |
| 83989 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 83990 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 83991 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 83992 | return retVal; |
| 83993 | } |
| 83994 | |
| 83995 | static UA_StatusCode function_namespace0_generated_544_finish(UA_Server *server, UA_UInt16* ns) { |
| 83996 | return UA_Server_addNode_finish(server, |
| 83997 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2196LU) |
| 83998 | ); |
| 83999 | } |
| 84000 | |
| 84001 | /* SessionDiagnostics - ns=0;i=12816 */ |
| 84002 | |
| 84003 | static UA_StatusCode function_namespace0_generated_545_begin(UA_Server *server, UA_UInt16* ns) { |
| 84004 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84005 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84006 | attr.minimumSamplingInterval = 0.000000; |
| 84007 | attr.userAccessLevel = 1; |
| 84008 | attr.accessLevel = 1; |
| 84009 | /* Value rank inherited */ |
| 84010 | attr.valueRank = -2; |
| 84011 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 865LU); |
| 84012 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionDiagnostics"); |
| 84013 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84014 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84015 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2196LU), |
| 84016 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84017 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionDiagnostics"), |
| 84018 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 84019 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84020 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84021 | return retVal; |
| 84022 | } |
| 84023 | |
| 84024 | static UA_StatusCode function_namespace0_generated_545_finish(UA_Server *server, UA_UInt16* ns) { |
| 84025 | return UA_Server_addNode_finish(server, |
| 84026 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU) |
| 84027 | ); |
| 84028 | } |
| 84029 | |
| 84030 | /* UnregisterNodesCount - ns=0;i=12859 */ |
| 84031 | |
| 84032 | static UA_StatusCode function_namespace0_generated_546_begin(UA_Server *server, UA_UInt16* ns) { |
| 84033 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84034 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84035 | attr.minimumSamplingInterval = 0.000000; |
| 84036 | attr.userAccessLevel = 1; |
| 84037 | attr.accessLevel = 1; |
| 84038 | /* Value rank inherited */ |
| 84039 | attr.valueRank = -2; |
| 84040 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84041 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UnregisterNodesCount"); |
| 84042 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84043 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12859LU), |
| 84044 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84045 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84046 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UnregisterNodesCount"), |
| 84047 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84048 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84049 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84050 | return retVal; |
| 84051 | } |
| 84052 | |
| 84053 | static UA_StatusCode function_namespace0_generated_546_finish(UA_Server *server, UA_UInt16* ns) { |
| 84054 | return UA_Server_addNode_finish(server, |
| 84055 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12859LU) |
| 84056 | ); |
| 84057 | } |
| 84058 | |
| 84059 | /* RegisterNodesCount - ns=0;i=12858 */ |
| 84060 | |
| 84061 | static UA_StatusCode function_namespace0_generated_547_begin(UA_Server *server, UA_UInt16* ns) { |
| 84062 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84063 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84064 | attr.minimumSamplingInterval = 0.000000; |
| 84065 | attr.userAccessLevel = 1; |
| 84066 | attr.accessLevel = 1; |
| 84067 | /* Value rank inherited */ |
| 84068 | attr.valueRank = -2; |
| 84069 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84070 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RegisterNodesCount"); |
| 84071 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84072 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12858LU), |
| 84073 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84074 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84075 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RegisterNodesCount"), |
| 84076 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84077 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84078 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84079 | return retVal; |
| 84080 | } |
| 84081 | |
| 84082 | static UA_StatusCode function_namespace0_generated_547_finish(UA_Server *server, UA_UInt16* ns) { |
| 84083 | return UA_Server_addNode_finish(server, |
| 84084 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12858LU) |
| 84085 | ); |
| 84086 | } |
| 84087 | |
| 84088 | /* QueryNextCount - ns=0;i=12857 */ |
| 84089 | |
| 84090 | static UA_StatusCode function_namespace0_generated_548_begin(UA_Server *server, UA_UInt16* ns) { |
| 84091 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84092 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84093 | attr.minimumSamplingInterval = 0.000000; |
| 84094 | attr.userAccessLevel = 1; |
| 84095 | attr.accessLevel = 1; |
| 84096 | /* Value rank inherited */ |
| 84097 | attr.valueRank = -2; |
| 84098 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84099 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QueryNextCount"); |
| 84100 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84101 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12857LU), |
| 84102 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84103 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84104 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QueryNextCount"), |
| 84105 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84106 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84107 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84108 | return retVal; |
| 84109 | } |
| 84110 | |
| 84111 | static UA_StatusCode function_namespace0_generated_548_finish(UA_Server *server, UA_UInt16* ns) { |
| 84112 | return UA_Server_addNode_finish(server, |
| 84113 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12857LU) |
| 84114 | ); |
| 84115 | } |
| 84116 | |
| 84117 | /* QueryFirstCount - ns=0;i=12856 */ |
| 84118 | |
| 84119 | static UA_StatusCode function_namespace0_generated_549_begin(UA_Server *server, UA_UInt16* ns) { |
| 84120 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84121 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84122 | attr.minimumSamplingInterval = 0.000000; |
| 84123 | attr.userAccessLevel = 1; |
| 84124 | attr.accessLevel = 1; |
| 84125 | /* Value rank inherited */ |
| 84126 | attr.valueRank = -2; |
| 84127 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84128 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QueryFirstCount"); |
| 84129 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84130 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12856LU), |
| 84131 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84132 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84133 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QueryFirstCount"), |
| 84134 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84135 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84136 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84137 | return retVal; |
| 84138 | } |
| 84139 | |
| 84140 | static UA_StatusCode function_namespace0_generated_549_finish(UA_Server *server, UA_UInt16* ns) { |
| 84141 | return UA_Server_addNode_finish(server, |
| 84142 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12856LU) |
| 84143 | ); |
| 84144 | } |
| 84145 | |
| 84146 | /* TranslateBrowsePathsToNodeIdsCount - ns=0;i=12855 */ |
| 84147 | |
| 84148 | static UA_StatusCode function_namespace0_generated_550_begin(UA_Server *server, UA_UInt16* ns) { |
| 84149 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84150 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84151 | attr.minimumSamplingInterval = 0.000000; |
| 84152 | attr.userAccessLevel = 1; |
| 84153 | attr.accessLevel = 1; |
| 84154 | /* Value rank inherited */ |
| 84155 | attr.valueRank = -2; |
| 84156 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84157 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TranslateBrowsePathsToNodeIdsCount"); |
| 84158 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84159 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12855LU), |
| 84160 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84161 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84162 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TranslateBrowsePathsToNodeIdsCount"), |
| 84163 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84164 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84165 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84166 | return retVal; |
| 84167 | } |
| 84168 | |
| 84169 | static UA_StatusCode function_namespace0_generated_550_finish(UA_Server *server, UA_UInt16* ns) { |
| 84170 | return UA_Server_addNode_finish(server, |
| 84171 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12855LU) |
| 84172 | ); |
| 84173 | } |
| 84174 | |
| 84175 | /* BrowseNextCount - ns=0;i=12854 */ |
| 84176 | |
| 84177 | static UA_StatusCode function_namespace0_generated_551_begin(UA_Server *server, UA_UInt16* ns) { |
| 84178 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84179 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84180 | attr.minimumSamplingInterval = 0.000000; |
| 84181 | attr.userAccessLevel = 1; |
| 84182 | attr.accessLevel = 1; |
| 84183 | /* Value rank inherited */ |
| 84184 | attr.valueRank = -2; |
| 84185 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84186 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BrowseNextCount"); |
| 84187 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84188 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12854LU), |
| 84189 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84190 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84191 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BrowseNextCount"), |
| 84192 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84193 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84194 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84195 | return retVal; |
| 84196 | } |
| 84197 | |
| 84198 | static UA_StatusCode function_namespace0_generated_551_finish(UA_Server *server, UA_UInt16* ns) { |
| 84199 | return UA_Server_addNode_finish(server, |
| 84200 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12854LU) |
| 84201 | ); |
| 84202 | } |
| 84203 | |
| 84204 | /* BrowseCount - ns=0;i=12853 */ |
| 84205 | |
| 84206 | static UA_StatusCode function_namespace0_generated_552_begin(UA_Server *server, UA_UInt16* ns) { |
| 84207 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84208 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84209 | attr.minimumSamplingInterval = 0.000000; |
| 84210 | attr.userAccessLevel = 1; |
| 84211 | attr.accessLevel = 1; |
| 84212 | /* Value rank inherited */ |
| 84213 | attr.valueRank = -2; |
| 84214 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84215 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BrowseCount"); |
| 84216 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84217 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12853LU), |
| 84218 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84219 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84220 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BrowseCount"), |
| 84221 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84222 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84223 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84224 | return retVal; |
| 84225 | } |
| 84226 | |
| 84227 | static UA_StatusCode function_namespace0_generated_552_finish(UA_Server *server, UA_UInt16* ns) { |
| 84228 | return UA_Server_addNode_finish(server, |
| 84229 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12853LU) |
| 84230 | ); |
| 84231 | } |
| 84232 | |
| 84233 | /* DeleteReferencesCount - ns=0;i=12852 */ |
| 84234 | |
| 84235 | static UA_StatusCode function_namespace0_generated_553_begin(UA_Server *server, UA_UInt16* ns) { |
| 84236 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84237 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84238 | attr.minimumSamplingInterval = 0.000000; |
| 84239 | attr.userAccessLevel = 1; |
| 84240 | attr.accessLevel = 1; |
| 84241 | /* Value rank inherited */ |
| 84242 | attr.valueRank = -2; |
| 84243 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84244 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteReferencesCount"); |
| 84245 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84246 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12852LU), |
| 84247 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84248 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84249 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteReferencesCount"), |
| 84250 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84251 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84252 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84253 | return retVal; |
| 84254 | } |
| 84255 | |
| 84256 | static UA_StatusCode function_namespace0_generated_553_finish(UA_Server *server, UA_UInt16* ns) { |
| 84257 | return UA_Server_addNode_finish(server, |
| 84258 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12852LU) |
| 84259 | ); |
| 84260 | } |
| 84261 | |
| 84262 | /* DeleteNodesCount - ns=0;i=12851 */ |
| 84263 | |
| 84264 | static UA_StatusCode function_namespace0_generated_554_begin(UA_Server *server, UA_UInt16* ns) { |
| 84265 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84266 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84267 | attr.minimumSamplingInterval = 0.000000; |
| 84268 | attr.userAccessLevel = 1; |
| 84269 | attr.accessLevel = 1; |
| 84270 | /* Value rank inherited */ |
| 84271 | attr.valueRank = -2; |
| 84272 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84273 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteNodesCount"); |
| 84274 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84275 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12851LU), |
| 84276 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84277 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84278 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteNodesCount"), |
| 84279 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84280 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84281 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84282 | return retVal; |
| 84283 | } |
| 84284 | |
| 84285 | static UA_StatusCode function_namespace0_generated_554_finish(UA_Server *server, UA_UInt16* ns) { |
| 84286 | return UA_Server_addNode_finish(server, |
| 84287 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12851LU) |
| 84288 | ); |
| 84289 | } |
| 84290 | |
| 84291 | /* AddReferencesCount - ns=0;i=12850 */ |
| 84292 | |
| 84293 | static UA_StatusCode function_namespace0_generated_555_begin(UA_Server *server, UA_UInt16* ns) { |
| 84294 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84295 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84296 | attr.minimumSamplingInterval = 0.000000; |
| 84297 | attr.userAccessLevel = 1; |
| 84298 | attr.accessLevel = 1; |
| 84299 | /* Value rank inherited */ |
| 84300 | attr.valueRank = -2; |
| 84301 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84302 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddReferencesCount"); |
| 84303 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84304 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12850LU), |
| 84305 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84306 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84307 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddReferencesCount"), |
| 84308 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84309 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84310 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84311 | return retVal; |
| 84312 | } |
| 84313 | |
| 84314 | static UA_StatusCode function_namespace0_generated_555_finish(UA_Server *server, UA_UInt16* ns) { |
| 84315 | return UA_Server_addNode_finish(server, |
| 84316 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12850LU) |
| 84317 | ); |
| 84318 | } |
| 84319 | |
| 84320 | /* AddNodesCount - ns=0;i=12849 */ |
| 84321 | |
| 84322 | static UA_StatusCode function_namespace0_generated_556_begin(UA_Server *server, UA_UInt16* ns) { |
| 84323 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84324 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84325 | attr.minimumSamplingInterval = 0.000000; |
| 84326 | attr.userAccessLevel = 1; |
| 84327 | attr.accessLevel = 1; |
| 84328 | /* Value rank inherited */ |
| 84329 | attr.valueRank = -2; |
| 84330 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84331 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddNodesCount"); |
| 84332 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84333 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12849LU), |
| 84334 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84335 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84336 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddNodesCount"), |
| 84337 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84338 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84339 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84340 | return retVal; |
| 84341 | } |
| 84342 | |
| 84343 | static UA_StatusCode function_namespace0_generated_556_finish(UA_Server *server, UA_UInt16* ns) { |
| 84344 | return UA_Server_addNode_finish(server, |
| 84345 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12849LU) |
| 84346 | ); |
| 84347 | } |
| 84348 | |
| 84349 | /* DeleteSubscriptionsCount - ns=0;i=12848 */ |
| 84350 | |
| 84351 | static UA_StatusCode function_namespace0_generated_557_begin(UA_Server *server, UA_UInt16* ns) { |
| 84352 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84353 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84354 | attr.minimumSamplingInterval = 0.000000; |
| 84355 | attr.userAccessLevel = 1; |
| 84356 | attr.accessLevel = 1; |
| 84357 | /* Value rank inherited */ |
| 84358 | attr.valueRank = -2; |
| 84359 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84360 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteSubscriptionsCount"); |
| 84361 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84362 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12848LU), |
| 84363 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84364 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84365 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteSubscriptionsCount"), |
| 84366 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84367 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84368 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84369 | return retVal; |
| 84370 | } |
| 84371 | |
| 84372 | static UA_StatusCode function_namespace0_generated_557_finish(UA_Server *server, UA_UInt16* ns) { |
| 84373 | return UA_Server_addNode_finish(server, |
| 84374 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12848LU) |
| 84375 | ); |
| 84376 | } |
| 84377 | |
| 84378 | /* TransferSubscriptionsCount - ns=0;i=12847 */ |
| 84379 | |
| 84380 | static UA_StatusCode function_namespace0_generated_558_begin(UA_Server *server, UA_UInt16* ns) { |
| 84381 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84382 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84383 | attr.minimumSamplingInterval = 0.000000; |
| 84384 | attr.userAccessLevel = 1; |
| 84385 | attr.accessLevel = 1; |
| 84386 | /* Value rank inherited */ |
| 84387 | attr.valueRank = -2; |
| 84388 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84389 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransferSubscriptionsCount"); |
| 84390 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84391 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12847LU), |
| 84392 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84393 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84394 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransferSubscriptionsCount"), |
| 84395 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84396 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84397 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84398 | return retVal; |
| 84399 | } |
| 84400 | |
| 84401 | static UA_StatusCode function_namespace0_generated_558_finish(UA_Server *server, UA_UInt16* ns) { |
| 84402 | return UA_Server_addNode_finish(server, |
| 84403 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12847LU) |
| 84404 | ); |
| 84405 | } |
| 84406 | |
| 84407 | /* RepublishCount - ns=0;i=12846 */ |
| 84408 | |
| 84409 | static UA_StatusCode function_namespace0_generated_559_begin(UA_Server *server, UA_UInt16* ns) { |
| 84410 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84411 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84412 | attr.minimumSamplingInterval = 0.000000; |
| 84413 | attr.userAccessLevel = 1; |
| 84414 | attr.accessLevel = 1; |
| 84415 | /* Value rank inherited */ |
| 84416 | attr.valueRank = -2; |
| 84417 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84418 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RepublishCount"); |
| 84419 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84420 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12846LU), |
| 84421 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84422 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84423 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RepublishCount"), |
| 84424 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84425 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84426 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84427 | return retVal; |
| 84428 | } |
| 84429 | |
| 84430 | static UA_StatusCode function_namespace0_generated_559_finish(UA_Server *server, UA_UInt16* ns) { |
| 84431 | return UA_Server_addNode_finish(server, |
| 84432 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12846LU) |
| 84433 | ); |
| 84434 | } |
| 84435 | |
| 84436 | /* PublishCount - ns=0;i=12845 */ |
| 84437 | |
| 84438 | static UA_StatusCode function_namespace0_generated_560_begin(UA_Server *server, UA_UInt16* ns) { |
| 84439 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84440 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84441 | attr.minimumSamplingInterval = 0.000000; |
| 84442 | attr.userAccessLevel = 1; |
| 84443 | attr.accessLevel = 1; |
| 84444 | /* Value rank inherited */ |
| 84445 | attr.valueRank = -2; |
| 84446 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84447 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishCount"); |
| 84448 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84449 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12845LU), |
| 84450 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84451 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84452 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishCount"), |
| 84453 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84454 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84455 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84456 | return retVal; |
| 84457 | } |
| 84458 | |
| 84459 | static UA_StatusCode function_namespace0_generated_560_finish(UA_Server *server, UA_UInt16* ns) { |
| 84460 | return UA_Server_addNode_finish(server, |
| 84461 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12845LU) |
| 84462 | ); |
| 84463 | } |
| 84464 | |
| 84465 | /* SetPublishingModeCount - ns=0;i=12844 */ |
| 84466 | |
| 84467 | static UA_StatusCode function_namespace0_generated_561_begin(UA_Server *server, UA_UInt16* ns) { |
| 84468 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84469 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84470 | attr.minimumSamplingInterval = 0.000000; |
| 84471 | attr.userAccessLevel = 1; |
| 84472 | attr.accessLevel = 1; |
| 84473 | /* Value rank inherited */ |
| 84474 | attr.valueRank = -2; |
| 84475 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84476 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetPublishingModeCount"); |
| 84477 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84478 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12844LU), |
| 84479 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84480 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84481 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetPublishingModeCount"), |
| 84482 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84483 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84484 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84485 | return retVal; |
| 84486 | } |
| 84487 | |
| 84488 | static UA_StatusCode function_namespace0_generated_561_finish(UA_Server *server, UA_UInt16* ns) { |
| 84489 | return UA_Server_addNode_finish(server, |
| 84490 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12844LU) |
| 84491 | ); |
| 84492 | } |
| 84493 | |
| 84494 | /* ModifySubscriptionCount - ns=0;i=12843 */ |
| 84495 | |
| 84496 | static UA_StatusCode function_namespace0_generated_562_begin(UA_Server *server, UA_UInt16* ns) { |
| 84497 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84498 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84499 | attr.minimumSamplingInterval = 0.000000; |
| 84500 | attr.userAccessLevel = 1; |
| 84501 | attr.accessLevel = 1; |
| 84502 | /* Value rank inherited */ |
| 84503 | attr.valueRank = -2; |
| 84504 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84505 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModifySubscriptionCount"); |
| 84506 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84507 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12843LU), |
| 84508 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84509 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84510 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModifySubscriptionCount"), |
| 84511 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84512 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84513 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84514 | return retVal; |
| 84515 | } |
| 84516 | |
| 84517 | static UA_StatusCode function_namespace0_generated_562_finish(UA_Server *server, UA_UInt16* ns) { |
| 84518 | return UA_Server_addNode_finish(server, |
| 84519 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12843LU) |
| 84520 | ); |
| 84521 | } |
| 84522 | |
| 84523 | /* CreateSubscriptionCount - ns=0;i=12842 */ |
| 84524 | |
| 84525 | static UA_StatusCode function_namespace0_generated_563_begin(UA_Server *server, UA_UInt16* ns) { |
| 84526 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84527 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84528 | attr.minimumSamplingInterval = 0.000000; |
| 84529 | attr.userAccessLevel = 1; |
| 84530 | attr.accessLevel = 1; |
| 84531 | /* Value rank inherited */ |
| 84532 | attr.valueRank = -2; |
| 84533 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84534 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CreateSubscriptionCount"); |
| 84535 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84536 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12842LU), |
| 84537 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84538 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84539 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CreateSubscriptionCount"), |
| 84540 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84541 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84542 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84543 | return retVal; |
| 84544 | } |
| 84545 | |
| 84546 | static UA_StatusCode function_namespace0_generated_563_finish(UA_Server *server, UA_UInt16* ns) { |
| 84547 | return UA_Server_addNode_finish(server, |
| 84548 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12842LU) |
| 84549 | ); |
| 84550 | } |
| 84551 | |
| 84552 | /* DeleteMonitoredItemsCount - ns=0;i=12841 */ |
| 84553 | |
| 84554 | static UA_StatusCode function_namespace0_generated_564_begin(UA_Server *server, UA_UInt16* ns) { |
| 84555 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84556 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84557 | attr.minimumSamplingInterval = 0.000000; |
| 84558 | attr.userAccessLevel = 1; |
| 84559 | attr.accessLevel = 1; |
| 84560 | /* Value rank inherited */ |
| 84561 | attr.valueRank = -2; |
| 84562 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84563 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteMonitoredItemsCount"); |
| 84564 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84565 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12841LU), |
| 84566 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84567 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84568 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteMonitoredItemsCount"), |
| 84569 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84570 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84571 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84572 | return retVal; |
| 84573 | } |
| 84574 | |
| 84575 | static UA_StatusCode function_namespace0_generated_564_finish(UA_Server *server, UA_UInt16* ns) { |
| 84576 | return UA_Server_addNode_finish(server, |
| 84577 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12841LU) |
| 84578 | ); |
| 84579 | } |
| 84580 | |
| 84581 | /* SetTriggeringCount - ns=0;i=12840 */ |
| 84582 | |
| 84583 | static UA_StatusCode function_namespace0_generated_565_begin(UA_Server *server, UA_UInt16* ns) { |
| 84584 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84585 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84586 | attr.minimumSamplingInterval = 0.000000; |
| 84587 | attr.userAccessLevel = 1; |
| 84588 | attr.accessLevel = 1; |
| 84589 | /* Value rank inherited */ |
| 84590 | attr.valueRank = -2; |
| 84591 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84592 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetTriggeringCount"); |
| 84593 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84594 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12840LU), |
| 84595 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84596 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84597 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetTriggeringCount"), |
| 84598 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84599 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84600 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84601 | return retVal; |
| 84602 | } |
| 84603 | |
| 84604 | static UA_StatusCode function_namespace0_generated_565_finish(UA_Server *server, UA_UInt16* ns) { |
| 84605 | return UA_Server_addNode_finish(server, |
| 84606 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12840LU) |
| 84607 | ); |
| 84608 | } |
| 84609 | |
| 84610 | /* SetMonitoringModeCount - ns=0;i=12839 */ |
| 84611 | |
| 84612 | static UA_StatusCode function_namespace0_generated_566_begin(UA_Server *server, UA_UInt16* ns) { |
| 84613 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84614 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84615 | attr.minimumSamplingInterval = 0.000000; |
| 84616 | attr.userAccessLevel = 1; |
| 84617 | attr.accessLevel = 1; |
| 84618 | /* Value rank inherited */ |
| 84619 | attr.valueRank = -2; |
| 84620 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84621 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetMonitoringModeCount"); |
| 84622 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84623 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12839LU), |
| 84624 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84625 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84626 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetMonitoringModeCount"), |
| 84627 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84628 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84629 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84630 | return retVal; |
| 84631 | } |
| 84632 | |
| 84633 | static UA_StatusCode function_namespace0_generated_566_finish(UA_Server *server, UA_UInt16* ns) { |
| 84634 | return UA_Server_addNode_finish(server, |
| 84635 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12839LU) |
| 84636 | ); |
| 84637 | } |
| 84638 | |
| 84639 | /* ModifyMonitoredItemsCount - ns=0;i=12838 */ |
| 84640 | |
| 84641 | static UA_StatusCode function_namespace0_generated_567_begin(UA_Server *server, UA_UInt16* ns) { |
| 84642 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84643 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84644 | attr.minimumSamplingInterval = 0.000000; |
| 84645 | attr.userAccessLevel = 1; |
| 84646 | attr.accessLevel = 1; |
| 84647 | /* Value rank inherited */ |
| 84648 | attr.valueRank = -2; |
| 84649 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84650 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModifyMonitoredItemsCount"); |
| 84651 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84652 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12838LU), |
| 84653 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84654 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84655 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModifyMonitoredItemsCount"), |
| 84656 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84657 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84658 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84659 | return retVal; |
| 84660 | } |
| 84661 | |
| 84662 | static UA_StatusCode function_namespace0_generated_567_finish(UA_Server *server, UA_UInt16* ns) { |
| 84663 | return UA_Server_addNode_finish(server, |
| 84664 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12838LU) |
| 84665 | ); |
| 84666 | } |
| 84667 | |
| 84668 | /* CreateMonitoredItemsCount - ns=0;i=12837 */ |
| 84669 | |
| 84670 | static UA_StatusCode function_namespace0_generated_568_begin(UA_Server *server, UA_UInt16* ns) { |
| 84671 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84672 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84673 | attr.minimumSamplingInterval = 0.000000; |
| 84674 | attr.userAccessLevel = 1; |
| 84675 | attr.accessLevel = 1; |
| 84676 | /* Value rank inherited */ |
| 84677 | attr.valueRank = -2; |
| 84678 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84679 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CreateMonitoredItemsCount"); |
| 84680 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84681 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12837LU), |
| 84682 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84683 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84684 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CreateMonitoredItemsCount"), |
| 84685 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84686 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84687 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84688 | return retVal; |
| 84689 | } |
| 84690 | |
| 84691 | static UA_StatusCode function_namespace0_generated_568_finish(UA_Server *server, UA_UInt16* ns) { |
| 84692 | return UA_Server_addNode_finish(server, |
| 84693 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12837LU) |
| 84694 | ); |
| 84695 | } |
| 84696 | |
| 84697 | /* CallCount - ns=0;i=12836 */ |
| 84698 | |
| 84699 | static UA_StatusCode function_namespace0_generated_569_begin(UA_Server *server, UA_UInt16* ns) { |
| 84700 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84701 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84702 | attr.minimumSamplingInterval = 0.000000; |
| 84703 | attr.userAccessLevel = 1; |
| 84704 | attr.accessLevel = 1; |
| 84705 | /* Value rank inherited */ |
| 84706 | attr.valueRank = -2; |
| 84707 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84708 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CallCount"); |
| 84709 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84710 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12836LU), |
| 84711 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84712 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84713 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CallCount"), |
| 84714 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84715 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84716 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84717 | return retVal; |
| 84718 | } |
| 84719 | |
| 84720 | static UA_StatusCode function_namespace0_generated_569_finish(UA_Server *server, UA_UInt16* ns) { |
| 84721 | return UA_Server_addNode_finish(server, |
| 84722 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12836LU) |
| 84723 | ); |
| 84724 | } |
| 84725 | |
| 84726 | /* HistoryUpdateCount - ns=0;i=12835 */ |
| 84727 | |
| 84728 | static UA_StatusCode function_namespace0_generated_570_begin(UA_Server *server, UA_UInt16* ns) { |
| 84729 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84730 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84731 | attr.minimumSamplingInterval = 0.000000; |
| 84732 | attr.userAccessLevel = 1; |
| 84733 | attr.accessLevel = 1; |
| 84734 | /* Value rank inherited */ |
| 84735 | attr.valueRank = -2; |
| 84736 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84737 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryUpdateCount"); |
| 84738 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84739 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12835LU), |
| 84740 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84741 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84742 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryUpdateCount"), |
| 84743 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84744 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84745 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84746 | return retVal; |
| 84747 | } |
| 84748 | |
| 84749 | static UA_StatusCode function_namespace0_generated_570_finish(UA_Server *server, UA_UInt16* ns) { |
| 84750 | return UA_Server_addNode_finish(server, |
| 84751 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12835LU) |
| 84752 | ); |
| 84753 | } |
| 84754 | |
| 84755 | /* WriteCount - ns=0;i=12834 */ |
| 84756 | |
| 84757 | static UA_StatusCode function_namespace0_generated_571_begin(UA_Server *server, UA_UInt16* ns) { |
| 84758 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84759 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84760 | attr.minimumSamplingInterval = 0.000000; |
| 84761 | attr.userAccessLevel = 1; |
| 84762 | attr.accessLevel = 1; |
| 84763 | /* Value rank inherited */ |
| 84764 | attr.valueRank = -2; |
| 84765 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84766 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "WriteCount"); |
| 84767 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84768 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12834LU), |
| 84769 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84770 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84771 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "WriteCount"), |
| 84772 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84773 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84774 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84775 | return retVal; |
| 84776 | } |
| 84777 | |
| 84778 | static UA_StatusCode function_namespace0_generated_571_finish(UA_Server *server, UA_UInt16* ns) { |
| 84779 | return UA_Server_addNode_finish(server, |
| 84780 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12834LU) |
| 84781 | ); |
| 84782 | } |
| 84783 | |
| 84784 | /* HistoryReadCount - ns=0;i=12833 */ |
| 84785 | |
| 84786 | static UA_StatusCode function_namespace0_generated_572_begin(UA_Server *server, UA_UInt16* ns) { |
| 84787 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84788 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84789 | attr.minimumSamplingInterval = 0.000000; |
| 84790 | attr.userAccessLevel = 1; |
| 84791 | attr.accessLevel = 1; |
| 84792 | /* Value rank inherited */ |
| 84793 | attr.valueRank = -2; |
| 84794 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84795 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryReadCount"); |
| 84796 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84797 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12833LU), |
| 84798 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84799 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84800 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryReadCount"), |
| 84801 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84802 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84803 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84804 | return retVal; |
| 84805 | } |
| 84806 | |
| 84807 | static UA_StatusCode function_namespace0_generated_572_finish(UA_Server *server, UA_UInt16* ns) { |
| 84808 | return UA_Server_addNode_finish(server, |
| 84809 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12833LU) |
| 84810 | ); |
| 84811 | } |
| 84812 | |
| 84813 | /* ReadCount - ns=0;i=12832 */ |
| 84814 | |
| 84815 | static UA_StatusCode function_namespace0_generated_573_begin(UA_Server *server, UA_UInt16* ns) { |
| 84816 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84817 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84818 | attr.minimumSamplingInterval = 0.000000; |
| 84819 | attr.userAccessLevel = 1; |
| 84820 | attr.accessLevel = 1; |
| 84821 | /* Value rank inherited */ |
| 84822 | attr.valueRank = -2; |
| 84823 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84824 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReadCount"); |
| 84825 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84826 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12832LU), |
| 84827 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84828 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84829 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReadCount"), |
| 84830 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84831 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84832 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84833 | return retVal; |
| 84834 | } |
| 84835 | |
| 84836 | static UA_StatusCode function_namespace0_generated_573_finish(UA_Server *server, UA_UInt16* ns) { |
| 84837 | return UA_Server_addNode_finish(server, |
| 84838 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12832LU) |
| 84839 | ); |
| 84840 | } |
| 84841 | |
| 84842 | /* UnauthorizedRequestCount - ns=0;i=12831 */ |
| 84843 | |
| 84844 | static UA_StatusCode function_namespace0_generated_574_begin(UA_Server *server, UA_UInt16* ns) { |
| 84845 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84846 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84847 | attr.minimumSamplingInterval = 0.000000; |
| 84848 | attr.userAccessLevel = 1; |
| 84849 | attr.accessLevel = 1; |
| 84850 | /* Value rank inherited */ |
| 84851 | attr.valueRank = -2; |
| 84852 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 84853 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UnauthorizedRequestCount"); |
| 84854 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84855 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12831LU), |
| 84856 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84857 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84858 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UnauthorizedRequestCount"), |
| 84859 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84860 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84861 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84862 | return retVal; |
| 84863 | } |
| 84864 | |
| 84865 | static UA_StatusCode function_namespace0_generated_574_finish(UA_Server *server, UA_UInt16* ns) { |
| 84866 | return UA_Server_addNode_finish(server, |
| 84867 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12831LU) |
| 84868 | ); |
| 84869 | } |
| 84870 | |
| 84871 | /* TotalRequestCount - ns=0;i=12830 */ |
| 84872 | |
| 84873 | static UA_StatusCode function_namespace0_generated_575_begin(UA_Server *server, UA_UInt16* ns) { |
| 84874 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84875 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84876 | attr.minimumSamplingInterval = 0.000000; |
| 84877 | attr.userAccessLevel = 1; |
| 84878 | attr.accessLevel = 1; |
| 84879 | /* Value rank inherited */ |
| 84880 | attr.valueRank = -2; |
| 84881 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 84882 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TotalRequestCount"); |
| 84883 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84884 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12830LU), |
| 84885 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84886 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84887 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TotalRequestCount"), |
| 84888 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84889 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84890 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84891 | return retVal; |
| 84892 | } |
| 84893 | |
| 84894 | static UA_StatusCode function_namespace0_generated_575_finish(UA_Server *server, UA_UInt16* ns) { |
| 84895 | return UA_Server_addNode_finish(server, |
| 84896 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12830LU) |
| 84897 | ); |
| 84898 | } |
| 84899 | |
| 84900 | /* CurrentPublishRequestsInQueue - ns=0;i=12829 */ |
| 84901 | |
| 84902 | static UA_StatusCode function_namespace0_generated_576_begin(UA_Server *server, UA_UInt16* ns) { |
| 84903 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84904 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84905 | attr.minimumSamplingInterval = 0.000000; |
| 84906 | attr.userAccessLevel = 1; |
| 84907 | attr.accessLevel = 1; |
| 84908 | /* Value rank inherited */ |
| 84909 | attr.valueRank = -2; |
| 84910 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 84911 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentPublishRequestsInQueue"); |
| 84912 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84913 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12829LU), |
| 84914 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84915 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84916 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentPublishRequestsInQueue"), |
| 84917 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84918 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84919 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84920 | return retVal; |
| 84921 | } |
| 84922 | |
| 84923 | static UA_StatusCode function_namespace0_generated_576_finish(UA_Server *server, UA_UInt16* ns) { |
| 84924 | return UA_Server_addNode_finish(server, |
| 84925 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12829LU) |
| 84926 | ); |
| 84927 | } |
| 84928 | |
| 84929 | /* CurrentMonitoredItemsCount - ns=0;i=12828 */ |
| 84930 | |
| 84931 | static UA_StatusCode function_namespace0_generated_577_begin(UA_Server *server, UA_UInt16* ns) { |
| 84932 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84933 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84934 | attr.minimumSamplingInterval = 0.000000; |
| 84935 | attr.userAccessLevel = 1; |
| 84936 | attr.accessLevel = 1; |
| 84937 | /* Value rank inherited */ |
| 84938 | attr.valueRank = -2; |
| 84939 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 84940 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentMonitoredItemsCount"); |
| 84941 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84942 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12828LU), |
| 84943 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84944 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84945 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentMonitoredItemsCount"), |
| 84946 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84947 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84948 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84949 | return retVal; |
| 84950 | } |
| 84951 | |
| 84952 | static UA_StatusCode function_namespace0_generated_577_finish(UA_Server *server, UA_UInt16* ns) { |
| 84953 | return UA_Server_addNode_finish(server, |
| 84954 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12828LU) |
| 84955 | ); |
| 84956 | } |
| 84957 | |
| 84958 | /* CurrentSubscriptionsCount - ns=0;i=12827 */ |
| 84959 | |
| 84960 | static UA_StatusCode function_namespace0_generated_578_begin(UA_Server *server, UA_UInt16* ns) { |
| 84961 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84962 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84963 | attr.minimumSamplingInterval = 0.000000; |
| 84964 | attr.userAccessLevel = 1; |
| 84965 | attr.accessLevel = 1; |
| 84966 | /* Value rank inherited */ |
| 84967 | attr.valueRank = -2; |
| 84968 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 84969 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentSubscriptionsCount"); |
| 84970 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 84971 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12827LU), |
| 84972 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 84973 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 84974 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentSubscriptionsCount"), |
| 84975 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 84976 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 84977 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 84978 | return retVal; |
| 84979 | } |
| 84980 | |
| 84981 | static UA_StatusCode function_namespace0_generated_578_finish(UA_Server *server, UA_UInt16* ns) { |
| 84982 | return UA_Server_addNode_finish(server, |
| 84983 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12827LU) |
| 84984 | ); |
| 84985 | } |
| 84986 | |
| 84987 | /* ClientLastContactTime - ns=0;i=12826 */ |
| 84988 | |
| 84989 | static UA_StatusCode function_namespace0_generated_579_begin(UA_Server *server, UA_UInt16* ns) { |
| 84990 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 84991 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 84992 | attr.minimumSamplingInterval = 0.000000; |
| 84993 | attr.userAccessLevel = 1; |
| 84994 | attr.accessLevel = 1; |
| 84995 | /* Value rank inherited */ |
| 84996 | attr.valueRank = -2; |
| 84997 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 84998 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientLastContactTime"); |
| 84999 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85000 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12826LU), |
| 85001 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 85002 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85003 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientLastContactTime"), |
| 85004 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85005 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85006 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85007 | return retVal; |
| 85008 | } |
| 85009 | |
| 85010 | static UA_StatusCode function_namespace0_generated_579_finish(UA_Server *server, UA_UInt16* ns) { |
| 85011 | return UA_Server_addNode_finish(server, |
| 85012 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12826LU) |
| 85013 | ); |
| 85014 | } |
| 85015 | |
| 85016 | /* ClientConnectionTime - ns=0;i=12825 */ |
| 85017 | |
| 85018 | static UA_StatusCode function_namespace0_generated_580_begin(UA_Server *server, UA_UInt16* ns) { |
| 85019 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85020 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85021 | attr.minimumSamplingInterval = 0.000000; |
| 85022 | attr.userAccessLevel = 1; |
| 85023 | attr.accessLevel = 1; |
| 85024 | /* Value rank inherited */ |
| 85025 | attr.valueRank = -2; |
| 85026 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 85027 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientConnectionTime"); |
| 85028 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85029 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12825LU), |
| 85030 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 85031 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85032 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientConnectionTime"), |
| 85033 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85034 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85035 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85036 | return retVal; |
| 85037 | } |
| 85038 | |
| 85039 | static UA_StatusCode function_namespace0_generated_580_finish(UA_Server *server, UA_UInt16* ns) { |
| 85040 | return UA_Server_addNode_finish(server, |
| 85041 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12825LU) |
| 85042 | ); |
| 85043 | } |
| 85044 | |
| 85045 | /* MaxResponseMessageSize - ns=0;i=12824 */ |
| 85046 | |
| 85047 | static UA_StatusCode function_namespace0_generated_581_begin(UA_Server *server, UA_UInt16* ns) { |
| 85048 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85049 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85050 | attr.minimumSamplingInterval = 0.000000; |
| 85051 | attr.userAccessLevel = 1; |
| 85052 | attr.accessLevel = 1; |
| 85053 | /* Value rank inherited */ |
| 85054 | attr.valueRank = -2; |
| 85055 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 85056 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxResponseMessageSize"); |
| 85057 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85058 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12824LU), |
| 85059 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 85060 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85061 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxResponseMessageSize"), |
| 85062 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85063 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85064 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85065 | return retVal; |
| 85066 | } |
| 85067 | |
| 85068 | static UA_StatusCode function_namespace0_generated_581_finish(UA_Server *server, UA_UInt16* ns) { |
| 85069 | return UA_Server_addNode_finish(server, |
| 85070 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12824LU) |
| 85071 | ); |
| 85072 | } |
| 85073 | |
| 85074 | /* ActualSessionTimeout - ns=0;i=12823 */ |
| 85075 | |
| 85076 | static UA_StatusCode function_namespace0_generated_582_begin(UA_Server *server, UA_UInt16* ns) { |
| 85077 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85078 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85079 | attr.minimumSamplingInterval = 0.000000; |
| 85080 | attr.userAccessLevel = 1; |
| 85081 | attr.accessLevel = 1; |
| 85082 | /* Value rank inherited */ |
| 85083 | attr.valueRank = -2; |
| 85084 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 85085 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ActualSessionTimeout"); |
| 85086 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85087 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12823LU), |
| 85088 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 85089 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85090 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ActualSessionTimeout"), |
| 85091 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85092 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85093 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85094 | return retVal; |
| 85095 | } |
| 85096 | |
| 85097 | static UA_StatusCode function_namespace0_generated_582_finish(UA_Server *server, UA_UInt16* ns) { |
| 85098 | return UA_Server_addNode_finish(server, |
| 85099 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12823LU) |
| 85100 | ); |
| 85101 | } |
| 85102 | |
| 85103 | /* LocaleIds - ns=0;i=12822 */ |
| 85104 | |
| 85105 | static UA_StatusCode function_namespace0_generated_583_begin(UA_Server *server, UA_UInt16* ns) { |
| 85106 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85107 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85108 | attr.minimumSamplingInterval = 0.000000; |
| 85109 | attr.userAccessLevel = 1; |
| 85110 | attr.accessLevel = 1; |
| 85111 | attr.valueRank = 1; |
| 85112 | attr.arrayDimensionsSize = 1; |
| 85113 | UA_UInt32 arrayDimensions[1]; |
| 85114 | arrayDimensions[0] = 0; |
| 85115 | attr.arrayDimensions = &arrayDimensions[0]; |
| 85116 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU); |
| 85117 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleIds"); |
| 85118 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85119 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12822LU), |
| 85120 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 85121 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85122 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleIds"), |
| 85123 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85124 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85125 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85126 | return retVal; |
| 85127 | } |
| 85128 | |
| 85129 | static UA_StatusCode function_namespace0_generated_583_finish(UA_Server *server, UA_UInt16* ns) { |
| 85130 | return UA_Server_addNode_finish(server, |
| 85131 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12822LU) |
| 85132 | ); |
| 85133 | } |
| 85134 | |
| 85135 | /* EndpointUrl - ns=0;i=12821 */ |
| 85136 | |
| 85137 | static UA_StatusCode function_namespace0_generated_584_begin(UA_Server *server, UA_UInt16* ns) { |
| 85138 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85139 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85140 | attr.minimumSamplingInterval = 0.000000; |
| 85141 | attr.userAccessLevel = 1; |
| 85142 | attr.accessLevel = 1; |
| 85143 | /* Value rank inherited */ |
| 85144 | attr.valueRank = -2; |
| 85145 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85146 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EndpointUrl"); |
| 85147 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85148 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12821LU), |
| 85149 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 85150 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85151 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EndpointUrl"), |
| 85152 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85153 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85154 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85155 | return retVal; |
| 85156 | } |
| 85157 | |
| 85158 | static UA_StatusCode function_namespace0_generated_584_finish(UA_Server *server, UA_UInt16* ns) { |
| 85159 | return UA_Server_addNode_finish(server, |
| 85160 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12821LU) |
| 85161 | ); |
| 85162 | } |
| 85163 | |
| 85164 | /* ServerUri - ns=0;i=12820 */ |
| 85165 | |
| 85166 | static UA_StatusCode function_namespace0_generated_585_begin(UA_Server *server, UA_UInt16* ns) { |
| 85167 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85168 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85169 | attr.minimumSamplingInterval = 0.000000; |
| 85170 | attr.userAccessLevel = 1; |
| 85171 | attr.accessLevel = 1; |
| 85172 | /* Value rank inherited */ |
| 85173 | attr.valueRank = -2; |
| 85174 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85175 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerUri"); |
| 85176 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85177 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12820LU), |
| 85178 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 85179 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85180 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerUri"), |
| 85181 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85182 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85183 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85184 | return retVal; |
| 85185 | } |
| 85186 | |
| 85187 | static UA_StatusCode function_namespace0_generated_585_finish(UA_Server *server, UA_UInt16* ns) { |
| 85188 | return UA_Server_addNode_finish(server, |
| 85189 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12820LU) |
| 85190 | ); |
| 85191 | } |
| 85192 | |
| 85193 | /* ClientDescription - ns=0;i=12819 */ |
| 85194 | |
| 85195 | static UA_StatusCode function_namespace0_generated_586_begin(UA_Server *server, UA_UInt16* ns) { |
| 85196 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85197 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85198 | attr.minimumSamplingInterval = 0.000000; |
| 85199 | attr.userAccessLevel = 1; |
| 85200 | attr.accessLevel = 1; |
| 85201 | /* Value rank inherited */ |
| 85202 | attr.valueRank = -2; |
| 85203 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 308LU); |
| 85204 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientDescription"); |
| 85205 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85206 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12819LU), |
| 85207 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 85208 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85209 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientDescription"), |
| 85210 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85211 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85212 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85213 | return retVal; |
| 85214 | } |
| 85215 | |
| 85216 | static UA_StatusCode function_namespace0_generated_586_finish(UA_Server *server, UA_UInt16* ns) { |
| 85217 | return UA_Server_addNode_finish(server, |
| 85218 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12819LU) |
| 85219 | ); |
| 85220 | } |
| 85221 | |
| 85222 | /* SessionName - ns=0;i=12818 */ |
| 85223 | |
| 85224 | static UA_StatusCode function_namespace0_generated_587_begin(UA_Server *server, UA_UInt16* ns) { |
| 85225 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85226 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85227 | attr.minimumSamplingInterval = 0.000000; |
| 85228 | attr.userAccessLevel = 1; |
| 85229 | attr.accessLevel = 1; |
| 85230 | /* Value rank inherited */ |
| 85231 | attr.valueRank = -2; |
| 85232 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85233 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionName"); |
| 85234 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85235 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12818LU), |
| 85236 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 85237 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85238 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionName"), |
| 85239 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85240 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85241 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85242 | return retVal; |
| 85243 | } |
| 85244 | |
| 85245 | static UA_StatusCode function_namespace0_generated_587_finish(UA_Server *server, UA_UInt16* ns) { |
| 85246 | return UA_Server_addNode_finish(server, |
| 85247 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12818LU) |
| 85248 | ); |
| 85249 | } |
| 85250 | |
| 85251 | /* SessionId - ns=0;i=12817 */ |
| 85252 | |
| 85253 | static UA_StatusCode function_namespace0_generated_588_begin(UA_Server *server, UA_UInt16* ns) { |
| 85254 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85255 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85256 | attr.minimumSamplingInterval = 0.000000; |
| 85257 | attr.userAccessLevel = 1; |
| 85258 | attr.accessLevel = 1; |
| 85259 | /* Value rank inherited */ |
| 85260 | attr.valueRank = -2; |
| 85261 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 85262 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionId"); |
| 85263 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85264 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12817LU), |
| 85265 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), |
| 85266 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85267 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionId"), |
| 85268 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85269 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85270 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85271 | return retVal; |
| 85272 | } |
| 85273 | |
| 85274 | static UA_StatusCode function_namespace0_generated_588_finish(UA_Server *server, UA_UInt16* ns) { |
| 85275 | return UA_Server_addNode_finish(server, |
| 85276 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12817LU) |
| 85277 | ); |
| 85278 | } |
| 85279 | |
| 85280 | /* SessionSecurityDiagnosticsArrayType - ns=0;i=2243 */ |
| 85281 | |
| 85282 | static UA_StatusCode function_namespace0_generated_589_begin(UA_Server *server, UA_UInt16* ns) { |
| 85283 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85284 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 85285 | attr.valueRank = 1; |
| 85286 | attr.arrayDimensionsSize = 1; |
| 85287 | UA_UInt32 arrayDimensions[1]; |
| 85288 | arrayDimensions[0] = 0; |
| 85289 | attr.arrayDimensions = &arrayDimensions[0]; |
| 85290 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 868LU); |
| 85291 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionSecurityDiagnosticsArrayType"); |
| 85292 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 85293 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2243LU), |
| 85294 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85295 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 85296 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionSecurityDiagnosticsArrayType"), |
| 85297 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 85298 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 85299 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85300 | return retVal; |
| 85301 | } |
| 85302 | |
| 85303 | static UA_StatusCode function_namespace0_generated_589_finish(UA_Server *server, UA_UInt16* ns) { |
| 85304 | return UA_Server_addNode_finish(server, |
| 85305 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2243LU) |
| 85306 | ); |
| 85307 | } |
| 85308 | |
| 85309 | /* SessionSecurityDiagnostics - ns=0;i=12860 */ |
| 85310 | |
| 85311 | static UA_StatusCode function_namespace0_generated_590_begin(UA_Server *server, UA_UInt16* ns) { |
| 85312 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85313 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85314 | attr.minimumSamplingInterval = 0.000000; |
| 85315 | attr.userAccessLevel = 1; |
| 85316 | attr.accessLevel = 1; |
| 85317 | /* Value rank inherited */ |
| 85318 | attr.valueRank = -2; |
| 85319 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 868LU); |
| 85320 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionSecurityDiagnostics"); |
| 85321 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85322 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), |
| 85323 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2243LU), |
| 85324 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85325 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionSecurityDiagnostics"), |
| 85326 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 85327 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85328 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85329 | return retVal; |
| 85330 | } |
| 85331 | |
| 85332 | static UA_StatusCode function_namespace0_generated_590_finish(UA_Server *server, UA_UInt16* ns) { |
| 85333 | return UA_Server_addNode_finish(server, |
| 85334 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU) |
| 85335 | ); |
| 85336 | } |
| 85337 | |
| 85338 | /* ClientCertificate - ns=0;i=12869 */ |
| 85339 | |
| 85340 | static UA_StatusCode function_namespace0_generated_591_begin(UA_Server *server, UA_UInt16* ns) { |
| 85341 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85342 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85343 | attr.minimumSamplingInterval = 0.000000; |
| 85344 | attr.userAccessLevel = 1; |
| 85345 | attr.accessLevel = 1; |
| 85346 | /* Value rank inherited */ |
| 85347 | attr.valueRank = -2; |
| 85348 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU); |
| 85349 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientCertificate"); |
| 85350 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85351 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12869LU), |
| 85352 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), |
| 85353 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85354 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientCertificate"), |
| 85355 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85356 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85357 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85358 | return retVal; |
| 85359 | } |
| 85360 | |
| 85361 | static UA_StatusCode function_namespace0_generated_591_finish(UA_Server *server, UA_UInt16* ns) { |
| 85362 | return UA_Server_addNode_finish(server, |
| 85363 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12869LU) |
| 85364 | ); |
| 85365 | } |
| 85366 | |
| 85367 | /* SecurityPolicyUri - ns=0;i=12868 */ |
| 85368 | |
| 85369 | static UA_StatusCode function_namespace0_generated_592_begin(UA_Server *server, UA_UInt16* ns) { |
| 85370 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85371 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85372 | attr.minimumSamplingInterval = 0.000000; |
| 85373 | attr.userAccessLevel = 1; |
| 85374 | attr.accessLevel = 1; |
| 85375 | /* Value rank inherited */ |
| 85376 | attr.valueRank = -2; |
| 85377 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85378 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityPolicyUri"); |
| 85379 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85380 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12868LU), |
| 85381 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), |
| 85382 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85383 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityPolicyUri"), |
| 85384 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85385 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85386 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85387 | return retVal; |
| 85388 | } |
| 85389 | |
| 85390 | static UA_StatusCode function_namespace0_generated_592_finish(UA_Server *server, UA_UInt16* ns) { |
| 85391 | return UA_Server_addNode_finish(server, |
| 85392 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12868LU) |
| 85393 | ); |
| 85394 | } |
| 85395 | |
| 85396 | /* SecurityMode - ns=0;i=12867 */ |
| 85397 | |
| 85398 | static UA_StatusCode function_namespace0_generated_593_begin(UA_Server *server, UA_UInt16* ns) { |
| 85399 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85400 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85401 | attr.minimumSamplingInterval = 0.000000; |
| 85402 | attr.userAccessLevel = 1; |
| 85403 | attr.accessLevel = 1; |
| 85404 | /* Value rank inherited */ |
| 85405 | attr.valueRank = -2; |
| 85406 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 302LU); |
| 85407 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityMode"); |
| 85408 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85409 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12867LU), |
| 85410 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), |
| 85411 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85412 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityMode"), |
| 85413 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85414 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85415 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85416 | return retVal; |
| 85417 | } |
| 85418 | |
| 85419 | static UA_StatusCode function_namespace0_generated_593_finish(UA_Server *server, UA_UInt16* ns) { |
| 85420 | return UA_Server_addNode_finish(server, |
| 85421 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12867LU) |
| 85422 | ); |
| 85423 | } |
| 85424 | |
| 85425 | /* TransportProtocol - ns=0;i=12866 */ |
| 85426 | |
| 85427 | static UA_StatusCode function_namespace0_generated_594_begin(UA_Server *server, UA_UInt16* ns) { |
| 85428 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85429 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85430 | attr.minimumSamplingInterval = 0.000000; |
| 85431 | attr.userAccessLevel = 1; |
| 85432 | attr.accessLevel = 1; |
| 85433 | /* Value rank inherited */ |
| 85434 | attr.valueRank = -2; |
| 85435 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85436 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransportProtocol"); |
| 85437 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85438 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12866LU), |
| 85439 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), |
| 85440 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85441 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransportProtocol"), |
| 85442 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85443 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85444 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85445 | return retVal; |
| 85446 | } |
| 85447 | |
| 85448 | static UA_StatusCode function_namespace0_generated_594_finish(UA_Server *server, UA_UInt16* ns) { |
| 85449 | return UA_Server_addNode_finish(server, |
| 85450 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12866LU) |
| 85451 | ); |
| 85452 | } |
| 85453 | |
| 85454 | /* Encoding - ns=0;i=12865 */ |
| 85455 | |
| 85456 | static UA_StatusCode function_namespace0_generated_595_begin(UA_Server *server, UA_UInt16* ns) { |
| 85457 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85458 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85459 | attr.minimumSamplingInterval = 0.000000; |
| 85460 | attr.userAccessLevel = 1; |
| 85461 | attr.accessLevel = 1; |
| 85462 | /* Value rank inherited */ |
| 85463 | attr.valueRank = -2; |
| 85464 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85465 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Encoding"); |
| 85466 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85467 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12865LU), |
| 85468 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), |
| 85469 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85470 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Encoding"), |
| 85471 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85472 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85473 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85474 | return retVal; |
| 85475 | } |
| 85476 | |
| 85477 | static UA_StatusCode function_namespace0_generated_595_finish(UA_Server *server, UA_UInt16* ns) { |
| 85478 | return UA_Server_addNode_finish(server, |
| 85479 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12865LU) |
| 85480 | ); |
| 85481 | } |
| 85482 | |
| 85483 | /* AuthenticationMechanism - ns=0;i=12864 */ |
| 85484 | |
| 85485 | static UA_StatusCode function_namespace0_generated_596_begin(UA_Server *server, UA_UInt16* ns) { |
| 85486 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85487 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85488 | attr.minimumSamplingInterval = 0.000000; |
| 85489 | attr.userAccessLevel = 1; |
| 85490 | attr.accessLevel = 1; |
| 85491 | /* Value rank inherited */ |
| 85492 | attr.valueRank = -2; |
| 85493 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85494 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AuthenticationMechanism"); |
| 85495 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85496 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12864LU), |
| 85497 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), |
| 85498 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85499 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AuthenticationMechanism"), |
| 85500 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85501 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85502 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85503 | return retVal; |
| 85504 | } |
| 85505 | |
| 85506 | static UA_StatusCode function_namespace0_generated_596_finish(UA_Server *server, UA_UInt16* ns) { |
| 85507 | return UA_Server_addNode_finish(server, |
| 85508 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12864LU) |
| 85509 | ); |
| 85510 | } |
| 85511 | |
| 85512 | /* ClientUserIdHistory - ns=0;i=12863 */ |
| 85513 | |
| 85514 | static UA_StatusCode function_namespace0_generated_597_begin(UA_Server *server, UA_UInt16* ns) { |
| 85515 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85516 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85517 | attr.minimumSamplingInterval = 0.000000; |
| 85518 | attr.userAccessLevel = 1; |
| 85519 | attr.accessLevel = 1; |
| 85520 | attr.valueRank = 1; |
| 85521 | attr.arrayDimensionsSize = 1; |
| 85522 | UA_UInt32 arrayDimensions[1]; |
| 85523 | arrayDimensions[0] = 0; |
| 85524 | attr.arrayDimensions = &arrayDimensions[0]; |
| 85525 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85526 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientUserIdHistory"); |
| 85527 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85528 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12863LU), |
| 85529 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), |
| 85530 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85531 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientUserIdHistory"), |
| 85532 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85533 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85534 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85535 | return retVal; |
| 85536 | } |
| 85537 | |
| 85538 | static UA_StatusCode function_namespace0_generated_597_finish(UA_Server *server, UA_UInt16* ns) { |
| 85539 | return UA_Server_addNode_finish(server, |
| 85540 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12863LU) |
| 85541 | ); |
| 85542 | } |
| 85543 | |
| 85544 | /* ClientUserIdOfSession - ns=0;i=12862 */ |
| 85545 | |
| 85546 | static UA_StatusCode function_namespace0_generated_598_begin(UA_Server *server, UA_UInt16* ns) { |
| 85547 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85548 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85549 | attr.minimumSamplingInterval = 0.000000; |
| 85550 | attr.userAccessLevel = 1; |
| 85551 | attr.accessLevel = 1; |
| 85552 | /* Value rank inherited */ |
| 85553 | attr.valueRank = -2; |
| 85554 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85555 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientUserIdOfSession"); |
| 85556 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85557 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12862LU), |
| 85558 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), |
| 85559 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85560 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientUserIdOfSession"), |
| 85561 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85562 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85563 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85564 | return retVal; |
| 85565 | } |
| 85566 | |
| 85567 | static UA_StatusCode function_namespace0_generated_598_finish(UA_Server *server, UA_UInt16* ns) { |
| 85568 | return UA_Server_addNode_finish(server, |
| 85569 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12862LU) |
| 85570 | ); |
| 85571 | } |
| 85572 | |
| 85573 | /* SessionId - ns=0;i=12861 */ |
| 85574 | |
| 85575 | static UA_StatusCode function_namespace0_generated_599_begin(UA_Server *server, UA_UInt16* ns) { |
| 85576 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85577 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85578 | attr.minimumSamplingInterval = 0.000000; |
| 85579 | attr.userAccessLevel = 1; |
| 85580 | attr.accessLevel = 1; |
| 85581 | /* Value rank inherited */ |
| 85582 | attr.valueRank = -2; |
| 85583 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 85584 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionId"); |
| 85585 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85586 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12861LU), |
| 85587 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), |
| 85588 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85589 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionId"), |
| 85590 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85591 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85592 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85593 | return retVal; |
| 85594 | } |
| 85595 | |
| 85596 | static UA_StatusCode function_namespace0_generated_599_finish(UA_Server *server, UA_UInt16* ns) { |
| 85597 | return UA_Server_addNode_finish(server, |
| 85598 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12861LU) |
| 85599 | ); |
| 85600 | } |
| 85601 | |
| 85602 | /* SessionsDiagnosticsSummaryType - ns=0;i=2026 */ |
| 85603 | |
| 85604 | static UA_StatusCode function_namespace0_generated_600_begin(UA_Server *server, UA_UInt16* ns) { |
| 85605 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85606 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 85607 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionsDiagnosticsSummaryType"); |
| 85608 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 85609 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2026LU), |
| 85610 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 85611 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 85612 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionsDiagnosticsSummaryType"), |
| 85613 | typeDefinition: UA_NODEID_NULL, |
| 85614 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 85615 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85616 | return retVal; |
| 85617 | } |
| 85618 | |
| 85619 | static UA_StatusCode function_namespace0_generated_600_finish(UA_Server *server, UA_UInt16* ns) { |
| 85620 | return UA_Server_addNode_finish(server, |
| 85621 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2026LU) |
| 85622 | ); |
| 85623 | } |
| 85624 | |
| 85625 | /* SessionSecurityDiagnosticsArray - ns=0;i=2028 */ |
| 85626 | |
| 85627 | static UA_StatusCode function_namespace0_generated_601_begin(UA_Server *server, UA_UInt16* ns) { |
| 85628 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85629 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85630 | attr.minimumSamplingInterval = 0.000000; |
| 85631 | attr.userAccessLevel = 1; |
| 85632 | attr.accessLevel = 1; |
| 85633 | attr.valueRank = 1; |
| 85634 | attr.arrayDimensionsSize = 1; |
| 85635 | UA_UInt32 arrayDimensions[1]; |
| 85636 | arrayDimensions[0] = 0; |
| 85637 | attr.arrayDimensions = &arrayDimensions[0]; |
| 85638 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 868LU); |
| 85639 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionSecurityDiagnosticsArray"); |
| 85640 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85641 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2028LU), |
| 85642 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2026LU), |
| 85643 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85644 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionSecurityDiagnosticsArray"), |
| 85645 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2243LU), |
| 85646 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85647 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85648 | return retVal; |
| 85649 | } |
| 85650 | |
| 85651 | static UA_StatusCode function_namespace0_generated_601_finish(UA_Server *server, UA_UInt16* ns) { |
| 85652 | return UA_Server_addNode_finish(server, |
| 85653 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2028LU) |
| 85654 | ); |
| 85655 | } |
| 85656 | |
| 85657 | /* SessionDiagnosticsArray - ns=0;i=2027 */ |
| 85658 | |
| 85659 | static UA_StatusCode function_namespace0_generated_602_begin(UA_Server *server, UA_UInt16* ns) { |
| 85660 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85661 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85662 | attr.minimumSamplingInterval = 0.000000; |
| 85663 | attr.userAccessLevel = 1; |
| 85664 | attr.accessLevel = 1; |
| 85665 | attr.valueRank = 1; |
| 85666 | attr.arrayDimensionsSize = 1; |
| 85667 | UA_UInt32 arrayDimensions[1]; |
| 85668 | arrayDimensions[0] = 0; |
| 85669 | attr.arrayDimensions = &arrayDimensions[0]; |
| 85670 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 865LU); |
| 85671 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionDiagnosticsArray"); |
| 85672 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85673 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2027LU), |
| 85674 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2026LU), |
| 85675 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85676 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionDiagnosticsArray"), |
| 85677 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2196LU), |
| 85678 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85679 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85680 | return retVal; |
| 85681 | } |
| 85682 | |
| 85683 | static UA_StatusCode function_namespace0_generated_602_finish(UA_Server *server, UA_UInt16* ns) { |
| 85684 | return UA_Server_addNode_finish(server, |
| 85685 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2027LU) |
| 85686 | ); |
| 85687 | } |
| 85688 | |
| 85689 | /* <ClientName> - ns=0;i=12097 */ |
| 85690 | |
| 85691 | static UA_StatusCode function_namespace0_generated_603_begin(UA_Server *server, UA_UInt16* ns) { |
| 85692 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85693 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 85694 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "<ClientName>"); |
| 85695 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 85696 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12097LU), |
| 85697 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2026LU), |
| 85698 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85699 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "<ClientName>"), |
| 85700 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2029LU), |
| 85701 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 85702 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85703 | return retVal; |
| 85704 | } |
| 85705 | |
| 85706 | static UA_StatusCode function_namespace0_generated_603_finish(UA_Server *server, UA_UInt16* ns) { |
| 85707 | return UA_Server_addNode_finish(server, |
| 85708 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12097LU) |
| 85709 | ); |
| 85710 | } |
| 85711 | |
| 85712 | /* SubscriptionDiagnosticsArray - ns=0;i=12152 */ |
| 85713 | |
| 85714 | static UA_StatusCode function_namespace0_generated_604_begin(UA_Server *server, UA_UInt16* ns) { |
| 85715 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85716 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85717 | attr.minimumSamplingInterval = 0.000000; |
| 85718 | attr.userAccessLevel = 1; |
| 85719 | attr.accessLevel = 1; |
| 85720 | attr.valueRank = 1; |
| 85721 | attr.arrayDimensionsSize = 1; |
| 85722 | UA_UInt32 arrayDimensions[1]; |
| 85723 | arrayDimensions[0] = 0; |
| 85724 | attr.arrayDimensions = &arrayDimensions[0]; |
| 85725 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 874LU); |
| 85726 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscriptionDiagnosticsArray"); |
| 85727 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85728 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12152LU), |
| 85729 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12097LU), |
| 85730 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85731 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscriptionDiagnosticsArray"), |
| 85732 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2171LU), |
| 85733 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85734 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85735 | return retVal; |
| 85736 | } |
| 85737 | |
| 85738 | static UA_StatusCode function_namespace0_generated_604_finish(UA_Server *server, UA_UInt16* ns) { |
| 85739 | return UA_Server_addNode_finish(server, |
| 85740 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12152LU) |
| 85741 | ); |
| 85742 | } |
| 85743 | |
| 85744 | /* SessionSecurityDiagnostics - ns=0;i=12142 */ |
| 85745 | |
| 85746 | static UA_StatusCode function_namespace0_generated_605_begin(UA_Server *server, UA_UInt16* ns) { |
| 85747 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85748 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85749 | attr.minimumSamplingInterval = 0.000000; |
| 85750 | attr.userAccessLevel = 1; |
| 85751 | attr.accessLevel = 1; |
| 85752 | /* Value rank inherited */ |
| 85753 | attr.valueRank = -2; |
| 85754 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 868LU); |
| 85755 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionSecurityDiagnostics"); |
| 85756 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85757 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), |
| 85758 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12097LU), |
| 85759 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85760 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionSecurityDiagnostics"), |
| 85761 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2244LU), |
| 85762 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85763 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85764 | return retVal; |
| 85765 | } |
| 85766 | |
| 85767 | static UA_StatusCode function_namespace0_generated_605_finish(UA_Server *server, UA_UInt16* ns) { |
| 85768 | return UA_Server_addNode_finish(server, |
| 85769 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU) |
| 85770 | ); |
| 85771 | } |
| 85772 | |
| 85773 | /* ClientCertificate - ns=0;i=12151 */ |
| 85774 | |
| 85775 | static UA_StatusCode function_namespace0_generated_606_begin(UA_Server *server, UA_UInt16* ns) { |
| 85776 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85777 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85778 | attr.minimumSamplingInterval = 0.000000; |
| 85779 | attr.userAccessLevel = 1; |
| 85780 | attr.accessLevel = 1; |
| 85781 | /* Value rank inherited */ |
| 85782 | attr.valueRank = -2; |
| 85783 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU); |
| 85784 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientCertificate"); |
| 85785 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85786 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12151LU), |
| 85787 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), |
| 85788 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85789 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientCertificate"), |
| 85790 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85791 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85792 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85793 | return retVal; |
| 85794 | } |
| 85795 | |
| 85796 | static UA_StatusCode function_namespace0_generated_606_finish(UA_Server *server, UA_UInt16* ns) { |
| 85797 | return UA_Server_addNode_finish(server, |
| 85798 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12151LU) |
| 85799 | ); |
| 85800 | } |
| 85801 | |
| 85802 | /* SecurityPolicyUri - ns=0;i=12150 */ |
| 85803 | |
| 85804 | static UA_StatusCode function_namespace0_generated_607_begin(UA_Server *server, UA_UInt16* ns) { |
| 85805 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85806 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85807 | attr.minimumSamplingInterval = 0.000000; |
| 85808 | attr.userAccessLevel = 1; |
| 85809 | attr.accessLevel = 1; |
| 85810 | /* Value rank inherited */ |
| 85811 | attr.valueRank = -2; |
| 85812 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85813 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityPolicyUri"); |
| 85814 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85815 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12150LU), |
| 85816 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), |
| 85817 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85818 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityPolicyUri"), |
| 85819 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85820 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85821 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85822 | return retVal; |
| 85823 | } |
| 85824 | |
| 85825 | static UA_StatusCode function_namespace0_generated_607_finish(UA_Server *server, UA_UInt16* ns) { |
| 85826 | return UA_Server_addNode_finish(server, |
| 85827 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12150LU) |
| 85828 | ); |
| 85829 | } |
| 85830 | |
| 85831 | /* SecurityMode - ns=0;i=12149 */ |
| 85832 | |
| 85833 | static UA_StatusCode function_namespace0_generated_608_begin(UA_Server *server, UA_UInt16* ns) { |
| 85834 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85835 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85836 | attr.minimumSamplingInterval = 0.000000; |
| 85837 | attr.userAccessLevel = 1; |
| 85838 | attr.accessLevel = 1; |
| 85839 | /* Value rank inherited */ |
| 85840 | attr.valueRank = -2; |
| 85841 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 302LU); |
| 85842 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityMode"); |
| 85843 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85844 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12149LU), |
| 85845 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), |
| 85846 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85847 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityMode"), |
| 85848 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85849 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85850 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85851 | return retVal; |
| 85852 | } |
| 85853 | |
| 85854 | static UA_StatusCode function_namespace0_generated_608_finish(UA_Server *server, UA_UInt16* ns) { |
| 85855 | return UA_Server_addNode_finish(server, |
| 85856 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12149LU) |
| 85857 | ); |
| 85858 | } |
| 85859 | |
| 85860 | /* TransportProtocol - ns=0;i=12148 */ |
| 85861 | |
| 85862 | static UA_StatusCode function_namespace0_generated_609_begin(UA_Server *server, UA_UInt16* ns) { |
| 85863 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85864 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85865 | attr.minimumSamplingInterval = 0.000000; |
| 85866 | attr.userAccessLevel = 1; |
| 85867 | attr.accessLevel = 1; |
| 85868 | /* Value rank inherited */ |
| 85869 | attr.valueRank = -2; |
| 85870 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85871 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransportProtocol"); |
| 85872 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85873 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12148LU), |
| 85874 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), |
| 85875 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85876 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransportProtocol"), |
| 85877 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85878 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85879 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85880 | return retVal; |
| 85881 | } |
| 85882 | |
| 85883 | static UA_StatusCode function_namespace0_generated_609_finish(UA_Server *server, UA_UInt16* ns) { |
| 85884 | return UA_Server_addNode_finish(server, |
| 85885 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12148LU) |
| 85886 | ); |
| 85887 | } |
| 85888 | |
| 85889 | /* Encoding - ns=0;i=12147 */ |
| 85890 | |
| 85891 | static UA_StatusCode function_namespace0_generated_610_begin(UA_Server *server, UA_UInt16* ns) { |
| 85892 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85893 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85894 | attr.minimumSamplingInterval = 0.000000; |
| 85895 | attr.userAccessLevel = 1; |
| 85896 | attr.accessLevel = 1; |
| 85897 | /* Value rank inherited */ |
| 85898 | attr.valueRank = -2; |
| 85899 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85900 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Encoding"); |
| 85901 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85902 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12147LU), |
| 85903 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), |
| 85904 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85905 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Encoding"), |
| 85906 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85907 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85908 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85909 | return retVal; |
| 85910 | } |
| 85911 | |
| 85912 | static UA_StatusCode function_namespace0_generated_610_finish(UA_Server *server, UA_UInt16* ns) { |
| 85913 | return UA_Server_addNode_finish(server, |
| 85914 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12147LU) |
| 85915 | ); |
| 85916 | } |
| 85917 | |
| 85918 | /* AuthenticationMechanism - ns=0;i=12146 */ |
| 85919 | |
| 85920 | static UA_StatusCode function_namespace0_generated_611_begin(UA_Server *server, UA_UInt16* ns) { |
| 85921 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85922 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85923 | attr.minimumSamplingInterval = 0.000000; |
| 85924 | attr.userAccessLevel = 1; |
| 85925 | attr.accessLevel = 1; |
| 85926 | /* Value rank inherited */ |
| 85927 | attr.valueRank = -2; |
| 85928 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85929 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AuthenticationMechanism"); |
| 85930 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85931 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12146LU), |
| 85932 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), |
| 85933 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85934 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AuthenticationMechanism"), |
| 85935 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85936 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85937 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85938 | return retVal; |
| 85939 | } |
| 85940 | |
| 85941 | static UA_StatusCode function_namespace0_generated_611_finish(UA_Server *server, UA_UInt16* ns) { |
| 85942 | return UA_Server_addNode_finish(server, |
| 85943 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12146LU) |
| 85944 | ); |
| 85945 | } |
| 85946 | |
| 85947 | /* ClientUserIdHistory - ns=0;i=12145 */ |
| 85948 | |
| 85949 | static UA_StatusCode function_namespace0_generated_612_begin(UA_Server *server, UA_UInt16* ns) { |
| 85950 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85951 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85952 | attr.minimumSamplingInterval = 0.000000; |
| 85953 | attr.userAccessLevel = 1; |
| 85954 | attr.accessLevel = 1; |
| 85955 | attr.valueRank = 1; |
| 85956 | attr.arrayDimensionsSize = 1; |
| 85957 | UA_UInt32 arrayDimensions[1]; |
| 85958 | arrayDimensions[0] = 0; |
| 85959 | attr.arrayDimensions = &arrayDimensions[0]; |
| 85960 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85961 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientUserIdHistory"); |
| 85962 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85963 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12145LU), |
| 85964 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), |
| 85965 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85966 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientUserIdHistory"), |
| 85967 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85968 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85969 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85970 | return retVal; |
| 85971 | } |
| 85972 | |
| 85973 | static UA_StatusCode function_namespace0_generated_612_finish(UA_Server *server, UA_UInt16* ns) { |
| 85974 | return UA_Server_addNode_finish(server, |
| 85975 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12145LU) |
| 85976 | ); |
| 85977 | } |
| 85978 | |
| 85979 | /* ClientUserIdOfSession - ns=0;i=12144 */ |
| 85980 | |
| 85981 | static UA_StatusCode function_namespace0_generated_613_begin(UA_Server *server, UA_UInt16* ns) { |
| 85982 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 85983 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 85984 | attr.minimumSamplingInterval = 0.000000; |
| 85985 | attr.userAccessLevel = 1; |
| 85986 | attr.accessLevel = 1; |
| 85987 | /* Value rank inherited */ |
| 85988 | attr.valueRank = -2; |
| 85989 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 85990 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientUserIdOfSession"); |
| 85991 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 85992 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12144LU), |
| 85993 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), |
| 85994 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 85995 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientUserIdOfSession"), |
| 85996 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 85997 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 85998 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 85999 | return retVal; |
| 86000 | } |
| 86001 | |
| 86002 | static UA_StatusCode function_namespace0_generated_613_finish(UA_Server *server, UA_UInt16* ns) { |
| 86003 | return UA_Server_addNode_finish(server, |
| 86004 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12144LU) |
| 86005 | ); |
| 86006 | } |
| 86007 | |
| 86008 | /* SessionId - ns=0;i=12143 */ |
| 86009 | |
| 86010 | static UA_StatusCode function_namespace0_generated_614_begin(UA_Server *server, UA_UInt16* ns) { |
| 86011 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86012 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86013 | attr.minimumSamplingInterval = 0.000000; |
| 86014 | attr.userAccessLevel = 1; |
| 86015 | attr.accessLevel = 1; |
| 86016 | /* Value rank inherited */ |
| 86017 | attr.valueRank = -2; |
| 86018 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 86019 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionId"); |
| 86020 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86021 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12143LU), |
| 86022 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), |
| 86023 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86024 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionId"), |
| 86025 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86026 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86027 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86028 | return retVal; |
| 86029 | } |
| 86030 | |
| 86031 | static UA_StatusCode function_namespace0_generated_614_finish(UA_Server *server, UA_UInt16* ns) { |
| 86032 | return UA_Server_addNode_finish(server, |
| 86033 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12143LU) |
| 86034 | ); |
| 86035 | } |
| 86036 | |
| 86037 | /* SessionDiagnostics - ns=0;i=12098 */ |
| 86038 | |
| 86039 | static UA_StatusCode function_namespace0_generated_615_begin(UA_Server *server, UA_UInt16* ns) { |
| 86040 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86041 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86042 | attr.minimumSamplingInterval = 0.000000; |
| 86043 | attr.userAccessLevel = 1; |
| 86044 | attr.accessLevel = 1; |
| 86045 | /* Value rank inherited */ |
| 86046 | attr.valueRank = -2; |
| 86047 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 865LU); |
| 86048 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionDiagnostics"); |
| 86049 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86050 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86051 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12097LU), |
| 86052 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86053 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionDiagnostics"), |
| 86054 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2197LU), |
| 86055 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86056 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86057 | return retVal; |
| 86058 | } |
| 86059 | |
| 86060 | static UA_StatusCode function_namespace0_generated_615_finish(UA_Server *server, UA_UInt16* ns) { |
| 86061 | return UA_Server_addNode_finish(server, |
| 86062 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU) |
| 86063 | ); |
| 86064 | } |
| 86065 | |
| 86066 | /* UnregisterNodesCount - ns=0;i=12141 */ |
| 86067 | |
| 86068 | static UA_StatusCode function_namespace0_generated_616_begin(UA_Server *server, UA_UInt16* ns) { |
| 86069 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86070 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86071 | attr.minimumSamplingInterval = 0.000000; |
| 86072 | attr.userAccessLevel = 1; |
| 86073 | attr.accessLevel = 1; |
| 86074 | /* Value rank inherited */ |
| 86075 | attr.valueRank = -2; |
| 86076 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86077 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UnregisterNodesCount"); |
| 86078 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86079 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12141LU), |
| 86080 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86081 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86082 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UnregisterNodesCount"), |
| 86083 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86084 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86085 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86086 | return retVal; |
| 86087 | } |
| 86088 | |
| 86089 | static UA_StatusCode function_namespace0_generated_616_finish(UA_Server *server, UA_UInt16* ns) { |
| 86090 | return UA_Server_addNode_finish(server, |
| 86091 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12141LU) |
| 86092 | ); |
| 86093 | } |
| 86094 | |
| 86095 | /* RegisterNodesCount - ns=0;i=12140 */ |
| 86096 | |
| 86097 | static UA_StatusCode function_namespace0_generated_617_begin(UA_Server *server, UA_UInt16* ns) { |
| 86098 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86099 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86100 | attr.minimumSamplingInterval = 0.000000; |
| 86101 | attr.userAccessLevel = 1; |
| 86102 | attr.accessLevel = 1; |
| 86103 | /* Value rank inherited */ |
| 86104 | attr.valueRank = -2; |
| 86105 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86106 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RegisterNodesCount"); |
| 86107 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86108 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12140LU), |
| 86109 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86110 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86111 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RegisterNodesCount"), |
| 86112 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86113 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86114 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86115 | return retVal; |
| 86116 | } |
| 86117 | |
| 86118 | static UA_StatusCode function_namespace0_generated_617_finish(UA_Server *server, UA_UInt16* ns) { |
| 86119 | return UA_Server_addNode_finish(server, |
| 86120 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12140LU) |
| 86121 | ); |
| 86122 | } |
| 86123 | |
| 86124 | /* QueryNextCount - ns=0;i=12139 */ |
| 86125 | |
| 86126 | static UA_StatusCode function_namespace0_generated_618_begin(UA_Server *server, UA_UInt16* ns) { |
| 86127 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86128 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86129 | attr.minimumSamplingInterval = 0.000000; |
| 86130 | attr.userAccessLevel = 1; |
| 86131 | attr.accessLevel = 1; |
| 86132 | /* Value rank inherited */ |
| 86133 | attr.valueRank = -2; |
| 86134 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86135 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QueryNextCount"); |
| 86136 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86137 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12139LU), |
| 86138 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86139 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86140 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QueryNextCount"), |
| 86141 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86142 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86143 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86144 | return retVal; |
| 86145 | } |
| 86146 | |
| 86147 | static UA_StatusCode function_namespace0_generated_618_finish(UA_Server *server, UA_UInt16* ns) { |
| 86148 | return UA_Server_addNode_finish(server, |
| 86149 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12139LU) |
| 86150 | ); |
| 86151 | } |
| 86152 | |
| 86153 | /* QueryFirstCount - ns=0;i=12138 */ |
| 86154 | |
| 86155 | static UA_StatusCode function_namespace0_generated_619_begin(UA_Server *server, UA_UInt16* ns) { |
| 86156 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86157 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86158 | attr.minimumSamplingInterval = 0.000000; |
| 86159 | attr.userAccessLevel = 1; |
| 86160 | attr.accessLevel = 1; |
| 86161 | /* Value rank inherited */ |
| 86162 | attr.valueRank = -2; |
| 86163 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86164 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "QueryFirstCount"); |
| 86165 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86166 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12138LU), |
| 86167 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86168 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86169 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "QueryFirstCount"), |
| 86170 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86171 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86172 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86173 | return retVal; |
| 86174 | } |
| 86175 | |
| 86176 | static UA_StatusCode function_namespace0_generated_619_finish(UA_Server *server, UA_UInt16* ns) { |
| 86177 | return UA_Server_addNode_finish(server, |
| 86178 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12138LU) |
| 86179 | ); |
| 86180 | } |
| 86181 | |
| 86182 | /* TranslateBrowsePathsToNodeIdsCount - ns=0;i=12137 */ |
| 86183 | |
| 86184 | static UA_StatusCode function_namespace0_generated_620_begin(UA_Server *server, UA_UInt16* ns) { |
| 86185 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86186 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86187 | attr.minimumSamplingInterval = 0.000000; |
| 86188 | attr.userAccessLevel = 1; |
| 86189 | attr.accessLevel = 1; |
| 86190 | /* Value rank inherited */ |
| 86191 | attr.valueRank = -2; |
| 86192 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86193 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TranslateBrowsePathsToNodeIdsCount"); |
| 86194 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86195 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12137LU), |
| 86196 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86197 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86198 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TranslateBrowsePathsToNodeIdsCount"), |
| 86199 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86200 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86201 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86202 | return retVal; |
| 86203 | } |
| 86204 | |
| 86205 | static UA_StatusCode function_namespace0_generated_620_finish(UA_Server *server, UA_UInt16* ns) { |
| 86206 | return UA_Server_addNode_finish(server, |
| 86207 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12137LU) |
| 86208 | ); |
| 86209 | } |
| 86210 | |
| 86211 | /* BrowseNextCount - ns=0;i=12136 */ |
| 86212 | |
| 86213 | static UA_StatusCode function_namespace0_generated_621_begin(UA_Server *server, UA_UInt16* ns) { |
| 86214 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86215 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86216 | attr.minimumSamplingInterval = 0.000000; |
| 86217 | attr.userAccessLevel = 1; |
| 86218 | attr.accessLevel = 1; |
| 86219 | /* Value rank inherited */ |
| 86220 | attr.valueRank = -2; |
| 86221 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86222 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BrowseNextCount"); |
| 86223 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86224 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12136LU), |
| 86225 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86226 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86227 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BrowseNextCount"), |
| 86228 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86229 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86230 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86231 | return retVal; |
| 86232 | } |
| 86233 | |
| 86234 | static UA_StatusCode function_namespace0_generated_621_finish(UA_Server *server, UA_UInt16* ns) { |
| 86235 | return UA_Server_addNode_finish(server, |
| 86236 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12136LU) |
| 86237 | ); |
| 86238 | } |
| 86239 | |
| 86240 | /* BrowseCount - ns=0;i=12135 */ |
| 86241 | |
| 86242 | static UA_StatusCode function_namespace0_generated_622_begin(UA_Server *server, UA_UInt16* ns) { |
| 86243 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86244 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86245 | attr.minimumSamplingInterval = 0.000000; |
| 86246 | attr.userAccessLevel = 1; |
| 86247 | attr.accessLevel = 1; |
| 86248 | /* Value rank inherited */ |
| 86249 | attr.valueRank = -2; |
| 86250 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86251 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BrowseCount"); |
| 86252 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86253 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12135LU), |
| 86254 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86255 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86256 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BrowseCount"), |
| 86257 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86258 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86259 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86260 | return retVal; |
| 86261 | } |
| 86262 | |
| 86263 | static UA_StatusCode function_namespace0_generated_622_finish(UA_Server *server, UA_UInt16* ns) { |
| 86264 | return UA_Server_addNode_finish(server, |
| 86265 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12135LU) |
| 86266 | ); |
| 86267 | } |
| 86268 | |
| 86269 | /* DeleteReferencesCount - ns=0;i=12134 */ |
| 86270 | |
| 86271 | static UA_StatusCode function_namespace0_generated_623_begin(UA_Server *server, UA_UInt16* ns) { |
| 86272 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86273 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86274 | attr.minimumSamplingInterval = 0.000000; |
| 86275 | attr.userAccessLevel = 1; |
| 86276 | attr.accessLevel = 1; |
| 86277 | /* Value rank inherited */ |
| 86278 | attr.valueRank = -2; |
| 86279 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86280 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteReferencesCount"); |
| 86281 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86282 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12134LU), |
| 86283 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86284 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86285 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteReferencesCount"), |
| 86286 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86287 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86288 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86289 | return retVal; |
| 86290 | } |
| 86291 | |
| 86292 | static UA_StatusCode function_namespace0_generated_623_finish(UA_Server *server, UA_UInt16* ns) { |
| 86293 | return UA_Server_addNode_finish(server, |
| 86294 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12134LU) |
| 86295 | ); |
| 86296 | } |
| 86297 | |
| 86298 | /* DeleteNodesCount - ns=0;i=12133 */ |
| 86299 | |
| 86300 | static UA_StatusCode function_namespace0_generated_624_begin(UA_Server *server, UA_UInt16* ns) { |
| 86301 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86302 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86303 | attr.minimumSamplingInterval = 0.000000; |
| 86304 | attr.userAccessLevel = 1; |
| 86305 | attr.accessLevel = 1; |
| 86306 | /* Value rank inherited */ |
| 86307 | attr.valueRank = -2; |
| 86308 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86309 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteNodesCount"); |
| 86310 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86311 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12133LU), |
| 86312 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86313 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86314 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteNodesCount"), |
| 86315 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86316 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86317 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86318 | return retVal; |
| 86319 | } |
| 86320 | |
| 86321 | static UA_StatusCode function_namespace0_generated_624_finish(UA_Server *server, UA_UInt16* ns) { |
| 86322 | return UA_Server_addNode_finish(server, |
| 86323 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12133LU) |
| 86324 | ); |
| 86325 | } |
| 86326 | |
| 86327 | /* AddReferencesCount - ns=0;i=12132 */ |
| 86328 | |
| 86329 | static UA_StatusCode function_namespace0_generated_625_begin(UA_Server *server, UA_UInt16* ns) { |
| 86330 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86331 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86332 | attr.minimumSamplingInterval = 0.000000; |
| 86333 | attr.userAccessLevel = 1; |
| 86334 | attr.accessLevel = 1; |
| 86335 | /* Value rank inherited */ |
| 86336 | attr.valueRank = -2; |
| 86337 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86338 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddReferencesCount"); |
| 86339 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86340 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12132LU), |
| 86341 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86342 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86343 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddReferencesCount"), |
| 86344 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86345 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86346 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86347 | return retVal; |
| 86348 | } |
| 86349 | |
| 86350 | static UA_StatusCode function_namespace0_generated_625_finish(UA_Server *server, UA_UInt16* ns) { |
| 86351 | return UA_Server_addNode_finish(server, |
| 86352 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12132LU) |
| 86353 | ); |
| 86354 | } |
| 86355 | |
| 86356 | /* AddNodesCount - ns=0;i=12131 */ |
| 86357 | |
| 86358 | static UA_StatusCode function_namespace0_generated_626_begin(UA_Server *server, UA_UInt16* ns) { |
| 86359 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86360 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86361 | attr.minimumSamplingInterval = 0.000000; |
| 86362 | attr.userAccessLevel = 1; |
| 86363 | attr.accessLevel = 1; |
| 86364 | /* Value rank inherited */ |
| 86365 | attr.valueRank = -2; |
| 86366 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86367 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddNodesCount"); |
| 86368 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86369 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12131LU), |
| 86370 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86371 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86372 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddNodesCount"), |
| 86373 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86374 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86375 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86376 | return retVal; |
| 86377 | } |
| 86378 | |
| 86379 | static UA_StatusCode function_namespace0_generated_626_finish(UA_Server *server, UA_UInt16* ns) { |
| 86380 | return UA_Server_addNode_finish(server, |
| 86381 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12131LU) |
| 86382 | ); |
| 86383 | } |
| 86384 | |
| 86385 | /* DeleteSubscriptionsCount - ns=0;i=12130 */ |
| 86386 | |
| 86387 | static UA_StatusCode function_namespace0_generated_627_begin(UA_Server *server, UA_UInt16* ns) { |
| 86388 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86389 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86390 | attr.minimumSamplingInterval = 0.000000; |
| 86391 | attr.userAccessLevel = 1; |
| 86392 | attr.accessLevel = 1; |
| 86393 | /* Value rank inherited */ |
| 86394 | attr.valueRank = -2; |
| 86395 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86396 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteSubscriptionsCount"); |
| 86397 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86398 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12130LU), |
| 86399 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86400 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86401 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteSubscriptionsCount"), |
| 86402 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86403 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86404 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86405 | return retVal; |
| 86406 | } |
| 86407 | |
| 86408 | static UA_StatusCode function_namespace0_generated_627_finish(UA_Server *server, UA_UInt16* ns) { |
| 86409 | return UA_Server_addNode_finish(server, |
| 86410 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12130LU) |
| 86411 | ); |
| 86412 | } |
| 86413 | |
| 86414 | /* TransferSubscriptionsCount - ns=0;i=12129 */ |
| 86415 | |
| 86416 | static UA_StatusCode function_namespace0_generated_628_begin(UA_Server *server, UA_UInt16* ns) { |
| 86417 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86418 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86419 | attr.minimumSamplingInterval = 0.000000; |
| 86420 | attr.userAccessLevel = 1; |
| 86421 | attr.accessLevel = 1; |
| 86422 | /* Value rank inherited */ |
| 86423 | attr.valueRank = -2; |
| 86424 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86425 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TransferSubscriptionsCount"); |
| 86426 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86427 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12129LU), |
| 86428 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86429 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86430 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TransferSubscriptionsCount"), |
| 86431 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86432 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86433 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86434 | return retVal; |
| 86435 | } |
| 86436 | |
| 86437 | static UA_StatusCode function_namespace0_generated_628_finish(UA_Server *server, UA_UInt16* ns) { |
| 86438 | return UA_Server_addNode_finish(server, |
| 86439 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12129LU) |
| 86440 | ); |
| 86441 | } |
| 86442 | |
| 86443 | /* RepublishCount - ns=0;i=12128 */ |
| 86444 | |
| 86445 | static UA_StatusCode function_namespace0_generated_629_begin(UA_Server *server, UA_UInt16* ns) { |
| 86446 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86447 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86448 | attr.minimumSamplingInterval = 0.000000; |
| 86449 | attr.userAccessLevel = 1; |
| 86450 | attr.accessLevel = 1; |
| 86451 | /* Value rank inherited */ |
| 86452 | attr.valueRank = -2; |
| 86453 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86454 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RepublishCount"); |
| 86455 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86456 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12128LU), |
| 86457 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86458 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86459 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RepublishCount"), |
| 86460 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86461 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86462 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86463 | return retVal; |
| 86464 | } |
| 86465 | |
| 86466 | static UA_StatusCode function_namespace0_generated_629_finish(UA_Server *server, UA_UInt16* ns) { |
| 86467 | return UA_Server_addNode_finish(server, |
| 86468 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12128LU) |
| 86469 | ); |
| 86470 | } |
| 86471 | |
| 86472 | /* PublishCount - ns=0;i=12127 */ |
| 86473 | |
| 86474 | static UA_StatusCode function_namespace0_generated_630_begin(UA_Server *server, UA_UInt16* ns) { |
| 86475 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86476 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86477 | attr.minimumSamplingInterval = 0.000000; |
| 86478 | attr.userAccessLevel = 1; |
| 86479 | attr.accessLevel = 1; |
| 86480 | /* Value rank inherited */ |
| 86481 | attr.valueRank = -2; |
| 86482 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86483 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishCount"); |
| 86484 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86485 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12127LU), |
| 86486 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86487 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86488 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishCount"), |
| 86489 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86490 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86491 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86492 | return retVal; |
| 86493 | } |
| 86494 | |
| 86495 | static UA_StatusCode function_namespace0_generated_630_finish(UA_Server *server, UA_UInt16* ns) { |
| 86496 | return UA_Server_addNode_finish(server, |
| 86497 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12127LU) |
| 86498 | ); |
| 86499 | } |
| 86500 | |
| 86501 | /* SetPublishingModeCount - ns=0;i=12126 */ |
| 86502 | |
| 86503 | static UA_StatusCode function_namespace0_generated_631_begin(UA_Server *server, UA_UInt16* ns) { |
| 86504 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86505 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86506 | attr.minimumSamplingInterval = 0.000000; |
| 86507 | attr.userAccessLevel = 1; |
| 86508 | attr.accessLevel = 1; |
| 86509 | /* Value rank inherited */ |
| 86510 | attr.valueRank = -2; |
| 86511 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86512 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetPublishingModeCount"); |
| 86513 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86514 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12126LU), |
| 86515 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86516 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86517 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetPublishingModeCount"), |
| 86518 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86519 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86520 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86521 | return retVal; |
| 86522 | } |
| 86523 | |
| 86524 | static UA_StatusCode function_namespace0_generated_631_finish(UA_Server *server, UA_UInt16* ns) { |
| 86525 | return UA_Server_addNode_finish(server, |
| 86526 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12126LU) |
| 86527 | ); |
| 86528 | } |
| 86529 | |
| 86530 | /* ModifySubscriptionCount - ns=0;i=12125 */ |
| 86531 | |
| 86532 | static UA_StatusCode function_namespace0_generated_632_begin(UA_Server *server, UA_UInt16* ns) { |
| 86533 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86534 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86535 | attr.minimumSamplingInterval = 0.000000; |
| 86536 | attr.userAccessLevel = 1; |
| 86537 | attr.accessLevel = 1; |
| 86538 | /* Value rank inherited */ |
| 86539 | attr.valueRank = -2; |
| 86540 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86541 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModifySubscriptionCount"); |
| 86542 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86543 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12125LU), |
| 86544 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86545 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86546 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModifySubscriptionCount"), |
| 86547 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86548 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86549 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86550 | return retVal; |
| 86551 | } |
| 86552 | |
| 86553 | static UA_StatusCode function_namespace0_generated_632_finish(UA_Server *server, UA_UInt16* ns) { |
| 86554 | return UA_Server_addNode_finish(server, |
| 86555 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12125LU) |
| 86556 | ); |
| 86557 | } |
| 86558 | |
| 86559 | /* CreateSubscriptionCount - ns=0;i=12124 */ |
| 86560 | |
| 86561 | static UA_StatusCode function_namespace0_generated_633_begin(UA_Server *server, UA_UInt16* ns) { |
| 86562 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86563 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86564 | attr.minimumSamplingInterval = 0.000000; |
| 86565 | attr.userAccessLevel = 1; |
| 86566 | attr.accessLevel = 1; |
| 86567 | /* Value rank inherited */ |
| 86568 | attr.valueRank = -2; |
| 86569 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86570 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CreateSubscriptionCount"); |
| 86571 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86572 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12124LU), |
| 86573 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86574 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86575 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CreateSubscriptionCount"), |
| 86576 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86577 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86578 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86579 | return retVal; |
| 86580 | } |
| 86581 | |
| 86582 | static UA_StatusCode function_namespace0_generated_633_finish(UA_Server *server, UA_UInt16* ns) { |
| 86583 | return UA_Server_addNode_finish(server, |
| 86584 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12124LU) |
| 86585 | ); |
| 86586 | } |
| 86587 | |
| 86588 | /* DeleteMonitoredItemsCount - ns=0;i=12123 */ |
| 86589 | |
| 86590 | static UA_StatusCode function_namespace0_generated_634_begin(UA_Server *server, UA_UInt16* ns) { |
| 86591 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86592 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86593 | attr.minimumSamplingInterval = 0.000000; |
| 86594 | attr.userAccessLevel = 1; |
| 86595 | attr.accessLevel = 1; |
| 86596 | /* Value rank inherited */ |
| 86597 | attr.valueRank = -2; |
| 86598 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86599 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteMonitoredItemsCount"); |
| 86600 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86601 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12123LU), |
| 86602 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86603 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86604 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteMonitoredItemsCount"), |
| 86605 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86606 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86607 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86608 | return retVal; |
| 86609 | } |
| 86610 | |
| 86611 | static UA_StatusCode function_namespace0_generated_634_finish(UA_Server *server, UA_UInt16* ns) { |
| 86612 | return UA_Server_addNode_finish(server, |
| 86613 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12123LU) |
| 86614 | ); |
| 86615 | } |
| 86616 | |
| 86617 | /* SetTriggeringCount - ns=0;i=12122 */ |
| 86618 | |
| 86619 | static UA_StatusCode function_namespace0_generated_635_begin(UA_Server *server, UA_UInt16* ns) { |
| 86620 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86621 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86622 | attr.minimumSamplingInterval = 0.000000; |
| 86623 | attr.userAccessLevel = 1; |
| 86624 | attr.accessLevel = 1; |
| 86625 | /* Value rank inherited */ |
| 86626 | attr.valueRank = -2; |
| 86627 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86628 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetTriggeringCount"); |
| 86629 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86630 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12122LU), |
| 86631 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86632 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86633 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetTriggeringCount"), |
| 86634 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86635 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86636 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86637 | return retVal; |
| 86638 | } |
| 86639 | |
| 86640 | static UA_StatusCode function_namespace0_generated_635_finish(UA_Server *server, UA_UInt16* ns) { |
| 86641 | return UA_Server_addNode_finish(server, |
| 86642 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12122LU) |
| 86643 | ); |
| 86644 | } |
| 86645 | |
| 86646 | /* SetMonitoringModeCount - ns=0;i=12121 */ |
| 86647 | |
| 86648 | static UA_StatusCode function_namespace0_generated_636_begin(UA_Server *server, UA_UInt16* ns) { |
| 86649 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86650 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86651 | attr.minimumSamplingInterval = 0.000000; |
| 86652 | attr.userAccessLevel = 1; |
| 86653 | attr.accessLevel = 1; |
| 86654 | /* Value rank inherited */ |
| 86655 | attr.valueRank = -2; |
| 86656 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86657 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SetMonitoringModeCount"); |
| 86658 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86659 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12121LU), |
| 86660 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86661 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86662 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SetMonitoringModeCount"), |
| 86663 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86664 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86665 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86666 | return retVal; |
| 86667 | } |
| 86668 | |
| 86669 | static UA_StatusCode function_namespace0_generated_636_finish(UA_Server *server, UA_UInt16* ns) { |
| 86670 | return UA_Server_addNode_finish(server, |
| 86671 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12121LU) |
| 86672 | ); |
| 86673 | } |
| 86674 | |
| 86675 | /* ModifyMonitoredItemsCount - ns=0;i=12120 */ |
| 86676 | |
| 86677 | static UA_StatusCode function_namespace0_generated_637_begin(UA_Server *server, UA_UInt16* ns) { |
| 86678 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86679 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86680 | attr.minimumSamplingInterval = 0.000000; |
| 86681 | attr.userAccessLevel = 1; |
| 86682 | attr.accessLevel = 1; |
| 86683 | /* Value rank inherited */ |
| 86684 | attr.valueRank = -2; |
| 86685 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86686 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModifyMonitoredItemsCount"); |
| 86687 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86688 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12120LU), |
| 86689 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86690 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86691 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModifyMonitoredItemsCount"), |
| 86692 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86693 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86694 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86695 | return retVal; |
| 86696 | } |
| 86697 | |
| 86698 | static UA_StatusCode function_namespace0_generated_637_finish(UA_Server *server, UA_UInt16* ns) { |
| 86699 | return UA_Server_addNode_finish(server, |
| 86700 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12120LU) |
| 86701 | ); |
| 86702 | } |
| 86703 | |
| 86704 | /* CreateMonitoredItemsCount - ns=0;i=12119 */ |
| 86705 | |
| 86706 | static UA_StatusCode function_namespace0_generated_638_begin(UA_Server *server, UA_UInt16* ns) { |
| 86707 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86708 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86709 | attr.minimumSamplingInterval = 0.000000; |
| 86710 | attr.userAccessLevel = 1; |
| 86711 | attr.accessLevel = 1; |
| 86712 | /* Value rank inherited */ |
| 86713 | attr.valueRank = -2; |
| 86714 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86715 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CreateMonitoredItemsCount"); |
| 86716 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86717 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12119LU), |
| 86718 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86719 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86720 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CreateMonitoredItemsCount"), |
| 86721 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86722 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86723 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86724 | return retVal; |
| 86725 | } |
| 86726 | |
| 86727 | static UA_StatusCode function_namespace0_generated_638_finish(UA_Server *server, UA_UInt16* ns) { |
| 86728 | return UA_Server_addNode_finish(server, |
| 86729 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12119LU) |
| 86730 | ); |
| 86731 | } |
| 86732 | |
| 86733 | /* CallCount - ns=0;i=12118 */ |
| 86734 | |
| 86735 | static UA_StatusCode function_namespace0_generated_639_begin(UA_Server *server, UA_UInt16* ns) { |
| 86736 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86737 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86738 | attr.minimumSamplingInterval = 0.000000; |
| 86739 | attr.userAccessLevel = 1; |
| 86740 | attr.accessLevel = 1; |
| 86741 | /* Value rank inherited */ |
| 86742 | attr.valueRank = -2; |
| 86743 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86744 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CallCount"); |
| 86745 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86746 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12118LU), |
| 86747 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86748 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86749 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CallCount"), |
| 86750 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86751 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86752 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86753 | return retVal; |
| 86754 | } |
| 86755 | |
| 86756 | static UA_StatusCode function_namespace0_generated_639_finish(UA_Server *server, UA_UInt16* ns) { |
| 86757 | return UA_Server_addNode_finish(server, |
| 86758 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12118LU) |
| 86759 | ); |
| 86760 | } |
| 86761 | |
| 86762 | /* HistoryUpdateCount - ns=0;i=12117 */ |
| 86763 | |
| 86764 | static UA_StatusCode function_namespace0_generated_640_begin(UA_Server *server, UA_UInt16* ns) { |
| 86765 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86766 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86767 | attr.minimumSamplingInterval = 0.000000; |
| 86768 | attr.userAccessLevel = 1; |
| 86769 | attr.accessLevel = 1; |
| 86770 | /* Value rank inherited */ |
| 86771 | attr.valueRank = -2; |
| 86772 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86773 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryUpdateCount"); |
| 86774 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86775 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12117LU), |
| 86776 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86777 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86778 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryUpdateCount"), |
| 86779 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86780 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86781 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86782 | return retVal; |
| 86783 | } |
| 86784 | |
| 86785 | static UA_StatusCode function_namespace0_generated_640_finish(UA_Server *server, UA_UInt16* ns) { |
| 86786 | return UA_Server_addNode_finish(server, |
| 86787 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12117LU) |
| 86788 | ); |
| 86789 | } |
| 86790 | |
| 86791 | /* WriteCount - ns=0;i=12116 */ |
| 86792 | |
| 86793 | static UA_StatusCode function_namespace0_generated_641_begin(UA_Server *server, UA_UInt16* ns) { |
| 86794 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86795 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86796 | attr.minimumSamplingInterval = 0.000000; |
| 86797 | attr.userAccessLevel = 1; |
| 86798 | attr.accessLevel = 1; |
| 86799 | /* Value rank inherited */ |
| 86800 | attr.valueRank = -2; |
| 86801 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86802 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "WriteCount"); |
| 86803 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86804 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12116LU), |
| 86805 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86806 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86807 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "WriteCount"), |
| 86808 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86809 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86810 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86811 | return retVal; |
| 86812 | } |
| 86813 | |
| 86814 | static UA_StatusCode function_namespace0_generated_641_finish(UA_Server *server, UA_UInt16* ns) { |
| 86815 | return UA_Server_addNode_finish(server, |
| 86816 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12116LU) |
| 86817 | ); |
| 86818 | } |
| 86819 | |
| 86820 | /* HistoryReadCount - ns=0;i=12115 */ |
| 86821 | |
| 86822 | static UA_StatusCode function_namespace0_generated_642_begin(UA_Server *server, UA_UInt16* ns) { |
| 86823 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86824 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86825 | attr.minimumSamplingInterval = 0.000000; |
| 86826 | attr.userAccessLevel = 1; |
| 86827 | attr.accessLevel = 1; |
| 86828 | /* Value rank inherited */ |
| 86829 | attr.valueRank = -2; |
| 86830 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86831 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryReadCount"); |
| 86832 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86833 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12115LU), |
| 86834 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86835 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86836 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryReadCount"), |
| 86837 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86838 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86839 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86840 | return retVal; |
| 86841 | } |
| 86842 | |
| 86843 | static UA_StatusCode function_namespace0_generated_642_finish(UA_Server *server, UA_UInt16* ns) { |
| 86844 | return UA_Server_addNode_finish(server, |
| 86845 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12115LU) |
| 86846 | ); |
| 86847 | } |
| 86848 | |
| 86849 | /* ReadCount - ns=0;i=12114 */ |
| 86850 | |
| 86851 | static UA_StatusCode function_namespace0_generated_643_begin(UA_Server *server, UA_UInt16* ns) { |
| 86852 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86853 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86854 | attr.minimumSamplingInterval = 0.000000; |
| 86855 | attr.userAccessLevel = 1; |
| 86856 | attr.accessLevel = 1; |
| 86857 | /* Value rank inherited */ |
| 86858 | attr.valueRank = -2; |
| 86859 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86860 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReadCount"); |
| 86861 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86862 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12114LU), |
| 86863 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86864 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86865 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReadCount"), |
| 86866 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86867 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86868 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86869 | return retVal; |
| 86870 | } |
| 86871 | |
| 86872 | static UA_StatusCode function_namespace0_generated_643_finish(UA_Server *server, UA_UInt16* ns) { |
| 86873 | return UA_Server_addNode_finish(server, |
| 86874 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12114LU) |
| 86875 | ); |
| 86876 | } |
| 86877 | |
| 86878 | /* UnauthorizedRequestCount - ns=0;i=12113 */ |
| 86879 | |
| 86880 | static UA_StatusCode function_namespace0_generated_644_begin(UA_Server *server, UA_UInt16* ns) { |
| 86881 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86882 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86883 | attr.minimumSamplingInterval = 0.000000; |
| 86884 | attr.userAccessLevel = 1; |
| 86885 | attr.accessLevel = 1; |
| 86886 | /* Value rank inherited */ |
| 86887 | attr.valueRank = -2; |
| 86888 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 86889 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UnauthorizedRequestCount"); |
| 86890 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86891 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12113LU), |
| 86892 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86893 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86894 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UnauthorizedRequestCount"), |
| 86895 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86896 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86897 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86898 | return retVal; |
| 86899 | } |
| 86900 | |
| 86901 | static UA_StatusCode function_namespace0_generated_644_finish(UA_Server *server, UA_UInt16* ns) { |
| 86902 | return UA_Server_addNode_finish(server, |
| 86903 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12113LU) |
| 86904 | ); |
| 86905 | } |
| 86906 | |
| 86907 | /* TotalRequestCount - ns=0;i=12112 */ |
| 86908 | |
| 86909 | static UA_StatusCode function_namespace0_generated_645_begin(UA_Server *server, UA_UInt16* ns) { |
| 86910 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86911 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86912 | attr.minimumSamplingInterval = 0.000000; |
| 86913 | attr.userAccessLevel = 1; |
| 86914 | attr.accessLevel = 1; |
| 86915 | /* Value rank inherited */ |
| 86916 | attr.valueRank = -2; |
| 86917 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 871LU); |
| 86918 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "TotalRequestCount"); |
| 86919 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86920 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12112LU), |
| 86921 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86922 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86923 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "TotalRequestCount"), |
| 86924 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86925 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86926 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86927 | return retVal; |
| 86928 | } |
| 86929 | |
| 86930 | static UA_StatusCode function_namespace0_generated_645_finish(UA_Server *server, UA_UInt16* ns) { |
| 86931 | return UA_Server_addNode_finish(server, |
| 86932 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12112LU) |
| 86933 | ); |
| 86934 | } |
| 86935 | |
| 86936 | /* CurrentPublishRequestsInQueue - ns=0;i=12111 */ |
| 86937 | |
| 86938 | static UA_StatusCode function_namespace0_generated_646_begin(UA_Server *server, UA_UInt16* ns) { |
| 86939 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86940 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86941 | attr.minimumSamplingInterval = 0.000000; |
| 86942 | attr.userAccessLevel = 1; |
| 86943 | attr.accessLevel = 1; |
| 86944 | /* Value rank inherited */ |
| 86945 | attr.valueRank = -2; |
| 86946 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 86947 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentPublishRequestsInQueue"); |
| 86948 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86949 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12111LU), |
| 86950 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86951 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86952 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentPublishRequestsInQueue"), |
| 86953 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86954 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86955 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86956 | return retVal; |
| 86957 | } |
| 86958 | |
| 86959 | static UA_StatusCode function_namespace0_generated_646_finish(UA_Server *server, UA_UInt16* ns) { |
| 86960 | return UA_Server_addNode_finish(server, |
| 86961 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12111LU) |
| 86962 | ); |
| 86963 | } |
| 86964 | |
| 86965 | /* CurrentMonitoredItemsCount - ns=0;i=12110 */ |
| 86966 | |
| 86967 | static UA_StatusCode function_namespace0_generated_647_begin(UA_Server *server, UA_UInt16* ns) { |
| 86968 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86969 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86970 | attr.minimumSamplingInterval = 0.000000; |
| 86971 | attr.userAccessLevel = 1; |
| 86972 | attr.accessLevel = 1; |
| 86973 | /* Value rank inherited */ |
| 86974 | attr.valueRank = -2; |
| 86975 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 86976 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentMonitoredItemsCount"); |
| 86977 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 86978 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12110LU), |
| 86979 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 86980 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 86981 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentMonitoredItemsCount"), |
| 86982 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 86983 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 86984 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 86985 | return retVal; |
| 86986 | } |
| 86987 | |
| 86988 | static UA_StatusCode function_namespace0_generated_647_finish(UA_Server *server, UA_UInt16* ns) { |
| 86989 | return UA_Server_addNode_finish(server, |
| 86990 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12110LU) |
| 86991 | ); |
| 86992 | } |
| 86993 | |
| 86994 | /* CurrentSubscriptionsCount - ns=0;i=12109 */ |
| 86995 | |
| 86996 | static UA_StatusCode function_namespace0_generated_648_begin(UA_Server *server, UA_UInt16* ns) { |
| 86997 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 86998 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 86999 | attr.minimumSamplingInterval = 0.000000; |
| 87000 | attr.userAccessLevel = 1; |
| 87001 | attr.accessLevel = 1; |
| 87002 | /* Value rank inherited */ |
| 87003 | attr.valueRank = -2; |
| 87004 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87005 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentSubscriptionsCount"); |
| 87006 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87007 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12109LU), |
| 87008 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87009 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87010 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentSubscriptionsCount"), |
| 87011 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87012 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87013 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87014 | return retVal; |
| 87015 | } |
| 87016 | |
| 87017 | static UA_StatusCode function_namespace0_generated_648_finish(UA_Server *server, UA_UInt16* ns) { |
| 87018 | return UA_Server_addNode_finish(server, |
| 87019 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12109LU) |
| 87020 | ); |
| 87021 | } |
| 87022 | |
| 87023 | /* ClientLastContactTime - ns=0;i=12108 */ |
| 87024 | |
| 87025 | static UA_StatusCode function_namespace0_generated_649_begin(UA_Server *server, UA_UInt16* ns) { |
| 87026 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87027 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87028 | attr.minimumSamplingInterval = 0.000000; |
| 87029 | attr.userAccessLevel = 1; |
| 87030 | attr.accessLevel = 1; |
| 87031 | /* Value rank inherited */ |
| 87032 | attr.valueRank = -2; |
| 87033 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 87034 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientLastContactTime"); |
| 87035 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87036 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12108LU), |
| 87037 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87038 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87039 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientLastContactTime"), |
| 87040 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87041 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87042 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87043 | return retVal; |
| 87044 | } |
| 87045 | |
| 87046 | static UA_StatusCode function_namespace0_generated_649_finish(UA_Server *server, UA_UInt16* ns) { |
| 87047 | return UA_Server_addNode_finish(server, |
| 87048 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12108LU) |
| 87049 | ); |
| 87050 | } |
| 87051 | |
| 87052 | /* ClientConnectionTime - ns=0;i=12107 */ |
| 87053 | |
| 87054 | static UA_StatusCode function_namespace0_generated_650_begin(UA_Server *server, UA_UInt16* ns) { |
| 87055 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87056 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87057 | attr.minimumSamplingInterval = 0.000000; |
| 87058 | attr.userAccessLevel = 1; |
| 87059 | attr.accessLevel = 1; |
| 87060 | /* Value rank inherited */ |
| 87061 | attr.valueRank = -2; |
| 87062 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 87063 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientConnectionTime"); |
| 87064 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87065 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12107LU), |
| 87066 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87067 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87068 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientConnectionTime"), |
| 87069 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87070 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87071 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87072 | return retVal; |
| 87073 | } |
| 87074 | |
| 87075 | static UA_StatusCode function_namespace0_generated_650_finish(UA_Server *server, UA_UInt16* ns) { |
| 87076 | return UA_Server_addNode_finish(server, |
| 87077 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12107LU) |
| 87078 | ); |
| 87079 | } |
| 87080 | |
| 87081 | /* MaxResponseMessageSize - ns=0;i=12106 */ |
| 87082 | |
| 87083 | static UA_StatusCode function_namespace0_generated_651_begin(UA_Server *server, UA_UInt16* ns) { |
| 87084 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87085 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87086 | attr.minimumSamplingInterval = 0.000000; |
| 87087 | attr.userAccessLevel = 1; |
| 87088 | attr.accessLevel = 1; |
| 87089 | /* Value rank inherited */ |
| 87090 | attr.valueRank = -2; |
| 87091 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87092 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxResponseMessageSize"); |
| 87093 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87094 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12106LU), |
| 87095 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87096 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87097 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxResponseMessageSize"), |
| 87098 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87099 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87100 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87101 | return retVal; |
| 87102 | } |
| 87103 | |
| 87104 | static UA_StatusCode function_namespace0_generated_651_finish(UA_Server *server, UA_UInt16* ns) { |
| 87105 | return UA_Server_addNode_finish(server, |
| 87106 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12106LU) |
| 87107 | ); |
| 87108 | } |
| 87109 | |
| 87110 | /* ActualSessionTimeout - ns=0;i=12105 */ |
| 87111 | |
| 87112 | static UA_StatusCode function_namespace0_generated_652_begin(UA_Server *server, UA_UInt16* ns) { |
| 87113 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87114 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87115 | attr.minimumSamplingInterval = 0.000000; |
| 87116 | attr.userAccessLevel = 1; |
| 87117 | attr.accessLevel = 1; |
| 87118 | /* Value rank inherited */ |
| 87119 | attr.valueRank = -2; |
| 87120 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 87121 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ActualSessionTimeout"); |
| 87122 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87123 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12105LU), |
| 87124 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87125 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87126 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ActualSessionTimeout"), |
| 87127 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87128 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87129 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87130 | return retVal; |
| 87131 | } |
| 87132 | |
| 87133 | static UA_StatusCode function_namespace0_generated_652_finish(UA_Server *server, UA_UInt16* ns) { |
| 87134 | return UA_Server_addNode_finish(server, |
| 87135 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12105LU) |
| 87136 | ); |
| 87137 | } |
| 87138 | |
| 87139 | /* LocaleIds - ns=0;i=12104 */ |
| 87140 | |
| 87141 | static UA_StatusCode function_namespace0_generated_653_begin(UA_Server *server, UA_UInt16* ns) { |
| 87142 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87143 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87144 | attr.minimumSamplingInterval = 0.000000; |
| 87145 | attr.userAccessLevel = 1; |
| 87146 | attr.accessLevel = 1; |
| 87147 | attr.valueRank = 1; |
| 87148 | attr.arrayDimensionsSize = 1; |
| 87149 | UA_UInt32 arrayDimensions[1]; |
| 87150 | arrayDimensions[0] = 0; |
| 87151 | attr.arrayDimensions = &arrayDimensions[0]; |
| 87152 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU); |
| 87153 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleIds"); |
| 87154 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87155 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12104LU), |
| 87156 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87157 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87158 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleIds"), |
| 87159 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87160 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87161 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87162 | return retVal; |
| 87163 | } |
| 87164 | |
| 87165 | static UA_StatusCode function_namespace0_generated_653_finish(UA_Server *server, UA_UInt16* ns) { |
| 87166 | return UA_Server_addNode_finish(server, |
| 87167 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12104LU) |
| 87168 | ); |
| 87169 | } |
| 87170 | |
| 87171 | /* EndpointUrl - ns=0;i=12103 */ |
| 87172 | |
| 87173 | static UA_StatusCode function_namespace0_generated_654_begin(UA_Server *server, UA_UInt16* ns) { |
| 87174 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87175 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87176 | attr.minimumSamplingInterval = 0.000000; |
| 87177 | attr.userAccessLevel = 1; |
| 87178 | attr.accessLevel = 1; |
| 87179 | /* Value rank inherited */ |
| 87180 | attr.valueRank = -2; |
| 87181 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 87182 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EndpointUrl"); |
| 87183 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87184 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12103LU), |
| 87185 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87186 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87187 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EndpointUrl"), |
| 87188 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87189 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87190 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87191 | return retVal; |
| 87192 | } |
| 87193 | |
| 87194 | static UA_StatusCode function_namespace0_generated_654_finish(UA_Server *server, UA_UInt16* ns) { |
| 87195 | return UA_Server_addNode_finish(server, |
| 87196 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12103LU) |
| 87197 | ); |
| 87198 | } |
| 87199 | |
| 87200 | /* ServerUri - ns=0;i=12102 */ |
| 87201 | |
| 87202 | static UA_StatusCode function_namespace0_generated_655_begin(UA_Server *server, UA_UInt16* ns) { |
| 87203 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87204 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87205 | attr.minimumSamplingInterval = 0.000000; |
| 87206 | attr.userAccessLevel = 1; |
| 87207 | attr.accessLevel = 1; |
| 87208 | /* Value rank inherited */ |
| 87209 | attr.valueRank = -2; |
| 87210 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 87211 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerUri"); |
| 87212 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87213 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12102LU), |
| 87214 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87215 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87216 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerUri"), |
| 87217 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87218 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87219 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87220 | return retVal; |
| 87221 | } |
| 87222 | |
| 87223 | static UA_StatusCode function_namespace0_generated_655_finish(UA_Server *server, UA_UInt16* ns) { |
| 87224 | return UA_Server_addNode_finish(server, |
| 87225 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12102LU) |
| 87226 | ); |
| 87227 | } |
| 87228 | |
| 87229 | /* ClientDescription - ns=0;i=12101 */ |
| 87230 | |
| 87231 | static UA_StatusCode function_namespace0_generated_656_begin(UA_Server *server, UA_UInt16* ns) { |
| 87232 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87233 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87234 | attr.minimumSamplingInterval = 0.000000; |
| 87235 | attr.userAccessLevel = 1; |
| 87236 | attr.accessLevel = 1; |
| 87237 | /* Value rank inherited */ |
| 87238 | attr.valueRank = -2; |
| 87239 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 308LU); |
| 87240 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ClientDescription"); |
| 87241 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87242 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12101LU), |
| 87243 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87244 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87245 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ClientDescription"), |
| 87246 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87247 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87248 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87249 | return retVal; |
| 87250 | } |
| 87251 | |
| 87252 | static UA_StatusCode function_namespace0_generated_656_finish(UA_Server *server, UA_UInt16* ns) { |
| 87253 | return UA_Server_addNode_finish(server, |
| 87254 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12101LU) |
| 87255 | ); |
| 87256 | } |
| 87257 | |
| 87258 | /* SessionName - ns=0;i=12100 */ |
| 87259 | |
| 87260 | static UA_StatusCode function_namespace0_generated_657_begin(UA_Server *server, UA_UInt16* ns) { |
| 87261 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87262 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87263 | attr.minimumSamplingInterval = 0.000000; |
| 87264 | attr.userAccessLevel = 1; |
| 87265 | attr.accessLevel = 1; |
| 87266 | /* Value rank inherited */ |
| 87267 | attr.valueRank = -2; |
| 87268 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 87269 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionName"); |
| 87270 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87271 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12100LU), |
| 87272 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87273 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87274 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionName"), |
| 87275 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87276 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87277 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87278 | return retVal; |
| 87279 | } |
| 87280 | |
| 87281 | static UA_StatusCode function_namespace0_generated_657_finish(UA_Server *server, UA_UInt16* ns) { |
| 87282 | return UA_Server_addNode_finish(server, |
| 87283 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12100LU) |
| 87284 | ); |
| 87285 | } |
| 87286 | |
| 87287 | /* SessionId - ns=0;i=12099 */ |
| 87288 | |
| 87289 | static UA_StatusCode function_namespace0_generated_658_begin(UA_Server *server, UA_UInt16* ns) { |
| 87290 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87291 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87292 | attr.minimumSamplingInterval = 0.000000; |
| 87293 | attr.userAccessLevel = 1; |
| 87294 | attr.accessLevel = 1; |
| 87295 | /* Value rank inherited */ |
| 87296 | attr.valueRank = -2; |
| 87297 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 87298 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionId"); |
| 87299 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87300 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12099LU), |
| 87301 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), |
| 87302 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87303 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionId"), |
| 87304 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87305 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87306 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87307 | return retVal; |
| 87308 | } |
| 87309 | |
| 87310 | static UA_StatusCode function_namespace0_generated_658_finish(UA_Server *server, UA_UInt16* ns) { |
| 87311 | return UA_Server_addNode_finish(server, |
| 87312 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12099LU) |
| 87313 | ); |
| 87314 | } |
| 87315 | |
| 87316 | /* InterfaceTypes - ns=0;i=17708 */ |
| 87317 | |
| 87318 | static UA_StatusCode function_namespace0_generated_659_begin(UA_Server *server, UA_UInt16* ns) { |
| 87319 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87320 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 87321 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InterfaceTypes"); |
| 87322 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 87323 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17708LU), |
| 87324 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 86LU), |
| 87325 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU), |
| 87326 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InterfaceTypes"), |
| 87327 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU), |
| 87328 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 87329 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87330 | return retVal; |
| 87331 | } |
| 87332 | |
| 87333 | static UA_StatusCode function_namespace0_generated_659_finish(UA_Server *server, UA_UInt16* ns) { |
| 87334 | return UA_Server_addNode_finish(server, |
| 87335 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17708LU) |
| 87336 | ); |
| 87337 | } |
| 87338 | |
| 87339 | /* BaseInterfaceType - ns=0;i=17602 */ |
| 87340 | |
| 87341 | static UA_StatusCode function_namespace0_generated_660_begin(UA_Server *server, UA_UInt16* ns) { |
| 87342 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87343 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 87344 | attr.isAbstract = true; |
| 87345 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BaseInterfaceType"); |
| 87346 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 87347 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17602LU), |
| 87348 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 87349 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 87350 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BaseInterfaceType"), |
| 87351 | typeDefinition: UA_NODEID_NULL, |
| 87352 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 87353 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87354 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17602LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17708LU), false); |
| 87355 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87356 | return retVal; |
| 87357 | } |
| 87358 | |
| 87359 | static UA_StatusCode function_namespace0_generated_660_finish(UA_Server *server, UA_UInt16* ns) { |
| 87360 | return UA_Server_addNode_finish(server, |
| 87361 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17602LU) |
| 87362 | ); |
| 87363 | } |
| 87364 | |
| 87365 | /* BuildInfoType - ns=0;i=3051 */ |
| 87366 | |
| 87367 | static UA_StatusCode function_namespace0_generated_661_begin(UA_Server *server, UA_UInt16* ns) { |
| 87368 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87369 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 87370 | /* Value rank inherited */ |
| 87371 | attr.valueRank = -2; |
| 87372 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU); |
| 87373 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildInfoType"); |
| 87374 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 87375 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3051LU), |
| 87376 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87377 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 87378 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildInfoType"), |
| 87379 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 87380 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 87381 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87382 | return retVal; |
| 87383 | } |
| 87384 | |
| 87385 | static UA_StatusCode function_namespace0_generated_661_finish(UA_Server *server, UA_UInt16* ns) { |
| 87386 | return UA_Server_addNode_finish(server, |
| 87387 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3051LU) |
| 87388 | ); |
| 87389 | } |
| 87390 | |
| 87391 | /* ServerStatusType - ns=0;i=2138 */ |
| 87392 | |
| 87393 | static UA_StatusCode function_namespace0_generated_662_begin(UA_Server *server, UA_UInt16* ns) { |
| 87394 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87395 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 87396 | /* Value rank inherited */ |
| 87397 | attr.valueRank = -2; |
| 87398 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU); |
| 87399 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerStatusType"); |
| 87400 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 87401 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2138LU), |
| 87402 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87403 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 87404 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerStatusType"), |
| 87405 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 87406 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 87407 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87408 | return retVal; |
| 87409 | } |
| 87410 | |
| 87411 | static UA_StatusCode function_namespace0_generated_662_finish(UA_Server *server, UA_UInt16* ns) { |
| 87412 | return UA_Server_addNode_finish(server, |
| 87413 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2138LU) |
| 87414 | ); |
| 87415 | } |
| 87416 | |
| 87417 | /* OperationLimitsType - ns=0;i=11564 */ |
| 87418 | |
| 87419 | static UA_StatusCode function_namespace0_generated_663_begin(UA_Server *server, UA_UInt16* ns) { |
| 87420 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87421 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 87422 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OperationLimitsType"); |
| 87423 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 87424 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 87425 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU), |
| 87426 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 87427 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OperationLimitsType"), |
| 87428 | typeDefinition: UA_NODEID_NULL, |
| 87429 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 87430 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87431 | return retVal; |
| 87432 | } |
| 87433 | |
| 87434 | static UA_StatusCode function_namespace0_generated_663_finish(UA_Server *server, UA_UInt16* ns) { |
| 87435 | return UA_Server_addNode_finish(server, |
| 87436 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU) |
| 87437 | ); |
| 87438 | } |
| 87439 | |
| 87440 | /* MaxMonitoredItemsPerCall - ns=0;i=11574 */ |
| 87441 | |
| 87442 | static UA_StatusCode function_namespace0_generated_664_begin(UA_Server *server, UA_UInt16* ns) { |
| 87443 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87444 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87445 | attr.minimumSamplingInterval = 0.000000; |
| 87446 | attr.userAccessLevel = 1; |
| 87447 | attr.accessLevel = 1; |
| 87448 | /* Value rank inherited */ |
| 87449 | attr.valueRank = -2; |
| 87450 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87451 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxMonitoredItemsPerCall"); |
| 87452 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87453 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11574LU), |
| 87454 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 87455 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 87456 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxMonitoredItemsPerCall"), |
| 87457 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 87458 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87459 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87460 | return retVal; |
| 87461 | } |
| 87462 | |
| 87463 | static UA_StatusCode function_namespace0_generated_664_finish(UA_Server *server, UA_UInt16* ns) { |
| 87464 | return UA_Server_addNode_finish(server, |
| 87465 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11574LU) |
| 87466 | ); |
| 87467 | } |
| 87468 | |
| 87469 | /* MaxNodesPerNodeManagement - ns=0;i=11573 */ |
| 87470 | |
| 87471 | static UA_StatusCode function_namespace0_generated_665_begin(UA_Server *server, UA_UInt16* ns) { |
| 87472 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87473 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87474 | attr.minimumSamplingInterval = 0.000000; |
| 87475 | attr.userAccessLevel = 1; |
| 87476 | attr.accessLevel = 1; |
| 87477 | /* Value rank inherited */ |
| 87478 | attr.valueRank = -2; |
| 87479 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87480 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerNodeManagement"); |
| 87481 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87482 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11573LU), |
| 87483 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 87484 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 87485 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerNodeManagement"), |
| 87486 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 87487 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87488 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87489 | return retVal; |
| 87490 | } |
| 87491 | |
| 87492 | static UA_StatusCode function_namespace0_generated_665_finish(UA_Server *server, UA_UInt16* ns) { |
| 87493 | return UA_Server_addNode_finish(server, |
| 87494 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11573LU) |
| 87495 | ); |
| 87496 | } |
| 87497 | |
| 87498 | /* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11572 */ |
| 87499 | |
| 87500 | static UA_StatusCode function_namespace0_generated_666_begin(UA_Server *server, UA_UInt16* ns) { |
| 87501 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87502 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87503 | attr.minimumSamplingInterval = 0.000000; |
| 87504 | attr.userAccessLevel = 1; |
| 87505 | attr.accessLevel = 1; |
| 87506 | /* Value rank inherited */ |
| 87507 | attr.valueRank = -2; |
| 87508 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87509 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerTranslateBrowsePathsToNodeIds"); |
| 87510 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87511 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11572LU), |
| 87512 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 87513 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 87514 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerTranslateBrowsePathsToNodeIds"), |
| 87515 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 87516 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87517 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87518 | return retVal; |
| 87519 | } |
| 87520 | |
| 87521 | static UA_StatusCode function_namespace0_generated_666_finish(UA_Server *server, UA_UInt16* ns) { |
| 87522 | return UA_Server_addNode_finish(server, |
| 87523 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11572LU) |
| 87524 | ); |
| 87525 | } |
| 87526 | |
| 87527 | /* MaxNodesPerRegisterNodes - ns=0;i=11571 */ |
| 87528 | |
| 87529 | static UA_StatusCode function_namespace0_generated_667_begin(UA_Server *server, UA_UInt16* ns) { |
| 87530 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87531 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87532 | attr.minimumSamplingInterval = 0.000000; |
| 87533 | attr.userAccessLevel = 1; |
| 87534 | attr.accessLevel = 1; |
| 87535 | /* Value rank inherited */ |
| 87536 | attr.valueRank = -2; |
| 87537 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87538 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRegisterNodes"); |
| 87539 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87540 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11571LU), |
| 87541 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 87542 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 87543 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRegisterNodes"), |
| 87544 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 87545 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87546 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87547 | return retVal; |
| 87548 | } |
| 87549 | |
| 87550 | static UA_StatusCode function_namespace0_generated_667_finish(UA_Server *server, UA_UInt16* ns) { |
| 87551 | return UA_Server_addNode_finish(server, |
| 87552 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11571LU) |
| 87553 | ); |
| 87554 | } |
| 87555 | |
| 87556 | /* MaxNodesPerBrowse - ns=0;i=11570 */ |
| 87557 | |
| 87558 | static UA_StatusCode function_namespace0_generated_668_begin(UA_Server *server, UA_UInt16* ns) { |
| 87559 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87560 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87561 | attr.minimumSamplingInterval = 0.000000; |
| 87562 | attr.userAccessLevel = 1; |
| 87563 | attr.accessLevel = 1; |
| 87564 | /* Value rank inherited */ |
| 87565 | attr.valueRank = -2; |
| 87566 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87567 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerBrowse"); |
| 87568 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87569 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11570LU), |
| 87570 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 87571 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 87572 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerBrowse"), |
| 87573 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 87574 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87575 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87576 | return retVal; |
| 87577 | } |
| 87578 | |
| 87579 | static UA_StatusCode function_namespace0_generated_668_finish(UA_Server *server, UA_UInt16* ns) { |
| 87580 | return UA_Server_addNode_finish(server, |
| 87581 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11570LU) |
| 87582 | ); |
| 87583 | } |
| 87584 | |
| 87585 | /* MaxNodesPerMethodCall - ns=0;i=11569 */ |
| 87586 | |
| 87587 | static UA_StatusCode function_namespace0_generated_669_begin(UA_Server *server, UA_UInt16* ns) { |
| 87588 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87589 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87590 | attr.minimumSamplingInterval = 0.000000; |
| 87591 | attr.userAccessLevel = 1; |
| 87592 | attr.accessLevel = 1; |
| 87593 | /* Value rank inherited */ |
| 87594 | attr.valueRank = -2; |
| 87595 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87596 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerMethodCall"); |
| 87597 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87598 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11569LU), |
| 87599 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 87600 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 87601 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerMethodCall"), |
| 87602 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 87603 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87604 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87605 | return retVal; |
| 87606 | } |
| 87607 | |
| 87608 | static UA_StatusCode function_namespace0_generated_669_finish(UA_Server *server, UA_UInt16* ns) { |
| 87609 | return UA_Server_addNode_finish(server, |
| 87610 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11569LU) |
| 87611 | ); |
| 87612 | } |
| 87613 | |
| 87614 | /* MaxNodesPerWrite - ns=0;i=11567 */ |
| 87615 | |
| 87616 | static UA_StatusCode function_namespace0_generated_670_begin(UA_Server *server, UA_UInt16* ns) { |
| 87617 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87618 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87619 | attr.minimumSamplingInterval = 0.000000; |
| 87620 | attr.userAccessLevel = 1; |
| 87621 | attr.accessLevel = 1; |
| 87622 | /* Value rank inherited */ |
| 87623 | attr.valueRank = -2; |
| 87624 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87625 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerWrite"); |
| 87626 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87627 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11567LU), |
| 87628 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 87629 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 87630 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerWrite"), |
| 87631 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 87632 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87633 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87634 | return retVal; |
| 87635 | } |
| 87636 | |
| 87637 | static UA_StatusCode function_namespace0_generated_670_finish(UA_Server *server, UA_UInt16* ns) { |
| 87638 | return UA_Server_addNode_finish(server, |
| 87639 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11567LU) |
| 87640 | ); |
| 87641 | } |
| 87642 | |
| 87643 | /* MaxNodesPerRead - ns=0;i=11565 */ |
| 87644 | |
| 87645 | static UA_StatusCode function_namespace0_generated_671_begin(UA_Server *server, UA_UInt16* ns) { |
| 87646 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87647 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87648 | attr.minimumSamplingInterval = 0.000000; |
| 87649 | attr.userAccessLevel = 1; |
| 87650 | attr.accessLevel = 1; |
| 87651 | /* Value rank inherited */ |
| 87652 | attr.valueRank = -2; |
| 87653 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87654 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRead"); |
| 87655 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87656 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11565LU), |
| 87657 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 87658 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 87659 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRead"), |
| 87660 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 87661 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87662 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87663 | return retVal; |
| 87664 | } |
| 87665 | |
| 87666 | static UA_StatusCode function_namespace0_generated_671_finish(UA_Server *server, UA_UInt16* ns) { |
| 87667 | return UA_Server_addNode_finish(server, |
| 87668 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11565LU) |
| 87669 | ); |
| 87670 | } |
| 87671 | |
| 87672 | /* ServerRedundancyType - ns=0;i=2034 */ |
| 87673 | |
| 87674 | static UA_StatusCode function_namespace0_generated_672_begin(UA_Server *server, UA_UInt16* ns) { |
| 87675 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87676 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 87677 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerRedundancyType"); |
| 87678 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 87679 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU), |
| 87680 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 87681 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 87682 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerRedundancyType"), |
| 87683 | typeDefinition: UA_NODEID_NULL, |
| 87684 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 87685 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87686 | return retVal; |
| 87687 | } |
| 87688 | |
| 87689 | static UA_StatusCode function_namespace0_generated_672_finish(UA_Server *server, UA_UInt16* ns) { |
| 87690 | return UA_Server_addNode_finish(server, |
| 87691 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU) |
| 87692 | ); |
| 87693 | } |
| 87694 | |
| 87695 | /* RedundancySupport - ns=0;i=2035 */ |
| 87696 | |
| 87697 | static UA_StatusCode function_namespace0_generated_673_begin(UA_Server *server, UA_UInt16* ns) { |
| 87698 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87699 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87700 | attr.minimumSamplingInterval = 0.000000; |
| 87701 | attr.userAccessLevel = 1; |
| 87702 | attr.accessLevel = 1; |
| 87703 | /* Value rank inherited */ |
| 87704 | attr.valueRank = -2; |
| 87705 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU); |
| 87706 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RedundancySupport"); |
| 87707 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87708 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2035LU), |
| 87709 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU), |
| 87710 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 87711 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RedundancySupport"), |
| 87712 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 87713 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87714 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87715 | return retVal; |
| 87716 | } |
| 87717 | |
| 87718 | static UA_StatusCode function_namespace0_generated_673_finish(UA_Server *server, UA_UInt16* ns) { |
| 87719 | return UA_Server_addNode_finish(server, |
| 87720 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2035LU) |
| 87721 | ); |
| 87722 | } |
| 87723 | |
| 87724 | /* VendorServerInfoType - ns=0;i=2033 */ |
| 87725 | |
| 87726 | static UA_StatusCode function_namespace0_generated_674_begin(UA_Server *server, UA_UInt16* ns) { |
| 87727 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87728 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 87729 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "VendorServerInfoType"); |
| 87730 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 87731 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU), |
| 87732 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 87733 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 87734 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "VendorServerInfoType"), |
| 87735 | typeDefinition: UA_NODEID_NULL, |
| 87736 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 87737 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87738 | return retVal; |
| 87739 | } |
| 87740 | |
| 87741 | static UA_StatusCode function_namespace0_generated_674_finish(UA_Server *server, UA_UInt16* ns) { |
| 87742 | return UA_Server_addNode_finish(server, |
| 87743 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU) |
| 87744 | ); |
| 87745 | } |
| 87746 | |
| 87747 | /* ServerDiagnosticsType - ns=0;i=2020 */ |
| 87748 | |
| 87749 | static UA_StatusCode function_namespace0_generated_675_begin(UA_Server *server, UA_UInt16* ns) { |
| 87750 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87751 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 87752 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerDiagnosticsType"); |
| 87753 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 87754 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU), |
| 87755 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 87756 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 87757 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerDiagnosticsType"), |
| 87758 | typeDefinition: UA_NODEID_NULL, |
| 87759 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 87760 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87761 | return retVal; |
| 87762 | } |
| 87763 | |
| 87764 | static UA_StatusCode function_namespace0_generated_675_finish(UA_Server *server, UA_UInt16* ns) { |
| 87765 | return UA_Server_addNode_finish(server, |
| 87766 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU) |
| 87767 | ); |
| 87768 | } |
| 87769 | |
| 87770 | /* SessionsDiagnosticsSummary - ns=0;i=2744 */ |
| 87771 | |
| 87772 | static UA_StatusCode function_namespace0_generated_676_begin(UA_Server *server, UA_UInt16* ns) { |
| 87773 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87774 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 87775 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionsDiagnosticsSummary"); |
| 87776 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 87777 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2744LU), |
| 87778 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU), |
| 87779 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87780 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionsDiagnosticsSummary"), |
| 87781 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2026LU), |
| 87782 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 87783 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87784 | return retVal; |
| 87785 | } |
| 87786 | |
| 87787 | static UA_StatusCode function_namespace0_generated_676_finish(UA_Server *server, UA_UInt16* ns) { |
| 87788 | return UA_Server_addNode_finish(server, |
| 87789 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2744LU) |
| 87790 | ); |
| 87791 | } |
| 87792 | |
| 87793 | /* SessionSecurityDiagnosticsArray - ns=0;i=3130 */ |
| 87794 | |
| 87795 | static UA_StatusCode function_namespace0_generated_677_begin(UA_Server *server, UA_UInt16* ns) { |
| 87796 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87797 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87798 | attr.minimumSamplingInterval = 0.000000; |
| 87799 | attr.userAccessLevel = 1; |
| 87800 | attr.accessLevel = 1; |
| 87801 | attr.valueRank = 1; |
| 87802 | attr.arrayDimensionsSize = 1; |
| 87803 | UA_UInt32 arrayDimensions[1]; |
| 87804 | arrayDimensions[0] = 0; |
| 87805 | attr.arrayDimensions = &arrayDimensions[0]; |
| 87806 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 868LU); |
| 87807 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionSecurityDiagnosticsArray"); |
| 87808 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87809 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3130LU), |
| 87810 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2744LU), |
| 87811 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87812 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionSecurityDiagnosticsArray"), |
| 87813 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2243LU), |
| 87814 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87815 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87816 | return retVal; |
| 87817 | } |
| 87818 | |
| 87819 | static UA_StatusCode function_namespace0_generated_677_finish(UA_Server *server, UA_UInt16* ns) { |
| 87820 | return UA_Server_addNode_finish(server, |
| 87821 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3130LU) |
| 87822 | ); |
| 87823 | } |
| 87824 | |
| 87825 | /* SessionDiagnosticsArray - ns=0;i=3129 */ |
| 87826 | |
| 87827 | static UA_StatusCode function_namespace0_generated_678_begin(UA_Server *server, UA_UInt16* ns) { |
| 87828 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87829 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87830 | attr.minimumSamplingInterval = 0.000000; |
| 87831 | attr.userAccessLevel = 1; |
| 87832 | attr.accessLevel = 1; |
| 87833 | attr.valueRank = 1; |
| 87834 | attr.arrayDimensionsSize = 1; |
| 87835 | UA_UInt32 arrayDimensions[1]; |
| 87836 | arrayDimensions[0] = 0; |
| 87837 | attr.arrayDimensions = &arrayDimensions[0]; |
| 87838 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 865LU); |
| 87839 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionDiagnosticsArray"); |
| 87840 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87841 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3129LU), |
| 87842 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2744LU), |
| 87843 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87844 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionDiagnosticsArray"), |
| 87845 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2196LU), |
| 87846 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87847 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87848 | return retVal; |
| 87849 | } |
| 87850 | |
| 87851 | static UA_StatusCode function_namespace0_generated_678_finish(UA_Server *server, UA_UInt16* ns) { |
| 87852 | return UA_Server_addNode_finish(server, |
| 87853 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3129LU) |
| 87854 | ); |
| 87855 | } |
| 87856 | |
| 87857 | /* EnabledFlag - ns=0;i=2025 */ |
| 87858 | |
| 87859 | static UA_StatusCode function_namespace0_generated_679_begin(UA_Server *server, UA_UInt16* ns) { |
| 87860 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87861 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87862 | attr.minimumSamplingInterval = 0.000000; |
| 87863 | attr.userAccessLevel = 1; |
| 87864 | attr.accessLevel = 3; |
| 87865 | /* Value rank inherited */ |
| 87866 | attr.valueRank = -2; |
| 87867 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 87868 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnabledFlag"); |
| 87869 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87870 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2025LU), |
| 87871 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU), |
| 87872 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 87873 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnabledFlag"), |
| 87874 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 87875 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87876 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87877 | return retVal; |
| 87878 | } |
| 87879 | |
| 87880 | static UA_StatusCode function_namespace0_generated_679_finish(UA_Server *server, UA_UInt16* ns) { |
| 87881 | return UA_Server_addNode_finish(server, |
| 87882 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2025LU) |
| 87883 | ); |
| 87884 | } |
| 87885 | |
| 87886 | /* SubscriptionDiagnosticsArray - ns=0;i=2023 */ |
| 87887 | |
| 87888 | static UA_StatusCode function_namespace0_generated_680_begin(UA_Server *server, UA_UInt16* ns) { |
| 87889 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87890 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87891 | attr.minimumSamplingInterval = 0.000000; |
| 87892 | attr.userAccessLevel = 1; |
| 87893 | attr.accessLevel = 1; |
| 87894 | attr.valueRank = 1; |
| 87895 | attr.arrayDimensionsSize = 1; |
| 87896 | UA_UInt32 arrayDimensions[1]; |
| 87897 | arrayDimensions[0] = 0; |
| 87898 | attr.arrayDimensions = &arrayDimensions[0]; |
| 87899 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 874LU); |
| 87900 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscriptionDiagnosticsArray"); |
| 87901 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87902 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2023LU), |
| 87903 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU), |
| 87904 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87905 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscriptionDiagnosticsArray"), |
| 87906 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2171LU), |
| 87907 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87908 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87909 | return retVal; |
| 87910 | } |
| 87911 | |
| 87912 | static UA_StatusCode function_namespace0_generated_680_finish(UA_Server *server, UA_UInt16* ns) { |
| 87913 | return UA_Server_addNode_finish(server, |
| 87914 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2023LU) |
| 87915 | ); |
| 87916 | } |
| 87917 | |
| 87918 | /* SamplingIntervalDiagnosticsArray - ns=0;i=2022 */ |
| 87919 | |
| 87920 | static UA_StatusCode function_namespace0_generated_681_begin(UA_Server *server, UA_UInt16* ns) { |
| 87921 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87922 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87923 | attr.minimumSamplingInterval = 0.000000; |
| 87924 | attr.userAccessLevel = 1; |
| 87925 | attr.accessLevel = 1; |
| 87926 | attr.valueRank = 1; |
| 87927 | attr.arrayDimensionsSize = 1; |
| 87928 | UA_UInt32 arrayDimensions[1]; |
| 87929 | arrayDimensions[0] = 0; |
| 87930 | attr.arrayDimensions = &arrayDimensions[0]; |
| 87931 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 856LU); |
| 87932 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SamplingIntervalDiagnosticsArray"); |
| 87933 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87934 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2022LU), |
| 87935 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU), |
| 87936 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87937 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SamplingIntervalDiagnosticsArray"), |
| 87938 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2164LU), |
| 87939 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87940 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87941 | return retVal; |
| 87942 | } |
| 87943 | |
| 87944 | static UA_StatusCode function_namespace0_generated_681_finish(UA_Server *server, UA_UInt16* ns) { |
| 87945 | return UA_Server_addNode_finish(server, |
| 87946 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2022LU) |
| 87947 | ); |
| 87948 | } |
| 87949 | |
| 87950 | /* ServerDiagnosticsSummary - ns=0;i=2021 */ |
| 87951 | |
| 87952 | static UA_StatusCode function_namespace0_generated_682_begin(UA_Server *server, UA_UInt16* ns) { |
| 87953 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87954 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87955 | attr.minimumSamplingInterval = 0.000000; |
| 87956 | attr.userAccessLevel = 1; |
| 87957 | attr.accessLevel = 1; |
| 87958 | /* Value rank inherited */ |
| 87959 | attr.valueRank = -2; |
| 87960 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 859LU); |
| 87961 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerDiagnosticsSummary"); |
| 87962 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87963 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 87964 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU), |
| 87965 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87966 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerDiagnosticsSummary"), |
| 87967 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 87968 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87969 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87970 | return retVal; |
| 87971 | } |
| 87972 | |
| 87973 | static UA_StatusCode function_namespace0_generated_682_finish(UA_Server *server, UA_UInt16* ns) { |
| 87974 | return UA_Server_addNode_finish(server, |
| 87975 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU) |
| 87976 | ); |
| 87977 | } |
| 87978 | |
| 87979 | /* RejectedRequestsCount - ns=0;i=3128 */ |
| 87980 | |
| 87981 | static UA_StatusCode function_namespace0_generated_683_begin(UA_Server *server, UA_UInt16* ns) { |
| 87982 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 87983 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 87984 | attr.minimumSamplingInterval = 0.000000; |
| 87985 | attr.userAccessLevel = 1; |
| 87986 | attr.accessLevel = 1; |
| 87987 | /* Value rank inherited */ |
| 87988 | attr.valueRank = -2; |
| 87989 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 87990 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RejectedRequestsCount"); |
| 87991 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 87992 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3128LU), |
| 87993 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 87994 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 87995 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RejectedRequestsCount"), |
| 87996 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 87997 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 87998 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 87999 | return retVal; |
| 88000 | } |
| 88001 | |
| 88002 | static UA_StatusCode function_namespace0_generated_683_finish(UA_Server *server, UA_UInt16* ns) { |
| 88003 | return UA_Server_addNode_finish(server, |
| 88004 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3128LU) |
| 88005 | ); |
| 88006 | } |
| 88007 | |
| 88008 | /* SecurityRejectedRequestsCount - ns=0;i=3127 */ |
| 88009 | |
| 88010 | static UA_StatusCode function_namespace0_generated_684_begin(UA_Server *server, UA_UInt16* ns) { |
| 88011 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88012 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88013 | attr.minimumSamplingInterval = 0.000000; |
| 88014 | attr.userAccessLevel = 1; |
| 88015 | attr.accessLevel = 1; |
| 88016 | /* Value rank inherited */ |
| 88017 | attr.valueRank = -2; |
| 88018 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88019 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityRejectedRequestsCount"); |
| 88020 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88021 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3127LU), |
| 88022 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88023 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88024 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityRejectedRequestsCount"), |
| 88025 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88026 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88027 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88028 | return retVal; |
| 88029 | } |
| 88030 | |
| 88031 | static UA_StatusCode function_namespace0_generated_684_finish(UA_Server *server, UA_UInt16* ns) { |
| 88032 | return UA_Server_addNode_finish(server, |
| 88033 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3127LU) |
| 88034 | ); |
| 88035 | } |
| 88036 | |
| 88037 | /* CumulatedSubscriptionCount - ns=0;i=3126 */ |
| 88038 | |
| 88039 | static UA_StatusCode function_namespace0_generated_685_begin(UA_Server *server, UA_UInt16* ns) { |
| 88040 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88041 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88042 | attr.minimumSamplingInterval = 0.000000; |
| 88043 | attr.userAccessLevel = 1; |
| 88044 | attr.accessLevel = 1; |
| 88045 | /* Value rank inherited */ |
| 88046 | attr.valueRank = -2; |
| 88047 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88048 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CumulatedSubscriptionCount"); |
| 88049 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88050 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3126LU), |
| 88051 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88052 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88053 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CumulatedSubscriptionCount"), |
| 88054 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88055 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88056 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88057 | return retVal; |
| 88058 | } |
| 88059 | |
| 88060 | static UA_StatusCode function_namespace0_generated_685_finish(UA_Server *server, UA_UInt16* ns) { |
| 88061 | return UA_Server_addNode_finish(server, |
| 88062 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3126LU) |
| 88063 | ); |
| 88064 | } |
| 88065 | |
| 88066 | /* CurrentSubscriptionCount - ns=0;i=3125 */ |
| 88067 | |
| 88068 | static UA_StatusCode function_namespace0_generated_686_begin(UA_Server *server, UA_UInt16* ns) { |
| 88069 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88070 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88071 | attr.minimumSamplingInterval = 0.000000; |
| 88072 | attr.userAccessLevel = 1; |
| 88073 | attr.accessLevel = 1; |
| 88074 | /* Value rank inherited */ |
| 88075 | attr.valueRank = -2; |
| 88076 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88077 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentSubscriptionCount"); |
| 88078 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88079 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3125LU), |
| 88080 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88081 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88082 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentSubscriptionCount"), |
| 88083 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88084 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88085 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88086 | return retVal; |
| 88087 | } |
| 88088 | |
| 88089 | static UA_StatusCode function_namespace0_generated_686_finish(UA_Server *server, UA_UInt16* ns) { |
| 88090 | return UA_Server_addNode_finish(server, |
| 88091 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3125LU) |
| 88092 | ); |
| 88093 | } |
| 88094 | |
| 88095 | /* PublishingIntervalCount - ns=0;i=3124 */ |
| 88096 | |
| 88097 | static UA_StatusCode function_namespace0_generated_687_begin(UA_Server *server, UA_UInt16* ns) { |
| 88098 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88099 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88100 | attr.minimumSamplingInterval = 0.000000; |
| 88101 | attr.userAccessLevel = 1; |
| 88102 | attr.accessLevel = 1; |
| 88103 | /* Value rank inherited */ |
| 88104 | attr.valueRank = -2; |
| 88105 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88106 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishingIntervalCount"); |
| 88107 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88108 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3124LU), |
| 88109 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88110 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88111 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishingIntervalCount"), |
| 88112 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88113 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88114 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88115 | return retVal; |
| 88116 | } |
| 88117 | |
| 88118 | static UA_StatusCode function_namespace0_generated_687_finish(UA_Server *server, UA_UInt16* ns) { |
| 88119 | return UA_Server_addNode_finish(server, |
| 88120 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3124LU) |
| 88121 | ); |
| 88122 | } |
| 88123 | |
| 88124 | /* SessionAbortCount - ns=0;i=3122 */ |
| 88125 | |
| 88126 | static UA_StatusCode function_namespace0_generated_688_begin(UA_Server *server, UA_UInt16* ns) { |
| 88127 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88128 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88129 | attr.minimumSamplingInterval = 0.000000; |
| 88130 | attr.userAccessLevel = 1; |
| 88131 | attr.accessLevel = 1; |
| 88132 | /* Value rank inherited */ |
| 88133 | attr.valueRank = -2; |
| 88134 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88135 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionAbortCount"); |
| 88136 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88137 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3122LU), |
| 88138 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88139 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88140 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionAbortCount"), |
| 88141 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88142 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88143 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88144 | return retVal; |
| 88145 | } |
| 88146 | |
| 88147 | static UA_StatusCode function_namespace0_generated_688_finish(UA_Server *server, UA_UInt16* ns) { |
| 88148 | return UA_Server_addNode_finish(server, |
| 88149 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3122LU) |
| 88150 | ); |
| 88151 | } |
| 88152 | |
| 88153 | /* SessionTimeoutCount - ns=0;i=3121 */ |
| 88154 | |
| 88155 | static UA_StatusCode function_namespace0_generated_689_begin(UA_Server *server, UA_UInt16* ns) { |
| 88156 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88157 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88158 | attr.minimumSamplingInterval = 0.000000; |
| 88159 | attr.userAccessLevel = 1; |
| 88160 | attr.accessLevel = 1; |
| 88161 | /* Value rank inherited */ |
| 88162 | attr.valueRank = -2; |
| 88163 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88164 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionTimeoutCount"); |
| 88165 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88166 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3121LU), |
| 88167 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88168 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88169 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionTimeoutCount"), |
| 88170 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88171 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88172 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88173 | return retVal; |
| 88174 | } |
| 88175 | |
| 88176 | static UA_StatusCode function_namespace0_generated_689_finish(UA_Server *server, UA_UInt16* ns) { |
| 88177 | return UA_Server_addNode_finish(server, |
| 88178 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3121LU) |
| 88179 | ); |
| 88180 | } |
| 88181 | |
| 88182 | /* RejectedSessionCount - ns=0;i=3120 */ |
| 88183 | |
| 88184 | static UA_StatusCode function_namespace0_generated_690_begin(UA_Server *server, UA_UInt16* ns) { |
| 88185 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88186 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88187 | attr.minimumSamplingInterval = 0.000000; |
| 88188 | attr.userAccessLevel = 1; |
| 88189 | attr.accessLevel = 1; |
| 88190 | /* Value rank inherited */ |
| 88191 | attr.valueRank = -2; |
| 88192 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88193 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RejectedSessionCount"); |
| 88194 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88195 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3120LU), |
| 88196 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88197 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88198 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RejectedSessionCount"), |
| 88199 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88200 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88201 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88202 | return retVal; |
| 88203 | } |
| 88204 | |
| 88205 | static UA_StatusCode function_namespace0_generated_690_finish(UA_Server *server, UA_UInt16* ns) { |
| 88206 | return UA_Server_addNode_finish(server, |
| 88207 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3120LU) |
| 88208 | ); |
| 88209 | } |
| 88210 | |
| 88211 | /* SecurityRejectedSessionCount - ns=0;i=3119 */ |
| 88212 | |
| 88213 | static UA_StatusCode function_namespace0_generated_691_begin(UA_Server *server, UA_UInt16* ns) { |
| 88214 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88215 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88216 | attr.minimumSamplingInterval = 0.000000; |
| 88217 | attr.userAccessLevel = 1; |
| 88218 | attr.accessLevel = 1; |
| 88219 | /* Value rank inherited */ |
| 88220 | attr.valueRank = -2; |
| 88221 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88222 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityRejectedSessionCount"); |
| 88223 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88224 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3119LU), |
| 88225 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88226 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88227 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityRejectedSessionCount"), |
| 88228 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88229 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88230 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88231 | return retVal; |
| 88232 | } |
| 88233 | |
| 88234 | static UA_StatusCode function_namespace0_generated_691_finish(UA_Server *server, UA_UInt16* ns) { |
| 88235 | return UA_Server_addNode_finish(server, |
| 88236 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3119LU) |
| 88237 | ); |
| 88238 | } |
| 88239 | |
| 88240 | /* CumulatedSessionCount - ns=0;i=3118 */ |
| 88241 | |
| 88242 | static UA_StatusCode function_namespace0_generated_692_begin(UA_Server *server, UA_UInt16* ns) { |
| 88243 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88244 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88245 | attr.minimumSamplingInterval = 0.000000; |
| 88246 | attr.userAccessLevel = 1; |
| 88247 | attr.accessLevel = 1; |
| 88248 | /* Value rank inherited */ |
| 88249 | attr.valueRank = -2; |
| 88250 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88251 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CumulatedSessionCount"); |
| 88252 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88253 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3118LU), |
| 88254 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88255 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88256 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CumulatedSessionCount"), |
| 88257 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88258 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88259 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88260 | return retVal; |
| 88261 | } |
| 88262 | |
| 88263 | static UA_StatusCode function_namespace0_generated_692_finish(UA_Server *server, UA_UInt16* ns) { |
| 88264 | return UA_Server_addNode_finish(server, |
| 88265 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3118LU) |
| 88266 | ); |
| 88267 | } |
| 88268 | |
| 88269 | /* CurrentSessionCount - ns=0;i=3117 */ |
| 88270 | |
| 88271 | static UA_StatusCode function_namespace0_generated_693_begin(UA_Server *server, UA_UInt16* ns) { |
| 88272 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88273 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88274 | attr.minimumSamplingInterval = 0.000000; |
| 88275 | attr.userAccessLevel = 1; |
| 88276 | attr.accessLevel = 1; |
| 88277 | /* Value rank inherited */ |
| 88278 | attr.valueRank = -2; |
| 88279 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88280 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentSessionCount"); |
| 88281 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88282 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3117LU), |
| 88283 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88284 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88285 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentSessionCount"), |
| 88286 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88287 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88288 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88289 | return retVal; |
| 88290 | } |
| 88291 | |
| 88292 | static UA_StatusCode function_namespace0_generated_693_finish(UA_Server *server, UA_UInt16* ns) { |
| 88293 | return UA_Server_addNode_finish(server, |
| 88294 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3117LU) |
| 88295 | ); |
| 88296 | } |
| 88297 | |
| 88298 | /* ServerViewCount - ns=0;i=3116 */ |
| 88299 | |
| 88300 | static UA_StatusCode function_namespace0_generated_694_begin(UA_Server *server, UA_UInt16* ns) { |
| 88301 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88302 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88303 | attr.minimumSamplingInterval = 0.000000; |
| 88304 | attr.userAccessLevel = 1; |
| 88305 | attr.accessLevel = 1; |
| 88306 | /* Value rank inherited */ |
| 88307 | attr.valueRank = -2; |
| 88308 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88309 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerViewCount"); |
| 88310 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88311 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3116LU), |
| 88312 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), |
| 88313 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88314 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerViewCount"), |
| 88315 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88316 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88317 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88318 | return retVal; |
| 88319 | } |
| 88320 | |
| 88321 | static UA_StatusCode function_namespace0_generated_694_finish(UA_Server *server, UA_UInt16* ns) { |
| 88322 | return UA_Server_addNode_finish(server, |
| 88323 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3116LU) |
| 88324 | ); |
| 88325 | } |
| 88326 | |
| 88327 | /* ServerCapabilitiesType - ns=0;i=2013 */ |
| 88328 | |
| 88329 | static UA_StatusCode function_namespace0_generated_695_begin(UA_Server *server, UA_UInt16* ns) { |
| 88330 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88331 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 88332 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerCapabilitiesType"); |
| 88333 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 88334 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU), |
| 88335 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 88336 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 88337 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerCapabilitiesType"), |
| 88338 | typeDefinition: UA_NODEID_NULL, |
| 88339 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 88340 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88341 | return retVal; |
| 88342 | } |
| 88343 | |
| 88344 | static UA_StatusCode function_namespace0_generated_695_finish(UA_Server *server, UA_UInt16* ns) { |
| 88345 | return UA_Server_addNode_finish(server, |
| 88346 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU) |
| 88347 | ); |
| 88348 | } |
| 88349 | |
| 88350 | /* OperationLimits - ns=0;i=11551 */ |
| 88351 | |
| 88352 | static UA_StatusCode function_namespace0_generated_696_begin(UA_Server *server, UA_UInt16* ns) { |
| 88353 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88354 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 88355 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OperationLimits"); |
| 88356 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 88357 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11551LU), |
| 88358 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU), |
| 88359 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88360 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OperationLimits"), |
| 88361 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 88362 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 88363 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88364 | return retVal; |
| 88365 | } |
| 88366 | |
| 88367 | static UA_StatusCode function_namespace0_generated_696_finish(UA_Server *server, UA_UInt16* ns) { |
| 88368 | return UA_Server_addNode_finish(server, |
| 88369 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11551LU) |
| 88370 | ); |
| 88371 | } |
| 88372 | |
| 88373 | /* ServerType - ns=0;i=2004 */ |
| 88374 | |
| 88375 | static UA_StatusCode function_namespace0_generated_697_begin(UA_Server *server, UA_UInt16* ns) { |
| 88376 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88377 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 88378 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerType"); |
| 88379 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 88380 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU), |
| 88381 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 88382 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 88383 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerType"), |
| 88384 | typeDefinition: UA_NODEID_NULL, |
| 88385 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 88386 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88387 | return retVal; |
| 88388 | } |
| 88389 | |
| 88390 | static UA_StatusCode function_namespace0_generated_697_finish(UA_Server *server, UA_UInt16* ns) { |
| 88391 | return UA_Server_addNode_finish(server, |
| 88392 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU) |
| 88393 | ); |
| 88394 | } |
| 88395 | |
| 88396 | /* Server - ns=0;i=2253 */ |
| 88397 | |
| 88398 | static UA_StatusCode function_namespace0_generated_698_begin(UA_Server *server, UA_UInt16* ns) { |
| 88399 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88400 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 88401 | attr.eventNotifier = UA_EVENTNOTIFIER_SUBSCRIBE_TO_EVENT; |
| 88402 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Server"); |
| 88403 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 88404 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 88405 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 85LU), |
| 88406 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU), |
| 88407 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Server"), |
| 88408 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU), |
| 88409 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 88410 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88411 | return retVal; |
| 88412 | } |
| 88413 | |
| 88414 | static UA_StatusCode function_namespace0_generated_698_finish(UA_Server *server, UA_UInt16* ns) { |
| 88415 | return UA_Server_addNode_finish(server, |
| 88416 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU) |
| 88417 | ); |
| 88418 | } |
| 88419 | |
| 88420 | /* Auditing - ns=0;i=2994 */ |
| 88421 | |
| 88422 | static UA_StatusCode function_namespace0_generated_699_begin(UA_Server *server, UA_UInt16* ns) { |
| 88423 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88424 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88425 | attr.minimumSamplingInterval = 1000.000000; |
| 88426 | attr.userAccessLevel = 1; |
| 88427 | attr.accessLevel = 1; |
| 88428 | /* Value rank inherited */ |
| 88429 | attr.valueRank = -2; |
| 88430 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 88431 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Auditing"); |
| 88432 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88433 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2994LU), |
| 88434 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 88435 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 88436 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Auditing"), |
| 88437 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 88438 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88439 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88440 | return retVal; |
| 88441 | } |
| 88442 | |
| 88443 | static UA_StatusCode function_namespace0_generated_699_finish(UA_Server *server, UA_UInt16* ns) { |
| 88444 | return UA_Server_addNode_finish(server, |
| 88445 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2994LU) |
| 88446 | ); |
| 88447 | } |
| 88448 | |
| 88449 | /* ServerRedundancy - ns=0;i=2296 */ |
| 88450 | |
| 88451 | static UA_StatusCode function_namespace0_generated_700_begin(UA_Server *server, UA_UInt16* ns) { |
| 88452 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88453 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 88454 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerRedundancy"); |
| 88455 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 88456 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2296LU), |
| 88457 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 88458 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88459 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerRedundancy"), |
| 88460 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2034LU), |
| 88461 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 88462 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88463 | return retVal; |
| 88464 | } |
| 88465 | |
| 88466 | static UA_StatusCode function_namespace0_generated_700_finish(UA_Server *server, UA_UInt16* ns) { |
| 88467 | return UA_Server_addNode_finish(server, |
| 88468 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2296LU) |
| 88469 | ); |
| 88470 | } |
| 88471 | |
| 88472 | /* RedundancySupport - ns=0;i=3709 */ |
| 88473 | |
| 88474 | static UA_StatusCode function_namespace0_generated_701_begin(UA_Server *server, UA_UInt16* ns) { |
| 88475 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88476 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88477 | attr.minimumSamplingInterval = 0.000000; |
| 88478 | attr.userAccessLevel = 1; |
| 88479 | attr.accessLevel = 1; |
| 88480 | /* Value rank inherited */ |
| 88481 | attr.valueRank = -2; |
| 88482 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 851LU); |
| 88483 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RedundancySupport"); |
| 88484 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88485 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3709LU), |
| 88486 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2296LU), |
| 88487 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 88488 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RedundancySupport"), |
| 88489 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 88490 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88491 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88492 | return retVal; |
| 88493 | } |
| 88494 | |
| 88495 | static UA_StatusCode function_namespace0_generated_701_finish(UA_Server *server, UA_UInt16* ns) { |
| 88496 | return UA_Server_addNode_finish(server, |
| 88497 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3709LU) |
| 88498 | ); |
| 88499 | } |
| 88500 | |
| 88501 | /* VendorServerInfo - ns=0;i=2295 */ |
| 88502 | |
| 88503 | static UA_StatusCode function_namespace0_generated_702_begin(UA_Server *server, UA_UInt16* ns) { |
| 88504 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88505 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 88506 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "VendorServerInfo"); |
| 88507 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 88508 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2295LU), |
| 88509 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 88510 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88511 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "VendorServerInfo"), |
| 88512 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU), |
| 88513 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 88514 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88515 | return retVal; |
| 88516 | } |
| 88517 | |
| 88518 | static UA_StatusCode function_namespace0_generated_702_finish(UA_Server *server, UA_UInt16* ns) { |
| 88519 | return UA_Server_addNode_finish(server, |
| 88520 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2295LU) |
| 88521 | ); |
| 88522 | } |
| 88523 | |
| 88524 | /* ServerDiagnostics - ns=0;i=2274 */ |
| 88525 | |
| 88526 | static UA_StatusCode function_namespace0_generated_703_begin(UA_Server *server, UA_UInt16* ns) { |
| 88527 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88528 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 88529 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerDiagnostics"); |
| 88530 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 88531 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU), |
| 88532 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 88533 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88534 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerDiagnostics"), |
| 88535 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2020LU), |
| 88536 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 88537 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88538 | return retVal; |
| 88539 | } |
| 88540 | |
| 88541 | static UA_StatusCode function_namespace0_generated_703_finish(UA_Server *server, UA_UInt16* ns) { |
| 88542 | return UA_Server_addNode_finish(server, |
| 88543 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU) |
| 88544 | ); |
| 88545 | } |
| 88546 | |
| 88547 | /* SessionsDiagnosticsSummary - ns=0;i=3706 */ |
| 88548 | |
| 88549 | static UA_StatusCode function_namespace0_generated_704_begin(UA_Server *server, UA_UInt16* ns) { |
| 88550 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88551 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 88552 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionsDiagnosticsSummary"); |
| 88553 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 88554 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3706LU), |
| 88555 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU), |
| 88556 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88557 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionsDiagnosticsSummary"), |
| 88558 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2026LU), |
| 88559 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 88560 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88561 | return retVal; |
| 88562 | } |
| 88563 | |
| 88564 | static UA_StatusCode function_namespace0_generated_704_finish(UA_Server *server, UA_UInt16* ns) { |
| 88565 | return UA_Server_addNode_finish(server, |
| 88566 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3706LU) |
| 88567 | ); |
| 88568 | } |
| 88569 | |
| 88570 | /* SessionSecurityDiagnosticsArray - ns=0;i=3708 */ |
| 88571 | |
| 88572 | static UA_StatusCode function_namespace0_generated_705_begin(UA_Server *server, UA_UInt16* ns) { |
| 88573 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88574 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88575 | attr.minimumSamplingInterval = 0.000000; |
| 88576 | attr.userAccessLevel = 1; |
| 88577 | attr.accessLevel = 1; |
| 88578 | attr.valueRank = 1; |
| 88579 | attr.arrayDimensionsSize = 1; |
| 88580 | UA_UInt32 arrayDimensions[1]; |
| 88581 | arrayDimensions[0] = 0; |
| 88582 | attr.arrayDimensions = &arrayDimensions[0]; |
| 88583 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 868LU); |
| 88584 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionSecurityDiagnosticsArray"); |
| 88585 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88586 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3708LU), |
| 88587 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3706LU), |
| 88588 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88589 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionSecurityDiagnosticsArray"), |
| 88590 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2243LU), |
| 88591 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88592 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88593 | return retVal; |
| 88594 | } |
| 88595 | |
| 88596 | static UA_StatusCode function_namespace0_generated_705_finish(UA_Server *server, UA_UInt16* ns) { |
| 88597 | return UA_Server_addNode_finish(server, |
| 88598 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3708LU) |
| 88599 | ); |
| 88600 | } |
| 88601 | |
| 88602 | /* SessionDiagnosticsArray - ns=0;i=3707 */ |
| 88603 | |
| 88604 | static UA_StatusCode function_namespace0_generated_706_begin(UA_Server *server, UA_UInt16* ns) { |
| 88605 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88606 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88607 | attr.minimumSamplingInterval = 0.000000; |
| 88608 | attr.userAccessLevel = 1; |
| 88609 | attr.accessLevel = 1; |
| 88610 | attr.valueRank = 1; |
| 88611 | attr.arrayDimensionsSize = 1; |
| 88612 | UA_UInt32 arrayDimensions[1]; |
| 88613 | arrayDimensions[0] = 0; |
| 88614 | attr.arrayDimensions = &arrayDimensions[0]; |
| 88615 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 865LU); |
| 88616 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionDiagnosticsArray"); |
| 88617 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88618 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3707LU), |
| 88619 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3706LU), |
| 88620 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88621 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionDiagnosticsArray"), |
| 88622 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2196LU), |
| 88623 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88624 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88625 | return retVal; |
| 88626 | } |
| 88627 | |
| 88628 | static UA_StatusCode function_namespace0_generated_706_finish(UA_Server *server, UA_UInt16* ns) { |
| 88629 | return UA_Server_addNode_finish(server, |
| 88630 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3707LU) |
| 88631 | ); |
| 88632 | } |
| 88633 | |
| 88634 | /* EnabledFlag - ns=0;i=2294 */ |
| 88635 | |
| 88636 | static UA_StatusCode function_namespace0_generated_707_begin(UA_Server *server, UA_UInt16* ns) { |
| 88637 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88638 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88639 | attr.minimumSamplingInterval = 0.000000; |
| 88640 | attr.userAccessLevel = 1; |
| 88641 | attr.accessLevel = 3; |
| 88642 | /* Value rank inherited */ |
| 88643 | attr.valueRank = -2; |
| 88644 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 88645 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnabledFlag"); |
| 88646 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88647 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2294LU), |
| 88648 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU), |
| 88649 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 88650 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnabledFlag"), |
| 88651 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 88652 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88653 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88654 | return retVal; |
| 88655 | } |
| 88656 | |
| 88657 | static UA_StatusCode function_namespace0_generated_707_finish(UA_Server *server, UA_UInt16* ns) { |
| 88658 | return UA_Server_addNode_finish(server, |
| 88659 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2294LU) |
| 88660 | ); |
| 88661 | } |
| 88662 | |
| 88663 | /* SubscriptionDiagnosticsArray - ns=0;i=2290 */ |
| 88664 | |
| 88665 | static UA_StatusCode function_namespace0_generated_708_begin(UA_Server *server, UA_UInt16* ns) { |
| 88666 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88667 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88668 | attr.minimumSamplingInterval = 0.000000; |
| 88669 | attr.userAccessLevel = 1; |
| 88670 | attr.accessLevel = 1; |
| 88671 | attr.valueRank = 1; |
| 88672 | attr.arrayDimensionsSize = 1; |
| 88673 | UA_UInt32 arrayDimensions[1]; |
| 88674 | arrayDimensions[0] = 0; |
| 88675 | attr.arrayDimensions = &arrayDimensions[0]; |
| 88676 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 874LU); |
| 88677 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscriptionDiagnosticsArray"); |
| 88678 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88679 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2290LU), |
| 88680 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU), |
| 88681 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88682 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscriptionDiagnosticsArray"), |
| 88683 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2171LU), |
| 88684 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88685 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88686 | return retVal; |
| 88687 | } |
| 88688 | |
| 88689 | static UA_StatusCode function_namespace0_generated_708_finish(UA_Server *server, UA_UInt16* ns) { |
| 88690 | return UA_Server_addNode_finish(server, |
| 88691 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2290LU) |
| 88692 | ); |
| 88693 | } |
| 88694 | |
| 88695 | /* ServerDiagnosticsSummary - ns=0;i=2275 */ |
| 88696 | |
| 88697 | static UA_StatusCode function_namespace0_generated_709_begin(UA_Server *server, UA_UInt16* ns) { |
| 88698 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88699 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88700 | attr.minimumSamplingInterval = 0.000000; |
| 88701 | attr.userAccessLevel = 1; |
| 88702 | attr.accessLevel = 1; |
| 88703 | /* Value rank inherited */ |
| 88704 | attr.valueRank = -2; |
| 88705 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 859LU); |
| 88706 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerDiagnosticsSummary"); |
| 88707 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88708 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 88709 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2274LU), |
| 88710 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88711 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerDiagnosticsSummary"), |
| 88712 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2150LU), |
| 88713 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88714 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88715 | return retVal; |
| 88716 | } |
| 88717 | |
| 88718 | static UA_StatusCode function_namespace0_generated_709_finish(UA_Server *server, UA_UInt16* ns) { |
| 88719 | return UA_Server_addNode_finish(server, |
| 88720 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU) |
| 88721 | ); |
| 88722 | } |
| 88723 | |
| 88724 | /* RejectedSessionCount - ns=0;i=3705 */ |
| 88725 | |
| 88726 | static UA_StatusCode function_namespace0_generated_710_begin(UA_Server *server, UA_UInt16* ns) { |
| 88727 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88728 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88729 | attr.minimumSamplingInterval = 0.000000; |
| 88730 | attr.userAccessLevel = 1; |
| 88731 | attr.accessLevel = 1; |
| 88732 | /* Value rank inherited */ |
| 88733 | attr.valueRank = -2; |
| 88734 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88735 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RejectedSessionCount"); |
| 88736 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88737 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3705LU), |
| 88738 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 88739 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88740 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RejectedSessionCount"), |
| 88741 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88742 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88743 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88744 | return retVal; |
| 88745 | } |
| 88746 | |
| 88747 | static UA_StatusCode function_namespace0_generated_710_finish(UA_Server *server, UA_UInt16* ns) { |
| 88748 | return UA_Server_addNode_finish(server, |
| 88749 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3705LU) |
| 88750 | ); |
| 88751 | } |
| 88752 | |
| 88753 | /* RejectedRequestsCount - ns=0;i=2288 */ |
| 88754 | |
| 88755 | static UA_StatusCode function_namespace0_generated_711_begin(UA_Server *server, UA_UInt16* ns) { |
| 88756 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88757 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88758 | attr.minimumSamplingInterval = 0.000000; |
| 88759 | attr.userAccessLevel = 1; |
| 88760 | attr.accessLevel = 1; |
| 88761 | /* Value rank inherited */ |
| 88762 | attr.valueRank = -2; |
| 88763 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88764 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RejectedRequestsCount"); |
| 88765 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88766 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2288LU), |
| 88767 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 88768 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88769 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RejectedRequestsCount"), |
| 88770 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88771 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88772 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88773 | return retVal; |
| 88774 | } |
| 88775 | |
| 88776 | static UA_StatusCode function_namespace0_generated_711_finish(UA_Server *server, UA_UInt16* ns) { |
| 88777 | return UA_Server_addNode_finish(server, |
| 88778 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2288LU) |
| 88779 | ); |
| 88780 | } |
| 88781 | |
| 88782 | /* SecurityRejectedRequestsCount - ns=0;i=2287 */ |
| 88783 | |
| 88784 | static UA_StatusCode function_namespace0_generated_712_begin(UA_Server *server, UA_UInt16* ns) { |
| 88785 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88786 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88787 | attr.minimumSamplingInterval = 0.000000; |
| 88788 | attr.userAccessLevel = 1; |
| 88789 | attr.accessLevel = 1; |
| 88790 | /* Value rank inherited */ |
| 88791 | attr.valueRank = -2; |
| 88792 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88793 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityRejectedRequestsCount"); |
| 88794 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88795 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2287LU), |
| 88796 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 88797 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88798 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityRejectedRequestsCount"), |
| 88799 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88800 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88801 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88802 | return retVal; |
| 88803 | } |
| 88804 | |
| 88805 | static UA_StatusCode function_namespace0_generated_712_finish(UA_Server *server, UA_UInt16* ns) { |
| 88806 | return UA_Server_addNode_finish(server, |
| 88807 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2287LU) |
| 88808 | ); |
| 88809 | } |
| 88810 | |
| 88811 | /* CumulatedSubscriptionCount - ns=0;i=2286 */ |
| 88812 | |
| 88813 | static UA_StatusCode function_namespace0_generated_713_begin(UA_Server *server, UA_UInt16* ns) { |
| 88814 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88815 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88816 | attr.minimumSamplingInterval = 0.000000; |
| 88817 | attr.userAccessLevel = 1; |
| 88818 | attr.accessLevel = 1; |
| 88819 | /* Value rank inherited */ |
| 88820 | attr.valueRank = -2; |
| 88821 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88822 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CumulatedSubscriptionCount"); |
| 88823 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88824 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2286LU), |
| 88825 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 88826 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88827 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CumulatedSubscriptionCount"), |
| 88828 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88829 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88830 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88831 | return retVal; |
| 88832 | } |
| 88833 | |
| 88834 | static UA_StatusCode function_namespace0_generated_713_finish(UA_Server *server, UA_UInt16* ns) { |
| 88835 | return UA_Server_addNode_finish(server, |
| 88836 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2286LU) |
| 88837 | ); |
| 88838 | } |
| 88839 | |
| 88840 | /* CurrentSubscriptionCount - ns=0;i=2285 */ |
| 88841 | |
| 88842 | static UA_StatusCode function_namespace0_generated_714_begin(UA_Server *server, UA_UInt16* ns) { |
| 88843 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88844 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88845 | attr.minimumSamplingInterval = 0.000000; |
| 88846 | attr.userAccessLevel = 1; |
| 88847 | attr.accessLevel = 1; |
| 88848 | /* Value rank inherited */ |
| 88849 | attr.valueRank = -2; |
| 88850 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88851 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentSubscriptionCount"); |
| 88852 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88853 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2285LU), |
| 88854 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 88855 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88856 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentSubscriptionCount"), |
| 88857 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88858 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88859 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88860 | return retVal; |
| 88861 | } |
| 88862 | |
| 88863 | static UA_StatusCode function_namespace0_generated_714_finish(UA_Server *server, UA_UInt16* ns) { |
| 88864 | return UA_Server_addNode_finish(server, |
| 88865 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2285LU) |
| 88866 | ); |
| 88867 | } |
| 88868 | |
| 88869 | /* PublishingIntervalCount - ns=0;i=2284 */ |
| 88870 | |
| 88871 | static UA_StatusCode function_namespace0_generated_715_begin(UA_Server *server, UA_UInt16* ns) { |
| 88872 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88873 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88874 | attr.minimumSamplingInterval = 0.000000; |
| 88875 | attr.userAccessLevel = 1; |
| 88876 | attr.accessLevel = 1; |
| 88877 | /* Value rank inherited */ |
| 88878 | attr.valueRank = -2; |
| 88879 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88880 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishingIntervalCount"); |
| 88881 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88882 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2284LU), |
| 88883 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 88884 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88885 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishingIntervalCount"), |
| 88886 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88887 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88888 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88889 | return retVal; |
| 88890 | } |
| 88891 | |
| 88892 | static UA_StatusCode function_namespace0_generated_715_finish(UA_Server *server, UA_UInt16* ns) { |
| 88893 | return UA_Server_addNode_finish(server, |
| 88894 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2284LU) |
| 88895 | ); |
| 88896 | } |
| 88897 | |
| 88898 | /* SessionAbortCount - ns=0;i=2282 */ |
| 88899 | |
| 88900 | static UA_StatusCode function_namespace0_generated_716_begin(UA_Server *server, UA_UInt16* ns) { |
| 88901 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88902 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88903 | attr.minimumSamplingInterval = 0.000000; |
| 88904 | attr.userAccessLevel = 1; |
| 88905 | attr.accessLevel = 1; |
| 88906 | /* Value rank inherited */ |
| 88907 | attr.valueRank = -2; |
| 88908 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88909 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionAbortCount"); |
| 88910 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88911 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2282LU), |
| 88912 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 88913 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88914 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionAbortCount"), |
| 88915 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88916 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88917 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88918 | return retVal; |
| 88919 | } |
| 88920 | |
| 88921 | static UA_StatusCode function_namespace0_generated_716_finish(UA_Server *server, UA_UInt16* ns) { |
| 88922 | return UA_Server_addNode_finish(server, |
| 88923 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2282LU) |
| 88924 | ); |
| 88925 | } |
| 88926 | |
| 88927 | /* SessionTimeoutCount - ns=0;i=2281 */ |
| 88928 | |
| 88929 | static UA_StatusCode function_namespace0_generated_717_begin(UA_Server *server, UA_UInt16* ns) { |
| 88930 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88931 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88932 | attr.minimumSamplingInterval = 0.000000; |
| 88933 | attr.userAccessLevel = 1; |
| 88934 | attr.accessLevel = 1; |
| 88935 | /* Value rank inherited */ |
| 88936 | attr.valueRank = -2; |
| 88937 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88938 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SessionTimeoutCount"); |
| 88939 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88940 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2281LU), |
| 88941 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 88942 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88943 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SessionTimeoutCount"), |
| 88944 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88945 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88946 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88947 | return retVal; |
| 88948 | } |
| 88949 | |
| 88950 | static UA_StatusCode function_namespace0_generated_717_finish(UA_Server *server, UA_UInt16* ns) { |
| 88951 | return UA_Server_addNode_finish(server, |
| 88952 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2281LU) |
| 88953 | ); |
| 88954 | } |
| 88955 | |
| 88956 | /* SecurityRejectedSessionCount - ns=0;i=2279 */ |
| 88957 | |
| 88958 | static UA_StatusCode function_namespace0_generated_718_begin(UA_Server *server, UA_UInt16* ns) { |
| 88959 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88960 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88961 | attr.minimumSamplingInterval = 0.000000; |
| 88962 | attr.userAccessLevel = 1; |
| 88963 | attr.accessLevel = 1; |
| 88964 | /* Value rank inherited */ |
| 88965 | attr.valueRank = -2; |
| 88966 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88967 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecurityRejectedSessionCount"); |
| 88968 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88969 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2279LU), |
| 88970 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 88971 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 88972 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecurityRejectedSessionCount"), |
| 88973 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 88974 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 88975 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 88976 | return retVal; |
| 88977 | } |
| 88978 | |
| 88979 | static UA_StatusCode function_namespace0_generated_718_finish(UA_Server *server, UA_UInt16* ns) { |
| 88980 | return UA_Server_addNode_finish(server, |
| 88981 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2279LU) |
| 88982 | ); |
| 88983 | } |
| 88984 | |
| 88985 | /* CumulatedSessionCount - ns=0;i=2278 */ |
| 88986 | |
| 88987 | static UA_StatusCode function_namespace0_generated_719_begin(UA_Server *server, UA_UInt16* ns) { |
| 88988 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 88989 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 88990 | attr.minimumSamplingInterval = 0.000000; |
| 88991 | attr.userAccessLevel = 1; |
| 88992 | attr.accessLevel = 1; |
| 88993 | /* Value rank inherited */ |
| 88994 | attr.valueRank = -2; |
| 88995 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 88996 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CumulatedSessionCount"); |
| 88997 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 88998 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2278LU), |
| 88999 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 89000 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 89001 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CumulatedSessionCount"), |
| 89002 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 89003 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89004 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89005 | return retVal; |
| 89006 | } |
| 89007 | |
| 89008 | static UA_StatusCode function_namespace0_generated_719_finish(UA_Server *server, UA_UInt16* ns) { |
| 89009 | return UA_Server_addNode_finish(server, |
| 89010 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2278LU) |
| 89011 | ); |
| 89012 | } |
| 89013 | |
| 89014 | /* CurrentSessionCount - ns=0;i=2277 */ |
| 89015 | |
| 89016 | static UA_StatusCode function_namespace0_generated_720_begin(UA_Server *server, UA_UInt16* ns) { |
| 89017 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89018 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89019 | attr.minimumSamplingInterval = 0.000000; |
| 89020 | attr.userAccessLevel = 1; |
| 89021 | attr.accessLevel = 1; |
| 89022 | /* Value rank inherited */ |
| 89023 | attr.valueRank = -2; |
| 89024 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89025 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentSessionCount"); |
| 89026 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89027 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2277LU), |
| 89028 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 89029 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 89030 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentSessionCount"), |
| 89031 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 89032 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89033 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89034 | return retVal; |
| 89035 | } |
| 89036 | |
| 89037 | static UA_StatusCode function_namespace0_generated_720_finish(UA_Server *server, UA_UInt16* ns) { |
| 89038 | return UA_Server_addNode_finish(server, |
| 89039 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2277LU) |
| 89040 | ); |
| 89041 | } |
| 89042 | |
| 89043 | /* ServerViewCount - ns=0;i=2276 */ |
| 89044 | |
| 89045 | static UA_StatusCode function_namespace0_generated_721_begin(UA_Server *server, UA_UInt16* ns) { |
| 89046 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89047 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89048 | attr.minimumSamplingInterval = 0.000000; |
| 89049 | attr.userAccessLevel = 1; |
| 89050 | attr.accessLevel = 1; |
| 89051 | /* Value rank inherited */ |
| 89052 | attr.valueRank = -2; |
| 89053 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89054 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerViewCount"); |
| 89055 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89056 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2276LU), |
| 89057 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2275LU), |
| 89058 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 89059 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerViewCount"), |
| 89060 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 89061 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89062 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89063 | return retVal; |
| 89064 | } |
| 89065 | |
| 89066 | static UA_StatusCode function_namespace0_generated_721_finish(UA_Server *server, UA_UInt16* ns) { |
| 89067 | return UA_Server_addNode_finish(server, |
| 89068 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2276LU) |
| 89069 | ); |
| 89070 | } |
| 89071 | |
| 89072 | /* ServerCapabilities - ns=0;i=2268 */ |
| 89073 | |
| 89074 | static UA_StatusCode function_namespace0_generated_722_begin(UA_Server *server, UA_UInt16* ns) { |
| 89075 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89076 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 89077 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerCapabilities"); |
| 89078 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 89079 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89080 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 89081 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 89082 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerCapabilities"), |
| 89083 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2013LU), |
| 89084 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 89085 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89086 | return retVal; |
| 89087 | } |
| 89088 | |
| 89089 | static UA_StatusCode function_namespace0_generated_722_finish(UA_Server *server, UA_UInt16* ns) { |
| 89090 | return UA_Server_addNode_finish(server, |
| 89091 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU) |
| 89092 | ); |
| 89093 | } |
| 89094 | |
| 89095 | /* SoftwareCertificates - ns=0;i=3704 */ |
| 89096 | |
| 89097 | static UA_StatusCode function_namespace0_generated_723_begin(UA_Server *server, UA_UInt16* ns) { |
| 89098 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89099 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89100 | attr.minimumSamplingInterval = 0.000000; |
| 89101 | attr.userAccessLevel = 1; |
| 89102 | attr.accessLevel = 1; |
| 89103 | attr.valueRank = 1; |
| 89104 | attr.arrayDimensionsSize = 1; |
| 89105 | UA_UInt32 arrayDimensions[1]; |
| 89106 | arrayDimensions[0] = 0; |
| 89107 | attr.arrayDimensions = &arrayDimensions[0]; |
| 89108 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 344LU); |
| 89109 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SoftwareCertificates"); |
| 89110 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89111 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3704LU), |
| 89112 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89113 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89114 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SoftwareCertificates"), |
| 89115 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89116 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89117 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89118 | return retVal; |
| 89119 | } |
| 89120 | |
| 89121 | static UA_StatusCode function_namespace0_generated_723_finish(UA_Server *server, UA_UInt16* ns) { |
| 89122 | return UA_Server_addNode_finish(server, |
| 89123 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3704LU) |
| 89124 | ); |
| 89125 | } |
| 89126 | |
| 89127 | /* AggregateFunctions - ns=0;i=2997 */ |
| 89128 | |
| 89129 | static UA_StatusCode function_namespace0_generated_724_begin(UA_Server *server, UA_UInt16* ns) { |
| 89130 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89131 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 89132 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AggregateFunctions"); |
| 89133 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 89134 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2997LU), |
| 89135 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89136 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 89137 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AggregateFunctions"), |
| 89138 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU), |
| 89139 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 89140 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89141 | return retVal; |
| 89142 | } |
| 89143 | |
| 89144 | static UA_StatusCode function_namespace0_generated_724_finish(UA_Server *server, UA_UInt16* ns) { |
| 89145 | return UA_Server_addNode_finish(server, |
| 89146 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2997LU) |
| 89147 | ); |
| 89148 | } |
| 89149 | |
| 89150 | /* ModellingRules - ns=0;i=2996 */ |
| 89151 | |
| 89152 | static UA_StatusCode function_namespace0_generated_725_begin(UA_Server *server, UA_UInt16* ns) { |
| 89153 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89154 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 89155 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModellingRules"); |
| 89156 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 89157 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2996LU), |
| 89158 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89159 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 89160 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModellingRules"), |
| 89161 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU), |
| 89162 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 89163 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89164 | return retVal; |
| 89165 | } |
| 89166 | |
| 89167 | static UA_StatusCode function_namespace0_generated_725_finish(UA_Server *server, UA_UInt16* ns) { |
| 89168 | return UA_Server_addNode_finish(server, |
| 89169 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2996LU) |
| 89170 | ); |
| 89171 | } |
| 89172 | |
| 89173 | /* MaxHistoryContinuationPoints - ns=0;i=2737 */ |
| 89174 | |
| 89175 | static UA_StatusCode function_namespace0_generated_726_begin(UA_Server *server, UA_UInt16* ns) { |
| 89176 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89177 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89178 | attr.minimumSamplingInterval = 0.000000; |
| 89179 | attr.userAccessLevel = 1; |
| 89180 | attr.accessLevel = 1; |
| 89181 | /* Value rank inherited */ |
| 89182 | attr.valueRank = -2; |
| 89183 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 89184 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxHistoryContinuationPoints"); |
| 89185 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89186 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2737LU), |
| 89187 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89188 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89189 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxHistoryContinuationPoints"), |
| 89190 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89191 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89192 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89193 | return retVal; |
| 89194 | } |
| 89195 | |
| 89196 | static UA_StatusCode function_namespace0_generated_726_finish(UA_Server *server, UA_UInt16* ns) { |
| 89197 | return UA_Server_addNode_finish(server, |
| 89198 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2737LU) |
| 89199 | ); |
| 89200 | } |
| 89201 | |
| 89202 | /* MaxQueryContinuationPoints - ns=0;i=2736 */ |
| 89203 | |
| 89204 | static UA_StatusCode function_namespace0_generated_727_begin(UA_Server *server, UA_UInt16* ns) { |
| 89205 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89206 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89207 | attr.minimumSamplingInterval = 0.000000; |
| 89208 | attr.userAccessLevel = 1; |
| 89209 | attr.accessLevel = 1; |
| 89210 | /* Value rank inherited */ |
| 89211 | attr.valueRank = -2; |
| 89212 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 89213 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxQueryContinuationPoints"); |
| 89214 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89215 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2736LU), |
| 89216 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89217 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89218 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxQueryContinuationPoints"), |
| 89219 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89220 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89221 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89222 | return retVal; |
| 89223 | } |
| 89224 | |
| 89225 | static UA_StatusCode function_namespace0_generated_727_finish(UA_Server *server, UA_UInt16* ns) { |
| 89226 | return UA_Server_addNode_finish(server, |
| 89227 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2736LU) |
| 89228 | ); |
| 89229 | } |
| 89230 | |
| 89231 | /* MaxBrowseContinuationPoints - ns=0;i=2735 */ |
| 89232 | |
| 89233 | static UA_StatusCode function_namespace0_generated_728_begin(UA_Server *server, UA_UInt16* ns) { |
| 89234 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89235 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89236 | attr.minimumSamplingInterval = 0.000000; |
| 89237 | attr.userAccessLevel = 1; |
| 89238 | attr.accessLevel = 1; |
| 89239 | /* Value rank inherited */ |
| 89240 | attr.valueRank = -2; |
| 89241 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 89242 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxBrowseContinuationPoints"); |
| 89243 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89244 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2735LU), |
| 89245 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89246 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89247 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxBrowseContinuationPoints"), |
| 89248 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89249 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89250 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89251 | return retVal; |
| 89252 | } |
| 89253 | |
| 89254 | static UA_StatusCode function_namespace0_generated_728_finish(UA_Server *server, UA_UInt16* ns) { |
| 89255 | return UA_Server_addNode_finish(server, |
| 89256 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2735LU) |
| 89257 | ); |
| 89258 | } |
| 89259 | |
| 89260 | /* MinSupportedSampleRate - ns=0;i=2272 */ |
| 89261 | |
| 89262 | static UA_StatusCode function_namespace0_generated_729_begin(UA_Server *server, UA_UInt16* ns) { |
| 89263 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89264 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89265 | attr.minimumSamplingInterval = 0.000000; |
| 89266 | attr.userAccessLevel = 1; |
| 89267 | attr.accessLevel = 1; |
| 89268 | /* Value rank inherited */ |
| 89269 | attr.valueRank = -2; |
| 89270 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 290LU); |
| 89271 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MinSupportedSampleRate"); |
| 89272 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89273 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2272LU), |
| 89274 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89275 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89276 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MinSupportedSampleRate"), |
| 89277 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89278 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89279 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89280 | return retVal; |
| 89281 | } |
| 89282 | |
| 89283 | static UA_StatusCode function_namespace0_generated_729_finish(UA_Server *server, UA_UInt16* ns) { |
| 89284 | return UA_Server_addNode_finish(server, |
| 89285 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2272LU) |
| 89286 | ); |
| 89287 | } |
| 89288 | |
| 89289 | /* LocaleIdArray - ns=0;i=2271 */ |
| 89290 | |
| 89291 | static UA_StatusCode function_namespace0_generated_730_begin(UA_Server *server, UA_UInt16* ns) { |
| 89292 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89293 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89294 | attr.minimumSamplingInterval = 0.000000; |
| 89295 | attr.userAccessLevel = 1; |
| 89296 | attr.accessLevel = 1; |
| 89297 | attr.valueRank = 1; |
| 89298 | attr.arrayDimensionsSize = 1; |
| 89299 | UA_UInt32 arrayDimensions[1]; |
| 89300 | arrayDimensions[0] = 0; |
| 89301 | attr.arrayDimensions = &arrayDimensions[0]; |
| 89302 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 295LU); |
| 89303 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "LocaleIdArray"); |
| 89304 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89305 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2271LU), |
| 89306 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89307 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89308 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "LocaleIdArray"), |
| 89309 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89310 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89311 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89312 | return retVal; |
| 89313 | } |
| 89314 | |
| 89315 | static UA_StatusCode function_namespace0_generated_730_finish(UA_Server *server, UA_UInt16* ns) { |
| 89316 | return UA_Server_addNode_finish(server, |
| 89317 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2271LU) |
| 89318 | ); |
| 89319 | } |
| 89320 | |
| 89321 | /* ServerProfileArray - ns=0;i=2269 */ |
| 89322 | |
| 89323 | static UA_StatusCode function_namespace0_generated_731_begin(UA_Server *server, UA_UInt16* ns) { |
| 89324 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89325 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89326 | attr.minimumSamplingInterval = 0.000000; |
| 89327 | attr.userAccessLevel = 1; |
| 89328 | attr.accessLevel = 1; |
| 89329 | attr.valueRank = 1; |
| 89330 | attr.arrayDimensionsSize = 1; |
| 89331 | UA_UInt32 arrayDimensions[1]; |
| 89332 | arrayDimensions[0] = 0; |
| 89333 | attr.arrayDimensions = &arrayDimensions[0]; |
| 89334 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 89335 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerProfileArray"); |
| 89336 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89337 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2269LU), |
| 89338 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89339 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89340 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerProfileArray"), |
| 89341 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89342 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89343 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89344 | return retVal; |
| 89345 | } |
| 89346 | |
| 89347 | static UA_StatusCode function_namespace0_generated_731_finish(UA_Server *server, UA_UInt16* ns) { |
| 89348 | return UA_Server_addNode_finish(server, |
| 89349 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2269LU) |
| 89350 | ); |
| 89351 | } |
| 89352 | |
| 89353 | /* OperationLimits - ns=0;i=11704 */ |
| 89354 | |
| 89355 | static UA_StatusCode function_namespace0_generated_732_begin(UA_Server *server, UA_UInt16* ns) { |
| 89356 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89357 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 89358 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OperationLimits"); |
| 89359 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 89360 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU), |
| 89361 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89362 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 89363 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OperationLimits"), |
| 89364 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11564LU), |
| 89365 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 89366 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89367 | return retVal; |
| 89368 | } |
| 89369 | |
| 89370 | static UA_StatusCode function_namespace0_generated_732_finish(UA_Server *server, UA_UInt16* ns) { |
| 89371 | return UA_Server_addNode_finish(server, |
| 89372 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU) |
| 89373 | ); |
| 89374 | } |
| 89375 | |
| 89376 | /* MaxMonitoredItemsPerCall - ns=0;i=11714 */ |
| 89377 | |
| 89378 | static UA_StatusCode function_namespace0_generated_733_begin(UA_Server *server, UA_UInt16* ns) { |
| 89379 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89380 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89381 | attr.minimumSamplingInterval = 0.000000; |
| 89382 | attr.userAccessLevel = 1; |
| 89383 | attr.accessLevel = 1; |
| 89384 | /* Value rank inherited */ |
| 89385 | attr.valueRank = -2; |
| 89386 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89387 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxMonitoredItemsPerCall"); |
| 89388 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89389 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11714LU), |
| 89390 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU), |
| 89391 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89392 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxMonitoredItemsPerCall"), |
| 89393 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89394 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89395 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89396 | return retVal; |
| 89397 | } |
| 89398 | |
| 89399 | static UA_StatusCode function_namespace0_generated_733_finish(UA_Server *server, UA_UInt16* ns) { |
| 89400 | return UA_Server_addNode_finish(server, |
| 89401 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11714LU) |
| 89402 | ); |
| 89403 | } |
| 89404 | |
| 89405 | /* MaxNodesPerNodeManagement - ns=0;i=11713 */ |
| 89406 | |
| 89407 | static UA_StatusCode function_namespace0_generated_734_begin(UA_Server *server, UA_UInt16* ns) { |
| 89408 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89409 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89410 | attr.minimumSamplingInterval = 0.000000; |
| 89411 | attr.userAccessLevel = 1; |
| 89412 | attr.accessLevel = 1; |
| 89413 | /* Value rank inherited */ |
| 89414 | attr.valueRank = -2; |
| 89415 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89416 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerNodeManagement"); |
| 89417 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89418 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11713LU), |
| 89419 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU), |
| 89420 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89421 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerNodeManagement"), |
| 89422 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89423 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89424 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89425 | return retVal; |
| 89426 | } |
| 89427 | |
| 89428 | static UA_StatusCode function_namespace0_generated_734_finish(UA_Server *server, UA_UInt16* ns) { |
| 89429 | return UA_Server_addNode_finish(server, |
| 89430 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11713LU) |
| 89431 | ); |
| 89432 | } |
| 89433 | |
| 89434 | /* MaxNodesPerTranslateBrowsePathsToNodeIds - ns=0;i=11712 */ |
| 89435 | |
| 89436 | static UA_StatusCode function_namespace0_generated_735_begin(UA_Server *server, UA_UInt16* ns) { |
| 89437 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89438 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89439 | attr.minimumSamplingInterval = 0.000000; |
| 89440 | attr.userAccessLevel = 1; |
| 89441 | attr.accessLevel = 1; |
| 89442 | /* Value rank inherited */ |
| 89443 | attr.valueRank = -2; |
| 89444 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89445 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerTranslateBrowsePathsToNodeIds"); |
| 89446 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89447 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11712LU), |
| 89448 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU), |
| 89449 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89450 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerTranslateBrowsePathsToNodeIds"), |
| 89451 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89452 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89453 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89454 | return retVal; |
| 89455 | } |
| 89456 | |
| 89457 | static UA_StatusCode function_namespace0_generated_735_finish(UA_Server *server, UA_UInt16* ns) { |
| 89458 | return UA_Server_addNode_finish(server, |
| 89459 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11712LU) |
| 89460 | ); |
| 89461 | } |
| 89462 | |
| 89463 | /* MaxNodesPerRegisterNodes - ns=0;i=11711 */ |
| 89464 | |
| 89465 | static UA_StatusCode function_namespace0_generated_736_begin(UA_Server *server, UA_UInt16* ns) { |
| 89466 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89467 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89468 | attr.minimumSamplingInterval = 0.000000; |
| 89469 | attr.userAccessLevel = 1; |
| 89470 | attr.accessLevel = 1; |
| 89471 | /* Value rank inherited */ |
| 89472 | attr.valueRank = -2; |
| 89473 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89474 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRegisterNodes"); |
| 89475 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89476 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11711LU), |
| 89477 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU), |
| 89478 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89479 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRegisterNodes"), |
| 89480 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89481 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89482 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89483 | return retVal; |
| 89484 | } |
| 89485 | |
| 89486 | static UA_StatusCode function_namespace0_generated_736_finish(UA_Server *server, UA_UInt16* ns) { |
| 89487 | return UA_Server_addNode_finish(server, |
| 89488 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11711LU) |
| 89489 | ); |
| 89490 | } |
| 89491 | |
| 89492 | /* MaxNodesPerBrowse - ns=0;i=11710 */ |
| 89493 | |
| 89494 | static UA_StatusCode function_namespace0_generated_737_begin(UA_Server *server, UA_UInt16* ns) { |
| 89495 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89496 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89497 | attr.minimumSamplingInterval = 0.000000; |
| 89498 | attr.userAccessLevel = 1; |
| 89499 | attr.accessLevel = 1; |
| 89500 | /* Value rank inherited */ |
| 89501 | attr.valueRank = -2; |
| 89502 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89503 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerBrowse"); |
| 89504 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89505 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11710LU), |
| 89506 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU), |
| 89507 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89508 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerBrowse"), |
| 89509 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89510 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89511 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89512 | return retVal; |
| 89513 | } |
| 89514 | |
| 89515 | static UA_StatusCode function_namespace0_generated_737_finish(UA_Server *server, UA_UInt16* ns) { |
| 89516 | return UA_Server_addNode_finish(server, |
| 89517 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11710LU) |
| 89518 | ); |
| 89519 | } |
| 89520 | |
| 89521 | /* MaxNodesPerMethodCall - ns=0;i=11709 */ |
| 89522 | |
| 89523 | static UA_StatusCode function_namespace0_generated_738_begin(UA_Server *server, UA_UInt16* ns) { |
| 89524 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89525 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89526 | attr.minimumSamplingInterval = 0.000000; |
| 89527 | attr.userAccessLevel = 1; |
| 89528 | attr.accessLevel = 1; |
| 89529 | /* Value rank inherited */ |
| 89530 | attr.valueRank = -2; |
| 89531 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89532 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerMethodCall"); |
| 89533 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89534 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11709LU), |
| 89535 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU), |
| 89536 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89537 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerMethodCall"), |
| 89538 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89539 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89540 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89541 | return retVal; |
| 89542 | } |
| 89543 | |
| 89544 | static UA_StatusCode function_namespace0_generated_738_finish(UA_Server *server, UA_UInt16* ns) { |
| 89545 | return UA_Server_addNode_finish(server, |
| 89546 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11709LU) |
| 89547 | ); |
| 89548 | } |
| 89549 | |
| 89550 | /* MaxNodesPerWrite - ns=0;i=11707 */ |
| 89551 | |
| 89552 | static UA_StatusCode function_namespace0_generated_739_begin(UA_Server *server, UA_UInt16* ns) { |
| 89553 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89554 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89555 | attr.minimumSamplingInterval = 0.000000; |
| 89556 | attr.userAccessLevel = 1; |
| 89557 | attr.accessLevel = 1; |
| 89558 | /* Value rank inherited */ |
| 89559 | attr.valueRank = -2; |
| 89560 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89561 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerWrite"); |
| 89562 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89563 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11707LU), |
| 89564 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU), |
| 89565 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89566 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerWrite"), |
| 89567 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89568 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89569 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89570 | return retVal; |
| 89571 | } |
| 89572 | |
| 89573 | static UA_StatusCode function_namespace0_generated_739_finish(UA_Server *server, UA_UInt16* ns) { |
| 89574 | return UA_Server_addNode_finish(server, |
| 89575 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11707LU) |
| 89576 | ); |
| 89577 | } |
| 89578 | |
| 89579 | /* MaxNodesPerRead - ns=0;i=11705 */ |
| 89580 | |
| 89581 | static UA_StatusCode function_namespace0_generated_740_begin(UA_Server *server, UA_UInt16* ns) { |
| 89582 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89583 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89584 | attr.minimumSamplingInterval = 0.000000; |
| 89585 | attr.userAccessLevel = 1; |
| 89586 | attr.accessLevel = 1; |
| 89587 | /* Value rank inherited */ |
| 89588 | attr.valueRank = -2; |
| 89589 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89590 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxNodesPerRead"); |
| 89591 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89592 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11705LU), |
| 89593 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11704LU), |
| 89594 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89595 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxNodesPerRead"), |
| 89596 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89597 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89598 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89599 | return retVal; |
| 89600 | } |
| 89601 | |
| 89602 | static UA_StatusCode function_namespace0_generated_740_finish(UA_Server *server, UA_UInt16* ns) { |
| 89603 | return UA_Server_addNode_finish(server, |
| 89604 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11705LU) |
| 89605 | ); |
| 89606 | } |
| 89607 | |
| 89608 | /* HistoryServerCapabilities - ns=0;i=11192 */ |
| 89609 | |
| 89610 | static UA_StatusCode function_namespace0_generated_741_begin(UA_Server *server, UA_UInt16* ns) { |
| 89611 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89612 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 89613 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "HistoryServerCapabilities"); |
| 89614 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 89615 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89616 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2268LU), |
| 89617 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 89618 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "HistoryServerCapabilities"), |
| 89619 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2330LU), |
| 89620 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 89621 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89622 | return retVal; |
| 89623 | } |
| 89624 | |
| 89625 | static UA_StatusCode function_namespace0_generated_741_finish(UA_Server *server, UA_UInt16* ns) { |
| 89626 | return UA_Server_addNode_finish(server, |
| 89627 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU) |
| 89628 | ); |
| 89629 | } |
| 89630 | |
| 89631 | /* DeleteEventCapability - ns=0;i=11502 */ |
| 89632 | |
| 89633 | static UA_StatusCode function_namespace0_generated_742_begin(UA_Server *server, UA_UInt16* ns) { |
| 89634 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89635 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89636 | attr.minimumSamplingInterval = 0.000000; |
| 89637 | attr.userAccessLevel = 1; |
| 89638 | attr.accessLevel = 1; |
| 89639 | /* Value rank inherited */ |
| 89640 | attr.valueRank = -2; |
| 89641 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 89642 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteEventCapability"); |
| 89643 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89644 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11502LU), |
| 89645 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89646 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89647 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteEventCapability"), |
| 89648 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89649 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89650 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89651 | return retVal; |
| 89652 | } |
| 89653 | |
| 89654 | static UA_StatusCode function_namespace0_generated_742_finish(UA_Server *server, UA_UInt16* ns) { |
| 89655 | return UA_Server_addNode_finish(server, |
| 89656 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11502LU) |
| 89657 | ); |
| 89658 | } |
| 89659 | |
| 89660 | /* UpdateEventCapability - ns=0;i=11283 */ |
| 89661 | |
| 89662 | static UA_StatusCode function_namespace0_generated_743_begin(UA_Server *server, UA_UInt16* ns) { |
| 89663 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89664 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89665 | attr.minimumSamplingInterval = 0.000000; |
| 89666 | attr.userAccessLevel = 1; |
| 89667 | attr.accessLevel = 1; |
| 89668 | /* Value rank inherited */ |
| 89669 | attr.valueRank = -2; |
| 89670 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 89671 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UpdateEventCapability"); |
| 89672 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89673 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11283LU), |
| 89674 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89675 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89676 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UpdateEventCapability"), |
| 89677 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89678 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89679 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89680 | return retVal; |
| 89681 | } |
| 89682 | |
| 89683 | static UA_StatusCode function_namespace0_generated_743_finish(UA_Server *server, UA_UInt16* ns) { |
| 89684 | return UA_Server_addNode_finish(server, |
| 89685 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11283LU) |
| 89686 | ); |
| 89687 | } |
| 89688 | |
| 89689 | /* ReplaceEventCapability - ns=0;i=11282 */ |
| 89690 | |
| 89691 | static UA_StatusCode function_namespace0_generated_744_begin(UA_Server *server, UA_UInt16* ns) { |
| 89692 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89693 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89694 | attr.minimumSamplingInterval = 0.000000; |
| 89695 | attr.userAccessLevel = 1; |
| 89696 | attr.accessLevel = 1; |
| 89697 | /* Value rank inherited */ |
| 89698 | attr.valueRank = -2; |
| 89699 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 89700 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReplaceEventCapability"); |
| 89701 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89702 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11282LU), |
| 89703 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89704 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89705 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReplaceEventCapability"), |
| 89706 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89707 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89708 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89709 | return retVal; |
| 89710 | } |
| 89711 | |
| 89712 | static UA_StatusCode function_namespace0_generated_744_finish(UA_Server *server, UA_UInt16* ns) { |
| 89713 | return UA_Server_addNode_finish(server, |
| 89714 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11282LU) |
| 89715 | ); |
| 89716 | } |
| 89717 | |
| 89718 | /* InsertEventCapability - ns=0;i=11281 */ |
| 89719 | |
| 89720 | static UA_StatusCode function_namespace0_generated_745_begin(UA_Server *server, UA_UInt16* ns) { |
| 89721 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89722 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89723 | attr.minimumSamplingInterval = 0.000000; |
| 89724 | attr.userAccessLevel = 1; |
| 89725 | attr.accessLevel = 1; |
| 89726 | /* Value rank inherited */ |
| 89727 | attr.valueRank = -2; |
| 89728 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 89729 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InsertEventCapability"); |
| 89730 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89731 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11281LU), |
| 89732 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89733 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89734 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InsertEventCapability"), |
| 89735 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89736 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89737 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89738 | return retVal; |
| 89739 | } |
| 89740 | |
| 89741 | static UA_StatusCode function_namespace0_generated_745_finish(UA_Server *server, UA_UInt16* ns) { |
| 89742 | return UA_Server_addNode_finish(server, |
| 89743 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11281LU) |
| 89744 | ); |
| 89745 | } |
| 89746 | |
| 89747 | /* InsertAnnotationCapability - ns=0;i=11275 */ |
| 89748 | |
| 89749 | static UA_StatusCode function_namespace0_generated_746_begin(UA_Server *server, UA_UInt16* ns) { |
| 89750 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89751 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89752 | attr.minimumSamplingInterval = 0.000000; |
| 89753 | attr.userAccessLevel = 1; |
| 89754 | attr.accessLevel = 1; |
| 89755 | /* Value rank inherited */ |
| 89756 | attr.valueRank = -2; |
| 89757 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 89758 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InsertAnnotationCapability"); |
| 89759 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89760 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11275LU), |
| 89761 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89762 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89763 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InsertAnnotationCapability"), |
| 89764 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89765 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89766 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89767 | return retVal; |
| 89768 | } |
| 89769 | |
| 89770 | static UA_StatusCode function_namespace0_generated_746_finish(UA_Server *server, UA_UInt16* ns) { |
| 89771 | return UA_Server_addNode_finish(server, |
| 89772 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11275LU) |
| 89773 | ); |
| 89774 | } |
| 89775 | |
| 89776 | /* MaxReturnEventValues - ns=0;i=11274 */ |
| 89777 | |
| 89778 | static UA_StatusCode function_namespace0_generated_747_begin(UA_Server *server, UA_UInt16* ns) { |
| 89779 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89780 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89781 | attr.minimumSamplingInterval = 0.000000; |
| 89782 | attr.userAccessLevel = 1; |
| 89783 | attr.accessLevel = 1; |
| 89784 | /* Value rank inherited */ |
| 89785 | attr.valueRank = -2; |
| 89786 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89787 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxReturnEventValues"); |
| 89788 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89789 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11274LU), |
| 89790 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89791 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89792 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxReturnEventValues"), |
| 89793 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89794 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89795 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89796 | return retVal; |
| 89797 | } |
| 89798 | |
| 89799 | static UA_StatusCode function_namespace0_generated_747_finish(UA_Server *server, UA_UInt16* ns) { |
| 89800 | return UA_Server_addNode_finish(server, |
| 89801 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11274LU) |
| 89802 | ); |
| 89803 | } |
| 89804 | |
| 89805 | /* MaxReturnDataValues - ns=0;i=11273 */ |
| 89806 | |
| 89807 | static UA_StatusCode function_namespace0_generated_748_begin(UA_Server *server, UA_UInt16* ns) { |
| 89808 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89809 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89810 | attr.minimumSamplingInterval = 0.000000; |
| 89811 | attr.userAccessLevel = 1; |
| 89812 | attr.accessLevel = 1; |
| 89813 | /* Value rank inherited */ |
| 89814 | attr.valueRank = -2; |
| 89815 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 89816 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MaxReturnDataValues"); |
| 89817 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89818 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11273LU), |
| 89819 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89820 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89821 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MaxReturnDataValues"), |
| 89822 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89823 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89824 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89825 | return retVal; |
| 89826 | } |
| 89827 | |
| 89828 | static UA_StatusCode function_namespace0_generated_748_finish(UA_Server *server, UA_UInt16* ns) { |
| 89829 | return UA_Server_addNode_finish(server, |
| 89830 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11273LU) |
| 89831 | ); |
| 89832 | } |
| 89833 | |
| 89834 | /* AccessHistoryEventsCapability - ns=0;i=11242 */ |
| 89835 | |
| 89836 | static UA_StatusCode function_namespace0_generated_749_begin(UA_Server *server, UA_UInt16* ns) { |
| 89837 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89838 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89839 | attr.minimumSamplingInterval = 0.000000; |
| 89840 | attr.userAccessLevel = 1; |
| 89841 | attr.accessLevel = 1; |
| 89842 | /* Value rank inherited */ |
| 89843 | attr.valueRank = -2; |
| 89844 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 89845 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AccessHistoryEventsCapability"); |
| 89846 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89847 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11242LU), |
| 89848 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89849 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89850 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AccessHistoryEventsCapability"), |
| 89851 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89852 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89853 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89854 | return retVal; |
| 89855 | } |
| 89856 | |
| 89857 | static UA_StatusCode function_namespace0_generated_749_finish(UA_Server *server, UA_UInt16* ns) { |
| 89858 | return UA_Server_addNode_finish(server, |
| 89859 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11242LU) |
| 89860 | ); |
| 89861 | } |
| 89862 | |
| 89863 | /* AggregateFunctions - ns=0;i=11201 */ |
| 89864 | |
| 89865 | static UA_StatusCode function_namespace0_generated_750_begin(UA_Server *server, UA_UInt16* ns) { |
| 89866 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89867 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 89868 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AggregateFunctions"); |
| 89869 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 89870 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11201LU), |
| 89871 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89872 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 89873 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AggregateFunctions"), |
| 89874 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 61LU), |
| 89875 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 89876 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89877 | return retVal; |
| 89878 | } |
| 89879 | |
| 89880 | static UA_StatusCode function_namespace0_generated_750_finish(UA_Server *server, UA_UInt16* ns) { |
| 89881 | return UA_Server_addNode_finish(server, |
| 89882 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11201LU) |
| 89883 | ); |
| 89884 | } |
| 89885 | |
| 89886 | /* DeleteAtTimeCapability - ns=0;i=11200 */ |
| 89887 | |
| 89888 | static UA_StatusCode function_namespace0_generated_751_begin(UA_Server *server, UA_UInt16* ns) { |
| 89889 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89890 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89891 | attr.minimumSamplingInterval = 0.000000; |
| 89892 | attr.userAccessLevel = 1; |
| 89893 | attr.accessLevel = 1; |
| 89894 | /* Value rank inherited */ |
| 89895 | attr.valueRank = -2; |
| 89896 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 89897 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteAtTimeCapability"); |
| 89898 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89899 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11200LU), |
| 89900 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89901 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89902 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteAtTimeCapability"), |
| 89903 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89904 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89905 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89906 | return retVal; |
| 89907 | } |
| 89908 | |
| 89909 | static UA_StatusCode function_namespace0_generated_751_finish(UA_Server *server, UA_UInt16* ns) { |
| 89910 | return UA_Server_addNode_finish(server, |
| 89911 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11200LU) |
| 89912 | ); |
| 89913 | } |
| 89914 | |
| 89915 | /* DeleteRawCapability - ns=0;i=11199 */ |
| 89916 | |
| 89917 | static UA_StatusCode function_namespace0_generated_752_begin(UA_Server *server, UA_UInt16* ns) { |
| 89918 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89919 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89920 | attr.minimumSamplingInterval = 0.000000; |
| 89921 | attr.userAccessLevel = 1; |
| 89922 | attr.accessLevel = 1; |
| 89923 | /* Value rank inherited */ |
| 89924 | attr.valueRank = -2; |
| 89925 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 89926 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DeleteRawCapability"); |
| 89927 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89928 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11199LU), |
| 89929 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89930 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89931 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DeleteRawCapability"), |
| 89932 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89933 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89934 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89935 | return retVal; |
| 89936 | } |
| 89937 | |
| 89938 | static UA_StatusCode function_namespace0_generated_752_finish(UA_Server *server, UA_UInt16* ns) { |
| 89939 | return UA_Server_addNode_finish(server, |
| 89940 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11199LU) |
| 89941 | ); |
| 89942 | } |
| 89943 | |
| 89944 | /* UpdateDataCapability - ns=0;i=11198 */ |
| 89945 | |
| 89946 | static UA_StatusCode function_namespace0_generated_753_begin(UA_Server *server, UA_UInt16* ns) { |
| 89947 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89948 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89949 | attr.minimumSamplingInterval = 0.000000; |
| 89950 | attr.userAccessLevel = 1; |
| 89951 | attr.accessLevel = 1; |
| 89952 | /* Value rank inherited */ |
| 89953 | attr.valueRank = -2; |
| 89954 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 89955 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "UpdateDataCapability"); |
| 89956 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89957 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11198LU), |
| 89958 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89959 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89960 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "UpdateDataCapability"), |
| 89961 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89962 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89963 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89964 | return retVal; |
| 89965 | } |
| 89966 | |
| 89967 | static UA_StatusCode function_namespace0_generated_753_finish(UA_Server *server, UA_UInt16* ns) { |
| 89968 | return UA_Server_addNode_finish(server, |
| 89969 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11198LU) |
| 89970 | ); |
| 89971 | } |
| 89972 | |
| 89973 | /* ReplaceDataCapability - ns=0;i=11197 */ |
| 89974 | |
| 89975 | static UA_StatusCode function_namespace0_generated_754_begin(UA_Server *server, UA_UInt16* ns) { |
| 89976 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 89977 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 89978 | attr.minimumSamplingInterval = 0.000000; |
| 89979 | attr.userAccessLevel = 1; |
| 89980 | attr.accessLevel = 1; |
| 89981 | /* Value rank inherited */ |
| 89982 | attr.valueRank = -2; |
| 89983 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 89984 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReplaceDataCapability"); |
| 89985 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 89986 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11197LU), |
| 89987 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 89988 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 89989 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReplaceDataCapability"), |
| 89990 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 89991 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 89992 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 89993 | return retVal; |
| 89994 | } |
| 89995 | |
| 89996 | static UA_StatusCode function_namespace0_generated_754_finish(UA_Server *server, UA_UInt16* ns) { |
| 89997 | return UA_Server_addNode_finish(server, |
| 89998 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11197LU) |
| 89999 | ); |
| 90000 | } |
| 90001 | |
| 90002 | /* InsertDataCapability - ns=0;i=11196 */ |
| 90003 | |
| 90004 | static UA_StatusCode function_namespace0_generated_755_begin(UA_Server *server, UA_UInt16* ns) { |
| 90005 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90006 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90007 | attr.minimumSamplingInterval = 0.000000; |
| 90008 | attr.userAccessLevel = 1; |
| 90009 | attr.accessLevel = 1; |
| 90010 | /* Value rank inherited */ |
| 90011 | attr.valueRank = -2; |
| 90012 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 90013 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InsertDataCapability"); |
| 90014 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90015 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11196LU), |
| 90016 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 90017 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90018 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InsertDataCapability"), |
| 90019 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90020 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90021 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90022 | return retVal; |
| 90023 | } |
| 90024 | |
| 90025 | static UA_StatusCode function_namespace0_generated_755_finish(UA_Server *server, UA_UInt16* ns) { |
| 90026 | return UA_Server_addNode_finish(server, |
| 90027 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11196LU) |
| 90028 | ); |
| 90029 | } |
| 90030 | |
| 90031 | /* AccessHistoryDataCapability - ns=0;i=11193 */ |
| 90032 | |
| 90033 | static UA_StatusCode function_namespace0_generated_756_begin(UA_Server *server, UA_UInt16* ns) { |
| 90034 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90035 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90036 | attr.minimumSamplingInterval = 0.000000; |
| 90037 | attr.userAccessLevel = 1; |
| 90038 | attr.accessLevel = 1; |
| 90039 | /* Value rank inherited */ |
| 90040 | attr.valueRank = -2; |
| 90041 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 1LU); |
| 90042 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AccessHistoryDataCapability"); |
| 90043 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90044 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11193LU), |
| 90045 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11192LU), |
| 90046 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90047 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AccessHistoryDataCapability"), |
| 90048 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90049 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90050 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90051 | return retVal; |
| 90052 | } |
| 90053 | |
| 90054 | static UA_StatusCode function_namespace0_generated_756_finish(UA_Server *server, UA_UInt16* ns) { |
| 90055 | return UA_Server_addNode_finish(server, |
| 90056 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11193LU) |
| 90057 | ); |
| 90058 | } |
| 90059 | |
| 90060 | /* ServiceLevel - ns=0;i=2267 */ |
| 90061 | |
| 90062 | static UA_StatusCode function_namespace0_generated_757_begin(UA_Server *server, UA_UInt16* ns) { |
| 90063 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90064 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90065 | attr.minimumSamplingInterval = 1000.000000; |
| 90066 | attr.userAccessLevel = 1; |
| 90067 | attr.accessLevel = 1; |
| 90068 | /* Value rank inherited */ |
| 90069 | attr.valueRank = -2; |
| 90070 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3LU); |
| 90071 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServiceLevel"); |
| 90072 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90073 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2267LU), |
| 90074 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 90075 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90076 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServiceLevel"), |
| 90077 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90078 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90079 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90080 | return retVal; |
| 90081 | } |
| 90082 | |
| 90083 | static UA_StatusCode function_namespace0_generated_757_finish(UA_Server *server, UA_UInt16* ns) { |
| 90084 | return UA_Server_addNode_finish(server, |
| 90085 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2267LU) |
| 90086 | ); |
| 90087 | } |
| 90088 | |
| 90089 | /* ServerStatus - ns=0;i=2256 */ |
| 90090 | |
| 90091 | static UA_StatusCode function_namespace0_generated_758_begin(UA_Server *server, UA_UInt16* ns) { |
| 90092 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90093 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90094 | attr.minimumSamplingInterval = 1000.000000; |
| 90095 | attr.userAccessLevel = 1; |
| 90096 | attr.accessLevel = 1; |
| 90097 | /* Value rank inherited */ |
| 90098 | attr.valueRank = -2; |
| 90099 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 862LU); |
| 90100 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerStatus"); |
| 90101 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90102 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU), |
| 90103 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 90104 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90105 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerStatus"), |
| 90106 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2138LU), |
| 90107 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90108 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90109 | return retVal; |
| 90110 | } |
| 90111 | |
| 90112 | static UA_StatusCode function_namespace0_generated_758_finish(UA_Server *server, UA_UInt16* ns) { |
| 90113 | return UA_Server_addNode_finish(server, |
| 90114 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU) |
| 90115 | ); |
| 90116 | } |
| 90117 | |
| 90118 | /* ShutdownReason - ns=0;i=2993 */ |
| 90119 | |
| 90120 | static UA_StatusCode function_namespace0_generated_759_begin(UA_Server *server, UA_UInt16* ns) { |
| 90121 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90122 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90123 | attr.minimumSamplingInterval = 0.000000; |
| 90124 | attr.userAccessLevel = 1; |
| 90125 | attr.accessLevel = 1; |
| 90126 | /* Value rank inherited */ |
| 90127 | attr.valueRank = -2; |
| 90128 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 21LU); |
| 90129 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ShutdownReason"); |
| 90130 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90131 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2993LU), |
| 90132 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU), |
| 90133 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90134 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ShutdownReason"), |
| 90135 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90136 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90137 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90138 | return retVal; |
| 90139 | } |
| 90140 | |
| 90141 | static UA_StatusCode function_namespace0_generated_759_finish(UA_Server *server, UA_UInt16* ns) { |
| 90142 | return UA_Server_addNode_finish(server, |
| 90143 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2993LU) |
| 90144 | ); |
| 90145 | } |
| 90146 | |
| 90147 | /* SecondsTillShutdown - ns=0;i=2992 */ |
| 90148 | |
| 90149 | static UA_StatusCode function_namespace0_generated_760_begin(UA_Server *server, UA_UInt16* ns) { |
| 90150 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90151 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90152 | attr.minimumSamplingInterval = 0.000000; |
| 90153 | attr.userAccessLevel = 1; |
| 90154 | attr.accessLevel = 1; |
| 90155 | /* Value rank inherited */ |
| 90156 | attr.valueRank = -2; |
| 90157 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 90158 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SecondsTillShutdown"); |
| 90159 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90160 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2992LU), |
| 90161 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU), |
| 90162 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90163 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SecondsTillShutdown"), |
| 90164 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90165 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90166 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90167 | return retVal; |
| 90168 | } |
| 90169 | |
| 90170 | static UA_StatusCode function_namespace0_generated_760_finish(UA_Server *server, UA_UInt16* ns) { |
| 90171 | return UA_Server_addNode_finish(server, |
| 90172 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2992LU) |
| 90173 | ); |
| 90174 | } |
| 90175 | |
| 90176 | /* BuildInfo - ns=0;i=2260 */ |
| 90177 | |
| 90178 | static UA_StatusCode function_namespace0_generated_761_begin(UA_Server *server, UA_UInt16* ns) { |
| 90179 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90180 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90181 | attr.minimumSamplingInterval = 0.000000; |
| 90182 | attr.userAccessLevel = 1; |
| 90183 | attr.accessLevel = 1; |
| 90184 | /* Value rank inherited */ |
| 90185 | attr.valueRank = -2; |
| 90186 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 338LU); |
| 90187 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildInfo"); |
| 90188 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90189 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU), |
| 90190 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU), |
| 90191 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90192 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildInfo"), |
| 90193 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3051LU), |
| 90194 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90195 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90196 | return retVal; |
| 90197 | } |
| 90198 | |
| 90199 | static UA_StatusCode function_namespace0_generated_761_finish(UA_Server *server, UA_UInt16* ns) { |
| 90200 | return UA_Server_addNode_finish(server, |
| 90201 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU) |
| 90202 | ); |
| 90203 | } |
| 90204 | |
| 90205 | /* BuildDate - ns=0;i=2266 */ |
| 90206 | |
| 90207 | static UA_StatusCode function_namespace0_generated_762_begin(UA_Server *server, UA_UInt16* ns) { |
| 90208 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90209 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90210 | attr.minimumSamplingInterval = 1000.000000; |
| 90211 | attr.userAccessLevel = 1; |
| 90212 | attr.accessLevel = 1; |
| 90213 | /* Value rank inherited */ |
| 90214 | attr.valueRank = -2; |
| 90215 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 90216 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildDate"); |
| 90217 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90218 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2266LU), |
| 90219 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU), |
| 90220 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90221 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildDate"), |
| 90222 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90223 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90224 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90225 | return retVal; |
| 90226 | } |
| 90227 | |
| 90228 | static UA_StatusCode function_namespace0_generated_762_finish(UA_Server *server, UA_UInt16* ns) { |
| 90229 | return UA_Server_addNode_finish(server, |
| 90230 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2266LU) |
| 90231 | ); |
| 90232 | } |
| 90233 | |
| 90234 | /* BuildNumber - ns=0;i=2265 */ |
| 90235 | |
| 90236 | static UA_StatusCode function_namespace0_generated_763_begin(UA_Server *server, UA_UInt16* ns) { |
| 90237 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90238 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90239 | attr.minimumSamplingInterval = 1000.000000; |
| 90240 | attr.userAccessLevel = 1; |
| 90241 | attr.accessLevel = 1; |
| 90242 | /* Value rank inherited */ |
| 90243 | attr.valueRank = -2; |
| 90244 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 90245 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "BuildNumber"); |
| 90246 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90247 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2265LU), |
| 90248 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU), |
| 90249 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90250 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "BuildNumber"), |
| 90251 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90252 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90253 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90254 | return retVal; |
| 90255 | } |
| 90256 | |
| 90257 | static UA_StatusCode function_namespace0_generated_763_finish(UA_Server *server, UA_UInt16* ns) { |
| 90258 | return UA_Server_addNode_finish(server, |
| 90259 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2265LU) |
| 90260 | ); |
| 90261 | } |
| 90262 | |
| 90263 | /* SoftwareVersion - ns=0;i=2264 */ |
| 90264 | |
| 90265 | static UA_StatusCode function_namespace0_generated_764_begin(UA_Server *server, UA_UInt16* ns) { |
| 90266 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90267 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90268 | attr.minimumSamplingInterval = 1000.000000; |
| 90269 | attr.userAccessLevel = 1; |
| 90270 | attr.accessLevel = 1; |
| 90271 | /* Value rank inherited */ |
| 90272 | attr.valueRank = -2; |
| 90273 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 90274 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SoftwareVersion"); |
| 90275 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90276 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2264LU), |
| 90277 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU), |
| 90278 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90279 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SoftwareVersion"), |
| 90280 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90281 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90282 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90283 | return retVal; |
| 90284 | } |
| 90285 | |
| 90286 | static UA_StatusCode function_namespace0_generated_764_finish(UA_Server *server, UA_UInt16* ns) { |
| 90287 | return UA_Server_addNode_finish(server, |
| 90288 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2264LU) |
| 90289 | ); |
| 90290 | } |
| 90291 | |
| 90292 | /* ManufacturerName - ns=0;i=2263 */ |
| 90293 | |
| 90294 | static UA_StatusCode function_namespace0_generated_765_begin(UA_Server *server, UA_UInt16* ns) { |
| 90295 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90296 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90297 | attr.minimumSamplingInterval = 1000.000000; |
| 90298 | attr.userAccessLevel = 1; |
| 90299 | attr.accessLevel = 1; |
| 90300 | /* Value rank inherited */ |
| 90301 | attr.valueRank = -2; |
| 90302 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 90303 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ManufacturerName"); |
| 90304 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90305 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2263LU), |
| 90306 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU), |
| 90307 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90308 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ManufacturerName"), |
| 90309 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90310 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90311 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90312 | return retVal; |
| 90313 | } |
| 90314 | |
| 90315 | static UA_StatusCode function_namespace0_generated_765_finish(UA_Server *server, UA_UInt16* ns) { |
| 90316 | return UA_Server_addNode_finish(server, |
| 90317 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2263LU) |
| 90318 | ); |
| 90319 | } |
| 90320 | |
| 90321 | /* ProductUri - ns=0;i=2262 */ |
| 90322 | |
| 90323 | static UA_StatusCode function_namespace0_generated_766_begin(UA_Server *server, UA_UInt16* ns) { |
| 90324 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90325 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90326 | attr.minimumSamplingInterval = 1000.000000; |
| 90327 | attr.userAccessLevel = 1; |
| 90328 | attr.accessLevel = 1; |
| 90329 | /* Value rank inherited */ |
| 90330 | attr.valueRank = -2; |
| 90331 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 90332 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ProductUri"); |
| 90333 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90334 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2262LU), |
| 90335 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU), |
| 90336 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90337 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ProductUri"), |
| 90338 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90339 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90340 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90341 | return retVal; |
| 90342 | } |
| 90343 | |
| 90344 | static UA_StatusCode function_namespace0_generated_766_finish(UA_Server *server, UA_UInt16* ns) { |
| 90345 | return UA_Server_addNode_finish(server, |
| 90346 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2262LU) |
| 90347 | ); |
| 90348 | } |
| 90349 | |
| 90350 | /* ProductName - ns=0;i=2261 */ |
| 90351 | |
| 90352 | static UA_StatusCode function_namespace0_generated_767_begin(UA_Server *server, UA_UInt16* ns) { |
| 90353 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90354 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90355 | attr.minimumSamplingInterval = 1000.000000; |
| 90356 | attr.userAccessLevel = 1; |
| 90357 | attr.accessLevel = 1; |
| 90358 | /* Value rank inherited */ |
| 90359 | attr.valueRank = -2; |
| 90360 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 90361 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ProductName"); |
| 90362 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90363 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2261LU), |
| 90364 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2260LU), |
| 90365 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90366 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ProductName"), |
| 90367 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90368 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90369 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90370 | return retVal; |
| 90371 | } |
| 90372 | |
| 90373 | static UA_StatusCode function_namespace0_generated_767_finish(UA_Server *server, UA_UInt16* ns) { |
| 90374 | return UA_Server_addNode_finish(server, |
| 90375 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2261LU) |
| 90376 | ); |
| 90377 | } |
| 90378 | |
| 90379 | /* State - ns=0;i=2259 */ |
| 90380 | |
| 90381 | static UA_StatusCode function_namespace0_generated_768_begin(UA_Server *server, UA_UInt16* ns) { |
| 90382 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90383 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90384 | attr.minimumSamplingInterval = 0.000000; |
| 90385 | attr.userAccessLevel = 1; |
| 90386 | attr.accessLevel = 1; |
| 90387 | /* Value rank inherited */ |
| 90388 | attr.valueRank = -2; |
| 90389 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 852LU); |
| 90390 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "State"); |
| 90391 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90392 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2259LU), |
| 90393 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU), |
| 90394 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90395 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "State"), |
| 90396 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90397 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90398 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90399 | return retVal; |
| 90400 | } |
| 90401 | |
| 90402 | static UA_StatusCode function_namespace0_generated_768_finish(UA_Server *server, UA_UInt16* ns) { |
| 90403 | return UA_Server_addNode_finish(server, |
| 90404 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2259LU) |
| 90405 | ); |
| 90406 | } |
| 90407 | |
| 90408 | /* CurrentTime - ns=0;i=2258 */ |
| 90409 | |
| 90410 | static UA_StatusCode function_namespace0_generated_769_begin(UA_Server *server, UA_UInt16* ns) { |
| 90411 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90412 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90413 | attr.minimumSamplingInterval = 0.000000; |
| 90414 | attr.userAccessLevel = 1; |
| 90415 | attr.accessLevel = 1; |
| 90416 | /* Value rank inherited */ |
| 90417 | attr.valueRank = -2; |
| 90418 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 90419 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "CurrentTime"); |
| 90420 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90421 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2258LU), |
| 90422 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU), |
| 90423 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90424 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "CurrentTime"), |
| 90425 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90426 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90427 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90428 | return retVal; |
| 90429 | } |
| 90430 | |
| 90431 | static UA_StatusCode function_namespace0_generated_769_finish(UA_Server *server, UA_UInt16* ns) { |
| 90432 | return UA_Server_addNode_finish(server, |
| 90433 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2258LU) |
| 90434 | ); |
| 90435 | } |
| 90436 | |
| 90437 | /* StartTime - ns=0;i=2257 */ |
| 90438 | |
| 90439 | static UA_StatusCode function_namespace0_generated_770_begin(UA_Server *server, UA_UInt16* ns) { |
| 90440 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90441 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90442 | attr.minimumSamplingInterval = 0.000000; |
| 90443 | attr.userAccessLevel = 1; |
| 90444 | attr.accessLevel = 1; |
| 90445 | /* Value rank inherited */ |
| 90446 | attr.valueRank = -2; |
| 90447 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 294LU); |
| 90448 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "StartTime"); |
| 90449 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90450 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2257LU), |
| 90451 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2256LU), |
| 90452 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90453 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "StartTime"), |
| 90454 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 90455 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90456 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90457 | return retVal; |
| 90458 | } |
| 90459 | |
| 90460 | static UA_StatusCode function_namespace0_generated_770_finish(UA_Server *server, UA_UInt16* ns) { |
| 90461 | return UA_Server_addNode_finish(server, |
| 90462 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2257LU) |
| 90463 | ); |
| 90464 | } |
| 90465 | |
| 90466 | /* NamespaceArray - ns=0;i=2255 */ |
| 90467 | |
| 90468 | static UA_StatusCode function_namespace0_generated_771_begin(UA_Server *server, UA_UInt16* ns) { |
| 90469 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90470 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90471 | attr.minimumSamplingInterval = 1000.000000; |
| 90472 | attr.userAccessLevel = 1; |
| 90473 | attr.accessLevel = 1; |
| 90474 | attr.valueRank = 1; |
| 90475 | attr.arrayDimensionsSize = 1; |
| 90476 | UA_UInt32 arrayDimensions[1]; |
| 90477 | arrayDimensions[0] = 0; |
| 90478 | attr.arrayDimensions = &arrayDimensions[0]; |
| 90479 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 90480 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamespaceArray"); |
| 90481 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90482 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2255LU), |
| 90483 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 90484 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90485 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamespaceArray"), |
| 90486 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90487 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90488 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90489 | return retVal; |
| 90490 | } |
| 90491 | |
| 90492 | static UA_StatusCode function_namespace0_generated_771_finish(UA_Server *server, UA_UInt16* ns) { |
| 90493 | return UA_Server_addNode_finish(server, |
| 90494 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2255LU) |
| 90495 | ); |
| 90496 | } |
| 90497 | |
| 90498 | /* ServerArray - ns=0;i=2254 */ |
| 90499 | |
| 90500 | static UA_StatusCode function_namespace0_generated_772_begin(UA_Server *server, UA_UInt16* ns) { |
| 90501 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90502 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90503 | attr.minimumSamplingInterval = 1000.000000; |
| 90504 | attr.userAccessLevel = 1; |
| 90505 | attr.accessLevel = 1; |
| 90506 | attr.valueRank = 1; |
| 90507 | attr.arrayDimensionsSize = 1; |
| 90508 | UA_UInt32 arrayDimensions[1]; |
| 90509 | arrayDimensions[0] = 0; |
| 90510 | attr.arrayDimensions = &arrayDimensions[0]; |
| 90511 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 90512 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ServerArray"); |
| 90513 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90514 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2254LU), |
| 90515 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 90516 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90517 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ServerArray"), |
| 90518 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90519 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90520 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90521 | return retVal; |
| 90522 | } |
| 90523 | |
| 90524 | static UA_StatusCode function_namespace0_generated_772_finish(UA_Server *server, UA_UInt16* ns) { |
| 90525 | return UA_Server_addNode_finish(server, |
| 90526 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2254LU) |
| 90527 | ); |
| 90528 | } |
| 90529 | |
| 90530 | /* PublishSubscribe - ns=0;i=14443 */ |
| 90531 | |
| 90532 | static UA_StatusCode function_namespace0_generated_773_begin(UA_Server *server, UA_UInt16* ns) { |
| 90533 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90534 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 90535 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishSubscribe"); |
| 90536 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 90537 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14443LU), |
| 90538 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 90539 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90540 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishSubscribe"), |
| 90541 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14416LU), |
| 90542 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 90543 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90544 | return retVal; |
| 90545 | } |
| 90546 | |
| 90547 | static UA_StatusCode function_namespace0_generated_773_finish(UA_Server *server, UA_UInt16* ns) { |
| 90548 | return UA_Server_addNode_finish(server, |
| 90549 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14443LU) |
| 90550 | ); |
| 90551 | } |
| 90552 | |
| 90553 | /* DefaultDatagramPublisherId - ns=0;i=25480 */ |
| 90554 | |
| 90555 | static UA_StatusCode function_namespace0_generated_774_begin(UA_Server *server, UA_UInt16* ns) { |
| 90556 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90557 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90558 | attr.minimumSamplingInterval = 0.000000; |
| 90559 | attr.userAccessLevel = 1; |
| 90560 | attr.accessLevel = 1; |
| 90561 | /* Value rank inherited */ |
| 90562 | attr.valueRank = -2; |
| 90563 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 9LU); |
| 90564 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DefaultDatagramPublisherId"); |
| 90565 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90566 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25480LU), |
| 90567 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14443LU), |
| 90568 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90569 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DefaultDatagramPublisherId"), |
| 90570 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90571 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90572 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90573 | return retVal; |
| 90574 | } |
| 90575 | |
| 90576 | static UA_StatusCode function_namespace0_generated_774_finish(UA_Server *server, UA_UInt16* ns) { |
| 90577 | return UA_Server_addNode_finish(server, |
| 90578 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25480LU) |
| 90579 | ); |
| 90580 | } |
| 90581 | |
| 90582 | /* PubSubConfiguration - ns=0;i=25451 */ |
| 90583 | |
| 90584 | static UA_StatusCode function_namespace0_generated_775_begin(UA_Server *server, UA_UInt16* ns) { |
| 90585 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90586 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 90587 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PubSubConfiguration"); |
| 90588 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 90589 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25451LU), |
| 90590 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14443LU), |
| 90591 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90592 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PubSubConfiguration"), |
| 90593 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 90594 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 90595 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90596 | return retVal; |
| 90597 | } |
| 90598 | |
| 90599 | static UA_StatusCode function_namespace0_generated_775_finish(UA_Server *server, UA_UInt16* ns) { |
| 90600 | return UA_Server_addNode_finish(server, |
| 90601 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25451LU) |
| 90602 | ); |
| 90603 | } |
| 90604 | |
| 90605 | /* ReserveIds - ns=0;i=25474 */ |
| 90606 | |
| 90607 | static UA_StatusCode function_namespace0_generated_776_begin(UA_Server *server, UA_UInt16* ns) { |
| 90608 | #ifdef UA_ENABLE_METHODCALLS |
| 90609 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90610 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 90611 | attr.executable = true; |
| 90612 | attr.userExecutable = true; |
| 90613 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ReserveIds"); |
| 90614 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 90615 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25474LU), |
| 90616 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25451LU), |
| 90617 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90618 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ReserveIds"), |
| 90619 | typeDefinition: UA_NODEID_NULL, |
| 90620 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 90621 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90622 | return retVal; |
| 90623 | #else |
| 90624 | return UA_STATUSCODE_GOOD; |
| 90625 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90626 | } |
| 90627 | |
| 90628 | static UA_StatusCode function_namespace0_generated_776_finish(UA_Server *server, UA_UInt16* ns) { |
| 90629 | #ifdef UA_ENABLE_METHODCALLS |
| 90630 | return UA_Server_addMethodNode_finish(server, |
| 90631 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25474LU) |
| 90632 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 90633 | #else |
| 90634 | return UA_STATUSCODE_GOOD; |
| 90635 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90636 | } |
| 90637 | |
| 90638 | /* OutputArguments - ns=0;i=25476 */ |
| 90639 | |
| 90640 | static UA_StatusCode function_namespace0_generated_777_begin(UA_Server *server, UA_UInt16* ns) { |
| 90641 | #ifdef UA_ENABLE_METHODCALLS |
| 90642 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90643 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90644 | attr.minimumSamplingInterval = 0.000000; |
| 90645 | attr.userAccessLevel = 1; |
| 90646 | attr.accessLevel = 1; |
| 90647 | attr.valueRank = 1; |
| 90648 | attr.arrayDimensionsSize = 1; |
| 90649 | UA_UInt32 arrayDimensions[1]; |
| 90650 | arrayDimensions[0] = 3; |
| 90651 | attr.arrayDimensions = &arrayDimensions[0]; |
| 90652 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 90653 | UA_Argument variablenode_ns_0_i_25476_variant_DataContents[3]; |
| 90654 | |
| 90655 | UA_init(p: &variablenode_ns_0_i_25476_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90656 | variablenode_ns_0_i_25476_variant_DataContents[0].name = UA_STRING(chars: "DefaultPublisherId"); |
| 90657 | variablenode_ns_0_i_25476_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 24LU); |
| 90658 | variablenode_ns_0_i_25476_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 90659 | |
| 90660 | UA_init(p: &variablenode_ns_0_i_25476_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90661 | variablenode_ns_0_i_25476_variant_DataContents[1].name = UA_STRING(chars: "WriterGroupIds"); |
| 90662 | variablenode_ns_0_i_25476_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 90663 | variablenode_ns_0_i_25476_variant_DataContents[1].valueRank = (UA_Int32) -1; |
| 90664 | |
| 90665 | UA_init(p: &variablenode_ns_0_i_25476_variant_DataContents[2], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90666 | variablenode_ns_0_i_25476_variant_DataContents[2].name = UA_STRING(chars: "DataSetWriterIds"); |
| 90667 | variablenode_ns_0_i_25476_variant_DataContents[2].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 90668 | variablenode_ns_0_i_25476_variant_DataContents[2].valueRank = (UA_Int32) -1; |
| 90669 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_25476_variant_DataContents, arraySize: (UA_Int32) 3, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90670 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 90671 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90672 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25476LU), |
| 90673 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25474LU), |
| 90674 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90675 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 90676 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90677 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90678 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90679 | |
| 90680 | |
| 90681 | |
| 90682 | return retVal; |
| 90683 | #else |
| 90684 | return UA_STATUSCODE_GOOD; |
| 90685 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90686 | } |
| 90687 | |
| 90688 | static UA_StatusCode function_namespace0_generated_777_finish(UA_Server *server, UA_UInt16* ns) { |
| 90689 | #ifdef UA_ENABLE_METHODCALLS |
| 90690 | return UA_Server_addNode_finish(server, |
| 90691 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25476LU) |
| 90692 | ); |
| 90693 | #else |
| 90694 | return UA_STATUSCODE_GOOD; |
| 90695 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90696 | } |
| 90697 | |
| 90698 | /* InputArguments - ns=0;i=25475 */ |
| 90699 | |
| 90700 | static UA_StatusCode function_namespace0_generated_778_begin(UA_Server *server, UA_UInt16* ns) { |
| 90701 | #ifdef UA_ENABLE_METHODCALLS |
| 90702 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90703 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90704 | attr.minimumSamplingInterval = 0.000000; |
| 90705 | attr.userAccessLevel = 1; |
| 90706 | attr.accessLevel = 1; |
| 90707 | attr.valueRank = 1; |
| 90708 | attr.arrayDimensionsSize = 1; |
| 90709 | UA_UInt32 arrayDimensions[1]; |
| 90710 | arrayDimensions[0] = 3; |
| 90711 | attr.arrayDimensions = &arrayDimensions[0]; |
| 90712 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 90713 | UA_Argument variablenode_ns_0_i_25475_variant_DataContents[3]; |
| 90714 | |
| 90715 | UA_init(p: &variablenode_ns_0_i_25475_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90716 | variablenode_ns_0_i_25475_variant_DataContents[0].name = UA_STRING(chars: "TransportProfileUri"); |
| 90717 | variablenode_ns_0_i_25475_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 90718 | variablenode_ns_0_i_25475_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 90719 | |
| 90720 | UA_init(p: &variablenode_ns_0_i_25475_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90721 | variablenode_ns_0_i_25475_variant_DataContents[1].name = UA_STRING(chars: "NumReqWriterGroupIds"); |
| 90722 | variablenode_ns_0_i_25475_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 90723 | variablenode_ns_0_i_25475_variant_DataContents[1].valueRank = (UA_Int32) -1; |
| 90724 | |
| 90725 | UA_init(p: &variablenode_ns_0_i_25475_variant_DataContents[2], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90726 | variablenode_ns_0_i_25475_variant_DataContents[2].name = UA_STRING(chars: "NumReqDataSetWriterIds"); |
| 90727 | variablenode_ns_0_i_25475_variant_DataContents[2].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 5LU); |
| 90728 | variablenode_ns_0_i_25475_variant_DataContents[2].valueRank = (UA_Int32) -1; |
| 90729 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_25475_variant_DataContents, arraySize: (UA_Int32) 3, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90730 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 90731 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90732 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25475LU), |
| 90733 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25474LU), |
| 90734 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90735 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 90736 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90737 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90738 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90739 | |
| 90740 | |
| 90741 | |
| 90742 | return retVal; |
| 90743 | #else |
| 90744 | return UA_STATUSCODE_GOOD; |
| 90745 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90746 | } |
| 90747 | |
| 90748 | static UA_StatusCode function_namespace0_generated_778_finish(UA_Server *server, UA_UInt16* ns) { |
| 90749 | #ifdef UA_ENABLE_METHODCALLS |
| 90750 | return UA_Server_addNode_finish(server, |
| 90751 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 25475LU) |
| 90752 | ); |
| 90753 | #else |
| 90754 | return UA_STATUSCODE_GOOD; |
| 90755 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90756 | } |
| 90757 | |
| 90758 | /* SubscribedDataSets - ns=0;i=23658 */ |
| 90759 | |
| 90760 | static UA_StatusCode function_namespace0_generated_779_begin(UA_Server *server, UA_UInt16* ns) { |
| 90761 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90762 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 90763 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SubscribedDataSets"); |
| 90764 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 90765 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23658LU), |
| 90766 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14443LU), |
| 90767 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90768 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SubscribedDataSets"), |
| 90769 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23795LU), |
| 90770 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 90771 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90772 | return retVal; |
| 90773 | } |
| 90774 | |
| 90775 | static UA_StatusCode function_namespace0_generated_779_finish(UA_Server *server, UA_UInt16* ns) { |
| 90776 | return UA_Server_addNode_finish(server, |
| 90777 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 23658LU) |
| 90778 | ); |
| 90779 | } |
| 90780 | |
| 90781 | /* SupportedTransportProfiles - ns=0;i=17481 */ |
| 90782 | |
| 90783 | static UA_StatusCode function_namespace0_generated_780_begin(UA_Server *server, UA_UInt16* ns) { |
| 90784 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90785 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90786 | attr.minimumSamplingInterval = 0.000000; |
| 90787 | attr.userAccessLevel = 1; |
| 90788 | attr.accessLevel = 1; |
| 90789 | attr.valueRank = 1; |
| 90790 | attr.arrayDimensionsSize = 1; |
| 90791 | UA_UInt32 arrayDimensions[1]; |
| 90792 | arrayDimensions[0] = 0; |
| 90793 | attr.arrayDimensions = &arrayDimensions[0]; |
| 90794 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 90795 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "SupportedTransportProfiles"); |
| 90796 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90797 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17481LU), |
| 90798 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14443LU), |
| 90799 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90800 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "SupportedTransportProfiles"), |
| 90801 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90802 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90803 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90804 | return retVal; |
| 90805 | } |
| 90806 | |
| 90807 | static UA_StatusCode function_namespace0_generated_780_finish(UA_Server *server, UA_UInt16* ns) { |
| 90808 | return UA_Server_addNode_finish(server, |
| 90809 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17481LU) |
| 90810 | ); |
| 90811 | } |
| 90812 | |
| 90813 | /* PublishedDataSets - ns=0;i=17371 */ |
| 90814 | |
| 90815 | static UA_StatusCode function_namespace0_generated_781_begin(UA_Server *server, UA_UInt16* ns) { |
| 90816 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90817 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 90818 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "PublishedDataSets"); |
| 90819 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 90820 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17371LU), |
| 90821 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14443LU), |
| 90822 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90823 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "PublishedDataSets"), |
| 90824 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14477LU), |
| 90825 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 90826 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90827 | return retVal; |
| 90828 | } |
| 90829 | |
| 90830 | static UA_StatusCode function_namespace0_generated_781_finish(UA_Server *server, UA_UInt16* ns) { |
| 90831 | return UA_Server_addNode_finish(server, |
| 90832 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17371LU) |
| 90833 | ); |
| 90834 | } |
| 90835 | |
| 90836 | /* RemoveConnection - ns=0;i=17369 */ |
| 90837 | |
| 90838 | static UA_StatusCode function_namespace0_generated_782_begin(UA_Server *server, UA_UInt16* ns) { |
| 90839 | #ifdef UA_ENABLE_METHODCALLS |
| 90840 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90841 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 90842 | attr.executable = true; |
| 90843 | attr.userExecutable = true; |
| 90844 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "RemoveConnection"); |
| 90845 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 90846 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17369LU), |
| 90847 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14443LU), |
| 90848 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90849 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "RemoveConnection"), |
| 90850 | typeDefinition: UA_NODEID_NULL, |
| 90851 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 90852 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90853 | return retVal; |
| 90854 | #else |
| 90855 | return UA_STATUSCODE_GOOD; |
| 90856 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90857 | } |
| 90858 | |
| 90859 | static UA_StatusCode function_namespace0_generated_782_finish(UA_Server *server, UA_UInt16* ns) { |
| 90860 | #ifdef UA_ENABLE_METHODCALLS |
| 90861 | return UA_Server_addMethodNode_finish(server, |
| 90862 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17369LU) |
| 90863 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 90864 | #else |
| 90865 | return UA_STATUSCODE_GOOD; |
| 90866 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90867 | } |
| 90868 | |
| 90869 | /* InputArguments - ns=0;i=17370 */ |
| 90870 | |
| 90871 | static UA_StatusCode function_namespace0_generated_783_begin(UA_Server *server, UA_UInt16* ns) { |
| 90872 | #ifdef UA_ENABLE_METHODCALLS |
| 90873 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90874 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90875 | attr.minimumSamplingInterval = 0.000000; |
| 90876 | attr.userAccessLevel = 1; |
| 90877 | attr.accessLevel = 1; |
| 90878 | attr.valueRank = 1; |
| 90879 | attr.arrayDimensionsSize = 1; |
| 90880 | UA_UInt32 arrayDimensions[1]; |
| 90881 | arrayDimensions[0] = 0; |
| 90882 | attr.arrayDimensions = &arrayDimensions[0]; |
| 90883 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 90884 | UA_Argument variablenode_ns_0_i_17370_variant_DataContents[1]; |
| 90885 | |
| 90886 | UA_init(p: &variablenode_ns_0_i_17370_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90887 | variablenode_ns_0_i_17370_variant_DataContents[0].name = UA_STRING(chars: "ConnectionId"); |
| 90888 | variablenode_ns_0_i_17370_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 90889 | variablenode_ns_0_i_17370_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 90890 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17370_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90891 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 90892 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90893 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17370LU), |
| 90894 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17369LU), |
| 90895 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90896 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 90897 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90898 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90899 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90900 | |
| 90901 | return retVal; |
| 90902 | #else |
| 90903 | return UA_STATUSCODE_GOOD; |
| 90904 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90905 | } |
| 90906 | |
| 90907 | static UA_StatusCode function_namespace0_generated_783_finish(UA_Server *server, UA_UInt16* ns) { |
| 90908 | #ifdef UA_ENABLE_METHODCALLS |
| 90909 | return UA_Server_addNode_finish(server, |
| 90910 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17370LU) |
| 90911 | ); |
| 90912 | #else |
| 90913 | return UA_STATUSCODE_GOOD; |
| 90914 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90915 | } |
| 90916 | |
| 90917 | /* AddConnection - ns=0;i=17366 */ |
| 90918 | |
| 90919 | static UA_StatusCode function_namespace0_generated_784_begin(UA_Server *server, UA_UInt16* ns) { |
| 90920 | #ifdef UA_ENABLE_METHODCALLS |
| 90921 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90922 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 90923 | attr.executable = true; |
| 90924 | attr.userExecutable = true; |
| 90925 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "AddConnection"); |
| 90926 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 90927 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17366LU), |
| 90928 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 14443LU), |
| 90929 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 90930 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "AddConnection"), |
| 90931 | typeDefinition: UA_NODEID_NULL, |
| 90932 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 90933 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90934 | return retVal; |
| 90935 | #else |
| 90936 | return UA_STATUSCODE_GOOD; |
| 90937 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90938 | } |
| 90939 | |
| 90940 | static UA_StatusCode function_namespace0_generated_784_finish(UA_Server *server, UA_UInt16* ns) { |
| 90941 | #ifdef UA_ENABLE_METHODCALLS |
| 90942 | return UA_Server_addMethodNode_finish(server, |
| 90943 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17366LU) |
| 90944 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 90945 | #else |
| 90946 | return UA_STATUSCODE_GOOD; |
| 90947 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90948 | } |
| 90949 | |
| 90950 | /* OutputArguments - ns=0;i=17368 */ |
| 90951 | |
| 90952 | static UA_StatusCode function_namespace0_generated_785_begin(UA_Server *server, UA_UInt16* ns) { |
| 90953 | #ifdef UA_ENABLE_METHODCALLS |
| 90954 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 90955 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 90956 | attr.minimumSamplingInterval = 0.000000; |
| 90957 | attr.userAccessLevel = 1; |
| 90958 | attr.accessLevel = 1; |
| 90959 | attr.valueRank = 1; |
| 90960 | attr.arrayDimensionsSize = 1; |
| 90961 | UA_UInt32 arrayDimensions[1]; |
| 90962 | arrayDimensions[0] = 0; |
| 90963 | attr.arrayDimensions = &arrayDimensions[0]; |
| 90964 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 90965 | UA_Argument variablenode_ns_0_i_17368_variant_DataContents[1]; |
| 90966 | |
| 90967 | UA_init(p: &variablenode_ns_0_i_17368_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90968 | variablenode_ns_0_i_17368_variant_DataContents[0].name = UA_STRING(chars: "ConnectionId"); |
| 90969 | variablenode_ns_0_i_17368_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17LU); |
| 90970 | variablenode_ns_0_i_17368_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 90971 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17368_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 90972 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 90973 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 90974 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17368LU), |
| 90975 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17366LU), |
| 90976 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 90977 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 90978 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 90979 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 90980 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 90981 | |
| 90982 | return retVal; |
| 90983 | #else |
| 90984 | return UA_STATUSCODE_GOOD; |
| 90985 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90986 | } |
| 90987 | |
| 90988 | static UA_StatusCode function_namespace0_generated_785_finish(UA_Server *server, UA_UInt16* ns) { |
| 90989 | #ifdef UA_ENABLE_METHODCALLS |
| 90990 | return UA_Server_addNode_finish(server, |
| 90991 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17368LU) |
| 90992 | ); |
| 90993 | #else |
| 90994 | return UA_STATUSCODE_GOOD; |
| 90995 | #endif /* UA_ENABLE_METHODCALLS */ |
| 90996 | } |
| 90997 | |
| 90998 | /* InputArguments - ns=0;i=17367 */ |
| 90999 | |
| 91000 | static UA_StatusCode function_namespace0_generated_786_begin(UA_Server *server, UA_UInt16* ns) { |
| 91001 | #ifdef UA_ENABLE_METHODCALLS |
| 91002 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91003 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 91004 | attr.minimumSamplingInterval = 0.000000; |
| 91005 | attr.userAccessLevel = 1; |
| 91006 | attr.accessLevel = 1; |
| 91007 | attr.valueRank = 1; |
| 91008 | attr.arrayDimensionsSize = 1; |
| 91009 | UA_UInt32 arrayDimensions[1]; |
| 91010 | arrayDimensions[0] = 0; |
| 91011 | attr.arrayDimensions = &arrayDimensions[0]; |
| 91012 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 91013 | UA_Argument variablenode_ns_0_i_17367_variant_DataContents[1]; |
| 91014 | |
| 91015 | UA_init(p: &variablenode_ns_0_i_17367_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 91016 | variablenode_ns_0_i_17367_variant_DataContents[0].name = UA_STRING(chars: "Configuration"); |
| 91017 | variablenode_ns_0_i_17367_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15617LU); |
| 91018 | variablenode_ns_0_i_17367_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 91019 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_17367_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 91020 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 91021 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 91022 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17367LU), |
| 91023 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17366LU), |
| 91024 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 91025 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 91026 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 91027 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 91028 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91029 | |
| 91030 | return retVal; |
| 91031 | #else |
| 91032 | return UA_STATUSCODE_GOOD; |
| 91033 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91034 | } |
| 91035 | |
| 91036 | static UA_StatusCode function_namespace0_generated_786_finish(UA_Server *server, UA_UInt16* ns) { |
| 91037 | #ifdef UA_ENABLE_METHODCALLS |
| 91038 | return UA_Server_addNode_finish(server, |
| 91039 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 17367LU) |
| 91040 | ); |
| 91041 | #else |
| 91042 | return UA_STATUSCODE_GOOD; |
| 91043 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91044 | } |
| 91045 | |
| 91046 | /* ResendData - ns=0;i=12873 */ |
| 91047 | |
| 91048 | static UA_StatusCode function_namespace0_generated_787_begin(UA_Server *server, UA_UInt16* ns) { |
| 91049 | #ifdef UA_ENABLE_METHODCALLS |
| 91050 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91051 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 91052 | attr.executable = true; |
| 91053 | attr.userExecutable = true; |
| 91054 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ResendData"); |
| 91055 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 91056 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12873LU), |
| 91057 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 91058 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 91059 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ResendData"), |
| 91060 | typeDefinition: UA_NODEID_NULL, |
| 91061 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 91062 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91063 | return retVal; |
| 91064 | #else |
| 91065 | return UA_STATUSCODE_GOOD; |
| 91066 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91067 | } |
| 91068 | |
| 91069 | static UA_StatusCode function_namespace0_generated_787_finish(UA_Server *server, UA_UInt16* ns) { |
| 91070 | #ifdef UA_ENABLE_METHODCALLS |
| 91071 | return UA_Server_addMethodNode_finish(server, |
| 91072 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12873LU) |
| 91073 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 91074 | #else |
| 91075 | return UA_STATUSCODE_GOOD; |
| 91076 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91077 | } |
| 91078 | |
| 91079 | /* InputArguments - ns=0;i=12874 */ |
| 91080 | |
| 91081 | static UA_StatusCode function_namespace0_generated_788_begin(UA_Server *server, UA_UInt16* ns) { |
| 91082 | #ifdef UA_ENABLE_METHODCALLS |
| 91083 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91084 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 91085 | attr.minimumSamplingInterval = 0.000000; |
| 91086 | attr.userAccessLevel = 1; |
| 91087 | attr.accessLevel = 1; |
| 91088 | attr.valueRank = 1; |
| 91089 | attr.arrayDimensionsSize = 1; |
| 91090 | UA_UInt32 arrayDimensions[1]; |
| 91091 | arrayDimensions[0] = 1; |
| 91092 | attr.arrayDimensions = &arrayDimensions[0]; |
| 91093 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 91094 | UA_Argument variablenode_ns_0_i_12874_variant_DataContents[1]; |
| 91095 | |
| 91096 | UA_init(p: &variablenode_ns_0_i_12874_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 91097 | variablenode_ns_0_i_12874_variant_DataContents[0].name = UA_STRING(chars: "SubscriptionId"); |
| 91098 | variablenode_ns_0_i_12874_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 91099 | variablenode_ns_0_i_12874_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 91100 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_12874_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 91101 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 91102 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 91103 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12874LU), |
| 91104 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12873LU), |
| 91105 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 91106 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 91107 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 91108 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 91109 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91110 | |
| 91111 | return retVal; |
| 91112 | #else |
| 91113 | return UA_STATUSCODE_GOOD; |
| 91114 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91115 | } |
| 91116 | |
| 91117 | static UA_StatusCode function_namespace0_generated_788_finish(UA_Server *server, UA_UInt16* ns) { |
| 91118 | #ifdef UA_ENABLE_METHODCALLS |
| 91119 | return UA_Server_addNode_finish(server, |
| 91120 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12874LU) |
| 91121 | ); |
| 91122 | #else |
| 91123 | return UA_STATUSCODE_GOOD; |
| 91124 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91125 | } |
| 91126 | |
| 91127 | /* GetMonitoredItems - ns=0;i=11492 */ |
| 91128 | |
| 91129 | static UA_StatusCode function_namespace0_generated_789_begin(UA_Server *server, UA_UInt16* ns) { |
| 91130 | #ifdef UA_ENABLE_METHODCALLS |
| 91131 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91132 | UA_MethodAttributes attr = UA_MethodAttributes_default; |
| 91133 | attr.executable = true; |
| 91134 | attr.userExecutable = true; |
| 91135 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "GetMonitoredItems"); |
| 91136 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_METHOD, |
| 91137 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU), |
| 91138 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2253LU), |
| 91139 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 91140 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "GetMonitoredItems"), |
| 91141 | typeDefinition: UA_NODEID_NULL, |
| 91142 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_METHODATTRIBUTES],NULL, NULL); |
| 91143 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91144 | return retVal; |
| 91145 | #else |
| 91146 | return UA_STATUSCODE_GOOD; |
| 91147 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91148 | } |
| 91149 | |
| 91150 | static UA_StatusCode function_namespace0_generated_789_finish(UA_Server *server, UA_UInt16* ns) { |
| 91151 | #ifdef UA_ENABLE_METHODCALLS |
| 91152 | return UA_Server_addMethodNode_finish(server, |
| 91153 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU) |
| 91154 | , NULL, inputArgumentsSize: 0, NULL, outputArgumentsSize: 0, NULL); |
| 91155 | #else |
| 91156 | return UA_STATUSCODE_GOOD; |
| 91157 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91158 | } |
| 91159 | |
| 91160 | /* OutputArguments - ns=0;i=11494 */ |
| 91161 | |
| 91162 | static UA_StatusCode function_namespace0_generated_790_begin(UA_Server *server, UA_UInt16* ns) { |
| 91163 | #ifdef UA_ENABLE_METHODCALLS |
| 91164 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91165 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 91166 | attr.minimumSamplingInterval = 0.000000; |
| 91167 | attr.userAccessLevel = 1; |
| 91168 | attr.accessLevel = 1; |
| 91169 | attr.valueRank = 1; |
| 91170 | attr.arrayDimensionsSize = 1; |
| 91171 | UA_UInt32 arrayDimensions[1]; |
| 91172 | arrayDimensions[0] = 0; |
| 91173 | attr.arrayDimensions = &arrayDimensions[0]; |
| 91174 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 91175 | UA_Argument variablenode_ns_0_i_11494_variant_DataContents[2]; |
| 91176 | |
| 91177 | UA_init(p: &variablenode_ns_0_i_11494_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 91178 | variablenode_ns_0_i_11494_variant_DataContents[0].name = UA_STRING(chars: "ServerHandles"); |
| 91179 | variablenode_ns_0_i_11494_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 91180 | variablenode_ns_0_i_11494_variant_DataContents[0].valueRank = (UA_Int32) 1; |
| 91181 | UA_STACKARRAY(UA_UInt32, variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions, 1); |
| 91182 | UA_init(p: variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 91183 | variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions[0] = (UA_UInt32) 0; |
| 91184 | variablenode_ns_0_i_11494_variant_DataContents[0].arrayDimensionsSize = 1; |
| 91185 | variablenode_ns_0_i_11494_variant_DataContents[0].arrayDimensions = variablenode_ns_0_i_11494_variant_DataContents0_arrayDimensions; |
| 91186 | |
| 91187 | UA_init(p: &variablenode_ns_0_i_11494_variant_DataContents[1], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 91188 | variablenode_ns_0_i_11494_variant_DataContents[1].name = UA_STRING(chars: "ClientHandles"); |
| 91189 | variablenode_ns_0_i_11494_variant_DataContents[1].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 91190 | variablenode_ns_0_i_11494_variant_DataContents[1].valueRank = (UA_Int32) 1; |
| 91191 | UA_STACKARRAY(UA_UInt32, variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions, 1); |
| 91192 | UA_init(p: variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 91193 | variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions[0] = (UA_UInt32) 0; |
| 91194 | variablenode_ns_0_i_11494_variant_DataContents[1].arrayDimensionsSize = 1; |
| 91195 | variablenode_ns_0_i_11494_variant_DataContents[1].arrayDimensions = variablenode_ns_0_i_11494_variant_DataContents1_arrayDimensions; |
| 91196 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_11494_variant_DataContents, arraySize: (UA_Int32) 2, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 91197 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OutputArguments"); |
| 91198 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 91199 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11494LU), |
| 91200 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU), |
| 91201 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 91202 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OutputArguments"), |
| 91203 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 91204 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 91205 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91206 | |
| 91207 | |
| 91208 | return retVal; |
| 91209 | #else |
| 91210 | return UA_STATUSCODE_GOOD; |
| 91211 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91212 | } |
| 91213 | |
| 91214 | static UA_StatusCode function_namespace0_generated_790_finish(UA_Server *server, UA_UInt16* ns) { |
| 91215 | #ifdef UA_ENABLE_METHODCALLS |
| 91216 | return UA_Server_addNode_finish(server, |
| 91217 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11494LU) |
| 91218 | ); |
| 91219 | #else |
| 91220 | return UA_STATUSCODE_GOOD; |
| 91221 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91222 | } |
| 91223 | |
| 91224 | /* InputArguments - ns=0;i=11493 */ |
| 91225 | |
| 91226 | static UA_StatusCode function_namespace0_generated_791_begin(UA_Server *server, UA_UInt16* ns) { |
| 91227 | #ifdef UA_ENABLE_METHODCALLS |
| 91228 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91229 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 91230 | attr.minimumSamplingInterval = 0.000000; |
| 91231 | attr.userAccessLevel = 1; |
| 91232 | attr.accessLevel = 1; |
| 91233 | attr.valueRank = 1; |
| 91234 | attr.arrayDimensionsSize = 1; |
| 91235 | UA_UInt32 arrayDimensions[1]; |
| 91236 | arrayDimensions[0] = 0; |
| 91237 | attr.arrayDimensions = &arrayDimensions[0]; |
| 91238 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU); |
| 91239 | UA_Argument variablenode_ns_0_i_11493_variant_DataContents[1]; |
| 91240 | |
| 91241 | UA_init(p: &variablenode_ns_0_i_11493_variant_DataContents[0], type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 91242 | variablenode_ns_0_i_11493_variant_DataContents[0].name = UA_STRING(chars: "SubscriptionId"); |
| 91243 | variablenode_ns_0_i_11493_variant_DataContents[0].dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7LU); |
| 91244 | variablenode_ns_0_i_11493_variant_DataContents[0].valueRank = (UA_Int32) -1; |
| 91245 | UA_Variant_setArray(v: &attr.value, array: &variablenode_ns_0_i_11493_variant_DataContents, arraySize: (UA_Int32) 1, type: &UA_TYPES[UA_TYPES_ARGUMENT]); |
| 91246 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "InputArguments"); |
| 91247 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 91248 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11493LU), |
| 91249 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11492LU), |
| 91250 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 91251 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "InputArguments"), |
| 91252 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 91253 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 91254 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91255 | |
| 91256 | return retVal; |
| 91257 | #else |
| 91258 | return UA_STATUSCODE_GOOD; |
| 91259 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91260 | } |
| 91261 | |
| 91262 | static UA_StatusCode function_namespace0_generated_791_finish(UA_Server *server, UA_UInt16* ns) { |
| 91263 | #ifdef UA_ENABLE_METHODCALLS |
| 91264 | return UA_Server_addNode_finish(server, |
| 91265 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11493LU) |
| 91266 | ); |
| 91267 | #else |
| 91268 | return UA_STATUSCODE_GOOD; |
| 91269 | #endif /* UA_ENABLE_METHODCALLS */ |
| 91270 | } |
| 91271 | |
| 91272 | /* VendorServerInfo - ns=0;i=2011 */ |
| 91273 | |
| 91274 | static UA_StatusCode function_namespace0_generated_792_begin(UA_Server *server, UA_UInt16* ns) { |
| 91275 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91276 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 91277 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "VendorServerInfo"); |
| 91278 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 91279 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2011LU), |
| 91280 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2004LU), |
| 91281 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 91282 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "VendorServerInfo"), |
| 91283 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2033LU), |
| 91284 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 91285 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91286 | return retVal; |
| 91287 | } |
| 91288 | |
| 91289 | static UA_StatusCode function_namespace0_generated_792_finish(UA_Server *server, UA_UInt16* ns) { |
| 91290 | return UA_Server_addNode_finish(server, |
| 91291 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 2011LU) |
| 91292 | ); |
| 91293 | } |
| 91294 | |
| 91295 | /* ModellingRuleType - ns=0;i=77 */ |
| 91296 | |
| 91297 | static UA_StatusCode function_namespace0_generated_793_begin(UA_Server *server, UA_UInt16* ns) { |
| 91298 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91299 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 91300 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ModellingRuleType"); |
| 91301 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 91302 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU), |
| 91303 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 91304 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 91305 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ModellingRuleType"), |
| 91306 | typeDefinition: UA_NODEID_NULL, |
| 91307 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 91308 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91309 | return retVal; |
| 91310 | } |
| 91311 | |
| 91312 | static UA_StatusCode function_namespace0_generated_793_finish(UA_Server *server, UA_UInt16* ns) { |
| 91313 | return UA_Server_addNode_finish(server, |
| 91314 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU) |
| 91315 | ); |
| 91316 | } |
| 91317 | |
| 91318 | /* ExposesItsArray - ns=0;i=83 */ |
| 91319 | |
| 91320 | static UA_StatusCode function_namespace0_generated_794_begin(UA_Server *server, UA_UInt16* ns) { |
| 91321 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91322 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 91323 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "ExposesItsArray"); |
| 91324 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 91325 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU), |
| 91326 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 91327 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 91328 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "ExposesItsArray"), |
| 91329 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU), |
| 91330 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 91331 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91332 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12860LU), false); |
| 91333 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91334 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12816LU), false); |
| 91335 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91336 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12779LU), false); |
| 91337 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91338 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12784LU), false); |
| 91339 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91340 | return retVal; |
| 91341 | } |
| 91342 | |
| 91343 | static UA_StatusCode function_namespace0_generated_794_finish(UA_Server *server, UA_UInt16* ns) { |
| 91344 | return UA_Server_addNode_finish(server, |
| 91345 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU) |
| 91346 | ); |
| 91347 | } |
| 91348 | |
| 91349 | /* NamingRule - ns=0;i=114 */ |
| 91350 | |
| 91351 | static UA_StatusCode function_namespace0_generated_795_begin(UA_Server *server, UA_UInt16* ns) { |
| 91352 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91353 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 91354 | attr.minimumSamplingInterval = 0.000000; |
| 91355 | attr.userAccessLevel = 1; |
| 91356 | attr.accessLevel = 1; |
| 91357 | /* Value rank inherited */ |
| 91358 | attr.valueRank = -2; |
| 91359 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU); |
| 91360 | UA_Int32 *variablenode_ns_0_i_114_variant_DataContents = UA_Int32_new(); |
| 91361 | if (!variablenode_ns_0_i_114_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 91362 | UA_Int32_init(p: variablenode_ns_0_i_114_variant_DataContents); |
| 91363 | *variablenode_ns_0_i_114_variant_DataContents = (UA_Int32) 3; |
| 91364 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_114_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]); |
| 91365 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule"); |
| 91366 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 91367 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 114LU), |
| 91368 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 83LU), |
| 91369 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 91370 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"), |
| 91371 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 91372 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 91373 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91374 | UA_Int32_delete(p: variablenode_ns_0_i_114_variant_DataContents); |
| 91375 | return retVal; |
| 91376 | } |
| 91377 | |
| 91378 | static UA_StatusCode function_namespace0_generated_795_finish(UA_Server *server, UA_UInt16* ns) { |
| 91379 | return UA_Server_addNode_finish(server, |
| 91380 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 114LU) |
| 91381 | ); |
| 91382 | } |
| 91383 | |
| 91384 | /* Optional - ns=0;i=80 */ |
| 91385 | |
| 91386 | static UA_StatusCode function_namespace0_generated_796_begin(UA_Server *server, UA_UInt16* ns) { |
| 91387 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91388 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 91389 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Optional"); |
| 91390 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 91391 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), |
| 91392 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 91393 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 91394 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Optional"), |
| 91395 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU), |
| 91396 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 91397 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91398 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11551LU), false); |
| 91399 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91400 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11565LU), false); |
| 91401 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91402 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11567LU), false); |
| 91403 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91404 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11569LU), false); |
| 91405 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91406 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11570LU), false); |
| 91407 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91408 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11571LU), false); |
| 91409 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91410 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11572LU), false); |
| 91411 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91412 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11573LU), false); |
| 91413 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91414 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11574LU), false); |
| 91415 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91416 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2022LU), false); |
| 91417 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91418 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3190LU), false); |
| 91419 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91420 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2757LU), false); |
| 91421 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91422 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2758LU), false); |
| 91423 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91424 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2759LU), false); |
| 91425 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91426 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9000LU), false); |
| 91427 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91428 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9001LU), false); |
| 91429 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91430 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11110LU), false); |
| 91431 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91432 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11111LU), false); |
| 91433 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91434 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9015LU), false); |
| 91435 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91436 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9016LU), false); |
| 91437 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91438 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9017LU), false); |
| 91439 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91440 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 25432LU), false); |
| 91441 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91442 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14493LU), false); |
| 91443 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91444 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14499LU), false); |
| 91445 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91446 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 16994LU), false); |
| 91447 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91448 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 16997LU), false); |
| 91449 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91450 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23622LU), false); |
| 91451 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91452 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 16759LU), false); |
| 91453 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91454 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14555LU), false); |
| 91455 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91456 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14558LU), false); |
| 91457 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91458 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17203LU), false); |
| 91459 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91460 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17427LU), false); |
| 91461 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91462 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17465LU), false); |
| 91463 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91464 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14225LU), false); |
| 91465 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91466 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15927LU), false); |
| 91467 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91468 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17969LU), false); |
| 91469 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91470 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17992LU), false); |
| 91471 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91472 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21094LU), false); |
| 91473 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91474 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15303LU), false); |
| 91475 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91476 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23797LU), false); |
| 91477 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91478 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23800LU), false); |
| 91479 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91480 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23802LU), false); |
| 91481 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91482 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23805LU), false); |
| 91483 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91484 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23811LU), false); |
| 91485 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91486 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23814LU), false); |
| 91487 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91488 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23816LU), false); |
| 91489 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91490 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23819LU), false); |
| 91491 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91492 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14645LU), false); |
| 91493 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91494 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14646LU), false); |
| 91495 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91496 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17633LU), false); |
| 91497 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91498 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 16312LU), false); |
| 91499 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91500 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 16598LU), false); |
| 91501 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91502 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14432LU), false); |
| 91503 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91504 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15115LU), false); |
| 91505 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91506 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15118LU), false); |
| 91507 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91508 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2366LU), false); |
| 91509 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91510 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2367LU), false); |
| 91511 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91512 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2370LU), false); |
| 91513 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91514 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2371LU), false); |
| 91515 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91516 | return retVal; |
| 91517 | } |
| 91518 | |
| 91519 | static UA_StatusCode function_namespace0_generated_796_finish(UA_Server *server, UA_UInt16* ns) { |
| 91520 | return UA_Server_addNode_finish(server, |
| 91521 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU) |
| 91522 | ); |
| 91523 | } |
| 91524 | |
| 91525 | /* NamingRule - ns=0;i=113 */ |
| 91526 | |
| 91527 | static UA_StatusCode function_namespace0_generated_797_begin(UA_Server *server, UA_UInt16* ns) { |
| 91528 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91529 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 91530 | attr.minimumSamplingInterval = 0.000000; |
| 91531 | attr.userAccessLevel = 1; |
| 91532 | attr.accessLevel = 1; |
| 91533 | /* Value rank inherited */ |
| 91534 | attr.valueRank = -2; |
| 91535 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU); |
| 91536 | UA_Int32 *variablenode_ns_0_i_113_variant_DataContents = UA_Int32_new(); |
| 91537 | if (!variablenode_ns_0_i_113_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 91538 | UA_Int32_init(p: variablenode_ns_0_i_113_variant_DataContents); |
| 91539 | *variablenode_ns_0_i_113_variant_DataContents = (UA_Int32) 2; |
| 91540 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_113_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]); |
| 91541 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule"); |
| 91542 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 91543 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 113LU), |
| 91544 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), |
| 91545 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 91546 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"), |
| 91547 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 91548 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 91549 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91550 | UA_Int32_delete(p: variablenode_ns_0_i_113_variant_DataContents); |
| 91551 | return retVal; |
| 91552 | } |
| 91553 | |
| 91554 | static UA_StatusCode function_namespace0_generated_797_finish(UA_Server *server, UA_UInt16* ns) { |
| 91555 | return UA_Server_addNode_finish(server, |
| 91556 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 113LU) |
| 91557 | ); |
| 91558 | } |
| 91559 | |
| 91560 | /* Mandatory - ns=0;i=78 */ |
| 91561 | |
| 91562 | static UA_StatusCode function_namespace0_generated_798_begin(UA_Server *server, UA_UInt16* ns) { |
| 91563 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 91564 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 91565 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Mandatory"); |
| 91566 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 91567 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), |
| 91568 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 91569 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 91570 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Mandatory"), |
| 91571 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU), |
| 91572 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 91573 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91574 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12169LU), false); |
| 91575 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91576 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2011LU), false); |
| 91577 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91578 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2035LU), false); |
| 91579 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91580 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 7611LU), false); |
| 91581 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91582 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2021LU), false); |
| 91583 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91584 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3116LU), false); |
| 91585 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91586 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3117LU), false); |
| 91587 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91588 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3118LU), false); |
| 91589 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91590 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3119LU), false); |
| 91591 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91592 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3120LU), false); |
| 91593 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91594 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3121LU), false); |
| 91595 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91596 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3122LU), false); |
| 91597 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91598 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3124LU), false); |
| 91599 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91600 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3125LU), false); |
| 91601 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91602 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3126LU), false); |
| 91603 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91604 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3127LU), false); |
| 91605 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91606 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3128LU), false); |
| 91607 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91608 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2023LU), false); |
| 91609 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91610 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12142LU), false); |
| 91611 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91612 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12152LU), false); |
| 91613 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91614 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12143LU), false); |
| 91615 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91616 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12144LU), false); |
| 91617 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91618 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12145LU), false); |
| 91619 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91620 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12146LU), false); |
| 91621 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91622 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12147LU), false); |
| 91623 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91624 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12148LU), false); |
| 91625 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91626 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12149LU), false); |
| 91627 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91628 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12150LU), false); |
| 91629 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91630 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12151LU), false); |
| 91631 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91632 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2027LU), false); |
| 91633 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91634 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2028LU), false); |
| 91635 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91636 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12098LU), false); |
| 91637 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91638 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12099LU), false); |
| 91639 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91640 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12100LU), false); |
| 91641 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91642 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12101LU), false); |
| 91643 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91644 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12102LU), false); |
| 91645 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91646 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12103LU), false); |
| 91647 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91648 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12104LU), false); |
| 91649 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91650 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12105LU), false); |
| 91651 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91652 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12106LU), false); |
| 91653 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91654 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12107LU), false); |
| 91655 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91656 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12108LU), false); |
| 91657 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91658 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12109LU), false); |
| 91659 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91660 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12110LU), false); |
| 91661 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91662 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12111LU), false); |
| 91663 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91664 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12112LU), false); |
| 91665 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91666 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12113LU), false); |
| 91667 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91668 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12114LU), false); |
| 91669 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91670 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12115LU), false); |
| 91671 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91672 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12116LU), false); |
| 91673 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91674 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12117LU), false); |
| 91675 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91676 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12118LU), false); |
| 91677 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91678 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12119LU), false); |
| 91679 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91680 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12120LU), false); |
| 91681 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91682 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12121LU), false); |
| 91683 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91684 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12122LU), false); |
| 91685 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91686 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12123LU), false); |
| 91687 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91688 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12124LU), false); |
| 91689 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91690 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12125LU), false); |
| 91691 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91692 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12126LU), false); |
| 91693 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91694 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12127LU), false); |
| 91695 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91696 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12128LU), false); |
| 91697 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91698 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12129LU), false); |
| 91699 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91700 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12130LU), false); |
| 91701 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91702 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12131LU), false); |
| 91703 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91704 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12132LU), false); |
| 91705 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91706 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12133LU), false); |
| 91707 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91708 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12134LU), false); |
| 91709 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91710 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12135LU), false); |
| 91711 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91712 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12136LU), false); |
| 91713 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91714 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12137LU), false); |
| 91715 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91716 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12138LU), false); |
| 91717 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91718 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12139LU), false); |
| 91719 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91720 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12140LU), false); |
| 91721 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91722 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12141LU), false); |
| 91723 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91724 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12861LU), false); |
| 91725 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91726 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12862LU), false); |
| 91727 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91728 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12863LU), false); |
| 91729 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91730 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12864LU), false); |
| 91731 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91732 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12865LU), false); |
| 91733 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91734 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12866LU), false); |
| 91735 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91736 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12867LU), false); |
| 91737 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91738 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12868LU), false); |
| 91739 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91740 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12869LU), false); |
| 91741 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91742 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2744LU), false); |
| 91743 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91744 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3129LU), false); |
| 91745 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91746 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3130LU), false); |
| 91747 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91748 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2025LU), false); |
| 91749 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91750 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12817LU), false); |
| 91751 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91752 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12818LU), false); |
| 91753 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91754 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12819LU), false); |
| 91755 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91756 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12820LU), false); |
| 91757 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91758 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12821LU), false); |
| 91759 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91760 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12822LU), false); |
| 91761 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91762 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12823LU), false); |
| 91763 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91764 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12824LU), false); |
| 91765 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91766 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12825LU), false); |
| 91767 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91768 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12826LU), false); |
| 91769 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91770 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12827LU), false); |
| 91771 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91772 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12828LU), false); |
| 91773 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91774 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12829LU), false); |
| 91775 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91776 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12830LU), false); |
| 91777 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91778 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12831LU), false); |
| 91779 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91780 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12832LU), false); |
| 91781 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91782 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12833LU), false); |
| 91783 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91784 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12834LU), false); |
| 91785 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91786 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12835LU), false); |
| 91787 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91788 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12836LU), false); |
| 91789 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91790 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12837LU), false); |
| 91791 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91792 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12838LU), false); |
| 91793 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91794 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12839LU), false); |
| 91795 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91796 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12840LU), false); |
| 91797 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91798 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12841LU), false); |
| 91799 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91800 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12842LU), false); |
| 91801 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91802 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12843LU), false); |
| 91803 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91804 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12844LU), false); |
| 91805 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91806 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12845LU), false); |
| 91807 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91808 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12846LU), false); |
| 91809 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91810 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12847LU), false); |
| 91811 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91812 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12848LU), false); |
| 91813 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91814 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12849LU), false); |
| 91815 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91816 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12850LU), false); |
| 91817 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91818 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12851LU), false); |
| 91819 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91820 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12852LU), false); |
| 91821 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91822 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12853LU), false); |
| 91823 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91824 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12854LU), false); |
| 91825 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91826 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12855LU), false); |
| 91827 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91828 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12856LU), false); |
| 91829 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91830 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12857LU), false); |
| 91831 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91832 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12858LU), false); |
| 91833 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91834 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12859LU), false); |
| 91835 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91836 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12780LU), false); |
| 91837 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91838 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12781LU), false); |
| 91839 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91840 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12782LU), false); |
| 91841 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91842 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12783LU), false); |
| 91843 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91844 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2166LU), false); |
| 91845 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91846 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11697LU), false); |
| 91847 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91848 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11698LU), false); |
| 91849 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91850 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11699LU), false); |
| 91851 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91852 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2151LU), false); |
| 91853 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91854 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2152LU), false); |
| 91855 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91856 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2153LU), false); |
| 91857 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91858 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2154LU), false); |
| 91859 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91860 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2155LU), false); |
| 91861 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91862 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2156LU), false); |
| 91863 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91864 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2157LU), false); |
| 91865 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91866 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2159LU), false); |
| 91867 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91868 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2160LU), false); |
| 91869 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91870 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2161LU), false); |
| 91871 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91872 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2162LU), false); |
| 91873 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91874 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2163LU), false); |
| 91875 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91876 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 7595LU), false); |
| 91877 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91878 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 7597LU), false); |
| 91879 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91880 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2030LU), false); |
| 91881 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91882 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3131LU), false); |
| 91883 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91884 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3132LU), false); |
| 91885 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91886 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3133LU), false); |
| 91887 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91888 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3134LU), false); |
| 91889 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91890 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3135LU), false); |
| 91891 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91892 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3136LU), false); |
| 91893 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91894 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3137LU), false); |
| 91895 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91896 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3138LU), false); |
| 91897 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91898 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3139LU), false); |
| 91899 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91900 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3140LU), false); |
| 91901 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91902 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3141LU), false); |
| 91903 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91904 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3142LU), false); |
| 91905 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91906 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3143LU), false); |
| 91907 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91908 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8898LU), false); |
| 91909 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91910 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11891LU), false); |
| 91911 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91912 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3151LU), false); |
| 91913 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91914 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3152LU), false); |
| 91915 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91916 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3153LU), false); |
| 91917 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91918 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3154LU), false); |
| 91919 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91920 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3155LU), false); |
| 91921 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91922 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3156LU), false); |
| 91923 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91924 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3157LU), false); |
| 91925 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91926 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3158LU), false); |
| 91927 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91928 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3159LU), false); |
| 91929 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91930 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3160LU), false); |
| 91931 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91932 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3161LU), false); |
| 91933 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91934 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3162LU), false); |
| 91935 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91936 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3163LU), false); |
| 91937 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91938 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3164LU), false); |
| 91939 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91940 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3165LU), false); |
| 91941 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91942 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3166LU), false); |
| 91943 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91944 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3167LU), false); |
| 91945 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91946 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3168LU), false); |
| 91947 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91948 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3169LU), false); |
| 91949 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91950 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3170LU), false); |
| 91951 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91952 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3171LU), false); |
| 91953 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91954 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3172LU), false); |
| 91955 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91956 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3173LU), false); |
| 91957 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91958 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3174LU), false); |
| 91959 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91960 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3175LU), false); |
| 91961 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91962 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3176LU), false); |
| 91963 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91964 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3177LU), false); |
| 91965 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91966 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3178LU), false); |
| 91967 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91968 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2031LU), false); |
| 91969 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91970 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3179LU), false); |
| 91971 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91972 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3180LU), false); |
| 91973 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91974 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3181LU), false); |
| 91975 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91976 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3182LU), false); |
| 91977 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91978 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3183LU), false); |
| 91979 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91980 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3184LU), false); |
| 91981 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91982 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3185LU), false); |
| 91983 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91984 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3186LU), false); |
| 91985 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91986 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3187LU), false); |
| 91987 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91988 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2245LU), false); |
| 91989 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91990 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2246LU), false); |
| 91991 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91992 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2247LU), false); |
| 91993 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91994 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2248LU), false); |
| 91995 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91996 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2249LU), false); |
| 91997 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 91998 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2250LU), false); |
| 91999 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92000 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2251LU), false); |
| 92001 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92002 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2252LU), false); |
| 92003 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92004 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3058LU), false); |
| 92005 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92006 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2032LU), false); |
| 92007 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92008 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12785LU), false); |
| 92009 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92010 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12786LU), false); |
| 92011 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92012 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12787LU), false); |
| 92013 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92014 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12788LU), false); |
| 92015 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92016 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12789LU), false); |
| 92017 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92018 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12790LU), false); |
| 92019 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92020 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12791LU), false); |
| 92021 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92022 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12792LU), false); |
| 92023 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92024 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12793LU), false); |
| 92025 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92026 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12794LU), false); |
| 92027 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92028 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12795LU), false); |
| 92029 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92030 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12796LU), false); |
| 92031 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92032 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12797LU), false); |
| 92033 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92034 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12798LU), false); |
| 92035 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92036 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12799LU), false); |
| 92037 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92038 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12800LU), false); |
| 92039 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92040 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12801LU), false); |
| 92041 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92042 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12802LU), false); |
| 92043 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92044 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12803LU), false); |
| 92045 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92046 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12804LU), false); |
| 92047 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92048 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12805LU), false); |
| 92049 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92050 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12806LU), false); |
| 92051 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92052 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12807LU), false); |
| 92053 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92054 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12808LU), false); |
| 92055 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92056 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12809LU), false); |
| 92057 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92058 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12810LU), false); |
| 92059 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92060 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12811LU), false); |
| 92061 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92062 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12812LU), false); |
| 92063 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92064 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12813LU), false); |
| 92065 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92066 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12814LU), false); |
| 92067 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92068 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12815LU), false); |
| 92069 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92070 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2173LU), false); |
| 92071 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92072 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2174LU), false); |
| 92073 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92074 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2175LU), false); |
| 92075 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92076 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2176LU), false); |
| 92077 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92078 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2177LU), false); |
| 92079 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92080 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8888LU), false); |
| 92081 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92082 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2179LU), false); |
| 92083 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92084 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2180LU), false); |
| 92085 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92086 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2181LU), false); |
| 92087 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92088 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2182LU), false); |
| 92089 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92090 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2183LU), false); |
| 92091 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92092 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2184LU), false); |
| 92093 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92094 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2185LU), false); |
| 92095 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92096 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2186LU), false); |
| 92097 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92098 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2187LU), false); |
| 92099 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92100 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2188LU), false); |
| 92101 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92102 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2189LU), false); |
| 92103 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92104 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2190LU), false); |
| 92105 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92106 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2191LU), false); |
| 92107 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92108 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2998LU), false); |
| 92109 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92110 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2193LU), false); |
| 92111 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92112 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8889LU), false); |
| 92113 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92114 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8890LU), false); |
| 92115 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92116 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8891LU), false); |
| 92117 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92118 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8892LU), false); |
| 92119 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92120 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8893LU), false); |
| 92121 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92122 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8894LU), false); |
| 92123 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92124 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8895LU), false); |
| 92125 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92126 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8896LU), false); |
| 92127 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92128 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8897LU), false); |
| 92129 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92130 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8902LU), false); |
| 92131 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92132 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2198LU), false); |
| 92133 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92134 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2199LU), false); |
| 92135 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92136 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2200LU), false); |
| 92137 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92138 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2201LU), false); |
| 92139 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92140 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2202LU), false); |
| 92141 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92142 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2203LU), false); |
| 92143 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92144 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2204LU), false); |
| 92145 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92146 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3050LU), false); |
| 92147 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92148 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2205LU), false); |
| 92149 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92150 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2206LU), false); |
| 92151 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92152 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2207LU), false); |
| 92153 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92154 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2208LU), false); |
| 92155 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92156 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2209LU), false); |
| 92157 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92158 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8900LU), false); |
| 92159 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92160 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11892LU), false); |
| 92161 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92162 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2217LU), false); |
| 92163 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92164 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2218LU), false); |
| 92165 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92166 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2219LU), false); |
| 92167 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92168 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2220LU), false); |
| 92169 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92170 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2221LU), false); |
| 92171 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92172 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2222LU), false); |
| 92173 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92174 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2223LU), false); |
| 92175 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92176 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2224LU), false); |
| 92177 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92178 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2225LU), false); |
| 92179 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92180 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2226LU), false); |
| 92181 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92182 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2227LU), false); |
| 92183 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92184 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2228LU), false); |
| 92185 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92186 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2229LU), false); |
| 92187 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92188 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2230LU), false); |
| 92189 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92190 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2231LU), false); |
| 92191 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92192 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2232LU), false); |
| 92193 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92194 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2233LU), false); |
| 92195 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92196 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2234LU), false); |
| 92197 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92198 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2235LU), false); |
| 92199 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92200 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2236LU), false); |
| 92201 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92202 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2237LU), false); |
| 92203 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92204 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2238LU), false); |
| 92205 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92206 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2239LU), false); |
| 92207 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92208 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2240LU), false); |
| 92209 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92210 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2241LU), false); |
| 92211 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92212 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2242LU), false); |
| 92213 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92214 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2730LU), false); |
| 92215 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92216 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2731LU), false); |
| 92217 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92218 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2042LU), false); |
| 92219 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92220 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2043LU), false); |
| 92221 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92222 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2044LU), false); |
| 92223 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92224 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2045LU), false); |
| 92225 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92226 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2046LU), false); |
| 92227 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92228 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2047LU), false); |
| 92229 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92230 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2050LU), false); |
| 92231 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92232 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2051LU), false); |
| 92233 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92234 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2134LU), false); |
| 92235 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92236 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17222LU), false); |
| 92237 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92238 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11851LU), false); |
| 92239 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92240 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2053LU), false); |
| 92241 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92242 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2054LU), false); |
| 92243 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92244 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2055LU), false); |
| 92245 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92246 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2056LU), false); |
| 92247 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92248 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2057LU), false); |
| 92249 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92250 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2128LU), false); |
| 92251 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92252 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2129LU), false); |
| 92253 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92254 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9003LU), false); |
| 92255 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92256 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2756LU), false); |
| 92257 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92258 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8996LU), false); |
| 92259 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92260 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11112LU), false); |
| 92261 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92262 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11113LU), false); |
| 92263 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92264 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9009LU), false); |
| 92265 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92266 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9010LU), false); |
| 92267 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92268 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3874LU), false); |
| 92269 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92270 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9011LU), false); |
| 92271 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92272 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9012LU), false); |
| 92273 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92274 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9020LU), false); |
| 92275 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92276 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9021LU), false); |
| 92277 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92278 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9022LU), false); |
| 92279 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92280 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9023LU), false); |
| 92281 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92282 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9024LU), false); |
| 92283 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92284 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9025LU), false); |
| 92285 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92286 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9026LU), false); |
| 92287 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92288 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9028LU), false); |
| 92289 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92290 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9027LU), false); |
| 92291 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92292 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9029LU), false); |
| 92293 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92294 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 9030LU), false); |
| 92295 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92296 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 3876LU), false); |
| 92297 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92298 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12913LU), false); |
| 92299 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92300 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17479LU), false); |
| 92301 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92302 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14494LU), false); |
| 92303 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92304 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14495LU), false); |
| 92305 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92306 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14500LU), false); |
| 92307 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92308 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 16995LU), false); |
| 92309 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92310 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 16996LU), false); |
| 92311 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92312 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17007LU), false); |
| 92313 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92314 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14434LU), false); |
| 92315 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92316 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15844LU), false); |
| 92317 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92318 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15845LU), false); |
| 92319 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92320 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14519LU), false); |
| 92321 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92322 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15229LU), false); |
| 92323 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92324 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14648LU), false); |
| 92325 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92326 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15584LU), false); |
| 92327 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92328 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14548LU), false); |
| 92329 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92330 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14556LU), false); |
| 92331 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92332 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14557LU), false); |
| 92333 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92334 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14559LU), false); |
| 92335 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92336 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14560LU), false); |
| 92337 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92338 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17485LU), false); |
| 92339 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92340 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14221LU), false); |
| 92341 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92342 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17202LU), false); |
| 92343 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92344 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21146LU), false); |
| 92345 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92346 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21149LU), false); |
| 92347 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92348 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14600LU), false); |
| 92349 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92350 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14601LU), false); |
| 92351 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92352 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17428LU), false); |
| 92353 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92354 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17456LU), false); |
| 92355 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92356 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17507LU), false); |
| 92357 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92358 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17508LU), false); |
| 92359 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92360 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14226LU), false); |
| 92361 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92362 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17724LU), false); |
| 92363 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92364 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17976LU), false); |
| 92365 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92366 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17987LU), false); |
| 92367 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92368 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17993LU), false); |
| 92369 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92370 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17736LU), false); |
| 92371 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92372 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17737LU), false); |
| 92373 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92374 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17738LU), false); |
| 92375 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92376 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17739LU), false); |
| 92377 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92378 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17740LU), false); |
| 92379 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92380 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17306LU), false); |
| 92381 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92382 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17710LU), false); |
| 92383 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92384 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21092LU), false); |
| 92385 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92386 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21093LU), false); |
| 92387 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92388 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17493LU), false); |
| 92389 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92390 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23798LU), false); |
| 92391 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92392 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23799LU), false); |
| 92393 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92394 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23801LU), false); |
| 92395 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92396 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23803LU), false); |
| 92397 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92398 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23804LU), false); |
| 92399 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92400 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23806LU), false); |
| 92401 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92402 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23808LU), false); |
| 92403 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92404 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23809LU), false); |
| 92405 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92406 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23810LU), false); |
| 92407 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92408 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23812LU), false); |
| 92409 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92410 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23813LU), false); |
| 92411 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92412 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23815LU), false); |
| 92413 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92414 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23817LU), false); |
| 92415 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92416 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23818LU), false); |
| 92417 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92418 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23820LU), false); |
| 92419 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92420 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23829LU), false); |
| 92421 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92422 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23830LU), false); |
| 92423 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92424 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23831LU), false); |
| 92425 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92426 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17744LU), false); |
| 92427 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92428 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17745LU), false); |
| 92429 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92430 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17490LU), false); |
| 92431 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92432 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17749LU), false); |
| 92433 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92434 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17750LU), false); |
| 92435 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92436 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14644LU), false); |
| 92437 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92438 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17632LU), false); |
| 92439 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92440 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14595LU), false); |
| 92441 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92442 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14418LU), false); |
| 92443 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92444 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17478LU), false); |
| 92445 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92446 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14423LU), false); |
| 92447 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92448 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15533LU), false); |
| 92449 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92450 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 16599LU), false); |
| 92451 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92452 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 16600LU), false); |
| 92453 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92454 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14433LU), false); |
| 92455 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92456 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17292LU), false); |
| 92457 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92458 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17706LU), false); |
| 92459 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92460 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21083LU), false); |
| 92461 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92462 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21084LU), false); |
| 92463 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92464 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21086LU), false); |
| 92465 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92466 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21097LU), false); |
| 92467 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92468 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21098LU), false); |
| 92469 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92470 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21099LU), false); |
| 92471 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92472 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21100LU), false); |
| 92473 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92474 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21101LU), false); |
| 92475 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92476 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21102LU), false); |
| 92477 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92478 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17494LU), false); |
| 92479 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92480 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15311LU), false); |
| 92481 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92482 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 21103LU), false); |
| 92483 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92484 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15316LU), false); |
| 92485 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92486 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15114LU), false); |
| 92487 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92488 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15116LU), false); |
| 92489 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92490 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15117LU), false); |
| 92491 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92492 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15119LU), false); |
| 92493 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92494 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 15120LU), false); |
| 92495 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92496 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2369LU), false); |
| 92497 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92498 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2374LU), false); |
| 92499 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92500 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2375LU), false); |
| 92501 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92502 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 2377LU), false); |
| 92503 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92504 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11241LU), false); |
| 92505 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92506 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 11461LU), false); |
| 92507 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92508 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12078LU), false); |
| 92509 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92510 | return retVal; |
| 92511 | } |
| 92512 | |
| 92513 | static UA_StatusCode function_namespace0_generated_798_finish(UA_Server *server, UA_UInt16* ns) { |
| 92514 | return UA_Server_addNode_finish(server, |
| 92515 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU) |
| 92516 | ); |
| 92517 | } |
| 92518 | |
| 92519 | /* NamingRule - ns=0;i=112 */ |
| 92520 | |
| 92521 | static UA_StatusCode function_namespace0_generated_799_begin(UA_Server *server, UA_UInt16* ns) { |
| 92522 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92523 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 92524 | attr.minimumSamplingInterval = 0.000000; |
| 92525 | attr.userAccessLevel = 1; |
| 92526 | attr.accessLevel = 1; |
| 92527 | /* Value rank inherited */ |
| 92528 | attr.valueRank = -2; |
| 92529 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU); |
| 92530 | UA_Int32 *variablenode_ns_0_i_112_variant_DataContents = UA_Int32_new(); |
| 92531 | if (!variablenode_ns_0_i_112_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 92532 | UA_Int32_init(p: variablenode_ns_0_i_112_variant_DataContents); |
| 92533 | *variablenode_ns_0_i_112_variant_DataContents = (UA_Int32) 1; |
| 92534 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_112_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]); |
| 92535 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule"); |
| 92536 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 92537 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 112LU), |
| 92538 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), |
| 92539 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 92540 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"), |
| 92541 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 92542 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 92543 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92544 | UA_Int32_delete(p: variablenode_ns_0_i_112_variant_DataContents); |
| 92545 | return retVal; |
| 92546 | } |
| 92547 | |
| 92548 | static UA_StatusCode function_namespace0_generated_799_finish(UA_Server *server, UA_UInt16* ns) { |
| 92549 | return UA_Server_addNode_finish(server, |
| 92550 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 112LU) |
| 92551 | ); |
| 92552 | } |
| 92553 | |
| 92554 | /* MandatoryPlaceholder - ns=0;i=11510 */ |
| 92555 | |
| 92556 | static UA_StatusCode function_namespace0_generated_800_begin(UA_Server *server, UA_UInt16* ns) { |
| 92557 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92558 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 92559 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "MandatoryPlaceholder"); |
| 92560 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 92561 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11510LU), |
| 92562 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92563 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92564 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "MandatoryPlaceholder"), |
| 92565 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU), |
| 92566 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 92567 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92568 | return retVal; |
| 92569 | } |
| 92570 | |
| 92571 | static UA_StatusCode function_namespace0_generated_800_finish(UA_Server *server, UA_UInt16* ns) { |
| 92572 | return UA_Server_addNode_finish(server, |
| 92573 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11510LU) |
| 92574 | ); |
| 92575 | } |
| 92576 | |
| 92577 | /* NamingRule - ns=0;i=11511 */ |
| 92578 | |
| 92579 | static UA_StatusCode function_namespace0_generated_801_begin(UA_Server *server, UA_UInt16* ns) { |
| 92580 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92581 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 92582 | attr.minimumSamplingInterval = 0.000000; |
| 92583 | attr.userAccessLevel = 1; |
| 92584 | attr.accessLevel = 1; |
| 92585 | /* Value rank inherited */ |
| 92586 | attr.valueRank = -2; |
| 92587 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU); |
| 92588 | UA_Int32 *variablenode_ns_0_i_11511_variant_DataContents = UA_Int32_new(); |
| 92589 | if (!variablenode_ns_0_i_11511_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 92590 | UA_Int32_init(p: variablenode_ns_0_i_11511_variant_DataContents); |
| 92591 | *variablenode_ns_0_i_11511_variant_DataContents = (UA_Int32) 1; |
| 92592 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_11511_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]); |
| 92593 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule"); |
| 92594 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 92595 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11511LU), |
| 92596 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11510LU), |
| 92597 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 92598 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"), |
| 92599 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 92600 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 92601 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92602 | UA_Int32_delete(p: variablenode_ns_0_i_11511_variant_DataContents); |
| 92603 | return retVal; |
| 92604 | } |
| 92605 | |
| 92606 | static UA_StatusCode function_namespace0_generated_801_finish(UA_Server *server, UA_UInt16* ns) { |
| 92607 | return UA_Server_addNode_finish(server, |
| 92608 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11511LU) |
| 92609 | ); |
| 92610 | } |
| 92611 | |
| 92612 | /* OptionalPlaceholder - ns=0;i=11508 */ |
| 92613 | |
| 92614 | static UA_StatusCode function_namespace0_generated_802_begin(UA_Server *server, UA_UInt16* ns) { |
| 92615 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92616 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 92617 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OptionalPlaceholder"); |
| 92618 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 92619 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), |
| 92620 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92621 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92622 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OptionalPlaceholder"), |
| 92623 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU), |
| 92624 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 92625 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92626 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 12097LU), false); |
| 92627 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92628 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14478LU), false); |
| 92629 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92630 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17310LU), false); |
| 92631 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92632 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23796LU), false); |
| 92633 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92634 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 23807LU), false); |
| 92635 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92636 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17743LU), false); |
| 92637 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92638 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 14417LU), false); |
| 92639 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92640 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 17325LU), false); |
| 92641 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92642 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 18076LU), false); |
| 92643 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92644 | return retVal; |
| 92645 | } |
| 92646 | |
| 92647 | static UA_StatusCode function_namespace0_generated_802_finish(UA_Server *server, UA_UInt16* ns) { |
| 92648 | return UA_Server_addNode_finish(server, |
| 92649 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU) |
| 92650 | ); |
| 92651 | } |
| 92652 | |
| 92653 | /* NamingRule - ns=0;i=11509 */ |
| 92654 | |
| 92655 | static UA_StatusCode function_namespace0_generated_803_begin(UA_Server *server, UA_UInt16* ns) { |
| 92656 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92657 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 92658 | attr.minimumSamplingInterval = 0.000000; |
| 92659 | attr.userAccessLevel = 1; |
| 92660 | attr.accessLevel = 1; |
| 92661 | /* Value rank inherited */ |
| 92662 | attr.valueRank = -2; |
| 92663 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU); |
| 92664 | UA_Int32 *variablenode_ns_0_i_11509_variant_DataContents = UA_Int32_new(); |
| 92665 | if (!variablenode_ns_0_i_11509_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 92666 | UA_Int32_init(p: variablenode_ns_0_i_11509_variant_DataContents); |
| 92667 | *variablenode_ns_0_i_11509_variant_DataContents = (UA_Int32) 2; |
| 92668 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_11509_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]); |
| 92669 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule"); |
| 92670 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 92671 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11509LU), |
| 92672 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11508LU), |
| 92673 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 92674 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"), |
| 92675 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 92676 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 92677 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92678 | UA_Int32_delete(p: variablenode_ns_0_i_11509_variant_DataContents); |
| 92679 | return retVal; |
| 92680 | } |
| 92681 | |
| 92682 | static UA_StatusCode function_namespace0_generated_803_finish(UA_Server *server, UA_UInt16* ns) { |
| 92683 | return UA_Server_addNode_finish(server, |
| 92684 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 11509LU) |
| 92685 | ); |
| 92686 | } |
| 92687 | |
| 92688 | /* NamingRule - ns=0;i=111 */ |
| 92689 | |
| 92690 | static UA_StatusCode function_namespace0_generated_804_begin(UA_Server *server, UA_UInt16* ns) { |
| 92691 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92692 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 92693 | attr.minimumSamplingInterval = 0.000000; |
| 92694 | attr.userAccessLevel = 1; |
| 92695 | attr.accessLevel = 1; |
| 92696 | /* Value rank inherited */ |
| 92697 | attr.valueRank = -2; |
| 92698 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 120LU); |
| 92699 | UA_Int32 *variablenode_ns_0_i_111_variant_DataContents = UA_Int32_new(); |
| 92700 | if (!variablenode_ns_0_i_111_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 92701 | UA_Int32_init(p: variablenode_ns_0_i_111_variant_DataContents); |
| 92702 | *variablenode_ns_0_i_111_variant_DataContents = (UA_Int32) 1; |
| 92703 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_111_variant_DataContents, type: &UA_TYPES[UA_TYPES_INT32]); |
| 92704 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamingRule"); |
| 92705 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 92706 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 111LU), |
| 92707 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 77LU), |
| 92708 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 92709 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamingRule"), |
| 92710 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 92711 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 92712 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92713 | UA_Int32_delete(p: variablenode_ns_0_i_111_variant_DataContents); |
| 92714 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 111LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 78LU), true); |
| 92715 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92716 | return retVal; |
| 92717 | } |
| 92718 | |
| 92719 | static UA_StatusCode function_namespace0_generated_804_finish(UA_Server *server, UA_UInt16* ns) { |
| 92720 | return UA_Server_addNode_finish(server, |
| 92721 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 111LU) |
| 92722 | ); |
| 92723 | } |
| 92724 | |
| 92725 | /* DataTypeEncodingType - ns=0;i=76 */ |
| 92726 | |
| 92727 | static UA_StatusCode function_namespace0_generated_805_begin(UA_Server *server, UA_UInt16* ns) { |
| 92728 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92729 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 92730 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeEncodingType"); |
| 92731 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 92732 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU), |
| 92733 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 92734 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 92735 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeEncodingType"), |
| 92736 | typeDefinition: UA_NODEID_NULL, |
| 92737 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 92738 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92739 | return retVal; |
| 92740 | } |
| 92741 | |
| 92742 | static UA_StatusCode function_namespace0_generated_805_finish(UA_Server *server, UA_UInt16* ns) { |
| 92743 | return UA_Server_addNode_finish(server, |
| 92744 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU) |
| 92745 | ); |
| 92746 | } |
| 92747 | |
| 92748 | /* Default Binary - ns=0;i=8251 */ |
| 92749 | |
| 92750 | static UA_StatusCode function_namespace0_generated_806_begin(UA_Server *server, UA_UInt16* ns) { |
| 92751 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92752 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 92753 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default Binary"); |
| 92754 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 92755 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8251LU), |
| 92756 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92757 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92758 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default Binary"), |
| 92759 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU), |
| 92760 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 92761 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92762 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8251LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 38LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 7594LU), false); |
| 92763 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92764 | return retVal; |
| 92765 | } |
| 92766 | |
| 92767 | static UA_StatusCode function_namespace0_generated_806_finish(UA_Server *server, UA_UInt16* ns) { |
| 92768 | return UA_Server_addNode_finish(server, |
| 92769 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 8251LU) |
| 92770 | ); |
| 92771 | } |
| 92772 | |
| 92773 | /* Default Binary - ns=0;i=298 */ |
| 92774 | |
| 92775 | static UA_StatusCode function_namespace0_generated_807_begin(UA_Server *server, UA_UInt16* ns) { |
| 92776 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92777 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 92778 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default Binary"); |
| 92779 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 92780 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 298LU), |
| 92781 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92782 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92783 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default Binary"), |
| 92784 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU), |
| 92785 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 92786 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92787 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 298LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 38LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 296LU), false); |
| 92788 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92789 | return retVal; |
| 92790 | } |
| 92791 | |
| 92792 | static UA_StatusCode function_namespace0_generated_807_finish(UA_Server *server, UA_UInt16* ns) { |
| 92793 | return UA_Server_addNode_finish(server, |
| 92794 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 298LU) |
| 92795 | ); |
| 92796 | } |
| 92797 | |
| 92798 | /* Default JSON - ns=0;i=15376 */ |
| 92799 | |
| 92800 | static UA_StatusCode function_namespace0_generated_808_begin(UA_Server *server, UA_UInt16* ns) { |
| 92801 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92802 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 92803 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default JSON"); |
| 92804 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 92805 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15376LU), |
| 92806 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92807 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92808 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default JSON"), |
| 92809 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU), |
| 92810 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 92811 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92812 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15376LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 38LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 887LU), false); |
| 92813 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92814 | return retVal; |
| 92815 | } |
| 92816 | |
| 92817 | static UA_StatusCode function_namespace0_generated_808_finish(UA_Server *server, UA_UInt16* ns) { |
| 92818 | return UA_Server_addNode_finish(server, |
| 92819 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15376LU) |
| 92820 | ); |
| 92821 | } |
| 92822 | |
| 92823 | /* Default JSON - ns=0;i=15375 */ |
| 92824 | |
| 92825 | static UA_StatusCode function_namespace0_generated_809_begin(UA_Server *server, UA_UInt16* ns) { |
| 92826 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92827 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 92828 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default JSON"); |
| 92829 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 92830 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15375LU), |
| 92831 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92832 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92833 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default JSON"), |
| 92834 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 76LU), |
| 92835 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 92836 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92837 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15375LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 38LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 884LU), false); |
| 92838 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92839 | return retVal; |
| 92840 | } |
| 92841 | |
| 92842 | static UA_StatusCode function_namespace0_generated_809_finish(UA_Server *server, UA_UInt16* ns) { |
| 92843 | return UA_Server_addNode_finish(server, |
| 92844 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15375LU) |
| 92845 | ); |
| 92846 | } |
| 92847 | |
| 92848 | /* DataTypeSystemType - ns=0;i=75 */ |
| 92849 | |
| 92850 | static UA_StatusCode function_namespace0_generated_810_begin(UA_Server *server, UA_UInt16* ns) { |
| 92851 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92852 | UA_ObjectTypeAttributes attr = UA_ObjectTypeAttributes_default; |
| 92853 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeSystemType"); |
| 92854 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECTTYPE, |
| 92855 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU), |
| 92856 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 92857 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 92858 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeSystemType"), |
| 92859 | typeDefinition: UA_NODEID_NULL, |
| 92860 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTTYPEATTRIBUTES],NULL, NULL); |
| 92861 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92862 | return retVal; |
| 92863 | } |
| 92864 | |
| 92865 | static UA_StatusCode function_namespace0_generated_810_finish(UA_Server *server, UA_UInt16* ns) { |
| 92866 | return UA_Server_addNode_finish(server, |
| 92867 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU) |
| 92868 | ); |
| 92869 | } |
| 92870 | |
| 92871 | /* OPC Binary - ns=0;i=93 */ |
| 92872 | |
| 92873 | static UA_StatusCode function_namespace0_generated_811_begin(UA_Server *server, UA_UInt16* ns) { |
| 92874 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92875 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 92876 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "OPC Binary"); |
| 92877 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 92878 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 93LU), |
| 92879 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 90LU), |
| 92880 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU), |
| 92881 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "OPC Binary"), |
| 92882 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU), |
| 92883 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 92884 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92885 | return retVal; |
| 92886 | } |
| 92887 | |
| 92888 | static UA_StatusCode function_namespace0_generated_811_finish(UA_Server *server, UA_UInt16* ns) { |
| 92889 | return UA_Server_addNode_finish(server, |
| 92890 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 93LU) |
| 92891 | ); |
| 92892 | } |
| 92893 | |
| 92894 | /* XML Schema - ns=0;i=92 */ |
| 92895 | |
| 92896 | static UA_StatusCode function_namespace0_generated_812_begin(UA_Server *server, UA_UInt16* ns) { |
| 92897 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92898 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 92899 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "XML Schema"); |
| 92900 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 92901 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 92LU), |
| 92902 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 90LU), |
| 92903 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 35LU), |
| 92904 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "XML Schema"), |
| 92905 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 75LU), |
| 92906 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 92907 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92908 | return retVal; |
| 92909 | } |
| 92910 | |
| 92911 | static UA_StatusCode function_namespace0_generated_812_finish(UA_Server *server, UA_UInt16* ns) { |
| 92912 | return UA_Server_addNode_finish(server, |
| 92913 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 92LU) |
| 92914 | ); |
| 92915 | } |
| 92916 | |
| 92917 | /* DataTypeDictionaryType - ns=0;i=72 */ |
| 92918 | |
| 92919 | static UA_StatusCode function_namespace0_generated_813_begin(UA_Server *server, UA_UInt16* ns) { |
| 92920 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92921 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 92922 | /* Value rank inherited */ |
| 92923 | attr.valueRank = -2; |
| 92924 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU); |
| 92925 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeDictionaryType"); |
| 92926 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 92927 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU), |
| 92928 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 92929 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 92930 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeDictionaryType"), |
| 92931 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 92932 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 92933 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92934 | return retVal; |
| 92935 | } |
| 92936 | |
| 92937 | static UA_StatusCode function_namespace0_generated_813_finish(UA_Server *server, UA_UInt16* ns) { |
| 92938 | return UA_Server_addNode_finish(server, |
| 92939 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU) |
| 92940 | ); |
| 92941 | } |
| 92942 | |
| 92943 | /* Opc.Ua - ns=0;i=7617 */ |
| 92944 | static const UA_Byte variablenode_ns_0_i_7617_variant_DataContents_byteArray[177218] = {60, 111, 112, 99, 58, 84, 121, 112, 101, 68, 105, 99, 116, 105, 111, 110, 97, 114, 121, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 111, 112, 99, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 66, 105, 110, 97, 114, 121, 83, 99, 104, 101, 109, 97, 47, 34, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 120, 115, 105, 61, 34, 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 49, 47, 88, 77, 76, 83, 99, 104, 101, 109, 97, 45, 105, 110, 115, 116, 97, 110, 99, 101, 34, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 117, 97, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 85, 65, 47, 34, 13, 10, 32, 32, 120, 109, 108, 110, 115, 58, 116, 110, 115, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 85, 65, 47, 34, 13, 10, 32, 32, 68, 101, 102, 97, 117, 108, 116, 66, 121, 116, 101, 79, 114, 100, 101, 114, 61, 34, 76, 105, 116, 116, 108, 101, 69, 110, 100, 105, 97, 110, 34, 13, 10, 32, 32, 84, 97, 114, 103, 101, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 85, 65, 47, 34, 13, 10, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 73, 109, 112, 111, 114, 116, 32, 78, 97, 109, 101, 115, 112, 97, 99, 101, 61, 34, 104, 116, 116, 112, 58, 47, 47, 111, 112, 99, 102, 111, 117, 110, 100, 97, 116, 105, 111, 110, 46, 111, 114, 103, 47, 66, 105, 110, 97, 114, 121, 83, 99, 104, 101, 109, 97, 47, 34, 32, 47, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 88, 109, 108, 69, 108, 101, 109, 101, 110, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 110, 32, 88, 77, 76, 32, 101, 108, 101, 109, 101, 110, 116, 32, 101, 110, 99, 111, 100, 101, 100, 32, 97, 115, 32, 97, 32, 85, 84, 70, 45, 56, 32, 115, 116, 114, 105, 110, 103, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 76, 101, 110, 103, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 54, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 84, 104, 101, 32, 112, 111, 115, 115, 105, 98, 108, 101, 32, 101, 110, 99, 111, 100, 105, 110, 103, 115, 32, 102, 111, 114, 32, 97, 32, 78, 111, 100, 101, 73, 100, 32, 118, 97, 108, 117, 101, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 110, 32, 105, 100, 101, 110, 116, 105, 102, 105, 101, 114, 32, 102, 111, 114, 32, 97, 32, 110, 111, 100, 101, 32, 105, 110, 32, 97, 32, 85, 65, 32, 115, 101, 114, 118, 101, 114, 32, 97, 100, 100, 114, 101, 115, 115, 32, 115, 112, 97, 99, 101, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 84, 119, 111, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 70, 111, 117, 114, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 117, 109, 101, 114, 105, 99, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 71, 117, 105, 100, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 110, 32, 105, 100, 101, 110, 116, 105, 102, 105, 101, 114, 32, 102, 111, 114, 32, 97, 32, 110, 111, 100, 101, 32, 105, 110, 32, 97, 32, 85, 65, 32, 115, 101, 114, 118, 101, 114, 32, 97, 100, 100, 114, 101, 115, 115, 32, 115, 112, 97, 99, 101, 32, 113, 117, 97, 108, 105, 102, 105, 101, 100, 32, 119, 105, 116, 104, 32, 97, 32, 99, 111, 109, 112, 108, 101, 116, 101, 32, 110, 97, 109, 101, 115, 112, 97, 99, 101, 32, 115, 116, 114, 105, 110, 103, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 73, 110, 100, 101, 120, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 119, 111, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 84, 119, 111, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 111, 117, 114, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 70, 111, 117, 114, 66, 121, 116, 101, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 117, 109, 101, 114, 105, 99, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 71, 117, 105, 100, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 100, 101, 73, 100, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 101, 114, 118, 101, 114, 73, 110, 100, 101, 120, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 66, 121, 116, 101, 79, 114, 100, 101, 114, 83, 105, 103, 110, 105, 102, 105, 99, 97, 110, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 51, 50, 45, 98, 105, 116, 32, 115, 116, 97, 116, 117, 115, 32, 99, 111, 100, 101, 32, 118, 97, 108, 117, 101, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 114, 101, 99, 117, 114, 115, 105, 118, 101, 32, 115, 116, 114, 117, 99, 116, 117, 114, 101, 32, 99, 111, 110, 116, 97, 105, 110, 105, 110, 103, 32, 100, 105, 97, 103, 110, 111, 115, 116, 105, 99, 32, 105, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 32, 97, 115, 115, 111, 99, 105, 97, 116, 101, 100, 32, 119, 105, 116, 104, 32, 97, 32, 115, 116, 97, 116, 117, 115, 32, 99, 111, 100, 101, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 98, 111, 108, 105, 99, 73, 100, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 73, 110, 102, 111, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 110, 101, 114, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 110, 101, 114, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 98, 111, 108, 105, 99, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 121, 109, 98, 111, 108, 105, 99, 73, 100, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 82, 73, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 76, 111, 99, 97, 108, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 73, 110, 102, 111, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 110, 101, 114, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 73, 110, 110, 101, 114, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 110, 101, 114, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 73, 110, 110, 101, 114, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 115, 116, 114, 105, 110, 103, 32, 113, 117, 97, 108, 105, 102, 105, 101, 100, 32, 119, 105, 116, 104, 32, 97, 32, 110, 97, 109, 101, 115, 112, 97, 99, 101, 32, 105, 110, 100, 101, 120, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 115, 116, 114, 105, 110, 103, 32, 113, 117, 97, 108, 105, 102, 105, 101, 100, 32, 119, 105, 116, 104, 32, 97, 32, 110, 97, 109, 101, 115, 112, 97, 99, 101, 32, 105, 110, 100, 101, 120, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 101, 120, 116, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 76, 111, 99, 97, 108, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 101, 120, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 84, 101, 120, 116, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 118, 97, 108, 117, 101, 32, 119, 105, 116, 104, 32, 97, 110, 32, 97, 115, 115, 111, 99, 105, 97, 116, 101, 100, 32, 116, 105, 109, 101, 115, 116, 97, 109, 112, 44, 32, 97, 110, 100, 32, 113, 117, 97, 108, 105, 116, 121, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 84, 105, 109, 101, 115, 116, 97, 109, 112, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 84, 105, 109, 101, 115, 116, 97, 109, 112, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 108, 117, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 111, 117, 114, 99, 101, 84, 105, 109, 101, 115, 116, 97, 109, 112, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 111, 117, 114, 99, 101, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 101, 114, 118, 101, 114, 84, 105, 109, 101, 115, 116, 97, 109, 112, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 83, 101, 114, 118, 101, 114, 80, 105, 99, 111, 115, 101, 99, 111, 110, 100, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 115, 101, 114, 105, 97, 108, 105, 122, 101, 100, 32, 111, 98, 106, 101, 99, 116, 32, 112, 114, 101, 102, 105, 120, 101, 100, 32, 119, 105, 116, 104, 32, 105, 116, 115, 32, 100, 97, 116, 97, 32, 116, 121, 112, 101, 32, 105, 100, 101, 110, 116, 105, 102, 105, 101, 114, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 73, 100, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 105, 110, 97, 114, 121, 66, 111, 100, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 88, 109, 108, 66, 111, 100, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 101, 114, 118, 101, 100, 49, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 84, 121, 112, 101, 73, 100, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 111, 100, 121, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 111, 100, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 66, 111, 100, 121, 76, 101, 110, 103, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 110, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 65, 32, 117, 110, 105, 111, 110, 32, 111, 102, 32, 115, 101, 118, 101, 114, 97, 108, 32, 116, 121, 112, 101, 115, 46, 60, 47, 111, 112, 99, 58, 68, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 49, 34, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 105, 116, 34, 32, 76, 101, 110, 103, 116, 104, 61, 34, 49, 34, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 111, 111, 108, 101, 97, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 66, 121, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 116, 49, 54, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 49, 54, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 73, 110, 116, 49, 54, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 116, 51, 50, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 73, 110, 116, 51, 50, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 55, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 116, 54, 52, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 54, 52, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 73, 110, 116, 54, 52, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 54, 52, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 57, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 108, 111, 97, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 70, 108, 111, 97, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 111, 117, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 67, 104, 97, 114, 65, 114, 114, 97, 121, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 88, 109, 108, 69, 108, 101, 109, 101, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 88, 109, 108, 69, 108, 101, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 55, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 49, 57, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 86, 97, 114, 105, 97, 110, 116, 84, 121, 112, 101, 34, 32, 83, 119, 105, 116, 99, 104, 86, 97, 108, 117, 101, 61, 34, 50, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 83, 119, 105, 116, 99, 104, 70, 105, 101, 108, 100, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 105, 110, 103, 82, 117, 108, 101, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 97, 110, 100, 97, 116, 111, 114, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 116, 105, 111, 110, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 115, 116, 114, 97, 105, 110, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 32, 32, 32, 32, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 101, 66, 77, 80, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 101, 71, 73, 70, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 101, 74, 80, 71, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 101, 80, 78, 71, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 117, 100, 105, 111, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 105, 116, 70, 105, 101, 108, 100, 77, 97, 115, 107, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 75, 101, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 112, 104, 101, 109, 101, 114, 97, 108, 75, 101, 121, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 99, 75, 101, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 80, 111, 108, 105, 99, 121, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 97, 116, 105, 111, 110, 97, 108, 78, 117, 109, 98, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 97, 116, 111, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 110, 111, 109, 105, 110, 97, 116, 111, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 101, 99, 116, 111, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 104, 114, 101, 101, 68, 86, 101, 99, 116, 111, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 86, 101, 99, 116, 111, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 88, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 89, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 90, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 114, 116, 101, 115, 105, 97, 110, 67, 111, 111, 114, 100, 105, 110, 97, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 104, 114, 101, 101, 68, 67, 97, 114, 116, 101, 115, 105, 97, 110, 67, 111, 111, 114, 100, 105, 110, 97, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 67, 97, 114, 116, 101, 115, 105, 97, 110, 67, 111, 111, 114, 100, 105, 110, 97, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 88, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 89, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 90, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 114, 105, 101, 110, 116, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 104, 114, 101, 101, 68, 79, 114, 105, 101, 110, 116, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 79, 114, 105, 101, 110, 116, 97, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 114, 97, 109, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 104, 114, 101, 101, 68, 70, 114, 97, 109, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 70, 114, 97, 109, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 97, 114, 116, 101, 115, 105, 97, 110, 67, 111, 111, 114, 100, 105, 110, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 104, 114, 101, 101, 68, 67, 97, 114, 116, 101, 115, 105, 97, 110, 67, 111, 111, 114, 100, 105, 110, 97, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 114, 105, 101, 110, 116, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 104, 114, 101, 101, 68, 79, 114, 105, 101, 110, 116, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 110, 70, 105, 108, 101, 77, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 114, 97, 115, 101, 69, 120, 105, 115, 116, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 101, 110, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 116, 121, 67, 114, 105, 116, 101, 114, 105, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 104, 117, 109, 98, 112, 114, 105, 110, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 110, 111, 110, 121, 109, 111, 117, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 101, 100, 85, 115, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 100, 101, 110, 116, 105, 116, 121, 77, 97, 112, 112, 105, 110, 103, 82, 117, 108, 101, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 105, 116, 101, 114, 105, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 73, 100, 101, 110, 116, 105, 116, 121, 67, 114, 105, 116, 101, 114, 105, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 105, 116, 101, 114, 105, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 99, 121, 85, 110, 105, 116, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 112, 111, 110, 101, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 108, 112, 104, 97, 98, 101, 116, 105, 99, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 99, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 76, 105, 115, 116, 77, 97, 115, 107, 115, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 101, 100, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 101, 100, 67, 114, 108, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 114, 67, 114, 108, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 108, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 53, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 76, 105, 115, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 76, 105, 115, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 84, 114, 117, 115, 116, 101, 100, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 101, 100, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 84, 114, 117, 115, 116, 101, 100, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 84, 114, 117, 115, 116, 101, 100, 67, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 117, 115, 116, 101, 100, 67, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 84, 114, 117, 115, 116, 101, 100, 67, 114, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 115, 115, 117, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 115, 115, 117, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 115, 115, 117, 101, 114, 67, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 114, 67, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 115, 115, 117, 101, 114, 67, 114, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 99, 105, 109, 97, 108, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 99, 97, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 83, 99, 104, 101, 109, 97, 72, 101, 97, 100, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 109, 112, 108, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 116, 73, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 109, 112, 108, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 97, 115, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 116, 73, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 65, 66, 105, 110, 97, 114, 121, 70, 105, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 83, 99, 104, 101, 109, 97, 72, 101, 97, 100, 101, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 109, 112, 108, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 99, 104, 101, 109, 97, 76, 111, 99, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 70, 105, 108, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 70, 105, 108, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 111, 100, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 83, 117, 98, 83, 116, 97, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 97, 117, 115, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 114, 97, 116, 105, 111, 110, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 114, 114, 111, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 116, 97, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 83, 99, 104, 101, 109, 97, 72, 101, 97, 100, 101, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 110, 117, 109, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 109, 112, 108, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 105, 109, 112, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 70, 105, 101, 108, 100, 77, 101, 116, 97, 68, 97, 116, 97, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 67, 108, 97, 115, 115, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 86, 101, 114, 115, 105, 111, 110, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 77, 101, 116, 97, 68, 97, 116, 97, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 70, 108, 97, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 70, 108, 97, 103, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 116, 73, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 83, 116, 114, 105, 110, 103, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 70, 108, 97, 103, 115, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 49, 54, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 109, 111, 116, 101, 100, 70, 105, 101, 108, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 86, 101, 114, 115, 105, 111, 110, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 106, 111, 114, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 111, 114, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 70, 111, 108, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 111, 108, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 70, 111, 108, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 116, 97, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 77, 101, 116, 97, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 120, 116, 101, 110, 115, 105, 111, 110, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 116, 101, 110, 115, 105, 111, 110, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 120, 116, 101, 110, 115, 105, 111, 110, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 83, 111, 117, 114, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 83, 111, 117, 114, 99, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 86, 97, 114, 105, 97, 98, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 86, 97, 114, 105, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 72, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 97, 100, 98, 97, 110, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 97, 100, 98, 97, 110, 100, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 116, 105, 116, 117, 116, 101, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 101, 116, 97, 68, 97, 116, 97, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 97, 68, 97, 116, 97, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 101, 116, 97, 68, 97, 116, 97, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 73, 116, 101, 109, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 83, 111, 117, 114, 99, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 108, 105, 115, 104, 101, 100, 86, 97, 114, 105, 97, 98, 108, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 69, 118, 101, 110, 116, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 83, 111, 117, 114, 99, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 101, 100, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 108, 101, 99, 116, 101, 100, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 109, 112, 108, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 79, 112, 101, 114, 97, 110, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 101, 100, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 80, 105, 99, 111, 83, 101, 99, 111, 110, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 80, 105, 99, 111, 83, 101, 99, 111, 110, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 97, 119, 68, 97, 116, 97, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 75, 101, 121, 70, 114, 97, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 75, 101, 101, 112, 65, 108, 105, 118, 101, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 105, 111, 114, 105, 116, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 101, 97, 100, 101, 114, 76, 97, 121, 111, 117, 116, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 83, 117, 98, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 114, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 114, 101, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 65, 100, 100, 114, 101, 115, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 73, 110, 116, 101, 114, 102, 97, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 65, 100, 100, 114, 101, 115, 115, 85, 114, 108, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 101, 116, 119, 111, 114, 107, 65, 100, 100, 114, 101, 115, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 73, 110, 116, 101, 114, 102, 97, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 101, 116, 119, 111, 114, 107, 65, 100, 100, 114, 101, 115, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 71, 114, 111, 117, 112, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 114, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 116, 97, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 77, 101, 116, 97, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 82, 101, 99, 101, 105, 118, 101, 84, 105, 109, 101, 111, 117, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 75, 101, 121, 70, 114, 97, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 101, 97, 100, 101, 114, 76, 97, 121, 111, 117, 116, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 71, 114, 111, 117, 112, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 99, 117, 114, 105, 116, 121, 75, 101, 121, 83, 101, 114, 118, 105, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 75, 101, 121, 86, 97, 108, 117, 101, 80, 97, 105, 114, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 83, 101, 116, 116, 105, 110, 103, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 98, 101, 100, 68, 97, 116, 97, 83, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 98, 101, 100, 68, 97, 116, 97, 83, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 86, 97, 114, 105, 97, 98, 108, 101, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 83, 117, 98, 115, 99, 114, 105, 98, 101, 100, 68, 97, 116, 97, 83, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 84, 97, 114, 103, 101, 116, 86, 97, 114, 105, 97, 98, 108, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 86, 97, 114, 105, 97, 98, 108, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 70, 105, 101, 108, 100, 84, 97, 114, 103, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 84, 97, 114, 103, 101, 116, 86, 97, 114, 105, 97, 98, 108, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 84, 97, 114, 103, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 70, 105, 101, 108, 100, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 99, 101, 105, 118, 101, 114, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 118, 101, 114, 114, 105, 100, 101, 86, 97, 108, 117, 101, 72, 97, 110, 100, 108, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 79, 118, 101, 114, 114, 105, 100, 101, 86, 97, 108, 117, 101, 72, 97, 110, 100, 108, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 118, 101, 114, 114, 105, 100, 101, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 118, 101, 114, 114, 105, 100, 101, 86, 97, 108, 117, 101, 72, 97, 110, 100, 108, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 85, 115, 97, 98, 108, 101, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 118, 101, 114, 114, 105, 100, 101, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 98, 101, 100, 68, 97, 116, 97, 83, 101, 116, 77, 105, 114, 114, 111, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 83, 117, 98, 115, 99, 114, 105, 98, 101, 100, 68, 97, 116, 97, 83, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 97, 114, 101, 110, 116, 78, 111, 100, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 83, 117, 98, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 101, 100, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 117, 98, 83, 117, 98, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 79, 114, 100, 101, 114, 105, 110, 103, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 100, 101, 102, 105, 110, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 115, 99, 101, 110, 100, 105, 110, 103, 87, 114, 105, 116, 101, 114, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 115, 99, 101, 110, 100, 105, 110, 103, 87, 114, 105, 116, 101, 114, 73, 100, 83, 105, 110, 103, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 97, 100, 112, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 114, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 72, 101, 97, 100, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 86, 101, 114, 115, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 78, 117, 109, 98, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 97, 121, 108, 111, 97, 100, 72, 101, 97, 100, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 105, 99, 111, 83, 101, 99, 111, 110, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 67, 108, 97, 115, 115, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 109, 111, 116, 101, 100, 70, 105, 101, 108, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 97, 100, 112, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 79, 114, 100, 101, 114, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 79, 114, 100, 101, 114, 105, 110, 103, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 97, 100, 112, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 79, 102, 102, 115, 101, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 97, 100, 112, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 105, 99, 111, 83, 101, 99, 111, 110, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 97, 106, 111, 114, 86, 101, 114, 115, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 111, 114, 86, 101, 114, 115, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 97, 100, 112, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 97, 100, 112, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 97, 100, 112, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 114, 111, 117, 112, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 67, 108, 97, 115, 115, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 71, 117, 105, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 97, 100, 112, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 97, 100, 112, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 99, 101, 105, 118, 101, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 99, 101, 115, 115, 105, 110, 103, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 74, 115, 111, 110, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 72, 101, 97, 100, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 72, 101, 97, 100, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 110, 103, 108, 101, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 101, 114, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 67, 108, 97, 115, 115, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 108, 121, 84, 111, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 74, 115, 111, 110, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 74, 115, 111, 110, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 74, 115, 111, 110, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 97, 68, 97, 116, 97, 86, 101, 114, 115, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 74, 115, 111, 110, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 74, 115, 111, 110, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 74, 115, 111, 110, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 77, 101, 115, 115, 97, 103, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 74, 115, 111, 110, 78, 101, 116, 119, 111, 114, 107, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 74, 115, 111, 110, 68, 97, 116, 97, 83, 101, 116, 77, 101, 115, 115, 97, 103, 101, 67, 111, 110, 116, 101, 110, 116, 77, 97, 115, 107, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 103, 114, 97, 109, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 65, 100, 100, 114, 101, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 103, 114, 97, 109, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 82, 101, 112, 101, 97, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 82, 101, 112, 101, 97, 116, 68, 101, 108, 97, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 107, 101, 114, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 111, 117, 114, 99, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 107, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 81, 117, 97, 108, 105, 116, 121, 79, 102, 83, 101, 114, 118, 105, 99, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 83, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 101, 115, 116, 69, 102, 102, 111, 114, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 116, 76, 101, 97, 115, 116, 79, 110, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 116, 77, 111, 115, 116, 79, 110, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 97, 99, 116, 108, 121, 79, 110, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 107, 101, 114, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 114, 71, 114, 111, 117, 112, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 117, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 111, 117, 114, 99, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 68, 101, 108, 105, 118, 101, 114, 121, 71, 117, 97, 114, 97, 110, 116, 101, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 107, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 81, 117, 97, 108, 105, 116, 121, 79, 102, 83, 101, 114, 118, 105, 99, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 107, 101, 114, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 87, 114, 105, 116, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 117, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 111, 117, 114, 99, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 68, 101, 108, 105, 118, 101, 114, 121, 71, 117, 97, 114, 97, 110, 116, 101, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 107, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 81, 117, 97, 108, 105, 116, 121, 79, 102, 83, 101, 114, 118, 105, 99, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 97, 68, 97, 116, 97, 81, 117, 101, 117, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 97, 68, 97, 116, 97, 85, 112, 100, 97, 116, 101, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 107, 101, 114, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 83, 101, 116, 82, 101, 97, 100, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 117, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 111, 117, 114, 99, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 68, 101, 108, 105, 118, 101, 114, 121, 71, 117, 97, 114, 97, 110, 116, 101, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 107, 101, 114, 84, 114, 97, 110, 115, 112, 111, 114, 116, 81, 117, 97, 108, 105, 116, 121, 79, 102, 83, 101, 114, 118, 105, 99, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 97, 68, 97, 116, 97, 81, 117, 101, 117, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 76, 101, 118, 101, 108, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 97, 115, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 118, 97, 110, 99, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 102, 111, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 111, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 98, 117, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 83, 117, 98, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 67, 111, 117, 110, 116, 101, 114, 67, 108, 97, 115, 115, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 114, 114, 111, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 108, 105, 97, 115, 78, 97, 109, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 108, 105, 97, 115, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 100, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 117, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 97, 113, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 115, 112, 101, 99, 105, 102, 105, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 56, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 72, 105, 115, 116, 111, 114, 105, 122, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 72, 105, 115, 116, 111, 114, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 115, 101, 114, 116, 72, 105, 115, 116, 111, 114, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 72, 105, 115, 116, 111, 114, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 72, 105, 115, 116, 111, 114, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 99, 101, 105, 118, 101, 69, 118, 101, 110, 116, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 48, 57, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 49, 57, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 109, 111, 118, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 51, 56, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 55, 54, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 53, 53, 51, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 56, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 109, 97, 110, 116, 105, 99, 67, 104, 97, 110, 103, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 69, 120, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 109, 97, 110, 116, 105, 99, 67, 104, 97, 110, 103, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 97, 116, 111, 109, 105, 99, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 97, 116, 111, 109, 105, 99, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 70, 117, 108, 108, 65, 114, 114, 97, 121, 79, 110, 108, 121, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 83, 117, 98, 68, 97, 116, 97, 84, 121, 112, 101, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 56, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 98, 101, 84, 111, 69, 118, 101, 110, 116, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 87, 114, 105, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 49, 54, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 105, 110, 103, 82, 101, 113, 117, 105, 114, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 99, 114, 121, 112, 116, 105, 111, 110, 82, 101, 113, 117, 105, 114, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 82, 101, 113, 117, 105, 114, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 121, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 84, 111, 66, 114, 111, 119, 115, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 87, 105, 116, 104, 79, 112, 116, 105, 111, 110, 97, 108, 70, 105, 101, 108, 100, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 70, 105, 101, 108, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 83, 116, 114, 105, 110, 103, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 79, 112, 116, 105, 111, 110, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 102, 97, 117, 108, 116, 69, 110, 99, 111, 100, 105, 110, 103, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 97, 115, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 117, 99, 116, 117, 114, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 70, 105, 101, 108, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 70, 105, 101, 108, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 115, 116, 97, 110, 99, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 73, 110, 115, 116, 97, 110, 99, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 84, 121, 112, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 84, 121, 112, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 73, 110, 115, 116, 97, 110, 99, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 105, 109, 117, 109, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 105, 122, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 69, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 84, 121, 112, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 84, 121, 112, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 109, 101, 116, 114, 105, 99, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 101, 114, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 73, 110, 115, 116, 97, 110, 99, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 73, 110, 115, 116, 97, 110, 99, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 97, 105, 110, 115, 78, 111, 76, 111, 111, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 84, 121, 112, 101, 78, 111, 100, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 49, 54, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 78, 111, 100, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 73, 110, 118, 101, 114, 115, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 114, 103, 117, 109, 101, 110, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 86, 97, 108, 117, 101, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 117, 109, 70, 105, 101, 108, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 86, 97, 108, 117, 101, 84, 121, 112, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 54, 52, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 86, 97, 108, 117, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 86, 97, 108, 117, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 69, 110, 117, 109, 86, 97, 108, 117, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 116, 105, 111, 110, 83, 101, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 105, 100, 66, 105, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 114, 109, 97, 108, 105, 122, 101, 100, 83, 116, 114, 105, 110, 103, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 99, 105, 109, 97, 108, 83, 116, 114, 105, 110, 103, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 117, 114, 97, 116, 105, 111, 110, 83, 116, 114, 105, 110, 103, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 83, 116, 114, 105, 110, 103, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 101, 83, 116, 114, 105, 110, 103, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 117, 114, 97, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 116, 99, 84, 105, 109, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 90, 111, 110, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 121, 108, 105, 103, 104, 116, 83, 97, 118, 105, 110, 103, 73, 110, 79, 102, 102, 115, 101, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 116, 101, 103, 101, 114, 73, 100, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 65, 110, 100, 83, 101, 114, 118, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 83, 101, 114, 118, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 100, 117, 99, 116, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 97, 116, 101, 119, 97, 121, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 84, 111, 107, 101, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 116, 117, 114, 110, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 100, 105, 116, 69, 110, 116, 114, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 111, 117, 116, 72, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 82, 101, 115, 117, 108, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 116, 114, 105, 110, 103, 84, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 114, 105, 110, 103, 84, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 116, 114, 105, 110, 103, 84, 97, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 105, 116, 105, 111, 110, 97, 108, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 101, 114, 115, 105, 111, 110, 84, 105, 109, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 70, 97, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 108, 101, 115, 115, 73, 110, 118, 111, 107, 101, 82, 101, 113, 117, 101, 115, 116, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 114, 105, 115, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 108, 101, 115, 115, 73, 110, 118, 111, 107, 101, 82, 101, 115, 112, 111, 110, 115, 101, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 110, 100, 83, 101, 114, 118, 101, 114, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 110, 100, 83, 101, 114, 118, 101, 114, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 79, 110, 78, 101, 116, 119, 111, 114, 107, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 99, 111, 114, 100, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 110, 100, 83, 101, 114, 118, 101, 114, 115, 79, 110, 78, 101, 116, 119, 111, 114, 107, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 105, 110, 103, 82, 101, 99, 111, 114, 100, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 82, 101, 99, 111, 114, 100, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 121, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 121, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 121, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 110, 100, 83, 101, 114, 118, 101, 114, 115, 79, 110, 78, 101, 116, 119, 111, 114, 107, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 67, 111, 117, 110, 116, 101, 114, 82, 101, 115, 101, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 101, 114, 79, 110, 78, 101, 116, 119, 111, 114, 107, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 73, 110, 115, 116, 97, 110, 99, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 97, 108, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 65, 110, 100, 69, 110, 99, 114, 121, 112, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 84, 111, 107, 101, 110, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 110, 111, 110, 121, 109, 111, 117, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 100, 84, 111, 107, 101, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 84, 111, 107, 101, 110, 80, 111, 108, 105, 99, 121, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 111, 107, 101, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 84, 111, 107, 101, 110, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 100, 84, 111, 107, 101, 110, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 114, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 80, 111, 108, 105, 99, 121, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 80, 111, 108, 105, 99, 121, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 84, 111, 107, 101, 110, 80, 111, 108, 105, 99, 121, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 101, 116, 69, 110, 100, 112, 111, 105, 110, 116, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 114, 111, 102, 105, 108, 101, 85, 114, 105, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 101, 116, 69, 110, 100, 112, 111, 105, 110, 116, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 83, 101, 114, 118, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 100, 117, 99, 116, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 78, 97, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 78, 97, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 78, 97, 109, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 71, 97, 116, 101, 119, 97, 121, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 85, 114, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 109, 97, 112, 104, 111, 114, 101, 70, 105, 108, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 79, 110, 108, 105, 110, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 83, 101, 114, 118, 101, 114, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 83, 101, 114, 118, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 83, 101, 114, 118, 101, 114, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 100, 110, 115, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 100, 110, 115, 83, 101, 114, 118, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 83, 101, 114, 118, 101, 114, 50, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 83, 101, 114, 118, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 115, 99, 111, 118, 101, 114, 121, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 83, 101, 114, 118, 101, 114, 50, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 82, 101, 113, 117, 101, 115, 116, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 110, 101, 119, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 104, 97, 110, 110, 101, 108, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 104, 97, 110, 110, 101, 108, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 111, 107, 101, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 100, 65, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 110, 83, 101, 99, 117, 114, 101, 67, 104, 97, 110, 110, 101, 108, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 80, 114, 111, 116, 111, 99, 111, 108, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 82, 101, 113, 117, 101, 115, 116, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 78, 111, 110, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 110, 83, 101, 99, 117, 114, 101, 67, 104, 97, 110, 110, 101, 108, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 80, 114, 111, 116, 111, 99, 111, 108, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 104, 97, 110, 110, 101, 108, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 78, 111, 110, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 111, 115, 101, 83, 101, 99, 117, 114, 101, 67, 104, 97, 110, 110, 101, 108, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 111, 115, 101, 83, 101, 99, 117, 114, 101, 67, 104, 97, 110, 110, 101, 108, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 101, 100, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 84, 111, 107, 101, 110, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 97, 116, 117, 114, 101, 68, 97, 116, 97, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 108, 103, 111, 114, 105, 116, 104, 109, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 78, 111, 110, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 83, 101, 115, 115, 105, 111, 110, 84, 105, 109, 101, 111, 117, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 82, 101, 115, 112, 111, 110, 115, 101, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 84, 111, 107, 101, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 83, 101, 115, 115, 105, 111, 110, 84, 105, 109, 101, 111, 117, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 78, 111, 110, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 69, 110, 100, 112, 111, 105, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 103, 110, 101, 100, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 114, 118, 101, 114, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 103, 110, 97, 116, 117, 114, 101, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 82, 101, 113, 117, 101, 115, 116, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 110, 111, 110, 121, 109, 111, 117, 115, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 97, 115, 115, 119, 111, 114, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 99, 114, 121, 112, 116, 105, 111, 110, 65, 108, 103, 111, 114, 105, 116, 104, 109, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 88, 53, 48, 57, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 115, 117, 101, 100, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 111, 108, 105, 99, 121, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 111, 107, 101, 110, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 99, 114, 121, 112, 116, 105, 111, 110, 65, 108, 103, 111, 114, 105, 116, 104, 109, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 115, 97, 69, 110, 99, 114, 121, 112, 116, 101, 100, 83, 101, 99, 114, 101, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 99, 99, 69, 110, 99, 114, 121, 112, 116, 101, 100, 83, 101, 99, 114, 101, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 116, 105, 118, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 103, 110, 97, 116, 117, 114, 101, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 108, 105, 101, 110, 116, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 103, 110, 101, 100, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 108, 105, 101, 110, 116, 83, 111, 102, 116, 119, 97, 114, 101, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 73, 100, 101, 110, 116, 105, 116, 121, 84, 111, 107, 101, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 84, 111, 107, 101, 110, 83, 105, 103, 110, 97, 116, 117, 114, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 103, 110, 97, 116, 117, 114, 101, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 116, 105, 118, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 78, 111, 110, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 111, 115, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 108, 111, 115, 101, 83, 101, 115, 115, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 110, 99, 101, 108, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 110, 99, 101, 108, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 97, 110, 99, 101, 108, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 97, 105, 110, 115, 78, 111, 76, 111, 111, 112, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 105, 122, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 101, 114, 115, 101, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 105, 109, 117, 109, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 48, 57, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 49, 57, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 51, 56, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 109, 101, 116, 114, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 55, 54, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 53, 53, 51, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 51, 49, 48, 55, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 50, 49, 52, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 50, 52, 50, 56, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 52, 56, 53, 55, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 57, 55, 49, 53, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 49, 57, 52, 51, 48, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 51, 56, 56, 54, 48, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 55, 55, 55, 50, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 108, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 51, 53, 53, 52, 52, 51, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 97, 115, 101, 78, 111, 100, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 48, 49, 50, 50, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 48, 49, 51, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 48, 51, 50, 54, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 55, 49, 51, 56, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 56, 54, 48, 48, 52, 51, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 54, 51, 50, 53, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 51, 55, 48, 54, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 53, 48, 49, 51, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 105, 109, 117, 109, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 105, 122, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 84, 121, 112, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 109, 101, 116, 114, 105, 99, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 101, 114, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 97, 105, 110, 115, 78, 111, 76, 111, 111, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 101, 110, 101, 114, 105, 99, 65, 116, 116, 114, 105, 98, 117, 116, 101, 86, 97, 108, 117, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 71, 101, 110, 101, 114, 105, 99, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 112, 101, 99, 105, 102, 105, 101, 100, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 116, 116, 114, 105, 98, 117, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 71, 101, 110, 101, 114, 105, 99, 65, 116, 116, 114, 105, 98, 117, 116, 101, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 116, 116, 114, 105, 98, 117, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 115, 73, 116, 101, 109, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 97, 114, 101, 110, 116, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 78, 101, 119, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 115, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 100, 100, 78, 111, 100, 101, 115, 73, 116, 101, 109, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 65, 100, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 100, 100, 78, 111, 100, 101, 115, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 73, 116, 101, 109, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 70, 111, 114, 119, 97, 114, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 73, 116, 101, 109, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 65, 100, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 115, 73, 116, 101, 109, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 84, 97, 114, 103, 101, 116, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 115, 73, 116, 101, 109, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 73, 116, 101, 109, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 70, 111, 114, 119, 97, 114, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 66, 105, 100, 105, 114, 101, 99, 116, 105, 111, 110, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 101, 108, 101, 116, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 73, 116, 101, 109, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 68, 101, 108, 101, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 32, 73, 115, 79, 112, 116, 105, 111, 110, 83, 101, 116, 61, 34, 116, 114, 117, 101, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 114, 114, 97, 121, 68, 105, 109, 101, 110, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 97, 105, 110, 115, 78, 111, 76, 111, 111, 112, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 53, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 105, 122, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 101, 114, 115, 101, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 50, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 65, 98, 115, 116, 114, 97, 99, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 52, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 77, 105, 110, 105, 109, 117, 109, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 48, 57, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 49, 57, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 51, 56, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 121, 109, 109, 101, 116, 114, 105, 99, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 55, 54, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 53, 53, 51, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 69, 120, 101, 99, 117, 116, 97, 98, 108, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 51, 49, 48, 55, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 54, 50, 49, 52, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 82, 97, 110, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 50, 52, 50, 56, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 77, 97, 115, 107, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 52, 56, 53, 55, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 70, 111, 114, 86, 97, 114, 105, 97, 98, 108, 101, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 48, 57, 55, 49, 53, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 49, 57, 52, 51, 48, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 111, 108, 101, 80, 101, 114, 109, 105, 115, 115, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 51, 56, 56, 54, 48, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 82, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 55, 55, 55, 50, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 99, 99, 101, 115, 115, 76, 101, 118, 101, 108, 69, 120, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 51, 53, 53, 52, 52, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 68, 105, 114, 101, 99, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 70, 111, 114, 119, 97, 114, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 101, 114, 115, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 111, 116, 104, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 97, 108, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 68, 105, 114, 101, 99, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 68, 105, 114, 101, 99, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 99, 108, 117, 100, 101, 83, 117, 98, 116, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 77, 97, 115, 107, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 82, 101, 115, 117, 108, 116, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 70, 111, 114, 119, 97, 114, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 108, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 110, 102, 111, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 73, 110, 102, 111, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 48, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 70, 111, 114, 119, 97, 114, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 67, 108, 97, 115, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 102, 101, 114, 101, 110, 99, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 86, 105, 101, 119, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 77, 97, 120, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 80, 101, 114, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 66, 114, 111, 119, 115, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 66, 114, 111, 119, 115, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 66, 114, 111, 119, 115, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 101, 120, 116, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 101, 97, 115, 101, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 101, 120, 116, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 69, 108, 101, 109, 101, 110, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 73, 110, 118, 101, 114, 115, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 99, 108, 117, 100, 101, 83, 117, 98, 116, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 69, 108, 101, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 105, 110, 103, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 84, 97, 114, 103, 101, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 109, 97, 105, 110, 105, 110, 103, 80, 97, 116, 104, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 84, 97, 114, 103, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 97, 114, 103, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 84, 97, 114, 103, 101, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 84, 97, 114, 103, 101, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 108, 97, 116, 101, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 84, 111, 78, 111, 100, 101, 73, 100, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 108, 97, 116, 101, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 84, 111, 78, 111, 100, 101, 73, 100, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 103, 105, 115, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 82, 101, 103, 105, 115, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 103, 105, 115, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 103, 105, 115, 116, 101, 114, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 117, 110, 116, 101, 114, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 101, 114, 105, 99, 82, 97, 110, 103, 101, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 79, 112, 97, 113, 117, 101, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 114, 97, 116, 105, 111, 110, 84, 105, 109, 101, 111, 117, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 66, 105, 110, 97, 114, 121, 69, 110, 99, 111, 100, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 83, 116, 114, 105, 110, 103, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 65, 114, 114, 97, 121, 76, 101, 110, 103, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 66, 117, 102, 102, 101, 114, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 104, 97, 110, 110, 101, 108, 76, 105, 102, 101, 116, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 84, 111, 107, 101, 110, 76, 105, 102, 101, 116, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 68, 97, 116, 97, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 99, 108, 117, 100, 101, 83, 117, 98, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 81, 117, 101, 114, 121, 68, 97, 116, 97, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 116, 111, 114, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 69, 113, 117, 97, 108, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 115, 78, 117, 108, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 114, 101, 97, 116, 101, 114, 84, 104, 97, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 101, 115, 115, 84, 104, 97, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 71, 114, 101, 97, 116, 101, 114, 84, 104, 97, 110, 79, 114, 69, 113, 117, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 101, 115, 115, 84, 104, 97, 110, 79, 114, 69, 113, 117, 97, 108, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 105, 107, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 55, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 101, 116, 119, 101, 101, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 76, 105, 115, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 57, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 110, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 115, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 86, 105, 101, 119, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 79, 102, 84, 121, 112, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 97, 116, 101, 100, 84, 111, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 105, 116, 119, 105, 115, 101, 65, 110, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 105, 116, 119, 105, 115, 101, 79, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 55, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 112, 97, 110, 100, 101, 100, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 84, 121, 112, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 70, 111, 114, 119, 97, 114, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 102, 101, 114, 101, 110, 99, 101, 100, 78, 111, 100, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 69, 108, 101, 109, 101, 110, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 116, 111, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 116, 111, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 69, 108, 101, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 108, 101, 109, 101, 110, 116, 79, 112, 101, 114, 97, 110, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 76, 105, 116, 101, 114, 97, 108, 79, 112, 101, 114, 97, 110, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 79, 112, 101, 114, 97, 110, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 108, 105, 97, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 108, 97, 116, 105, 118, 101, 80, 97, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 105, 109, 112, 108, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 79, 112, 101, 114, 97, 110, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 70, 105, 108, 116, 101, 114, 79, 112, 101, 114, 97, 110, 100, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 121, 112, 101, 68, 101, 102, 105, 110, 105, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 69, 108, 101, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 110, 100, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 114, 97, 110, 100, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 110, 100, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 110, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 114, 97, 110, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 110, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 108, 101, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 69, 108, 101, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 108, 101, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 108, 101, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 97, 114, 115, 105, 110, 103, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 70, 105, 114, 115, 116, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 105, 101, 119, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 86, 105, 101, 119, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 84, 121, 112, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 100, 101, 84, 121, 112, 101, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 84, 121, 112, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 68, 97, 116, 97, 83, 101, 116, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 70, 105, 114, 115, 116, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 80, 97, 114, 115, 105, 110, 103, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 97, 114, 115, 105, 110, 103, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 97, 114, 115, 105, 110, 103, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 80, 97, 114, 115, 105, 110, 103, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 78, 101, 120, 116, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 101, 97, 115, 101, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 78, 101, 120, 116, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 81, 117, 101, 114, 121, 68, 97, 116, 97, 83, 101, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 111, 117, 114, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 66, 111, 116, 104, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 105, 116, 104, 101, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 97, 108, 105, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 86, 97, 108, 117, 101, 73, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 69, 110, 99, 111, 100, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 65, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 97, 100, 86, 97, 108, 117, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 86, 97, 108, 117, 101, 73, 100, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 69, 110, 99, 111, 100, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 81, 117, 97, 108, 105, 102, 105, 101, 100, 78, 97, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 69, 118, 101, 110, 116, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 86, 97, 108, 117, 101, 115, 80, 101, 114, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 82, 97, 119, 77, 111, 100, 105, 102, 105, 101, 100, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 82, 101, 97, 100, 77, 111, 100, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 117, 109, 86, 97, 108, 117, 101, 115, 80, 101, 114, 78, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 116, 117, 114, 110, 66, 111, 117, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 80, 114, 111, 99, 101, 115, 115, 101, 100, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 99, 101, 115, 115, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 103, 103, 114, 101, 103, 97, 116, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 103, 103, 114, 101, 103, 97, 116, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 65, 116, 84, 105, 109, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 83, 105, 109, 112, 108, 101, 66, 111, 117, 110, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 68, 97, 116, 97, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 68, 97, 116, 97, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 77, 111, 100, 105, 102, 105, 101, 100, 68, 97, 116, 97, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 68, 97, 116, 97, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 97, 116, 97, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 111, 100, 105, 102, 105, 99, 97, 116, 105, 111, 110, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 69, 118, 101, 110, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 76, 105, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 68, 101, 116, 97, 105, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 108, 101, 97, 115, 101, 67, 111, 110, 116, 105, 110, 117, 97, 116, 105, 111, 110, 80, 111, 105, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 86, 97, 108, 117, 101, 73, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 82, 101, 97, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 86, 97, 108, 117, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 116, 116, 114, 105, 98, 117, 116, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 100, 101, 120, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 87, 114, 105, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 115, 84, 111, 87, 114, 105, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 87, 114, 105, 116, 101, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 100, 101, 115, 84, 111, 87, 114, 105, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 115, 101, 114, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 108, 97, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 102, 111, 114, 109, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 73, 110, 115, 101, 114, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 108, 97, 99, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 109, 111, 118, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 68, 97, 116, 97, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 102, 111, 114, 109, 73, 110, 115, 101, 114, 116, 82, 101, 112, 108, 97, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 101, 114, 102, 111, 114, 109, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 102, 111, 114, 109, 73, 110, 115, 101, 114, 116, 82, 101, 112, 108, 97, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 101, 114, 102, 111, 114, 109, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 85, 112, 100, 97, 116, 101, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 85, 112, 100, 97, 116, 101, 69, 118, 101, 110, 116, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 102, 111, 114, 109, 73, 110, 115, 101, 114, 116, 82, 101, 112, 108, 97, 99, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 80, 101, 114, 102, 111, 114, 109, 85, 112, 100, 97, 116, 101, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 76, 105, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 82, 97, 119, 77, 111, 100, 105, 102, 105, 101, 100, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 115, 68, 101, 108, 101, 116, 101, 77, 111, 100, 105, 102, 105, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 65, 116, 84, 105, 109, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 113, 84, 105, 109, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 69, 118, 101, 110, 116, 68, 101, 116, 97, 105, 108, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 83, 111, 117, 114, 99, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 112, 101, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 79, 112, 101, 114, 97, 116, 105, 111, 110, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 68, 101, 116, 97, 105, 108, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 77, 101, 116, 104, 111, 100, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 98, 106, 101, 99, 116, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 77, 101, 116, 104, 111, 100, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 101, 116, 104, 111, 100, 115, 84, 111, 67, 97, 108, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 116, 104, 111, 100, 115, 84, 111, 67, 97, 108, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 97, 108, 108, 77, 101, 116, 104, 111, 100, 82, 101, 113, 117, 101, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 101, 116, 104, 111, 100, 115, 84, 111, 67, 97, 108, 108, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 97, 108, 108, 77, 101, 116, 104, 111, 100, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 111, 114, 116, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 67, 104, 97, 110, 103, 101, 84, 114, 105, 103, 103, 101, 114, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 86, 97, 108, 117, 101, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 97, 100, 98, 97, 110, 100, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 98, 115, 111, 108, 117, 116, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 67, 104, 97, 110, 103, 101, 70, 105, 108, 116, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 105, 103, 103, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 68, 97, 116, 97, 67, 104, 97, 110, 103, 101, 84, 114, 105, 103, 103, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 97, 100, 98, 97, 110, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 97, 100, 98, 97, 110, 100, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 105, 109, 112, 108, 101, 65, 116, 116, 114, 105, 98, 117, 116, 101, 79, 112, 101, 114, 97, 110, 100, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 104, 101, 114, 101, 67, 108, 97, 117, 115, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 83, 101, 114, 118, 101, 114, 67, 97, 112, 97, 98, 105, 108, 105, 116, 105, 101, 115, 68, 101, 102, 97, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 101, 97, 116, 85, 110, 99, 101, 114, 116, 97, 105, 110, 65, 115, 66, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 68, 97, 116, 97, 66, 97, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 68, 97, 116, 97, 71, 111, 111, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 83, 108, 111, 112, 101, 100, 69, 120, 116, 114, 97, 112, 111, 108, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 70, 105, 108, 116, 101, 114, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 99, 101, 115, 115, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 101, 108, 101, 99, 116, 67, 108, 97, 117, 115, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 104, 101, 114, 101, 67, 108, 97, 117, 115, 101, 82, 101, 115, 117, 108, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 67, 111, 110, 116, 101, 110, 116, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 103, 103, 114, 101, 103, 97, 116, 101, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 80, 114, 111, 99, 101, 115, 115, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 103, 103, 114, 101, 103, 97, 116, 101, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 117, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 97, 114, 100, 79, 108, 100, 101, 115, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 114, 101, 97, 116, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 116, 101, 109, 84, 111, 77, 111, 110, 105, 116, 111, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 97, 100, 86, 97, 108, 117, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 114, 101, 97, 116, 101, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 81, 117, 101, 117, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 116, 101, 109, 115, 84, 111, 67, 114, 101, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 116, 101, 109, 115, 84, 111, 67, 114, 101, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 114, 101, 97, 116, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 116, 101, 109, 115, 84, 111, 67, 114, 101, 97, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 114, 101, 97, 116, 101, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 77, 111, 100, 105, 102, 121, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 80, 97, 114, 97, 109, 101, 116, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 77, 111, 100, 105, 102, 121, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 81, 117, 101, 117, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 70, 105, 108, 116, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 105, 109, 101, 115, 116, 97, 109, 112, 115, 84, 111, 82, 101, 116, 117, 114, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 73, 116, 101, 109, 115, 84, 111, 77, 111, 100, 105, 102, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 116, 101, 109, 115, 84, 111, 77, 111, 100, 105, 102, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 77, 111, 100, 105, 102, 121, 82, 101, 113, 117, 101, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 73, 116, 101, 109, 115, 84, 111, 77, 111, 100, 105, 102, 121, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 77, 111, 100, 105, 102, 121, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 84, 114, 105, 103, 103, 101, 114, 105, 110, 103, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 105, 103, 103, 101, 114, 105, 110, 103, 73, 116, 101, 109, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 105, 110, 107, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 105, 110, 107, 115, 84, 111, 65, 100, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 105, 110, 107, 115, 84, 111, 65, 100, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 105, 110, 107, 115, 84, 111, 82, 101, 109, 111, 118, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 105, 110, 107, 115, 84, 111, 82, 101, 109, 111, 118, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 105, 110, 107, 115, 84, 111, 82, 101, 109, 111, 118, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 84, 114, 105, 103, 103, 101, 114, 105, 110, 103, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 100, 100, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 100, 100, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 100, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 100, 100, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 109, 111, 118, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 109, 111, 118, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 109, 111, 118, 101, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 109, 111, 118, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 109, 111, 118, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 109, 111, 118, 101, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 77, 97, 120, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 80, 101, 114, 80, 117, 98, 108, 105, 115, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 105, 111, 114, 105, 116, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 77, 97, 120, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 101, 100, 77, 97, 120, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 80, 101, 114, 80, 117, 98, 108, 105, 115, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 105, 111, 114, 105, 116, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 118, 105, 115, 101, 100, 77, 97, 120, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 77, 111, 100, 101, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 77, 111, 100, 101, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 115, 115, 97, 103, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 67, 104, 97, 110, 103, 101, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 97, 116, 97, 86, 97, 108, 117, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 76, 105, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 76, 105, 115, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 76, 105, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 72, 97, 110, 100, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 76, 105, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 118, 101, 110, 116, 70, 105, 101, 108, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 104, 97, 110, 103, 101, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 116, 110, 115, 58, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 68, 97, 116, 97, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 65, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 109, 101, 110, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 65, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 65, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 65, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 65, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 114, 101, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 115, 115, 97, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 115, 115, 97, 103, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 116, 114, 97, 110, 115, 109, 105, 116, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 115, 115, 97, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 77, 101, 115, 115, 97, 103, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 118, 97, 105, 108, 97, 98, 108, 101, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 110, 100, 73, 110, 105, 116, 105, 97, 108, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 84, 114, 97, 110, 115, 102, 101, 114, 82, 101, 115, 117, 108, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 82, 101, 113, 117, 101, 115, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 113, 117, 101, 115, 116, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 82, 101, 115, 112, 111, 110, 115, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 101, 115, 112, 111, 110, 115, 101, 72, 101, 97, 100, 101, 114, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 115, 117, 108, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 82, 101, 115, 117, 108, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 100, 73, 110, 102, 111, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 100, 117, 99, 116, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 110, 117, 102, 97, 99, 116, 117, 114, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 100, 117, 99, 116, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 111, 102, 116, 119, 97, 114, 101, 86, 101, 114, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 100, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 100, 68, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 100, 117, 110, 100, 97, 110, 99, 121, 83, 117, 112, 112, 111, 114, 116, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 110, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 108, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 87, 97, 114, 109, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 111, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 97, 114, 101, 110, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 72, 111, 116, 65, 110, 100, 77, 105, 114, 114, 111, 114, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 83, 116, 97, 116, 101, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 117, 110, 110, 105, 110, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 70, 97, 105, 108, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 67, 111, 110, 102, 105, 103, 117, 114, 97, 116, 105, 111, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 115, 112, 101, 110, 100, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 83, 104, 117, 116, 100, 111, 119, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 84, 101, 115, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 53, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 109, 109, 117, 110, 105, 99, 97, 116, 105, 111, 110, 70, 97, 117, 108, 116, 34, 32, 86, 97, 108, 117, 101, 61, 34, 54, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 107, 110, 111, 119, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 55, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 100, 117, 110, 100, 97, 110, 116, 83, 101, 114, 118, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 76, 101, 118, 101, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 83, 116, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 101, 114, 83, 116, 97, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 76, 105, 115, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 76, 105, 115, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 76, 105, 115, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 76, 105, 115, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 71, 114, 111, 117, 112, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 78, 101, 116, 119, 111, 114, 107, 80, 97, 116, 104, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 116, 119, 111, 114, 107, 80, 97, 116, 104, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 76, 105, 115, 116, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 78, 101, 116, 119, 111, 114, 107, 80, 97, 116, 104, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 97, 109, 112, 108, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 100, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 83, 117, 109, 109, 97, 114, 121, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 86, 105, 101, 119, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 83, 101, 115, 115, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 109, 117, 108, 97, 116, 101, 100, 83, 101, 115, 115, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 82, 101, 106, 101, 99, 116, 101, 100, 83, 101, 115, 115, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 106, 101, 99, 116, 101, 100, 83, 101, 115, 115, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 84, 105, 109, 101, 111, 117, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 65, 98, 111, 114, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 109, 117, 108, 97, 116, 101, 100, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 82, 101, 106, 101, 99, 116, 101, 100, 82, 101, 113, 117, 101, 115, 116, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 106, 101, 99, 116, 101, 100, 82, 101, 113, 117, 101, 115, 116, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 83, 116, 97, 116, 117, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 114, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 101, 114, 83, 116, 97, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 117, 105, 108, 100, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 66, 117, 105, 108, 100, 73, 110, 102, 111, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 111, 110, 100, 115, 84, 105, 108, 108, 83, 104, 117, 116, 100, 111, 119, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 104, 117, 116, 100, 111, 119, 110, 82, 101, 97, 115, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 112, 112, 108, 105, 99, 97, 116, 105, 111, 110, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 101, 114, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 100, 112, 111, 105, 110, 116, 85, 114, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 111, 99, 97, 108, 101, 73, 100, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 99, 116, 117, 97, 108, 83, 101, 115, 115, 105, 111, 110, 84, 105, 109, 101, 111, 117, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 82, 101, 115, 112, 111, 110, 115, 101, 77, 101, 115, 115, 97, 103, 101, 83, 105, 122, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 67, 111, 110, 110, 101, 99, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 76, 97, 115, 116, 67, 111, 110, 116, 97, 99, 116, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 80, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 115, 73, 110, 81, 117, 101, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 111, 116, 97, 108, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 110, 97, 117, 116, 104, 111, 114, 105, 122, 101, 100, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 100, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 82, 101, 97, 100, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 87, 114, 105, 116, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 115, 116, 111, 114, 121, 85, 112, 100, 97, 116, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 97, 108, 108, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 77, 111, 100, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 84, 114, 105, 103, 103, 101, 114, 105, 110, 103, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 116, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 77, 111, 100, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 78, 111, 100, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 100, 100, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 78, 111, 100, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 108, 101, 116, 101, 82, 101, 102, 101, 114, 101, 110, 99, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 66, 114, 111, 119, 115, 101, 78, 101, 120, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 108, 97, 116, 101, 66, 114, 111, 119, 115, 101, 80, 97, 116, 104, 115, 84, 111, 78, 111, 100, 101, 73, 100, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 70, 105, 114, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 81, 117, 101, 114, 121, 78, 101, 120, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 110, 114, 101, 103, 105, 115, 116, 101, 114, 78, 111, 100, 101, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 83, 101, 99, 117, 114, 105, 116, 121, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 85, 115, 101, 114, 73, 100, 79, 102, 83, 101, 115, 115, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 67, 108, 105, 101, 110, 116, 85, 115, 101, 114, 73, 100, 72, 105, 115, 116, 111, 114, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 85, 115, 101, 114, 73, 100, 72, 105, 115, 116, 111, 114, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 67, 108, 105, 101, 110, 116, 85, 115, 101, 114, 73, 100, 72, 105, 115, 116, 111, 114, 121, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 117, 116, 104, 101, 110, 116, 105, 99, 97, 116, 105, 111, 110, 77, 101, 99, 104, 97, 110, 105, 115, 109, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 99, 111, 100, 105, 110, 103, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 112, 111, 114, 116, 80, 114, 111, 116, 111, 99, 111, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 77, 101, 115, 115, 97, 103, 101, 83, 101, 99, 117, 114, 105, 116, 121, 77, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 99, 117, 114, 105, 116, 121, 80, 111, 108, 105, 99, 121, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 108, 105, 101, 110, 116, 67, 101, 114, 116, 105, 102, 105, 99, 97, 116, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 114, 118, 105, 99, 101, 67, 111, 117, 110, 116, 101, 114, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 111, 116, 97, 108, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 114, 114, 111, 114, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 82, 101, 115, 117, 108, 116, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 83, 116, 97, 116, 117, 115, 67, 111, 100, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 73, 110, 102, 111, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 115, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 83, 117, 98, 115, 99, 114, 105, 112, 116, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 114, 105, 111, 114, 105, 116, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 73, 110, 116, 101, 114, 118, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 97, 120, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 80, 101, 114, 80, 117, 98, 108, 105, 115, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 105, 110, 103, 69, 110, 97, 98, 108, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 111, 111, 108, 101, 97, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 105, 102, 121, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 97, 98, 108, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 77, 101, 115, 115, 97, 103, 101, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 112, 117, 98, 108, 105, 115, 104, 77, 101, 115, 115, 97, 103, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 114, 101, 100, 84, 111, 65, 108, 116, 67, 108, 105, 101, 110, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 114, 97, 110, 115, 102, 101, 114, 114, 101, 100, 84, 111, 83, 97, 109, 101, 67, 108, 105, 101, 110, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 80, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 67, 104, 97, 110, 103, 101, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 116, 105, 102, 105, 99, 97, 116, 105, 111, 110, 115, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 116, 101, 80, 117, 98, 108, 105, 115, 104, 82, 101, 113, 117, 101, 115, 116, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 75, 101, 101, 112, 65, 108, 105, 118, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 117, 114, 114, 101, 110, 116, 76, 105, 102, 101, 116, 105, 109, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 110, 97, 99, 107, 110, 111, 119, 108, 101, 100, 103, 101, 100, 77, 101, 115, 115, 97, 103, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 99, 97, 114, 100, 101, 100, 77, 101, 115, 115, 97, 103, 101, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 97, 98, 108, 101, 100, 77, 111, 110, 105, 116, 111, 114, 101, 100, 73, 116, 101, 109, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 111, 110, 105, 116, 111, 114, 105, 110, 103, 81, 117, 101, 117, 101, 79, 118, 101, 114, 102, 108, 111, 119, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 101, 120, 116, 83, 101, 113, 117, 101, 110, 99, 101, 78, 117, 109, 98, 101, 114, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 118, 101, 110, 116, 81, 117, 101, 117, 101, 79, 118, 101, 114, 70, 108, 111, 119, 67, 111, 117, 110, 116, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 85, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 101, 108, 67, 104, 97, 110, 103, 101, 83, 116, 114, 117, 99, 116, 117, 114, 101, 86, 101, 114, 98, 77, 97, 115, 107, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 65, 100, 100, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 78, 111, 100, 101, 68, 101, 108, 101, 116, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 65, 100, 100, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 82, 101, 102, 101, 114, 101, 110, 99, 101, 68, 101, 108, 101, 116, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 56, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 68, 97, 116, 97, 84, 121, 112, 101, 67, 104, 97, 110, 103, 101, 100, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 54, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 77, 111, 100, 101, 108, 67, 104, 97, 110, 103, 101, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 102, 102, 101, 99, 116, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 102, 102, 101, 99, 116, 101, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 101, 114, 98, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 66, 121, 116, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 83, 101, 109, 97, 110, 116, 105, 99, 67, 104, 97, 110, 103, 101, 83, 116, 114, 117, 99, 116, 117, 114, 101, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 102, 102, 101, 99, 116, 101, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 102, 102, 101, 99, 116, 101, 100, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 82, 97, 110, 103, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 111, 119, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 72, 105, 103, 104, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 85, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 97, 109, 101, 115, 112, 97, 99, 101, 85, 114, 105, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 110, 105, 116, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 105, 115, 112, 108, 97, 121, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 68, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 120, 105, 115, 83, 99, 97, 108, 101, 69, 110, 117, 109, 101, 114, 97, 116, 105, 111, 110, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 105, 110, 101, 97, 114, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 111, 103, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 76, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 67, 111, 109, 112, 108, 101, 120, 78, 117, 109, 98, 101, 114, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 70, 108, 111, 97, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 105, 110, 97, 114, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 70, 108, 111, 97, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 68, 111, 117, 98, 108, 101, 67, 111, 109, 112, 108, 101, 120, 78, 117, 109, 98, 101, 114, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 82, 101, 97, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 109, 97, 103, 105, 110, 97, 114, 121, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 120, 105, 115, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 110, 103, 105, 110, 101, 101, 114, 105, 110, 103, 85, 110, 105, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 69, 85, 73, 110, 102, 111, 114, 109, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 69, 85, 82, 97, 110, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 82, 97, 110, 103, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 84, 105, 116, 108, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 76, 111, 99, 97, 108, 105, 122, 101, 100, 84, 101, 120, 116, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 120, 105, 115, 83, 99, 97, 108, 101, 84, 121, 112, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 120, 105, 115, 83, 99, 97, 108, 101, 69, 110, 117, 109, 101, 114, 97, 116, 105, 111, 110, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 65, 120, 105, 115, 83, 116, 101, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 120, 105, 115, 83, 116, 101, 112, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 65, 120, 105, 115, 83, 116, 101, 112, 115, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 88, 86, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 88, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 111, 117, 98, 108, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 86, 97, 108, 117, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 70, 108, 111, 97, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 103, 114, 97, 109, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 67, 108, 105, 101, 110, 116, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 111, 99, 97, 116, 105, 111, 110, 67, 114, 101, 97, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 84, 114, 97, 110, 115, 105, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 67, 97, 108, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 114, 103, 117, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 114, 103, 117, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 67, 97, 108, 108, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 82, 101, 116, 117, 114, 110, 83, 116, 97, 116, 117, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 97, 116, 117, 115, 82, 101, 115, 117, 108, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 80, 114, 111, 103, 114, 97, 109, 68, 105, 97, 103, 110, 111, 115, 116, 105, 99, 50, 68, 97, 116, 97, 84, 121, 112, 101, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 67, 114, 101, 97, 116, 101, 67, 108, 105, 101, 110, 116, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 73, 110, 118, 111, 99, 97, 116, 105, 111, 110, 67, 114, 101, 97, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 84, 114, 97, 110, 115, 105, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 67, 97, 108, 108, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 83, 101, 115, 115, 105, 111, 110, 73, 100, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 78, 111, 100, 101, 73, 100, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 114, 103, 117, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 65, 114, 103, 117, 109, 101, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 65, 114, 103, 117, 109, 101, 110, 116, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 73, 110, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 73, 110, 116, 51, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 117, 97, 58, 86, 97, 114, 105, 97, 110, 116, 34, 32, 76, 101, 110, 103, 116, 104, 70, 105, 101, 108, 100, 61, 34, 78, 111, 79, 102, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 79, 117, 116, 112, 117, 116, 86, 97, 108, 117, 101, 115, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 67, 97, 108, 108, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 76, 97, 115, 116, 77, 101, 116, 104, 111, 100, 82, 101, 116, 117, 114, 110, 83, 116, 97, 116, 117, 115, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 116, 110, 115, 58, 83, 116, 97, 116, 117, 115, 82, 101, 115, 117, 108, 116, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 34, 32, 66, 97, 115, 101, 84, 121, 112, 101, 61, 34, 117, 97, 58, 69, 120, 116, 101, 110, 115, 105, 111, 110, 79, 98, 106, 101, 99, 116, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 77, 101, 115, 115, 97, 103, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 85, 115, 101, 114, 78, 97, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 83, 116, 114, 105, 110, 103, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 70, 105, 101, 108, 100, 32, 78, 97, 109, 101, 61, 34, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 84, 105, 109, 101, 34, 32, 84, 121, 112, 101, 78, 97, 109, 101, 61, 34, 111, 112, 99, 58, 68, 97, 116, 101, 84, 105, 109, 101, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 83, 116, 114, 117, 99, 116, 117, 114, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 32, 78, 97, 109, 101, 61, 34, 69, 120, 99, 101, 112, 116, 105, 111, 110, 68, 101, 118, 105, 97, 116, 105, 111, 110, 70, 111, 114, 109, 97, 116, 34, 32, 76, 101, 110, 103, 116, 104, 73, 110, 66, 105, 116, 115, 61, 34, 51, 50, 34, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 65, 98, 115, 111, 108, 117, 116, 101, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 48, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 79, 102, 86, 97, 108, 117, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 49, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 79, 102, 82, 97, 110, 103, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 50, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 80, 101, 114, 99, 101, 110, 116, 79, 102, 69, 85, 82, 97, 110, 103, 101, 34, 32, 86, 97, 108, 117, 101, 61, 34, 51, 34, 32, 47, 62, 13, 10, 32, 32, 32, 32, 60, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 86, 97, 108, 117, 101, 32, 78, 97, 109, 101, 61, 34, 85, 110, 107, 110, 111, 119, 110, 34, 32, 86, 97, 108, 117, 101, 61, 34, 52, 34, 32, 47, 62, 13, 10, 32, 32, 60, 47, 111, 112, 99, 58, 69, 110, 117, 109, 101, 114, 97, 116, 101, 100, 84, 121, 112, 101, 62, 13, 10, 13, 10, 60, 47, 111, 112, 99, 58, 84, 121, 112, 101, 68, 105, 99, 116, 105, 111, 110, 97, 114, 121, 62}; |
| 92945 | |
| 92946 | |
| 92947 | |
| 92948 | static UA_StatusCode function_namespace0_generated_814_begin(UA_Server *server, UA_UInt16* ns) { |
| 92949 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92950 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 92951 | attr.minimumSamplingInterval = 0.000000; |
| 92952 | attr.userAccessLevel = 1; |
| 92953 | attr.accessLevel = 1; |
| 92954 | /* Value rank inherited */ |
| 92955 | attr.valueRank = -2; |
| 92956 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU); |
| 92957 | UA_ByteString *variablenode_ns_0_i_7617_variant_DataContents = UA_ByteString_new(); |
| 92958 | if (!variablenode_ns_0_i_7617_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 92959 | UA_ByteString_init(p: variablenode_ns_0_i_7617_variant_DataContents); |
| 92960 | variablenode_ns_0_i_7617_variant_DataContents->length = 177218; |
| 92961 | variablenode_ns_0_i_7617_variant_DataContents->data = (UA_Byte *)(void*)(uintptr_t)variablenode_ns_0_i_7617_variant_DataContents_byteArray; |
| 92962 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_7617_variant_DataContents, type: &UA_TYPES[UA_TYPES_BYTESTRING]); |
| 92963 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Opc.Ua"); |
| 92964 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 92965 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU), |
| 92966 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 93LU), |
| 92967 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 92968 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Opc.Ua"), |
| 92969 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU), |
| 92970 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 92971 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 92972 | variablenode_ns_0_i_7617_variant_DataContents->data = NULL; |
| 92973 | variablenode_ns_0_i_7617_variant_DataContents->length = 0; |
| 92974 | UA_ByteString_delete(p: variablenode_ns_0_i_7617_variant_DataContents); |
| 92975 | return retVal; |
| 92976 | } |
| 92977 | |
| 92978 | static UA_StatusCode function_namespace0_generated_814_finish(UA_Server *server, UA_UInt16* ns) { |
| 92979 | return UA_Server_addNode_finish(server, |
| 92980 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU) |
| 92981 | ); |
| 92982 | } |
| 92983 | |
| 92984 | /* NamespaceUri - ns=0;i=107 */ |
| 92985 | |
| 92986 | static UA_StatusCode function_namespace0_generated_815_begin(UA_Server *server, UA_UInt16* ns) { |
| 92987 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 92988 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 92989 | attr.minimumSamplingInterval = 0.000000; |
| 92990 | attr.userAccessLevel = 1; |
| 92991 | attr.accessLevel = 1; |
| 92992 | /* Value rank inherited */ |
| 92993 | attr.valueRank = -2; |
| 92994 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 92995 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "NamespaceUri"); |
| 92996 | #ifdef UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS |
| 92997 | attr.description = UA_LOCALIZEDTEXT(locale: "", text: "A URI that uniquely identifies the dictionary."); |
| 92998 | #endif |
| 92999 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 93000 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 107LU), |
| 93001 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU), |
| 93002 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 93003 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "NamespaceUri"), |
| 93004 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 93005 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 93006 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93007 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 107LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), true); |
| 93008 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93009 | return retVal; |
| 93010 | } |
| 93011 | |
| 93012 | static UA_StatusCode function_namespace0_generated_815_finish(UA_Server *server, UA_UInt16* ns) { |
| 93013 | return UA_Server_addNode_finish(server, |
| 93014 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 107LU) |
| 93015 | ); |
| 93016 | } |
| 93017 | |
| 93018 | /* DataTypeVersion - ns=0;i=106 */ |
| 93019 | |
| 93020 | static UA_StatusCode function_namespace0_generated_816_begin(UA_Server *server, UA_UInt16* ns) { |
| 93021 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 93022 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 93023 | attr.minimumSamplingInterval = 0.000000; |
| 93024 | attr.userAccessLevel = 1; |
| 93025 | attr.accessLevel = 1; |
| 93026 | /* Value rank inherited */ |
| 93027 | attr.valueRank = -2; |
| 93028 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 93029 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeVersion"); |
| 93030 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 93031 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 106LU), |
| 93032 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 72LU), |
| 93033 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 93034 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeVersion"), |
| 93035 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 93036 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 93037 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93038 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 106LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), true); |
| 93039 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93040 | return retVal; |
| 93041 | } |
| 93042 | |
| 93043 | static UA_StatusCode function_namespace0_generated_816_finish(UA_Server *server, UA_UInt16* ns) { |
| 93044 | return UA_Server_addNode_finish(server, |
| 93045 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 106LU) |
| 93046 | ); |
| 93047 | } |
| 93048 | |
| 93049 | /* DataTypeDescriptionType - ns=0;i=69 */ |
| 93050 | |
| 93051 | static UA_StatusCode function_namespace0_generated_817_begin(UA_Server *server, UA_UInt16* ns) { |
| 93052 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 93053 | UA_VariableTypeAttributes attr = UA_VariableTypeAttributes_default; |
| 93054 | /* Value rank inherited */ |
| 93055 | attr.valueRank = -2; |
| 93056 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 93057 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeDescriptionType"); |
| 93058 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLETYPE, |
| 93059 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU), |
| 93060 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 63LU), |
| 93061 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 45LU), |
| 93062 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeDescriptionType"), |
| 93063 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 93064 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLETYPEATTRIBUTES],NULL, NULL); |
| 93065 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93066 | return retVal; |
| 93067 | } |
| 93068 | |
| 93069 | static UA_StatusCode function_namespace0_generated_817_finish(UA_Server *server, UA_UInt16* ns) { |
| 93070 | return UA_Server_addNode_finish(server, |
| 93071 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU) |
| 93072 | ); |
| 93073 | } |
| 93074 | |
| 93075 | /* EnumValueType - ns=0;i=7656 */ |
| 93076 | |
| 93077 | static UA_StatusCode function_namespace0_generated_818_begin(UA_Server *server, UA_UInt16* ns) { |
| 93078 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 93079 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 93080 | attr.minimumSamplingInterval = 0.000000; |
| 93081 | attr.userAccessLevel = 1; |
| 93082 | attr.accessLevel = 1; |
| 93083 | /* Value rank inherited */ |
| 93084 | attr.valueRank = -2; |
| 93085 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 93086 | UA_String *variablenode_ns_0_i_7656_variant_DataContents = UA_String_new(); |
| 93087 | if (!variablenode_ns_0_i_7656_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 93088 | UA_String_init(p: variablenode_ns_0_i_7656_variant_DataContents); |
| 93089 | *variablenode_ns_0_i_7656_variant_DataContents = UA_STRING_ALLOC("EnumValueType"); |
| 93090 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_7656_variant_DataContents, type: &UA_TYPES[UA_TYPES_STRING]); |
| 93091 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "EnumValueType"); |
| 93092 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 93093 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7656LU), |
| 93094 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU), |
| 93095 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 93096 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "EnumValueType"), |
| 93097 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU), |
| 93098 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 93099 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93100 | UA_String_delete(p: variablenode_ns_0_i_7656_variant_DataContents); |
| 93101 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7656LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 39LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 8251LU), false); |
| 93102 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93103 | return retVal; |
| 93104 | } |
| 93105 | |
| 93106 | static UA_StatusCode function_namespace0_generated_818_finish(UA_Server *server, UA_UInt16* ns) { |
| 93107 | return UA_Server_addNode_finish(server, |
| 93108 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7656LU) |
| 93109 | ); |
| 93110 | } |
| 93111 | |
| 93112 | /* Argument - ns=0;i=7650 */ |
| 93113 | |
| 93114 | static UA_StatusCode function_namespace0_generated_819_begin(UA_Server *server, UA_UInt16* ns) { |
| 93115 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 93116 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 93117 | attr.minimumSamplingInterval = 0.000000; |
| 93118 | attr.userAccessLevel = 1; |
| 93119 | attr.accessLevel = 1; |
| 93120 | /* Value rank inherited */ |
| 93121 | attr.valueRank = -2; |
| 93122 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 93123 | UA_String *variablenode_ns_0_i_7650_variant_DataContents = UA_String_new(); |
| 93124 | if (!variablenode_ns_0_i_7650_variant_DataContents) return UA_STATUSCODE_BADOUTOFMEMORY; |
| 93125 | UA_String_init(p: variablenode_ns_0_i_7650_variant_DataContents); |
| 93126 | *variablenode_ns_0_i_7650_variant_DataContents = UA_STRING_ALLOC("Argument"); |
| 93127 | UA_Variant_setScalar(v: &attr.value, p: variablenode_ns_0_i_7650_variant_DataContents, type: &UA_TYPES[UA_TYPES_STRING]); |
| 93128 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Argument"); |
| 93129 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 93130 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7650LU), |
| 93131 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7617LU), |
| 93132 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 47LU), |
| 93133 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Argument"), |
| 93134 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU), |
| 93135 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 93136 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93137 | UA_String_delete(p: variablenode_ns_0_i_7650_variant_DataContents); |
| 93138 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7650LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 39LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 298LU), false); |
| 93139 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93140 | return retVal; |
| 93141 | } |
| 93142 | |
| 93143 | static UA_StatusCode function_namespace0_generated_819_finish(UA_Server *server, UA_UInt16* ns) { |
| 93144 | return UA_Server_addNode_finish(server, |
| 93145 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 7650LU) |
| 93146 | ); |
| 93147 | } |
| 93148 | |
| 93149 | /* DictionaryFragment - ns=0;i=105 */ |
| 93150 | |
| 93151 | static UA_StatusCode function_namespace0_generated_820_begin(UA_Server *server, UA_UInt16* ns) { |
| 93152 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 93153 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 93154 | attr.minimumSamplingInterval = 0.000000; |
| 93155 | attr.userAccessLevel = 1; |
| 93156 | attr.accessLevel = 1; |
| 93157 | /* Value rank inherited */ |
| 93158 | attr.valueRank = -2; |
| 93159 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 15LU); |
| 93160 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DictionaryFragment"); |
| 93161 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 93162 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 105LU), |
| 93163 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU), |
| 93164 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 93165 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DictionaryFragment"), |
| 93166 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 93167 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 93168 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93169 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 105LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), true); |
| 93170 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93171 | return retVal; |
| 93172 | } |
| 93173 | |
| 93174 | static UA_StatusCode function_namespace0_generated_820_finish(UA_Server *server, UA_UInt16* ns) { |
| 93175 | return UA_Server_addNode_finish(server, |
| 93176 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 105LU) |
| 93177 | ); |
| 93178 | } |
| 93179 | |
| 93180 | /* DataTypeVersion - ns=0;i=104 */ |
| 93181 | |
| 93182 | static UA_StatusCode function_namespace0_generated_821_begin(UA_Server *server, UA_UInt16* ns) { |
| 93183 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 93184 | UA_VariableAttributes attr = UA_VariableAttributes_default; |
| 93185 | attr.minimumSamplingInterval = 0.000000; |
| 93186 | attr.userAccessLevel = 1; |
| 93187 | attr.accessLevel = 1; |
| 93188 | /* Value rank inherited */ |
| 93189 | attr.valueRank = -2; |
| 93190 | attr.dataType = UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 12LU); |
| 93191 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "DataTypeVersion"); |
| 93192 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_VARIABLE, |
| 93193 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 104LU), |
| 93194 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 69LU), |
| 93195 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 46LU), |
| 93196 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "DataTypeVersion"), |
| 93197 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 68LU), |
| 93198 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_VARIABLEATTRIBUTES],NULL, NULL); |
| 93199 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93200 | retVal |= UA_Server_addReference(server, sourceId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 104LU), refTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 37LU), targetId: UA_EXPANDEDNODEID_NUMERIC(nsIndex: ns[0], identifier: 80LU), true); |
| 93201 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93202 | return retVal; |
| 93203 | } |
| 93204 | |
| 93205 | static UA_StatusCode function_namespace0_generated_821_finish(UA_Server *server, UA_UInt16* ns) { |
| 93206 | return UA_Server_addNode_finish(server, |
| 93207 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 104LU) |
| 93208 | ); |
| 93209 | } |
| 93210 | |
| 93211 | /* Default XML - ns=0;i=3063 */ |
| 93212 | |
| 93213 | static UA_StatusCode function_namespace0_generated_822_begin(UA_Server *server, UA_UInt16* ns) { |
| 93214 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 93215 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 93216 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default XML"); |
| 93217 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 93218 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3063LU), |
| 93219 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 93220 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 93221 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default XML"), |
| 93222 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 93223 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 93224 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93225 | return retVal; |
| 93226 | } |
| 93227 | |
| 93228 | static UA_StatusCode function_namespace0_generated_822_finish(UA_Server *server, UA_UInt16* ns) { |
| 93229 | return UA_Server_addNode_finish(server, |
| 93230 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3063LU) |
| 93231 | ); |
| 93232 | } |
| 93233 | |
| 93234 | /* Default Binary - ns=0;i=3062 */ |
| 93235 | |
| 93236 | static UA_StatusCode function_namespace0_generated_823_begin(UA_Server *server, UA_UInt16* ns) { |
| 93237 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 93238 | UA_ObjectAttributes attr = UA_ObjectAttributes_default; |
| 93239 | attr.displayName = UA_LOCALIZEDTEXT(locale: "", text: "Default Binary"); |
| 93240 | retVal |= UA_Server_addNode_begin(server, nodeClass: UA_NODECLASS_OBJECT, |
| 93241 | requestedNewNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3062LU), |
| 93242 | parentNodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 93243 | referenceTypeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 0LU), |
| 93244 | browseName: UA_QUALIFIEDNAME(nsIndex: ns[0], chars: "Default Binary"), |
| 93245 | typeDefinition: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 58LU), |
| 93246 | attr: (const UA_NodeAttributes*)&attr, attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES],NULL, NULL); |
| 93247 | if (retVal != UA_STATUSCODE_GOOD) return retVal; |
| 93248 | return retVal; |
| 93249 | } |
| 93250 | |
| 93251 | static UA_StatusCode function_namespace0_generated_823_finish(UA_Server *server, UA_UInt16* ns) { |
| 93252 | return UA_Server_addNode_finish(server, |
| 93253 | nodeId: UA_NODEID_NUMERIC(nsIndex: ns[0], identifier: 3062LU) |
| 93254 | ); |
| 93255 | } |
| 93256 | |
| 93257 | UA_StatusCode namespace0_generated(UA_Server *server) { |
| 93258 | UA_StatusCode retVal = UA_STATUSCODE_GOOD; |
| 93259 | /* Use namespace ids generated by the server */ |
| 93260 | UA_UInt16 ns[1]; |
| 93261 | ns[0] = UA_Server_addNamespace(server, name: "http://opcfoundation.org/UA/"); |
| 93262 | |
| 93263 | /* Load custom datatype definitions into the server */ |
| 93264 | if((retVal = function_namespace0_generated_0_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93265 | if((retVal = function_namespace0_generated_0_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93266 | if((retVal = function_namespace0_generated_1_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93267 | if((retVal = function_namespace0_generated_1_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93268 | if((retVal = function_namespace0_generated_2_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93269 | if((retVal = function_namespace0_generated_2_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93270 | if((retVal = function_namespace0_generated_3_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93271 | if((retVal = function_namespace0_generated_3_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93272 | if((retVal = function_namespace0_generated_4_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93273 | if((retVal = function_namespace0_generated_4_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93274 | if((retVal = function_namespace0_generated_5_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93275 | if((retVal = function_namespace0_generated_5_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93276 | if((retVal = function_namespace0_generated_6_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93277 | if((retVal = function_namespace0_generated_6_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93278 | if((retVal = function_namespace0_generated_7_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93279 | if((retVal = function_namespace0_generated_7_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93280 | if((retVal = function_namespace0_generated_8_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93281 | if((retVal = function_namespace0_generated_8_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93282 | if((retVal = function_namespace0_generated_9_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93283 | if((retVal = function_namespace0_generated_9_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93284 | if((retVal = function_namespace0_generated_10_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93285 | if((retVal = function_namespace0_generated_10_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93286 | if((retVal = function_namespace0_generated_11_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93287 | if((retVal = function_namespace0_generated_12_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93288 | if((retVal = function_namespace0_generated_13_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93289 | if((retVal = function_namespace0_generated_14_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93290 | if((retVal = function_namespace0_generated_15_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93291 | if((retVal = function_namespace0_generated_16_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93292 | if((retVal = function_namespace0_generated_17_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93293 | if((retVal = function_namespace0_generated_18_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93294 | if((retVal = function_namespace0_generated_19_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93295 | if((retVal = function_namespace0_generated_20_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93296 | if((retVal = function_namespace0_generated_21_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93297 | if((retVal = function_namespace0_generated_22_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93298 | if((retVal = function_namespace0_generated_23_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93299 | if((retVal = function_namespace0_generated_24_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93300 | if((retVal = function_namespace0_generated_25_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93301 | if((retVal = function_namespace0_generated_26_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93302 | if((retVal = function_namespace0_generated_27_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93303 | if((retVal = function_namespace0_generated_28_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93304 | if((retVal = function_namespace0_generated_29_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93305 | if((retVal = function_namespace0_generated_30_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93306 | if((retVal = function_namespace0_generated_31_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93307 | if((retVal = function_namespace0_generated_32_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93308 | if((retVal = function_namespace0_generated_33_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93309 | if((retVal = function_namespace0_generated_34_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93310 | if((retVal = function_namespace0_generated_35_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93311 | if((retVal = function_namespace0_generated_36_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93312 | if((retVal = function_namespace0_generated_37_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93313 | if((retVal = function_namespace0_generated_38_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93314 | if((retVal = function_namespace0_generated_39_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93315 | if((retVal = function_namespace0_generated_40_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93316 | if((retVal = function_namespace0_generated_41_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93317 | if((retVal = function_namespace0_generated_42_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93318 | if((retVal = function_namespace0_generated_43_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93319 | if((retVal = function_namespace0_generated_44_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93320 | if((retVal = function_namespace0_generated_45_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93321 | if((retVal = function_namespace0_generated_46_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93322 | if((retVal = function_namespace0_generated_47_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93323 | if((retVal = function_namespace0_generated_48_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93324 | if((retVal = function_namespace0_generated_49_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93325 | if((retVal = function_namespace0_generated_50_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93326 | if((retVal = function_namespace0_generated_51_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93327 | if((retVal = function_namespace0_generated_52_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93328 | if((retVal = function_namespace0_generated_53_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93329 | if((retVal = function_namespace0_generated_54_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93330 | if((retVal = function_namespace0_generated_55_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93331 | if((retVal = function_namespace0_generated_56_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93332 | if((retVal = function_namespace0_generated_57_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93333 | if((retVal = function_namespace0_generated_58_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93334 | if((retVal = function_namespace0_generated_59_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93335 | if((retVal = function_namespace0_generated_60_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93336 | if((retVal = function_namespace0_generated_61_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93337 | if((retVal = function_namespace0_generated_62_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93338 | if((retVal = function_namespace0_generated_63_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93339 | if((retVal = function_namespace0_generated_64_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93340 | if((retVal = function_namespace0_generated_65_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93341 | if((retVal = function_namespace0_generated_66_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93342 | if((retVal = function_namespace0_generated_67_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93343 | if((retVal = function_namespace0_generated_68_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93344 | if((retVal = function_namespace0_generated_69_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93345 | if((retVal = function_namespace0_generated_70_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93346 | if((retVal = function_namespace0_generated_71_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93347 | if((retVal = function_namespace0_generated_72_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93348 | if((retVal = function_namespace0_generated_73_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93349 | if((retVal = function_namespace0_generated_74_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93350 | if((retVal = function_namespace0_generated_75_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93351 | if((retVal = function_namespace0_generated_76_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93352 | if((retVal = function_namespace0_generated_77_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93353 | if((retVal = function_namespace0_generated_78_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93354 | if((retVal = function_namespace0_generated_79_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93355 | if((retVal = function_namespace0_generated_80_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93356 | if((retVal = function_namespace0_generated_81_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93357 | if((retVal = function_namespace0_generated_82_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93358 | if((retVal = function_namespace0_generated_83_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93359 | if((retVal = function_namespace0_generated_84_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93360 | if((retVal = function_namespace0_generated_85_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93361 | if((retVal = function_namespace0_generated_86_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93362 | if((retVal = function_namespace0_generated_87_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93363 | if((retVal = function_namespace0_generated_88_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93364 | if((retVal = function_namespace0_generated_89_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93365 | if((retVal = function_namespace0_generated_90_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93366 | if((retVal = function_namespace0_generated_91_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93367 | if((retVal = function_namespace0_generated_92_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93368 | if((retVal = function_namespace0_generated_93_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93369 | if((retVal = function_namespace0_generated_94_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93370 | if((retVal = function_namespace0_generated_95_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93371 | if((retVal = function_namespace0_generated_96_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93372 | if((retVal = function_namespace0_generated_97_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93373 | if((retVal = function_namespace0_generated_98_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93374 | if((retVal = function_namespace0_generated_99_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93375 | if((retVal = function_namespace0_generated_100_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93376 | if((retVal = function_namespace0_generated_101_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93377 | if((retVal = function_namespace0_generated_102_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93378 | if((retVal = function_namespace0_generated_103_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93379 | if((retVal = function_namespace0_generated_104_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93380 | if((retVal = function_namespace0_generated_105_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93381 | if((retVal = function_namespace0_generated_106_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93382 | if((retVal = function_namespace0_generated_107_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93383 | if((retVal = function_namespace0_generated_108_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93384 | if((retVal = function_namespace0_generated_109_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93385 | if((retVal = function_namespace0_generated_110_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93386 | if((retVal = function_namespace0_generated_111_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93387 | if((retVal = function_namespace0_generated_112_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93388 | if((retVal = function_namespace0_generated_113_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93389 | if((retVal = function_namespace0_generated_114_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93390 | if((retVal = function_namespace0_generated_115_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93391 | if((retVal = function_namespace0_generated_116_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93392 | if((retVal = function_namespace0_generated_117_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93393 | if((retVal = function_namespace0_generated_118_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93394 | if((retVal = function_namespace0_generated_119_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93395 | if((retVal = function_namespace0_generated_120_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93396 | if((retVal = function_namespace0_generated_121_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93397 | if((retVal = function_namespace0_generated_122_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93398 | if((retVal = function_namespace0_generated_123_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93399 | if((retVal = function_namespace0_generated_124_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93400 | if((retVal = function_namespace0_generated_125_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93401 | if((retVal = function_namespace0_generated_126_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93402 | if((retVal = function_namespace0_generated_127_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93403 | if((retVal = function_namespace0_generated_128_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93404 | if((retVal = function_namespace0_generated_129_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93405 | if((retVal = function_namespace0_generated_130_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93406 | if((retVal = function_namespace0_generated_131_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93407 | if((retVal = function_namespace0_generated_132_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93408 | if((retVal = function_namespace0_generated_133_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93409 | if((retVal = function_namespace0_generated_134_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93410 | if((retVal = function_namespace0_generated_135_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93411 | if((retVal = function_namespace0_generated_136_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93412 | if((retVal = function_namespace0_generated_137_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93413 | if((retVal = function_namespace0_generated_138_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93414 | if((retVal = function_namespace0_generated_139_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93415 | if((retVal = function_namespace0_generated_140_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93416 | if((retVal = function_namespace0_generated_141_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93417 | if((retVal = function_namespace0_generated_142_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93418 | if((retVal = function_namespace0_generated_143_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93419 | if((retVal = function_namespace0_generated_144_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93420 | if((retVal = function_namespace0_generated_145_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93421 | if((retVal = function_namespace0_generated_146_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93422 | if((retVal = function_namespace0_generated_147_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93423 | if((retVal = function_namespace0_generated_148_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93424 | if((retVal = function_namespace0_generated_149_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93425 | if((retVal = function_namespace0_generated_150_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93426 | if((retVal = function_namespace0_generated_151_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93427 | if((retVal = function_namespace0_generated_152_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93428 | if((retVal = function_namespace0_generated_153_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93429 | if((retVal = function_namespace0_generated_154_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93430 | if((retVal = function_namespace0_generated_155_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93431 | if((retVal = function_namespace0_generated_156_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93432 | if((retVal = function_namespace0_generated_157_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93433 | if((retVal = function_namespace0_generated_158_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93434 | if((retVal = function_namespace0_generated_159_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93435 | if((retVal = function_namespace0_generated_160_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93436 | if((retVal = function_namespace0_generated_161_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93437 | if((retVal = function_namespace0_generated_162_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93438 | if((retVal = function_namespace0_generated_163_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93439 | if((retVal = function_namespace0_generated_164_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93440 | if((retVal = function_namespace0_generated_165_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93441 | if((retVal = function_namespace0_generated_166_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93442 | if((retVal = function_namespace0_generated_167_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93443 | if((retVal = function_namespace0_generated_168_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93444 | if((retVal = function_namespace0_generated_169_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93445 | if((retVal = function_namespace0_generated_170_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93446 | if((retVal = function_namespace0_generated_171_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93447 | if((retVal = function_namespace0_generated_172_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93448 | if((retVal = function_namespace0_generated_173_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93449 | if((retVal = function_namespace0_generated_174_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93450 | if((retVal = function_namespace0_generated_175_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93451 | if((retVal = function_namespace0_generated_176_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93452 | if((retVal = function_namespace0_generated_177_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93453 | if((retVal = function_namespace0_generated_178_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93454 | if((retVal = function_namespace0_generated_179_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93455 | if((retVal = function_namespace0_generated_180_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93456 | if((retVal = function_namespace0_generated_181_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93457 | if((retVal = function_namespace0_generated_182_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93458 | if((retVal = function_namespace0_generated_183_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93459 | if((retVal = function_namespace0_generated_184_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93460 | if((retVal = function_namespace0_generated_185_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93461 | if((retVal = function_namespace0_generated_186_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93462 | if((retVal = function_namespace0_generated_187_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93463 | if((retVal = function_namespace0_generated_188_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93464 | if((retVal = function_namespace0_generated_189_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93465 | if((retVal = function_namespace0_generated_190_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93466 | if((retVal = function_namespace0_generated_191_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93467 | if((retVal = function_namespace0_generated_192_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93468 | if((retVal = function_namespace0_generated_193_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93469 | if((retVal = function_namespace0_generated_194_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93470 | if((retVal = function_namespace0_generated_195_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93471 | if((retVal = function_namespace0_generated_196_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93472 | if((retVal = function_namespace0_generated_197_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93473 | if((retVal = function_namespace0_generated_198_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93474 | if((retVal = function_namespace0_generated_199_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93475 | if((retVal = function_namespace0_generated_200_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93476 | if((retVal = function_namespace0_generated_201_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93477 | if((retVal = function_namespace0_generated_202_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93478 | if((retVal = function_namespace0_generated_203_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93479 | if((retVal = function_namespace0_generated_204_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93480 | if((retVal = function_namespace0_generated_205_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93481 | if((retVal = function_namespace0_generated_206_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93482 | if((retVal = function_namespace0_generated_207_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93483 | if((retVal = function_namespace0_generated_208_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93484 | if((retVal = function_namespace0_generated_209_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93485 | if((retVal = function_namespace0_generated_210_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93486 | if((retVal = function_namespace0_generated_211_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93487 | if((retVal = function_namespace0_generated_212_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93488 | if((retVal = function_namespace0_generated_213_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93489 | if((retVal = function_namespace0_generated_214_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93490 | if((retVal = function_namespace0_generated_215_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93491 | if((retVal = function_namespace0_generated_216_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93492 | if((retVal = function_namespace0_generated_217_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93493 | if((retVal = function_namespace0_generated_218_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93494 | if((retVal = function_namespace0_generated_219_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93495 | if((retVal = function_namespace0_generated_220_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93496 | if((retVal = function_namespace0_generated_221_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93497 | if((retVal = function_namespace0_generated_222_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93498 | if((retVal = function_namespace0_generated_223_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93499 | if((retVal = function_namespace0_generated_224_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93500 | if((retVal = function_namespace0_generated_225_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93501 | if((retVal = function_namespace0_generated_226_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93502 | if((retVal = function_namespace0_generated_227_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93503 | if((retVal = function_namespace0_generated_228_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93504 | if((retVal = function_namespace0_generated_229_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93505 | if((retVal = function_namespace0_generated_230_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93506 | if((retVal = function_namespace0_generated_231_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93507 | if((retVal = function_namespace0_generated_232_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93508 | if((retVal = function_namespace0_generated_233_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93509 | if((retVal = function_namespace0_generated_234_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93510 | if((retVal = function_namespace0_generated_235_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93511 | if((retVal = function_namespace0_generated_236_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93512 | if((retVal = function_namespace0_generated_237_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93513 | if((retVal = function_namespace0_generated_238_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93514 | if((retVal = function_namespace0_generated_239_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93515 | if((retVal = function_namespace0_generated_240_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93516 | if((retVal = function_namespace0_generated_241_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93517 | if((retVal = function_namespace0_generated_242_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93518 | if((retVal = function_namespace0_generated_243_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93519 | if((retVal = function_namespace0_generated_244_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93520 | if((retVal = function_namespace0_generated_245_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93521 | if((retVal = function_namespace0_generated_246_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93522 | if((retVal = function_namespace0_generated_247_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93523 | if((retVal = function_namespace0_generated_248_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93524 | if((retVal = function_namespace0_generated_249_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93525 | if((retVal = function_namespace0_generated_250_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93526 | if((retVal = function_namespace0_generated_251_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93527 | if((retVal = function_namespace0_generated_252_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93528 | if((retVal = function_namespace0_generated_253_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93529 | if((retVal = function_namespace0_generated_254_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93530 | if((retVal = function_namespace0_generated_255_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93531 | if((retVal = function_namespace0_generated_256_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93532 | if((retVal = function_namespace0_generated_257_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93533 | if((retVal = function_namespace0_generated_258_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93534 | if((retVal = function_namespace0_generated_259_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93535 | if((retVal = function_namespace0_generated_260_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93536 | if((retVal = function_namespace0_generated_261_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93537 | if((retVal = function_namespace0_generated_262_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93538 | if((retVal = function_namespace0_generated_263_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93539 | if((retVal = function_namespace0_generated_264_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93540 | if((retVal = function_namespace0_generated_265_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93541 | if((retVal = function_namespace0_generated_266_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93542 | if((retVal = function_namespace0_generated_267_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93543 | if((retVal = function_namespace0_generated_268_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93544 | if((retVal = function_namespace0_generated_269_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93545 | if((retVal = function_namespace0_generated_270_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93546 | if((retVal = function_namespace0_generated_271_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93547 | if((retVal = function_namespace0_generated_272_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93548 | if((retVal = function_namespace0_generated_273_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93549 | if((retVal = function_namespace0_generated_274_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93550 | if((retVal = function_namespace0_generated_275_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93551 | if((retVal = function_namespace0_generated_276_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93552 | if((retVal = function_namespace0_generated_277_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93553 | if((retVal = function_namespace0_generated_278_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93554 | if((retVal = function_namespace0_generated_279_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93555 | if((retVal = function_namespace0_generated_280_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93556 | if((retVal = function_namespace0_generated_281_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93557 | if((retVal = function_namespace0_generated_282_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93558 | if((retVal = function_namespace0_generated_283_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93559 | if((retVal = function_namespace0_generated_284_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93560 | if((retVal = function_namespace0_generated_285_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93561 | if((retVal = function_namespace0_generated_286_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93562 | if((retVal = function_namespace0_generated_287_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93563 | if((retVal = function_namespace0_generated_288_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93564 | if((retVal = function_namespace0_generated_289_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93565 | if((retVal = function_namespace0_generated_290_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93566 | if((retVal = function_namespace0_generated_291_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93567 | if((retVal = function_namespace0_generated_292_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93568 | if((retVal = function_namespace0_generated_293_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93569 | if((retVal = function_namespace0_generated_294_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93570 | if((retVal = function_namespace0_generated_295_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93571 | if((retVal = function_namespace0_generated_296_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93572 | if((retVal = function_namespace0_generated_297_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93573 | if((retVal = function_namespace0_generated_298_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93574 | if((retVal = function_namespace0_generated_299_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93575 | if((retVal = function_namespace0_generated_300_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93576 | if((retVal = function_namespace0_generated_301_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93577 | if((retVal = function_namespace0_generated_302_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93578 | if((retVal = function_namespace0_generated_303_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93579 | if((retVal = function_namespace0_generated_304_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93580 | if((retVal = function_namespace0_generated_305_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93581 | if((retVal = function_namespace0_generated_306_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93582 | if((retVal = function_namespace0_generated_307_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93583 | if((retVal = function_namespace0_generated_308_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93584 | if((retVal = function_namespace0_generated_309_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93585 | if((retVal = function_namespace0_generated_310_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93586 | if((retVal = function_namespace0_generated_311_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93587 | if((retVal = function_namespace0_generated_312_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93588 | if((retVal = function_namespace0_generated_313_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93589 | if((retVal = function_namespace0_generated_314_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93590 | if((retVal = function_namespace0_generated_315_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93591 | if((retVal = function_namespace0_generated_316_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93592 | if((retVal = function_namespace0_generated_317_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93593 | if((retVal = function_namespace0_generated_318_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93594 | if((retVal = function_namespace0_generated_319_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93595 | if((retVal = function_namespace0_generated_320_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93596 | if((retVal = function_namespace0_generated_321_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93597 | if((retVal = function_namespace0_generated_322_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93598 | if((retVal = function_namespace0_generated_323_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93599 | if((retVal = function_namespace0_generated_324_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93600 | if((retVal = function_namespace0_generated_325_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93601 | if((retVal = function_namespace0_generated_326_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93602 | if((retVal = function_namespace0_generated_327_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93603 | if((retVal = function_namespace0_generated_328_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93604 | if((retVal = function_namespace0_generated_329_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93605 | if((retVal = function_namespace0_generated_330_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93606 | if((retVal = function_namespace0_generated_331_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93607 | if((retVal = function_namespace0_generated_332_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93608 | if((retVal = function_namespace0_generated_333_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93609 | if((retVal = function_namespace0_generated_334_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93610 | if((retVal = function_namespace0_generated_335_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93611 | if((retVal = function_namespace0_generated_336_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93612 | if((retVal = function_namespace0_generated_337_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93613 | if((retVal = function_namespace0_generated_338_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93614 | if((retVal = function_namespace0_generated_339_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93615 | if((retVal = function_namespace0_generated_340_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93616 | if((retVal = function_namespace0_generated_341_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93617 | if((retVal = function_namespace0_generated_342_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93618 | if((retVal = function_namespace0_generated_343_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93619 | if((retVal = function_namespace0_generated_344_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93620 | if((retVal = function_namespace0_generated_345_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93621 | if((retVal = function_namespace0_generated_346_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93622 | if((retVal = function_namespace0_generated_347_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93623 | if((retVal = function_namespace0_generated_348_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93624 | if((retVal = function_namespace0_generated_349_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93625 | if((retVal = function_namespace0_generated_350_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93626 | if((retVal = function_namespace0_generated_351_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93627 | if((retVal = function_namespace0_generated_352_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93628 | if((retVal = function_namespace0_generated_353_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93629 | if((retVal = function_namespace0_generated_354_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93630 | if((retVal = function_namespace0_generated_355_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93631 | if((retVal = function_namespace0_generated_356_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93632 | if((retVal = function_namespace0_generated_357_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93633 | if((retVal = function_namespace0_generated_358_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93634 | if((retVal = function_namespace0_generated_359_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93635 | if((retVal = function_namespace0_generated_360_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93636 | if((retVal = function_namespace0_generated_361_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93637 | if((retVal = function_namespace0_generated_362_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93638 | if((retVal = function_namespace0_generated_363_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93639 | if((retVal = function_namespace0_generated_364_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93640 | if((retVal = function_namespace0_generated_365_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93641 | if((retVal = function_namespace0_generated_366_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93642 | if((retVal = function_namespace0_generated_367_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93643 | if((retVal = function_namespace0_generated_368_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93644 | if((retVal = function_namespace0_generated_369_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93645 | if((retVal = function_namespace0_generated_370_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93646 | if((retVal = function_namespace0_generated_371_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93647 | if((retVal = function_namespace0_generated_372_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93648 | if((retVal = function_namespace0_generated_373_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93649 | if((retVal = function_namespace0_generated_374_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93650 | if((retVal = function_namespace0_generated_375_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93651 | if((retVal = function_namespace0_generated_376_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93652 | if((retVal = function_namespace0_generated_377_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93653 | if((retVal = function_namespace0_generated_378_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93654 | if((retVal = function_namespace0_generated_379_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93655 | if((retVal = function_namespace0_generated_380_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93656 | if((retVal = function_namespace0_generated_381_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93657 | if((retVal = function_namespace0_generated_382_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93658 | if((retVal = function_namespace0_generated_383_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93659 | if((retVal = function_namespace0_generated_384_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93660 | if((retVal = function_namespace0_generated_385_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93661 | if((retVal = function_namespace0_generated_386_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93662 | if((retVal = function_namespace0_generated_387_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93663 | if((retVal = function_namespace0_generated_388_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93664 | if((retVal = function_namespace0_generated_389_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93665 | if((retVal = function_namespace0_generated_390_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93666 | if((retVal = function_namespace0_generated_391_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93667 | if((retVal = function_namespace0_generated_392_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93668 | if((retVal = function_namespace0_generated_393_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93669 | if((retVal = function_namespace0_generated_394_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93670 | if((retVal = function_namespace0_generated_395_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93671 | if((retVal = function_namespace0_generated_396_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93672 | if((retVal = function_namespace0_generated_397_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93673 | if((retVal = function_namespace0_generated_398_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93674 | if((retVal = function_namespace0_generated_399_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93675 | if((retVal = function_namespace0_generated_400_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93676 | if((retVal = function_namespace0_generated_401_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93677 | if((retVal = function_namespace0_generated_402_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93678 | if((retVal = function_namespace0_generated_403_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93679 | if((retVal = function_namespace0_generated_404_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93680 | if((retVal = function_namespace0_generated_405_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93681 | if((retVal = function_namespace0_generated_406_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93682 | if((retVal = function_namespace0_generated_407_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93683 | if((retVal = function_namespace0_generated_408_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93684 | if((retVal = function_namespace0_generated_409_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93685 | if((retVal = function_namespace0_generated_410_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93686 | if((retVal = function_namespace0_generated_411_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93687 | if((retVal = function_namespace0_generated_412_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93688 | if((retVal = function_namespace0_generated_413_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93689 | if((retVal = function_namespace0_generated_414_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93690 | if((retVal = function_namespace0_generated_415_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93691 | if((retVal = function_namespace0_generated_416_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93692 | if((retVal = function_namespace0_generated_417_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93693 | if((retVal = function_namespace0_generated_418_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93694 | if((retVal = function_namespace0_generated_419_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93695 | if((retVal = function_namespace0_generated_420_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93696 | if((retVal = function_namespace0_generated_421_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93697 | if((retVal = function_namespace0_generated_422_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93698 | if((retVal = function_namespace0_generated_423_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93699 | if((retVal = function_namespace0_generated_424_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93700 | if((retVal = function_namespace0_generated_425_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93701 | if((retVal = function_namespace0_generated_426_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93702 | if((retVal = function_namespace0_generated_427_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93703 | if((retVal = function_namespace0_generated_428_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93704 | if((retVal = function_namespace0_generated_429_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93705 | if((retVal = function_namespace0_generated_430_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93706 | if((retVal = function_namespace0_generated_431_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93707 | if((retVal = function_namespace0_generated_432_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93708 | if((retVal = function_namespace0_generated_433_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93709 | if((retVal = function_namespace0_generated_434_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93710 | if((retVal = function_namespace0_generated_435_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93711 | if((retVal = function_namespace0_generated_436_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93712 | if((retVal = function_namespace0_generated_437_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93713 | if((retVal = function_namespace0_generated_438_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93714 | if((retVal = function_namespace0_generated_439_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93715 | if((retVal = function_namespace0_generated_440_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93716 | if((retVal = function_namespace0_generated_441_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93717 | if((retVal = function_namespace0_generated_442_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93718 | if((retVal = function_namespace0_generated_443_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93719 | if((retVal = function_namespace0_generated_444_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93720 | if((retVal = function_namespace0_generated_445_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93721 | if((retVal = function_namespace0_generated_446_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93722 | if((retVal = function_namespace0_generated_447_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93723 | if((retVal = function_namespace0_generated_448_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93724 | if((retVal = function_namespace0_generated_449_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93725 | if((retVal = function_namespace0_generated_450_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93726 | if((retVal = function_namespace0_generated_451_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93727 | if((retVal = function_namespace0_generated_452_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93728 | if((retVal = function_namespace0_generated_453_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93729 | if((retVal = function_namespace0_generated_454_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93730 | if((retVal = function_namespace0_generated_455_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93731 | if((retVal = function_namespace0_generated_456_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93732 | if((retVal = function_namespace0_generated_457_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93733 | if((retVal = function_namespace0_generated_458_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93734 | if((retVal = function_namespace0_generated_459_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93735 | if((retVal = function_namespace0_generated_460_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93736 | if((retVal = function_namespace0_generated_461_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93737 | if((retVal = function_namespace0_generated_462_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93738 | if((retVal = function_namespace0_generated_463_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93739 | if((retVal = function_namespace0_generated_464_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93740 | if((retVal = function_namespace0_generated_465_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93741 | if((retVal = function_namespace0_generated_466_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93742 | if((retVal = function_namespace0_generated_467_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93743 | if((retVal = function_namespace0_generated_468_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93744 | if((retVal = function_namespace0_generated_469_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93745 | if((retVal = function_namespace0_generated_470_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93746 | if((retVal = function_namespace0_generated_471_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93747 | if((retVal = function_namespace0_generated_472_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93748 | if((retVal = function_namespace0_generated_473_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93749 | if((retVal = function_namespace0_generated_474_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93750 | if((retVal = function_namespace0_generated_475_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93751 | if((retVal = function_namespace0_generated_476_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93752 | if((retVal = function_namespace0_generated_477_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93753 | if((retVal = function_namespace0_generated_478_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93754 | if((retVal = function_namespace0_generated_479_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93755 | if((retVal = function_namespace0_generated_480_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93756 | if((retVal = function_namespace0_generated_481_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93757 | if((retVal = function_namespace0_generated_482_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93758 | if((retVal = function_namespace0_generated_483_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93759 | if((retVal = function_namespace0_generated_484_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93760 | if((retVal = function_namespace0_generated_485_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93761 | if((retVal = function_namespace0_generated_486_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93762 | if((retVal = function_namespace0_generated_487_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93763 | if((retVal = function_namespace0_generated_488_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93764 | if((retVal = function_namespace0_generated_489_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93765 | if((retVal = function_namespace0_generated_490_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93766 | if((retVal = function_namespace0_generated_491_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93767 | if((retVal = function_namespace0_generated_492_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93768 | if((retVal = function_namespace0_generated_493_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93769 | if((retVal = function_namespace0_generated_494_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93770 | if((retVal = function_namespace0_generated_495_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93771 | if((retVal = function_namespace0_generated_496_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93772 | if((retVal = function_namespace0_generated_497_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93773 | if((retVal = function_namespace0_generated_498_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93774 | if((retVal = function_namespace0_generated_499_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93775 | if((retVal = function_namespace0_generated_500_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93776 | if((retVal = function_namespace0_generated_501_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93777 | if((retVal = function_namespace0_generated_502_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93778 | if((retVal = function_namespace0_generated_503_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93779 | if((retVal = function_namespace0_generated_504_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93780 | if((retVal = function_namespace0_generated_505_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93781 | if((retVal = function_namespace0_generated_506_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93782 | if((retVal = function_namespace0_generated_507_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93783 | if((retVal = function_namespace0_generated_508_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93784 | if((retVal = function_namespace0_generated_509_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93785 | if((retVal = function_namespace0_generated_510_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93786 | if((retVal = function_namespace0_generated_511_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93787 | if((retVal = function_namespace0_generated_512_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93788 | if((retVal = function_namespace0_generated_513_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93789 | if((retVal = function_namespace0_generated_514_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93790 | if((retVal = function_namespace0_generated_515_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93791 | if((retVal = function_namespace0_generated_516_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93792 | if((retVal = function_namespace0_generated_517_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93793 | if((retVal = function_namespace0_generated_518_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93794 | if((retVal = function_namespace0_generated_519_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93795 | if((retVal = function_namespace0_generated_520_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93796 | if((retVal = function_namespace0_generated_521_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93797 | if((retVal = function_namespace0_generated_522_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93798 | if((retVal = function_namespace0_generated_523_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93799 | if((retVal = function_namespace0_generated_524_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93800 | if((retVal = function_namespace0_generated_525_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93801 | if((retVal = function_namespace0_generated_526_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93802 | if((retVal = function_namespace0_generated_527_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93803 | if((retVal = function_namespace0_generated_528_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93804 | if((retVal = function_namespace0_generated_529_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93805 | if((retVal = function_namespace0_generated_530_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93806 | if((retVal = function_namespace0_generated_531_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93807 | if((retVal = function_namespace0_generated_532_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93808 | if((retVal = function_namespace0_generated_533_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93809 | if((retVal = function_namespace0_generated_534_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93810 | if((retVal = function_namespace0_generated_535_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93811 | if((retVal = function_namespace0_generated_536_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93812 | if((retVal = function_namespace0_generated_537_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93813 | if((retVal = function_namespace0_generated_538_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93814 | if((retVal = function_namespace0_generated_539_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93815 | if((retVal = function_namespace0_generated_540_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93816 | if((retVal = function_namespace0_generated_541_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93817 | if((retVal = function_namespace0_generated_542_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93818 | if((retVal = function_namespace0_generated_543_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93819 | if((retVal = function_namespace0_generated_544_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93820 | if((retVal = function_namespace0_generated_545_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93821 | if((retVal = function_namespace0_generated_546_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93822 | if((retVal = function_namespace0_generated_547_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93823 | if((retVal = function_namespace0_generated_548_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93824 | if((retVal = function_namespace0_generated_549_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93825 | if((retVal = function_namespace0_generated_550_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93826 | if((retVal = function_namespace0_generated_551_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93827 | if((retVal = function_namespace0_generated_552_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93828 | if((retVal = function_namespace0_generated_553_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93829 | if((retVal = function_namespace0_generated_554_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93830 | if((retVal = function_namespace0_generated_555_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93831 | if((retVal = function_namespace0_generated_556_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93832 | if((retVal = function_namespace0_generated_557_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93833 | if((retVal = function_namespace0_generated_558_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93834 | if((retVal = function_namespace0_generated_559_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93835 | if((retVal = function_namespace0_generated_560_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93836 | if((retVal = function_namespace0_generated_561_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93837 | if((retVal = function_namespace0_generated_562_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93838 | if((retVal = function_namespace0_generated_563_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93839 | if((retVal = function_namespace0_generated_564_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93840 | if((retVal = function_namespace0_generated_565_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93841 | if((retVal = function_namespace0_generated_566_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93842 | if((retVal = function_namespace0_generated_567_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93843 | if((retVal = function_namespace0_generated_568_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93844 | if((retVal = function_namespace0_generated_569_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93845 | if((retVal = function_namespace0_generated_570_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93846 | if((retVal = function_namespace0_generated_571_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93847 | if((retVal = function_namespace0_generated_572_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93848 | if((retVal = function_namespace0_generated_573_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93849 | if((retVal = function_namespace0_generated_574_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93850 | if((retVal = function_namespace0_generated_575_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93851 | if((retVal = function_namespace0_generated_576_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93852 | if((retVal = function_namespace0_generated_577_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93853 | if((retVal = function_namespace0_generated_578_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93854 | if((retVal = function_namespace0_generated_579_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93855 | if((retVal = function_namespace0_generated_580_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93856 | if((retVal = function_namespace0_generated_581_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93857 | if((retVal = function_namespace0_generated_582_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93858 | if((retVal = function_namespace0_generated_583_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93859 | if((retVal = function_namespace0_generated_584_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93860 | if((retVal = function_namespace0_generated_585_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93861 | if((retVal = function_namespace0_generated_586_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93862 | if((retVal = function_namespace0_generated_587_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93863 | if((retVal = function_namespace0_generated_588_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93864 | if((retVal = function_namespace0_generated_589_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93865 | if((retVal = function_namespace0_generated_590_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93866 | if((retVal = function_namespace0_generated_591_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93867 | if((retVal = function_namespace0_generated_592_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93868 | if((retVal = function_namespace0_generated_593_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93869 | if((retVal = function_namespace0_generated_594_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93870 | if((retVal = function_namespace0_generated_595_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93871 | if((retVal = function_namespace0_generated_596_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93872 | if((retVal = function_namespace0_generated_597_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93873 | if((retVal = function_namespace0_generated_598_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93874 | if((retVal = function_namespace0_generated_599_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93875 | if((retVal = function_namespace0_generated_600_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93876 | if((retVal = function_namespace0_generated_601_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93877 | if((retVal = function_namespace0_generated_602_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93878 | if((retVal = function_namespace0_generated_603_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93879 | if((retVal = function_namespace0_generated_604_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93880 | if((retVal = function_namespace0_generated_605_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93881 | if((retVal = function_namespace0_generated_606_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93882 | if((retVal = function_namespace0_generated_607_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93883 | if((retVal = function_namespace0_generated_608_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93884 | if((retVal = function_namespace0_generated_609_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93885 | if((retVal = function_namespace0_generated_610_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93886 | if((retVal = function_namespace0_generated_611_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93887 | if((retVal = function_namespace0_generated_612_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93888 | if((retVal = function_namespace0_generated_613_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93889 | if((retVal = function_namespace0_generated_614_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93890 | if((retVal = function_namespace0_generated_615_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93891 | if((retVal = function_namespace0_generated_616_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93892 | if((retVal = function_namespace0_generated_617_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93893 | if((retVal = function_namespace0_generated_618_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93894 | if((retVal = function_namespace0_generated_619_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93895 | if((retVal = function_namespace0_generated_620_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93896 | if((retVal = function_namespace0_generated_621_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93897 | if((retVal = function_namespace0_generated_622_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93898 | if((retVal = function_namespace0_generated_623_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93899 | if((retVal = function_namespace0_generated_624_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93900 | if((retVal = function_namespace0_generated_625_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93901 | if((retVal = function_namespace0_generated_626_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93902 | if((retVal = function_namespace0_generated_627_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93903 | if((retVal = function_namespace0_generated_628_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93904 | if((retVal = function_namespace0_generated_629_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93905 | if((retVal = function_namespace0_generated_630_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93906 | if((retVal = function_namespace0_generated_631_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93907 | if((retVal = function_namespace0_generated_632_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93908 | if((retVal = function_namespace0_generated_633_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93909 | if((retVal = function_namespace0_generated_634_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93910 | if((retVal = function_namespace0_generated_635_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93911 | if((retVal = function_namespace0_generated_636_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93912 | if((retVal = function_namespace0_generated_637_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93913 | if((retVal = function_namespace0_generated_638_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93914 | if((retVal = function_namespace0_generated_639_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93915 | if((retVal = function_namespace0_generated_640_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93916 | if((retVal = function_namespace0_generated_641_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93917 | if((retVal = function_namespace0_generated_642_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93918 | if((retVal = function_namespace0_generated_643_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93919 | if((retVal = function_namespace0_generated_644_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93920 | if((retVal = function_namespace0_generated_645_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93921 | if((retVal = function_namespace0_generated_646_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93922 | if((retVal = function_namespace0_generated_647_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93923 | if((retVal = function_namespace0_generated_648_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93924 | if((retVal = function_namespace0_generated_649_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93925 | if((retVal = function_namespace0_generated_650_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93926 | if((retVal = function_namespace0_generated_651_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93927 | if((retVal = function_namespace0_generated_652_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93928 | if((retVal = function_namespace0_generated_653_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93929 | if((retVal = function_namespace0_generated_654_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93930 | if((retVal = function_namespace0_generated_655_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93931 | if((retVal = function_namespace0_generated_656_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93932 | if((retVal = function_namespace0_generated_657_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93933 | if((retVal = function_namespace0_generated_658_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93934 | if((retVal = function_namespace0_generated_659_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93935 | if((retVal = function_namespace0_generated_660_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93936 | if((retVal = function_namespace0_generated_661_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93937 | if((retVal = function_namespace0_generated_662_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93938 | if((retVal = function_namespace0_generated_663_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93939 | if((retVal = function_namespace0_generated_664_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93940 | if((retVal = function_namespace0_generated_665_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93941 | if((retVal = function_namespace0_generated_666_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93942 | if((retVal = function_namespace0_generated_667_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93943 | if((retVal = function_namespace0_generated_668_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93944 | if((retVal = function_namespace0_generated_669_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93945 | if((retVal = function_namespace0_generated_670_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93946 | if((retVal = function_namespace0_generated_671_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93947 | if((retVal = function_namespace0_generated_672_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93948 | if((retVal = function_namespace0_generated_673_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93949 | if((retVal = function_namespace0_generated_674_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93950 | if((retVal = function_namespace0_generated_675_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93951 | if((retVal = function_namespace0_generated_676_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93952 | if((retVal = function_namespace0_generated_677_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93953 | if((retVal = function_namespace0_generated_678_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93954 | if((retVal = function_namespace0_generated_679_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93955 | if((retVal = function_namespace0_generated_680_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93956 | if((retVal = function_namespace0_generated_681_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93957 | if((retVal = function_namespace0_generated_682_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93958 | if((retVal = function_namespace0_generated_683_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93959 | if((retVal = function_namespace0_generated_684_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93960 | if((retVal = function_namespace0_generated_685_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93961 | if((retVal = function_namespace0_generated_686_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93962 | if((retVal = function_namespace0_generated_687_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93963 | if((retVal = function_namespace0_generated_688_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93964 | if((retVal = function_namespace0_generated_689_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93965 | if((retVal = function_namespace0_generated_690_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93966 | if((retVal = function_namespace0_generated_691_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93967 | if((retVal = function_namespace0_generated_692_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93968 | if((retVal = function_namespace0_generated_693_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93969 | if((retVal = function_namespace0_generated_694_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93970 | if((retVal = function_namespace0_generated_695_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93971 | if((retVal = function_namespace0_generated_696_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93972 | if((retVal = function_namespace0_generated_697_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93973 | if((retVal = function_namespace0_generated_698_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93974 | if((retVal = function_namespace0_generated_699_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93975 | if((retVal = function_namespace0_generated_700_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93976 | if((retVal = function_namespace0_generated_701_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93977 | if((retVal = function_namespace0_generated_702_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93978 | if((retVal = function_namespace0_generated_703_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93979 | if((retVal = function_namespace0_generated_704_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93980 | if((retVal = function_namespace0_generated_705_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93981 | if((retVal = function_namespace0_generated_706_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93982 | if((retVal = function_namespace0_generated_707_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93983 | if((retVal = function_namespace0_generated_708_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93984 | if((retVal = function_namespace0_generated_709_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93985 | if((retVal = function_namespace0_generated_710_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93986 | if((retVal = function_namespace0_generated_711_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93987 | if((retVal = function_namespace0_generated_712_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93988 | if((retVal = function_namespace0_generated_713_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93989 | if((retVal = function_namespace0_generated_714_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93990 | if((retVal = function_namespace0_generated_715_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93991 | if((retVal = function_namespace0_generated_716_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93992 | if((retVal = function_namespace0_generated_717_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93993 | if((retVal = function_namespace0_generated_718_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93994 | if((retVal = function_namespace0_generated_719_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93995 | if((retVal = function_namespace0_generated_720_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93996 | if((retVal = function_namespace0_generated_721_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93997 | if((retVal = function_namespace0_generated_722_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93998 | if((retVal = function_namespace0_generated_723_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 93999 | if((retVal = function_namespace0_generated_724_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94000 | if((retVal = function_namespace0_generated_725_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94001 | if((retVal = function_namespace0_generated_726_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94002 | if((retVal = function_namespace0_generated_727_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94003 | if((retVal = function_namespace0_generated_728_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94004 | if((retVal = function_namespace0_generated_729_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94005 | if((retVal = function_namespace0_generated_730_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94006 | if((retVal = function_namespace0_generated_731_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94007 | if((retVal = function_namespace0_generated_732_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94008 | if((retVal = function_namespace0_generated_733_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94009 | if((retVal = function_namespace0_generated_734_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94010 | if((retVal = function_namespace0_generated_735_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94011 | if((retVal = function_namespace0_generated_736_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94012 | if((retVal = function_namespace0_generated_737_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94013 | if((retVal = function_namespace0_generated_738_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94014 | if((retVal = function_namespace0_generated_739_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94015 | if((retVal = function_namespace0_generated_740_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94016 | if((retVal = function_namespace0_generated_741_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94017 | if((retVal = function_namespace0_generated_742_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94018 | if((retVal = function_namespace0_generated_743_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94019 | if((retVal = function_namespace0_generated_744_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94020 | if((retVal = function_namespace0_generated_745_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94021 | if((retVal = function_namespace0_generated_746_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94022 | if((retVal = function_namespace0_generated_747_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94023 | if((retVal = function_namespace0_generated_748_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94024 | if((retVal = function_namespace0_generated_749_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94025 | if((retVal = function_namespace0_generated_750_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94026 | if((retVal = function_namespace0_generated_751_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94027 | if((retVal = function_namespace0_generated_752_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94028 | if((retVal = function_namespace0_generated_753_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94029 | if((retVal = function_namespace0_generated_754_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94030 | if((retVal = function_namespace0_generated_755_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94031 | if((retVal = function_namespace0_generated_756_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94032 | if((retVal = function_namespace0_generated_757_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94033 | if((retVal = function_namespace0_generated_758_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94034 | if((retVal = function_namespace0_generated_759_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94035 | if((retVal = function_namespace0_generated_760_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94036 | if((retVal = function_namespace0_generated_761_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94037 | if((retVal = function_namespace0_generated_762_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94038 | if((retVal = function_namespace0_generated_763_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94039 | if((retVal = function_namespace0_generated_764_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94040 | if((retVal = function_namespace0_generated_765_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94041 | if((retVal = function_namespace0_generated_766_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94042 | if((retVal = function_namespace0_generated_767_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94043 | if((retVal = function_namespace0_generated_768_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94044 | if((retVal = function_namespace0_generated_769_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94045 | if((retVal = function_namespace0_generated_770_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94046 | if((retVal = function_namespace0_generated_771_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94047 | if((retVal = function_namespace0_generated_772_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94048 | if((retVal = function_namespace0_generated_773_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94049 | if((retVal = function_namespace0_generated_774_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94050 | if((retVal = function_namespace0_generated_775_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94051 | if((retVal = function_namespace0_generated_776_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94052 | if((retVal = function_namespace0_generated_777_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94053 | if((retVal = function_namespace0_generated_778_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94054 | if((retVal = function_namespace0_generated_779_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94055 | if((retVal = function_namespace0_generated_780_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94056 | if((retVal = function_namespace0_generated_781_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94057 | if((retVal = function_namespace0_generated_782_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94058 | if((retVal = function_namespace0_generated_783_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94059 | if((retVal = function_namespace0_generated_784_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94060 | if((retVal = function_namespace0_generated_785_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94061 | if((retVal = function_namespace0_generated_786_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94062 | if((retVal = function_namespace0_generated_787_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94063 | if((retVal = function_namespace0_generated_788_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94064 | if((retVal = function_namespace0_generated_789_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94065 | if((retVal = function_namespace0_generated_790_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94066 | if((retVal = function_namespace0_generated_791_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94067 | if((retVal = function_namespace0_generated_792_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94068 | if((retVal = function_namespace0_generated_793_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94069 | if((retVal = function_namespace0_generated_794_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94070 | if((retVal = function_namespace0_generated_795_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94071 | if((retVal = function_namespace0_generated_796_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94072 | if((retVal = function_namespace0_generated_797_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94073 | if((retVal = function_namespace0_generated_798_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94074 | if((retVal = function_namespace0_generated_799_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94075 | if((retVal = function_namespace0_generated_800_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94076 | if((retVal = function_namespace0_generated_801_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94077 | if((retVal = function_namespace0_generated_802_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94078 | if((retVal = function_namespace0_generated_803_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94079 | if((retVal = function_namespace0_generated_804_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94080 | if((retVal = function_namespace0_generated_805_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94081 | if((retVal = function_namespace0_generated_806_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94082 | if((retVal = function_namespace0_generated_807_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94083 | if((retVal = function_namespace0_generated_808_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94084 | if((retVal = function_namespace0_generated_809_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94085 | if((retVal = function_namespace0_generated_810_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94086 | if((retVal = function_namespace0_generated_811_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94087 | if((retVal = function_namespace0_generated_812_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94088 | if((retVal = function_namespace0_generated_813_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94089 | if((retVal = function_namespace0_generated_814_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94090 | if((retVal = function_namespace0_generated_815_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94091 | if((retVal = function_namespace0_generated_816_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94092 | if((retVal = function_namespace0_generated_817_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94093 | if((retVal = function_namespace0_generated_818_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94094 | if((retVal = function_namespace0_generated_819_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94095 | if((retVal = function_namespace0_generated_820_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94096 | if((retVal = function_namespace0_generated_821_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94097 | if((retVal = function_namespace0_generated_822_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94098 | if((retVal = function_namespace0_generated_823_begin(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94099 | if((retVal = function_namespace0_generated_823_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94100 | if((retVal = function_namespace0_generated_822_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94101 | if((retVal = function_namespace0_generated_821_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94102 | if((retVal = function_namespace0_generated_820_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94103 | if((retVal = function_namespace0_generated_819_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94104 | if((retVal = function_namespace0_generated_818_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94105 | if((retVal = function_namespace0_generated_817_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94106 | if((retVal = function_namespace0_generated_816_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94107 | if((retVal = function_namespace0_generated_815_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94108 | if((retVal = function_namespace0_generated_814_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94109 | if((retVal = function_namespace0_generated_813_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94110 | if((retVal = function_namespace0_generated_812_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94111 | if((retVal = function_namespace0_generated_811_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94112 | if((retVal = function_namespace0_generated_810_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94113 | if((retVal = function_namespace0_generated_809_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94114 | if((retVal = function_namespace0_generated_808_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94115 | if((retVal = function_namespace0_generated_807_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94116 | if((retVal = function_namespace0_generated_806_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94117 | if((retVal = function_namespace0_generated_805_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94118 | if((retVal = function_namespace0_generated_804_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94119 | if((retVal = function_namespace0_generated_803_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94120 | if((retVal = function_namespace0_generated_802_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94121 | if((retVal = function_namespace0_generated_801_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94122 | if((retVal = function_namespace0_generated_800_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94123 | if((retVal = function_namespace0_generated_799_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94124 | if((retVal = function_namespace0_generated_798_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94125 | if((retVal = function_namespace0_generated_797_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94126 | if((retVal = function_namespace0_generated_796_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94127 | if((retVal = function_namespace0_generated_795_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94128 | if((retVal = function_namespace0_generated_794_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94129 | if((retVal = function_namespace0_generated_793_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94130 | if((retVal = function_namespace0_generated_792_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94131 | if((retVal = function_namespace0_generated_791_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94132 | if((retVal = function_namespace0_generated_790_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94133 | if((retVal = function_namespace0_generated_789_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94134 | if((retVal = function_namespace0_generated_788_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94135 | if((retVal = function_namespace0_generated_787_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94136 | if((retVal = function_namespace0_generated_786_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94137 | if((retVal = function_namespace0_generated_785_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94138 | if((retVal = function_namespace0_generated_784_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94139 | if((retVal = function_namespace0_generated_783_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94140 | if((retVal = function_namespace0_generated_782_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94141 | if((retVal = function_namespace0_generated_781_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94142 | if((retVal = function_namespace0_generated_780_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94143 | if((retVal = function_namespace0_generated_779_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94144 | if((retVal = function_namespace0_generated_778_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94145 | if((retVal = function_namespace0_generated_777_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94146 | if((retVal = function_namespace0_generated_776_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94147 | if((retVal = function_namespace0_generated_775_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94148 | if((retVal = function_namespace0_generated_774_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94149 | if((retVal = function_namespace0_generated_773_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94150 | if((retVal = function_namespace0_generated_772_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94151 | if((retVal = function_namespace0_generated_771_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94152 | if((retVal = function_namespace0_generated_770_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94153 | if((retVal = function_namespace0_generated_769_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94154 | if((retVal = function_namespace0_generated_768_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94155 | if((retVal = function_namespace0_generated_767_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94156 | if((retVal = function_namespace0_generated_766_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94157 | if((retVal = function_namespace0_generated_765_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94158 | if((retVal = function_namespace0_generated_764_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94159 | if((retVal = function_namespace0_generated_763_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94160 | if((retVal = function_namespace0_generated_762_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94161 | if((retVal = function_namespace0_generated_761_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94162 | if((retVal = function_namespace0_generated_760_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94163 | if((retVal = function_namespace0_generated_759_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94164 | if((retVal = function_namespace0_generated_758_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94165 | if((retVal = function_namespace0_generated_757_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94166 | if((retVal = function_namespace0_generated_756_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94167 | if((retVal = function_namespace0_generated_755_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94168 | if((retVal = function_namespace0_generated_754_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94169 | if((retVal = function_namespace0_generated_753_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94170 | if((retVal = function_namespace0_generated_752_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94171 | if((retVal = function_namespace0_generated_751_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94172 | if((retVal = function_namespace0_generated_750_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94173 | if((retVal = function_namespace0_generated_749_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94174 | if((retVal = function_namespace0_generated_748_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94175 | if((retVal = function_namespace0_generated_747_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94176 | if((retVal = function_namespace0_generated_746_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94177 | if((retVal = function_namespace0_generated_745_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94178 | if((retVal = function_namespace0_generated_744_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94179 | if((retVal = function_namespace0_generated_743_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94180 | if((retVal = function_namespace0_generated_742_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94181 | if((retVal = function_namespace0_generated_741_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94182 | if((retVal = function_namespace0_generated_740_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94183 | if((retVal = function_namespace0_generated_739_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94184 | if((retVal = function_namespace0_generated_738_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94185 | if((retVal = function_namespace0_generated_737_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94186 | if((retVal = function_namespace0_generated_736_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94187 | if((retVal = function_namespace0_generated_735_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94188 | if((retVal = function_namespace0_generated_734_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94189 | if((retVal = function_namespace0_generated_733_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94190 | if((retVal = function_namespace0_generated_732_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94191 | if((retVal = function_namespace0_generated_731_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94192 | if((retVal = function_namespace0_generated_730_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94193 | if((retVal = function_namespace0_generated_729_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94194 | if((retVal = function_namespace0_generated_728_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94195 | if((retVal = function_namespace0_generated_727_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94196 | if((retVal = function_namespace0_generated_726_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94197 | if((retVal = function_namespace0_generated_725_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94198 | if((retVal = function_namespace0_generated_724_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94199 | if((retVal = function_namespace0_generated_723_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94200 | if((retVal = function_namespace0_generated_722_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94201 | if((retVal = function_namespace0_generated_721_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94202 | if((retVal = function_namespace0_generated_720_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94203 | if((retVal = function_namespace0_generated_719_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94204 | if((retVal = function_namespace0_generated_718_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94205 | if((retVal = function_namespace0_generated_717_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94206 | if((retVal = function_namespace0_generated_716_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94207 | if((retVal = function_namespace0_generated_715_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94208 | if((retVal = function_namespace0_generated_714_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94209 | if((retVal = function_namespace0_generated_713_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94210 | if((retVal = function_namespace0_generated_712_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94211 | if((retVal = function_namespace0_generated_711_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94212 | if((retVal = function_namespace0_generated_710_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94213 | if((retVal = function_namespace0_generated_709_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94214 | if((retVal = function_namespace0_generated_708_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94215 | if((retVal = function_namespace0_generated_707_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94216 | if((retVal = function_namespace0_generated_706_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94217 | if((retVal = function_namespace0_generated_705_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94218 | if((retVal = function_namespace0_generated_704_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94219 | if((retVal = function_namespace0_generated_703_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94220 | if((retVal = function_namespace0_generated_702_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94221 | if((retVal = function_namespace0_generated_701_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94222 | if((retVal = function_namespace0_generated_700_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94223 | if((retVal = function_namespace0_generated_699_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94224 | if((retVal = function_namespace0_generated_698_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94225 | if((retVal = function_namespace0_generated_697_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94226 | if((retVal = function_namespace0_generated_696_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94227 | if((retVal = function_namespace0_generated_695_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94228 | if((retVal = function_namespace0_generated_694_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94229 | if((retVal = function_namespace0_generated_693_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94230 | if((retVal = function_namespace0_generated_692_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94231 | if((retVal = function_namespace0_generated_691_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94232 | if((retVal = function_namespace0_generated_690_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94233 | if((retVal = function_namespace0_generated_689_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94234 | if((retVal = function_namespace0_generated_688_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94235 | if((retVal = function_namespace0_generated_687_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94236 | if((retVal = function_namespace0_generated_686_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94237 | if((retVal = function_namespace0_generated_685_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94238 | if((retVal = function_namespace0_generated_684_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94239 | if((retVal = function_namespace0_generated_683_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94240 | if((retVal = function_namespace0_generated_682_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94241 | if((retVal = function_namespace0_generated_681_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94242 | if((retVal = function_namespace0_generated_680_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94243 | if((retVal = function_namespace0_generated_679_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94244 | if((retVal = function_namespace0_generated_678_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94245 | if((retVal = function_namespace0_generated_677_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94246 | if((retVal = function_namespace0_generated_676_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94247 | if((retVal = function_namespace0_generated_675_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94248 | if((retVal = function_namespace0_generated_674_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94249 | if((retVal = function_namespace0_generated_673_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94250 | if((retVal = function_namespace0_generated_672_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94251 | if((retVal = function_namespace0_generated_671_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94252 | if((retVal = function_namespace0_generated_670_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94253 | if((retVal = function_namespace0_generated_669_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94254 | if((retVal = function_namespace0_generated_668_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94255 | if((retVal = function_namespace0_generated_667_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94256 | if((retVal = function_namespace0_generated_666_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94257 | if((retVal = function_namespace0_generated_665_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94258 | if((retVal = function_namespace0_generated_664_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94259 | if((retVal = function_namespace0_generated_663_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94260 | if((retVal = function_namespace0_generated_662_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94261 | if((retVal = function_namespace0_generated_661_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94262 | if((retVal = function_namespace0_generated_660_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94263 | if((retVal = function_namespace0_generated_659_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94264 | if((retVal = function_namespace0_generated_658_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94265 | if((retVal = function_namespace0_generated_657_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94266 | if((retVal = function_namespace0_generated_656_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94267 | if((retVal = function_namespace0_generated_655_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94268 | if((retVal = function_namespace0_generated_654_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94269 | if((retVal = function_namespace0_generated_653_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94270 | if((retVal = function_namespace0_generated_652_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94271 | if((retVal = function_namespace0_generated_651_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94272 | if((retVal = function_namespace0_generated_650_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94273 | if((retVal = function_namespace0_generated_649_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94274 | if((retVal = function_namespace0_generated_648_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94275 | if((retVal = function_namespace0_generated_647_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94276 | if((retVal = function_namespace0_generated_646_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94277 | if((retVal = function_namespace0_generated_645_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94278 | if((retVal = function_namespace0_generated_644_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94279 | if((retVal = function_namespace0_generated_643_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94280 | if((retVal = function_namespace0_generated_642_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94281 | if((retVal = function_namespace0_generated_641_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94282 | if((retVal = function_namespace0_generated_640_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94283 | if((retVal = function_namespace0_generated_639_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94284 | if((retVal = function_namespace0_generated_638_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94285 | if((retVal = function_namespace0_generated_637_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94286 | if((retVal = function_namespace0_generated_636_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94287 | if((retVal = function_namespace0_generated_635_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94288 | if((retVal = function_namespace0_generated_634_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94289 | if((retVal = function_namespace0_generated_633_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94290 | if((retVal = function_namespace0_generated_632_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94291 | if((retVal = function_namespace0_generated_631_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94292 | if((retVal = function_namespace0_generated_630_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94293 | if((retVal = function_namespace0_generated_629_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94294 | if((retVal = function_namespace0_generated_628_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94295 | if((retVal = function_namespace0_generated_627_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94296 | if((retVal = function_namespace0_generated_626_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94297 | if((retVal = function_namespace0_generated_625_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94298 | if((retVal = function_namespace0_generated_624_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94299 | if((retVal = function_namespace0_generated_623_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94300 | if((retVal = function_namespace0_generated_622_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94301 | if((retVal = function_namespace0_generated_621_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94302 | if((retVal = function_namespace0_generated_620_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94303 | if((retVal = function_namespace0_generated_619_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94304 | if((retVal = function_namespace0_generated_618_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94305 | if((retVal = function_namespace0_generated_617_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94306 | if((retVal = function_namespace0_generated_616_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94307 | if((retVal = function_namespace0_generated_615_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94308 | if((retVal = function_namespace0_generated_614_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94309 | if((retVal = function_namespace0_generated_613_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94310 | if((retVal = function_namespace0_generated_612_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94311 | if((retVal = function_namespace0_generated_611_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94312 | if((retVal = function_namespace0_generated_610_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94313 | if((retVal = function_namespace0_generated_609_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94314 | if((retVal = function_namespace0_generated_608_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94315 | if((retVal = function_namespace0_generated_607_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94316 | if((retVal = function_namespace0_generated_606_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94317 | if((retVal = function_namespace0_generated_605_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94318 | if((retVal = function_namespace0_generated_604_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94319 | if((retVal = function_namespace0_generated_603_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94320 | if((retVal = function_namespace0_generated_602_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94321 | if((retVal = function_namespace0_generated_601_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94322 | if((retVal = function_namespace0_generated_600_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94323 | if((retVal = function_namespace0_generated_599_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94324 | if((retVal = function_namespace0_generated_598_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94325 | if((retVal = function_namespace0_generated_597_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94326 | if((retVal = function_namespace0_generated_596_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94327 | if((retVal = function_namespace0_generated_595_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94328 | if((retVal = function_namespace0_generated_594_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94329 | if((retVal = function_namespace0_generated_593_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94330 | if((retVal = function_namespace0_generated_592_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94331 | if((retVal = function_namespace0_generated_591_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94332 | if((retVal = function_namespace0_generated_590_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94333 | if((retVal = function_namespace0_generated_589_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94334 | if((retVal = function_namespace0_generated_588_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94335 | if((retVal = function_namespace0_generated_587_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94336 | if((retVal = function_namespace0_generated_586_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94337 | if((retVal = function_namespace0_generated_585_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94338 | if((retVal = function_namespace0_generated_584_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94339 | if((retVal = function_namespace0_generated_583_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94340 | if((retVal = function_namespace0_generated_582_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94341 | if((retVal = function_namespace0_generated_581_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94342 | if((retVal = function_namespace0_generated_580_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94343 | if((retVal = function_namespace0_generated_579_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94344 | if((retVal = function_namespace0_generated_578_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94345 | if((retVal = function_namespace0_generated_577_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94346 | if((retVal = function_namespace0_generated_576_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94347 | if((retVal = function_namespace0_generated_575_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94348 | if((retVal = function_namespace0_generated_574_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94349 | if((retVal = function_namespace0_generated_573_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94350 | if((retVal = function_namespace0_generated_572_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94351 | if((retVal = function_namespace0_generated_571_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94352 | if((retVal = function_namespace0_generated_570_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94353 | if((retVal = function_namespace0_generated_569_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94354 | if((retVal = function_namespace0_generated_568_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94355 | if((retVal = function_namespace0_generated_567_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94356 | if((retVal = function_namespace0_generated_566_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94357 | if((retVal = function_namespace0_generated_565_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94358 | if((retVal = function_namespace0_generated_564_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94359 | if((retVal = function_namespace0_generated_563_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94360 | if((retVal = function_namespace0_generated_562_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94361 | if((retVal = function_namespace0_generated_561_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94362 | if((retVal = function_namespace0_generated_560_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94363 | if((retVal = function_namespace0_generated_559_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94364 | if((retVal = function_namespace0_generated_558_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94365 | if((retVal = function_namespace0_generated_557_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94366 | if((retVal = function_namespace0_generated_556_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94367 | if((retVal = function_namespace0_generated_555_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94368 | if((retVal = function_namespace0_generated_554_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94369 | if((retVal = function_namespace0_generated_553_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94370 | if((retVal = function_namespace0_generated_552_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94371 | if((retVal = function_namespace0_generated_551_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94372 | if((retVal = function_namespace0_generated_550_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94373 | if((retVal = function_namespace0_generated_549_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94374 | if((retVal = function_namespace0_generated_548_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94375 | if((retVal = function_namespace0_generated_547_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94376 | if((retVal = function_namespace0_generated_546_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94377 | if((retVal = function_namespace0_generated_545_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94378 | if((retVal = function_namespace0_generated_544_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94379 | if((retVal = function_namespace0_generated_543_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94380 | if((retVal = function_namespace0_generated_542_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94381 | if((retVal = function_namespace0_generated_541_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94382 | if((retVal = function_namespace0_generated_540_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94383 | if((retVal = function_namespace0_generated_539_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94384 | if((retVal = function_namespace0_generated_538_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94385 | if((retVal = function_namespace0_generated_537_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94386 | if((retVal = function_namespace0_generated_536_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94387 | if((retVal = function_namespace0_generated_535_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94388 | if((retVal = function_namespace0_generated_534_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94389 | if((retVal = function_namespace0_generated_533_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94390 | if((retVal = function_namespace0_generated_532_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94391 | if((retVal = function_namespace0_generated_531_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94392 | if((retVal = function_namespace0_generated_530_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94393 | if((retVal = function_namespace0_generated_529_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94394 | if((retVal = function_namespace0_generated_528_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94395 | if((retVal = function_namespace0_generated_527_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94396 | if((retVal = function_namespace0_generated_526_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94397 | if((retVal = function_namespace0_generated_525_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94398 | if((retVal = function_namespace0_generated_524_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94399 | if((retVal = function_namespace0_generated_523_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94400 | if((retVal = function_namespace0_generated_522_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94401 | if((retVal = function_namespace0_generated_521_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94402 | if((retVal = function_namespace0_generated_520_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94403 | if((retVal = function_namespace0_generated_519_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94404 | if((retVal = function_namespace0_generated_518_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94405 | if((retVal = function_namespace0_generated_517_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94406 | if((retVal = function_namespace0_generated_516_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94407 | if((retVal = function_namespace0_generated_515_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94408 | if((retVal = function_namespace0_generated_514_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94409 | if((retVal = function_namespace0_generated_513_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94410 | if((retVal = function_namespace0_generated_512_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94411 | if((retVal = function_namespace0_generated_511_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94412 | if((retVal = function_namespace0_generated_510_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94413 | if((retVal = function_namespace0_generated_509_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94414 | if((retVal = function_namespace0_generated_508_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94415 | if((retVal = function_namespace0_generated_507_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94416 | if((retVal = function_namespace0_generated_506_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94417 | if((retVal = function_namespace0_generated_505_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94418 | if((retVal = function_namespace0_generated_504_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94419 | if((retVal = function_namespace0_generated_503_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94420 | if((retVal = function_namespace0_generated_502_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94421 | if((retVal = function_namespace0_generated_501_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94422 | if((retVal = function_namespace0_generated_500_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94423 | if((retVal = function_namespace0_generated_499_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94424 | if((retVal = function_namespace0_generated_498_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94425 | if((retVal = function_namespace0_generated_497_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94426 | if((retVal = function_namespace0_generated_496_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94427 | if((retVal = function_namespace0_generated_495_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94428 | if((retVal = function_namespace0_generated_494_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94429 | if((retVal = function_namespace0_generated_493_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94430 | if((retVal = function_namespace0_generated_492_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94431 | if((retVal = function_namespace0_generated_491_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94432 | if((retVal = function_namespace0_generated_490_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94433 | if((retVal = function_namespace0_generated_489_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94434 | if((retVal = function_namespace0_generated_488_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94435 | if((retVal = function_namespace0_generated_487_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94436 | if((retVal = function_namespace0_generated_486_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94437 | if((retVal = function_namespace0_generated_485_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94438 | if((retVal = function_namespace0_generated_484_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94439 | if((retVal = function_namespace0_generated_483_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94440 | if((retVal = function_namespace0_generated_482_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94441 | if((retVal = function_namespace0_generated_481_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94442 | if((retVal = function_namespace0_generated_480_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94443 | if((retVal = function_namespace0_generated_479_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94444 | if((retVal = function_namespace0_generated_478_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94445 | if((retVal = function_namespace0_generated_477_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94446 | if((retVal = function_namespace0_generated_476_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94447 | if((retVal = function_namespace0_generated_475_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94448 | if((retVal = function_namespace0_generated_474_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94449 | if((retVal = function_namespace0_generated_473_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94450 | if((retVal = function_namespace0_generated_472_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94451 | if((retVal = function_namespace0_generated_471_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94452 | if((retVal = function_namespace0_generated_470_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94453 | if((retVal = function_namespace0_generated_469_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94454 | if((retVal = function_namespace0_generated_468_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94455 | if((retVal = function_namespace0_generated_467_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94456 | if((retVal = function_namespace0_generated_466_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94457 | if((retVal = function_namespace0_generated_465_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94458 | if((retVal = function_namespace0_generated_464_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94459 | if((retVal = function_namespace0_generated_463_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94460 | if((retVal = function_namespace0_generated_462_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94461 | if((retVal = function_namespace0_generated_461_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94462 | if((retVal = function_namespace0_generated_460_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94463 | if((retVal = function_namespace0_generated_459_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94464 | if((retVal = function_namespace0_generated_458_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94465 | if((retVal = function_namespace0_generated_457_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94466 | if((retVal = function_namespace0_generated_456_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94467 | if((retVal = function_namespace0_generated_455_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94468 | if((retVal = function_namespace0_generated_454_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94469 | if((retVal = function_namespace0_generated_453_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94470 | if((retVal = function_namespace0_generated_452_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94471 | if((retVal = function_namespace0_generated_451_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94472 | if((retVal = function_namespace0_generated_450_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94473 | if((retVal = function_namespace0_generated_449_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94474 | if((retVal = function_namespace0_generated_448_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94475 | if((retVal = function_namespace0_generated_447_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94476 | if((retVal = function_namespace0_generated_446_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94477 | if((retVal = function_namespace0_generated_445_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94478 | if((retVal = function_namespace0_generated_444_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94479 | if((retVal = function_namespace0_generated_443_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94480 | if((retVal = function_namespace0_generated_442_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94481 | if((retVal = function_namespace0_generated_441_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94482 | if((retVal = function_namespace0_generated_440_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94483 | if((retVal = function_namespace0_generated_439_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94484 | if((retVal = function_namespace0_generated_438_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94485 | if((retVal = function_namespace0_generated_437_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94486 | if((retVal = function_namespace0_generated_436_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94487 | if((retVal = function_namespace0_generated_435_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94488 | if((retVal = function_namespace0_generated_434_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94489 | if((retVal = function_namespace0_generated_433_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94490 | if((retVal = function_namespace0_generated_432_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94491 | if((retVal = function_namespace0_generated_431_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94492 | if((retVal = function_namespace0_generated_430_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94493 | if((retVal = function_namespace0_generated_429_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94494 | if((retVal = function_namespace0_generated_428_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94495 | if((retVal = function_namespace0_generated_427_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94496 | if((retVal = function_namespace0_generated_426_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94497 | if((retVal = function_namespace0_generated_425_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94498 | if((retVal = function_namespace0_generated_424_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94499 | if((retVal = function_namespace0_generated_423_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94500 | if((retVal = function_namespace0_generated_422_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94501 | if((retVal = function_namespace0_generated_421_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94502 | if((retVal = function_namespace0_generated_420_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94503 | if((retVal = function_namespace0_generated_419_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94504 | if((retVal = function_namespace0_generated_418_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94505 | if((retVal = function_namespace0_generated_417_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94506 | if((retVal = function_namespace0_generated_416_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94507 | if((retVal = function_namespace0_generated_415_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94508 | if((retVal = function_namespace0_generated_414_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94509 | if((retVal = function_namespace0_generated_413_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94510 | if((retVal = function_namespace0_generated_412_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94511 | if((retVal = function_namespace0_generated_411_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94512 | if((retVal = function_namespace0_generated_410_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94513 | if((retVal = function_namespace0_generated_409_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94514 | if((retVal = function_namespace0_generated_408_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94515 | if((retVal = function_namespace0_generated_407_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94516 | if((retVal = function_namespace0_generated_406_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94517 | if((retVal = function_namespace0_generated_405_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94518 | if((retVal = function_namespace0_generated_404_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94519 | if((retVal = function_namespace0_generated_403_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94520 | if((retVal = function_namespace0_generated_402_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94521 | if((retVal = function_namespace0_generated_401_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94522 | if((retVal = function_namespace0_generated_400_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94523 | if((retVal = function_namespace0_generated_399_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94524 | if((retVal = function_namespace0_generated_398_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94525 | if((retVal = function_namespace0_generated_397_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94526 | if((retVal = function_namespace0_generated_396_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94527 | if((retVal = function_namespace0_generated_395_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94528 | if((retVal = function_namespace0_generated_394_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94529 | if((retVal = function_namespace0_generated_393_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94530 | if((retVal = function_namespace0_generated_392_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94531 | if((retVal = function_namespace0_generated_391_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94532 | if((retVal = function_namespace0_generated_390_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94533 | if((retVal = function_namespace0_generated_389_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94534 | if((retVal = function_namespace0_generated_388_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94535 | if((retVal = function_namespace0_generated_387_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94536 | if((retVal = function_namespace0_generated_386_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94537 | if((retVal = function_namespace0_generated_385_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94538 | if((retVal = function_namespace0_generated_384_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94539 | if((retVal = function_namespace0_generated_383_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94540 | if((retVal = function_namespace0_generated_382_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94541 | if((retVal = function_namespace0_generated_381_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94542 | if((retVal = function_namespace0_generated_380_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94543 | if((retVal = function_namespace0_generated_379_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94544 | if((retVal = function_namespace0_generated_378_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94545 | if((retVal = function_namespace0_generated_377_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94546 | if((retVal = function_namespace0_generated_376_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94547 | if((retVal = function_namespace0_generated_375_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94548 | if((retVal = function_namespace0_generated_374_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94549 | if((retVal = function_namespace0_generated_373_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94550 | if((retVal = function_namespace0_generated_372_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94551 | if((retVal = function_namespace0_generated_371_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94552 | if((retVal = function_namespace0_generated_370_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94553 | if((retVal = function_namespace0_generated_369_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94554 | if((retVal = function_namespace0_generated_368_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94555 | if((retVal = function_namespace0_generated_367_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94556 | if((retVal = function_namespace0_generated_366_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94557 | if((retVal = function_namespace0_generated_365_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94558 | if((retVal = function_namespace0_generated_364_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94559 | if((retVal = function_namespace0_generated_363_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94560 | if((retVal = function_namespace0_generated_362_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94561 | if((retVal = function_namespace0_generated_361_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94562 | if((retVal = function_namespace0_generated_360_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94563 | if((retVal = function_namespace0_generated_359_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94564 | if((retVal = function_namespace0_generated_358_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94565 | if((retVal = function_namespace0_generated_357_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94566 | if((retVal = function_namespace0_generated_356_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94567 | if((retVal = function_namespace0_generated_355_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94568 | if((retVal = function_namespace0_generated_354_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94569 | if((retVal = function_namespace0_generated_353_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94570 | if((retVal = function_namespace0_generated_352_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94571 | if((retVal = function_namespace0_generated_351_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94572 | if((retVal = function_namespace0_generated_350_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94573 | if((retVal = function_namespace0_generated_349_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94574 | if((retVal = function_namespace0_generated_348_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94575 | if((retVal = function_namespace0_generated_347_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94576 | if((retVal = function_namespace0_generated_346_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94577 | if((retVal = function_namespace0_generated_345_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94578 | if((retVal = function_namespace0_generated_344_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94579 | if((retVal = function_namespace0_generated_343_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94580 | if((retVal = function_namespace0_generated_342_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94581 | if((retVal = function_namespace0_generated_341_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94582 | if((retVal = function_namespace0_generated_340_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94583 | if((retVal = function_namespace0_generated_339_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94584 | if((retVal = function_namespace0_generated_338_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94585 | if((retVal = function_namespace0_generated_337_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94586 | if((retVal = function_namespace0_generated_336_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94587 | if((retVal = function_namespace0_generated_335_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94588 | if((retVal = function_namespace0_generated_334_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94589 | if((retVal = function_namespace0_generated_333_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94590 | if((retVal = function_namespace0_generated_332_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94591 | if((retVal = function_namespace0_generated_331_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94592 | if((retVal = function_namespace0_generated_330_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94593 | if((retVal = function_namespace0_generated_329_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94594 | if((retVal = function_namespace0_generated_328_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94595 | if((retVal = function_namespace0_generated_327_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94596 | if((retVal = function_namespace0_generated_326_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94597 | if((retVal = function_namespace0_generated_325_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94598 | if((retVal = function_namespace0_generated_324_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94599 | if((retVal = function_namespace0_generated_323_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94600 | if((retVal = function_namespace0_generated_322_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94601 | if((retVal = function_namespace0_generated_321_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94602 | if((retVal = function_namespace0_generated_320_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94603 | if((retVal = function_namespace0_generated_319_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94604 | if((retVal = function_namespace0_generated_318_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94605 | if((retVal = function_namespace0_generated_317_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94606 | if((retVal = function_namespace0_generated_316_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94607 | if((retVal = function_namespace0_generated_315_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94608 | if((retVal = function_namespace0_generated_314_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94609 | if((retVal = function_namespace0_generated_313_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94610 | if((retVal = function_namespace0_generated_312_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94611 | if((retVal = function_namespace0_generated_311_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94612 | if((retVal = function_namespace0_generated_310_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94613 | if((retVal = function_namespace0_generated_309_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94614 | if((retVal = function_namespace0_generated_308_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94615 | if((retVal = function_namespace0_generated_307_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94616 | if((retVal = function_namespace0_generated_306_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94617 | if((retVal = function_namespace0_generated_305_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94618 | if((retVal = function_namespace0_generated_304_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94619 | if((retVal = function_namespace0_generated_303_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94620 | if((retVal = function_namespace0_generated_302_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94621 | if((retVal = function_namespace0_generated_301_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94622 | if((retVal = function_namespace0_generated_300_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94623 | if((retVal = function_namespace0_generated_299_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94624 | if((retVal = function_namespace0_generated_298_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94625 | if((retVal = function_namespace0_generated_297_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94626 | if((retVal = function_namespace0_generated_296_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94627 | if((retVal = function_namespace0_generated_295_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94628 | if((retVal = function_namespace0_generated_294_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94629 | if((retVal = function_namespace0_generated_293_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94630 | if((retVal = function_namespace0_generated_292_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94631 | if((retVal = function_namespace0_generated_291_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94632 | if((retVal = function_namespace0_generated_290_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94633 | if((retVal = function_namespace0_generated_289_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94634 | if((retVal = function_namespace0_generated_288_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94635 | if((retVal = function_namespace0_generated_287_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94636 | if((retVal = function_namespace0_generated_286_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94637 | if((retVal = function_namespace0_generated_285_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94638 | if((retVal = function_namespace0_generated_284_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94639 | if((retVal = function_namespace0_generated_283_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94640 | if((retVal = function_namespace0_generated_282_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94641 | if((retVal = function_namespace0_generated_281_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94642 | if((retVal = function_namespace0_generated_280_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94643 | if((retVal = function_namespace0_generated_279_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94644 | if((retVal = function_namespace0_generated_278_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94645 | if((retVal = function_namespace0_generated_277_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94646 | if((retVal = function_namespace0_generated_276_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94647 | if((retVal = function_namespace0_generated_275_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94648 | if((retVal = function_namespace0_generated_274_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94649 | if((retVal = function_namespace0_generated_273_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94650 | if((retVal = function_namespace0_generated_272_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94651 | if((retVal = function_namespace0_generated_271_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94652 | if((retVal = function_namespace0_generated_270_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94653 | if((retVal = function_namespace0_generated_269_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94654 | if((retVal = function_namespace0_generated_268_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94655 | if((retVal = function_namespace0_generated_267_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94656 | if((retVal = function_namespace0_generated_266_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94657 | if((retVal = function_namespace0_generated_265_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94658 | if((retVal = function_namespace0_generated_264_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94659 | if((retVal = function_namespace0_generated_263_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94660 | if((retVal = function_namespace0_generated_262_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94661 | if((retVal = function_namespace0_generated_261_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94662 | if((retVal = function_namespace0_generated_260_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94663 | if((retVal = function_namespace0_generated_259_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94664 | if((retVal = function_namespace0_generated_258_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94665 | if((retVal = function_namespace0_generated_257_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94666 | if((retVal = function_namespace0_generated_256_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94667 | if((retVal = function_namespace0_generated_255_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94668 | if((retVal = function_namespace0_generated_254_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94669 | if((retVal = function_namespace0_generated_253_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94670 | if((retVal = function_namespace0_generated_252_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94671 | if((retVal = function_namespace0_generated_251_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94672 | if((retVal = function_namespace0_generated_250_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94673 | if((retVal = function_namespace0_generated_249_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94674 | if((retVal = function_namespace0_generated_248_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94675 | if((retVal = function_namespace0_generated_247_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94676 | if((retVal = function_namespace0_generated_246_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94677 | if((retVal = function_namespace0_generated_245_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94678 | if((retVal = function_namespace0_generated_244_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94679 | if((retVal = function_namespace0_generated_243_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94680 | if((retVal = function_namespace0_generated_242_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94681 | if((retVal = function_namespace0_generated_241_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94682 | if((retVal = function_namespace0_generated_240_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94683 | if((retVal = function_namespace0_generated_239_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94684 | if((retVal = function_namespace0_generated_238_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94685 | if((retVal = function_namespace0_generated_237_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94686 | if((retVal = function_namespace0_generated_236_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94687 | if((retVal = function_namespace0_generated_235_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94688 | if((retVal = function_namespace0_generated_234_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94689 | if((retVal = function_namespace0_generated_233_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94690 | if((retVal = function_namespace0_generated_232_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94691 | if((retVal = function_namespace0_generated_231_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94692 | if((retVal = function_namespace0_generated_230_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94693 | if((retVal = function_namespace0_generated_229_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94694 | if((retVal = function_namespace0_generated_228_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94695 | if((retVal = function_namespace0_generated_227_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94696 | if((retVal = function_namespace0_generated_226_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94697 | if((retVal = function_namespace0_generated_225_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94698 | if((retVal = function_namespace0_generated_224_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94699 | if((retVal = function_namespace0_generated_223_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94700 | if((retVal = function_namespace0_generated_222_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94701 | if((retVal = function_namespace0_generated_221_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94702 | if((retVal = function_namespace0_generated_220_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94703 | if((retVal = function_namespace0_generated_219_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94704 | if((retVal = function_namespace0_generated_218_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94705 | if((retVal = function_namespace0_generated_217_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94706 | if((retVal = function_namespace0_generated_216_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94707 | if((retVal = function_namespace0_generated_215_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94708 | if((retVal = function_namespace0_generated_214_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94709 | if((retVal = function_namespace0_generated_213_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94710 | if((retVal = function_namespace0_generated_212_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94711 | if((retVal = function_namespace0_generated_211_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94712 | if((retVal = function_namespace0_generated_210_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94713 | if((retVal = function_namespace0_generated_209_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94714 | if((retVal = function_namespace0_generated_208_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94715 | if((retVal = function_namespace0_generated_207_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94716 | if((retVal = function_namespace0_generated_206_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94717 | if((retVal = function_namespace0_generated_205_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94718 | if((retVal = function_namespace0_generated_204_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94719 | if((retVal = function_namespace0_generated_203_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94720 | if((retVal = function_namespace0_generated_202_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94721 | if((retVal = function_namespace0_generated_201_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94722 | if((retVal = function_namespace0_generated_200_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94723 | if((retVal = function_namespace0_generated_199_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94724 | if((retVal = function_namespace0_generated_198_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94725 | if((retVal = function_namespace0_generated_197_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94726 | if((retVal = function_namespace0_generated_196_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94727 | if((retVal = function_namespace0_generated_195_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94728 | if((retVal = function_namespace0_generated_194_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94729 | if((retVal = function_namespace0_generated_193_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94730 | if((retVal = function_namespace0_generated_192_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94731 | if((retVal = function_namespace0_generated_191_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94732 | if((retVal = function_namespace0_generated_190_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94733 | if((retVal = function_namespace0_generated_189_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94734 | if((retVal = function_namespace0_generated_188_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94735 | if((retVal = function_namespace0_generated_187_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94736 | if((retVal = function_namespace0_generated_186_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94737 | if((retVal = function_namespace0_generated_185_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94738 | if((retVal = function_namespace0_generated_184_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94739 | if((retVal = function_namespace0_generated_183_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94740 | if((retVal = function_namespace0_generated_182_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94741 | if((retVal = function_namespace0_generated_181_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94742 | if((retVal = function_namespace0_generated_180_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94743 | if((retVal = function_namespace0_generated_179_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94744 | if((retVal = function_namespace0_generated_178_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94745 | if((retVal = function_namespace0_generated_177_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94746 | if((retVal = function_namespace0_generated_176_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94747 | if((retVal = function_namespace0_generated_175_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94748 | if((retVal = function_namespace0_generated_174_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94749 | if((retVal = function_namespace0_generated_173_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94750 | if((retVal = function_namespace0_generated_172_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94751 | if((retVal = function_namespace0_generated_171_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94752 | if((retVal = function_namespace0_generated_170_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94753 | if((retVal = function_namespace0_generated_169_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94754 | if((retVal = function_namespace0_generated_168_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94755 | if((retVal = function_namespace0_generated_167_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94756 | if((retVal = function_namespace0_generated_166_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94757 | if((retVal = function_namespace0_generated_165_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94758 | if((retVal = function_namespace0_generated_164_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94759 | if((retVal = function_namespace0_generated_163_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94760 | if((retVal = function_namespace0_generated_162_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94761 | if((retVal = function_namespace0_generated_161_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94762 | if((retVal = function_namespace0_generated_160_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94763 | if((retVal = function_namespace0_generated_159_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94764 | if((retVal = function_namespace0_generated_158_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94765 | if((retVal = function_namespace0_generated_157_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94766 | if((retVal = function_namespace0_generated_156_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94767 | if((retVal = function_namespace0_generated_155_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94768 | if((retVal = function_namespace0_generated_154_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94769 | if((retVal = function_namespace0_generated_153_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94770 | if((retVal = function_namespace0_generated_152_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94771 | if((retVal = function_namespace0_generated_151_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94772 | if((retVal = function_namespace0_generated_150_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94773 | if((retVal = function_namespace0_generated_149_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94774 | if((retVal = function_namespace0_generated_148_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94775 | if((retVal = function_namespace0_generated_147_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94776 | if((retVal = function_namespace0_generated_146_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94777 | if((retVal = function_namespace0_generated_145_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94778 | if((retVal = function_namespace0_generated_144_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94779 | if((retVal = function_namespace0_generated_143_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94780 | if((retVal = function_namespace0_generated_142_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94781 | if((retVal = function_namespace0_generated_141_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94782 | if((retVal = function_namespace0_generated_140_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94783 | if((retVal = function_namespace0_generated_139_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94784 | if((retVal = function_namespace0_generated_138_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94785 | if((retVal = function_namespace0_generated_137_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94786 | if((retVal = function_namespace0_generated_136_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94787 | if((retVal = function_namespace0_generated_135_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94788 | if((retVal = function_namespace0_generated_134_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94789 | if((retVal = function_namespace0_generated_133_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94790 | if((retVal = function_namespace0_generated_132_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94791 | if((retVal = function_namespace0_generated_131_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94792 | if((retVal = function_namespace0_generated_130_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94793 | if((retVal = function_namespace0_generated_129_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94794 | if((retVal = function_namespace0_generated_128_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94795 | if((retVal = function_namespace0_generated_127_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94796 | if((retVal = function_namespace0_generated_126_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94797 | if((retVal = function_namespace0_generated_125_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94798 | if((retVal = function_namespace0_generated_124_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94799 | if((retVal = function_namespace0_generated_123_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94800 | if((retVal = function_namespace0_generated_122_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94801 | if((retVal = function_namespace0_generated_121_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94802 | if((retVal = function_namespace0_generated_120_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94803 | if((retVal = function_namespace0_generated_119_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94804 | if((retVal = function_namespace0_generated_118_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94805 | if((retVal = function_namespace0_generated_117_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94806 | if((retVal = function_namespace0_generated_116_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94807 | if((retVal = function_namespace0_generated_115_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94808 | if((retVal = function_namespace0_generated_114_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94809 | if((retVal = function_namespace0_generated_113_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94810 | if((retVal = function_namespace0_generated_112_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94811 | if((retVal = function_namespace0_generated_111_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94812 | if((retVal = function_namespace0_generated_110_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94813 | if((retVal = function_namespace0_generated_109_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94814 | if((retVal = function_namespace0_generated_108_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94815 | if((retVal = function_namespace0_generated_107_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94816 | if((retVal = function_namespace0_generated_106_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94817 | if((retVal = function_namespace0_generated_105_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94818 | if((retVal = function_namespace0_generated_104_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94819 | if((retVal = function_namespace0_generated_103_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94820 | if((retVal = function_namespace0_generated_102_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94821 | if((retVal = function_namespace0_generated_101_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94822 | if((retVal = function_namespace0_generated_100_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94823 | if((retVal = function_namespace0_generated_99_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94824 | if((retVal = function_namespace0_generated_98_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94825 | if((retVal = function_namespace0_generated_97_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94826 | if((retVal = function_namespace0_generated_96_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94827 | if((retVal = function_namespace0_generated_95_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94828 | if((retVal = function_namespace0_generated_94_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94829 | if((retVal = function_namespace0_generated_93_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94830 | if((retVal = function_namespace0_generated_92_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94831 | if((retVal = function_namespace0_generated_91_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94832 | if((retVal = function_namespace0_generated_90_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94833 | if((retVal = function_namespace0_generated_89_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94834 | if((retVal = function_namespace0_generated_88_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94835 | if((retVal = function_namespace0_generated_87_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94836 | if((retVal = function_namespace0_generated_86_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94837 | if((retVal = function_namespace0_generated_85_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94838 | if((retVal = function_namespace0_generated_84_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94839 | if((retVal = function_namespace0_generated_83_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94840 | if((retVal = function_namespace0_generated_82_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94841 | if((retVal = function_namespace0_generated_81_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94842 | if((retVal = function_namespace0_generated_80_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94843 | if((retVal = function_namespace0_generated_79_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94844 | if((retVal = function_namespace0_generated_78_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94845 | if((retVal = function_namespace0_generated_77_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94846 | if((retVal = function_namespace0_generated_76_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94847 | if((retVal = function_namespace0_generated_75_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94848 | if((retVal = function_namespace0_generated_74_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94849 | if((retVal = function_namespace0_generated_73_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94850 | if((retVal = function_namespace0_generated_72_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94851 | if((retVal = function_namespace0_generated_71_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94852 | if((retVal = function_namespace0_generated_70_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94853 | if((retVal = function_namespace0_generated_69_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94854 | if((retVal = function_namespace0_generated_68_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94855 | if((retVal = function_namespace0_generated_67_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94856 | if((retVal = function_namespace0_generated_66_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94857 | if((retVal = function_namespace0_generated_65_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94858 | if((retVal = function_namespace0_generated_64_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94859 | if((retVal = function_namespace0_generated_63_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94860 | if((retVal = function_namespace0_generated_62_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94861 | if((retVal = function_namespace0_generated_61_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94862 | if((retVal = function_namespace0_generated_60_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94863 | if((retVal = function_namespace0_generated_59_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94864 | if((retVal = function_namespace0_generated_58_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94865 | if((retVal = function_namespace0_generated_57_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94866 | if((retVal = function_namespace0_generated_56_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94867 | if((retVal = function_namespace0_generated_55_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94868 | if((retVal = function_namespace0_generated_54_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94869 | if((retVal = function_namespace0_generated_53_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94870 | if((retVal = function_namespace0_generated_52_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94871 | if((retVal = function_namespace0_generated_51_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94872 | if((retVal = function_namespace0_generated_50_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94873 | if((retVal = function_namespace0_generated_49_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94874 | if((retVal = function_namespace0_generated_48_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94875 | if((retVal = function_namespace0_generated_47_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94876 | if((retVal = function_namespace0_generated_46_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94877 | if((retVal = function_namespace0_generated_45_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94878 | if((retVal = function_namespace0_generated_44_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94879 | if((retVal = function_namespace0_generated_43_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94880 | if((retVal = function_namespace0_generated_42_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94881 | if((retVal = function_namespace0_generated_41_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94882 | if((retVal = function_namespace0_generated_40_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94883 | if((retVal = function_namespace0_generated_39_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94884 | if((retVal = function_namespace0_generated_38_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94885 | if((retVal = function_namespace0_generated_37_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94886 | if((retVal = function_namespace0_generated_36_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94887 | if((retVal = function_namespace0_generated_35_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94888 | if((retVal = function_namespace0_generated_34_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94889 | if((retVal = function_namespace0_generated_33_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94890 | if((retVal = function_namespace0_generated_32_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94891 | if((retVal = function_namespace0_generated_31_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94892 | if((retVal = function_namespace0_generated_30_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94893 | if((retVal = function_namespace0_generated_29_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94894 | if((retVal = function_namespace0_generated_28_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94895 | if((retVal = function_namespace0_generated_27_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94896 | if((retVal = function_namespace0_generated_26_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94897 | if((retVal = function_namespace0_generated_25_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94898 | if((retVal = function_namespace0_generated_24_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94899 | if((retVal = function_namespace0_generated_23_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94900 | if((retVal = function_namespace0_generated_22_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94901 | if((retVal = function_namespace0_generated_21_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94902 | if((retVal = function_namespace0_generated_20_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94903 | if((retVal = function_namespace0_generated_19_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94904 | if((retVal = function_namespace0_generated_18_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94905 | if((retVal = function_namespace0_generated_17_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94906 | if((retVal = function_namespace0_generated_16_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94907 | if((retVal = function_namespace0_generated_15_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94908 | if((retVal = function_namespace0_generated_14_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94909 | if((retVal = function_namespace0_generated_13_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94910 | if((retVal = function_namespace0_generated_12_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94911 | if((retVal = function_namespace0_generated_11_finish(server, ns)) != UA_STATUSCODE_GOOD) return retVal; |
| 94912 | return retVal; |
| 94913 | } |
| 94914 | |
| 94915 | /**** amalgamated original file "/src/ua_types_lex.c" ****/ |
| 94916 | |
| 94917 | /* Generated by re2c 3.1 */ |
| 94918 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 94919 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 94920 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 94921 | * |
| 94922 | * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 94923 | * |
| 94924 | */ |
| 94925 | |
| 94926 | |
| 94927 | /* Lexing and parsing of builtin data types. These are helper functions that not |
| 94928 | * required by the SDK internally. But they are useful for users who want to use |
| 94929 | * standard-specified humand readable encodings for NodeIds, etc. |
| 94930 | * |
| 94931 | * This compilation unit uses the re2c lexer generator. The final C source is |
| 94932 | * generated with the following script: |
| 94933 | * |
| 94934 | * re2c -i --no-generation-date ua_types_lex.re > ua_types_lex.c |
| 94935 | * |
| 94936 | * In order that users of the SDK don't need to install re2c, always commit a |
| 94937 | * recent ua_types_lex.c if changes are made to the lexer. */ |
| 94938 | |
| 94939 | #define YYCURSOR pos |
| 94940 | #define YYMARKER context.marker |
| 94941 | #define YYPEEK() (YYCURSOR < end) ? *YYCURSOR : 0 /* The lexer sees a stream of |
| 94942 | * \0 when the input ends*/ |
| 94943 | #define YYSKIP() ++YYCURSOR; |
| 94944 | #define YYBACKUP() YYMARKER = YYCURSOR |
| 94945 | #define YYRESTORE() YYCURSOR = YYMARKER |
| 94946 | #define YYSTAGP(t) t = YYCURSOR |
| 94947 | #define YYSTAGN(t) t = NULL |
| 94948 | #define YYSHIFTSTAG(t, shift) t += shift |
| 94949 | |
| 94950 | typedef struct { |
| 94951 | const char *marker; |
| 94952 | const char *yyt1;const char *yyt2;const char *yyt3;const char *yyt4; |
| 94953 | } LexContext; |
| 94954 | |
| 94955 | |
| 94956 | |
| 94957 | static UA_StatusCode |
| 94958 | parse_guid(UA_Guid *guid, const UA_Byte *s, const UA_Byte *e) { |
| 94959 | size_t len = (size_t)(e - s); |
| 94960 | if(len != 36 || s[8] != '-' || s[13] != '-' || s[23] != '-') |
| 94961 | return UA_STATUSCODE_BADDECODINGERROR; |
| 94962 | |
| 94963 | UA_UInt32 tmp; |
| 94964 | if(UA_readNumberWithBase(buf: s, buflen: 8, number: &tmp, base: 16) != 8) |
| 94965 | return UA_STATUSCODE_BADDECODINGERROR; |
| 94966 | guid->data1 = tmp; |
| 94967 | |
| 94968 | if(UA_readNumberWithBase(buf: &s[9], buflen: 4, number: &tmp, base: 16) != 4) |
| 94969 | return UA_STATUSCODE_BADDECODINGERROR; |
| 94970 | guid->data2 = (UA_UInt16)tmp; |
| 94971 | |
| 94972 | if(UA_readNumberWithBase(buf: &s[14], buflen: 4, number: &tmp, base: 16) != 4) |
| 94973 | return UA_STATUSCODE_BADDECODINGERROR; |
| 94974 | guid->data3 = (UA_UInt16)tmp; |
| 94975 | |
| 94976 | if(UA_readNumberWithBase(buf: &s[19], buflen: 2, number: &tmp, base: 16) != 2) |
| 94977 | return UA_STATUSCODE_BADDECODINGERROR; |
| 94978 | guid->data4[0] = (UA_Byte)tmp; |
| 94979 | |
| 94980 | if(UA_readNumberWithBase(buf: &s[21], buflen: 2, number: &tmp, base: 16) != 2) |
| 94981 | return UA_STATUSCODE_BADDECODINGERROR; |
| 94982 | guid->data4[1] = (UA_Byte)tmp; |
| 94983 | |
| 94984 | for(size_t pos = 2, spos = 24; pos < 8; pos++, spos += 2) { |
| 94985 | if(UA_readNumberWithBase(buf: &s[spos], buflen: 2, number: &tmp, base: 16) != 2) |
| 94986 | return UA_STATUSCODE_BADDECODINGERROR; |
| 94987 | guid->data4[pos] = (UA_Byte)tmp; |
| 94988 | } |
| 94989 | |
| 94990 | return UA_STATUSCODE_GOOD; |
| 94991 | } |
| 94992 | |
| 94993 | UA_StatusCode |
| 94994 | UA_Guid_parse(UA_Guid *guid, const UA_String str) { |
| 94995 | UA_StatusCode res = parse_guid(guid, s: str.data, e: str.data + str.length); |
| 94996 | if(res != UA_STATUSCODE_GOOD) |
| 94997 | *guid = UA_GUID_NULL; |
| 94998 | return res; |
| 94999 | } |
| 95000 | |
| 95001 | static UA_StatusCode |
| 95002 | parse_nodeid_body(UA_NodeId *id, const char *body, const char *end) { |
| 95003 | size_t len = (size_t)(end - (body+2)); |
| 95004 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 95005 | switch(*body) { |
| 95006 | case 'i': { |
| 95007 | if(UA_readNumber(buf: (const UA_Byte*)body+2, buflen: len, number: &id->identifier.numeric) != len) |
| 95008 | return UA_STATUSCODE_BADDECODINGERROR; |
| 95009 | id->identifierType = UA_NODEIDTYPE_NUMERIC; |
| 95010 | break; |
| 95011 | } |
| 95012 | case 's': { |
| 95013 | UA_String tmpstr; |
| 95014 | tmpstr.data = (UA_Byte*)(uintptr_t)body+2; |
| 95015 | tmpstr.length = len; |
| 95016 | res = UA_String_copy(src: &tmpstr, dst: &id->identifier.string); |
| 95017 | if(res != UA_STATUSCODE_GOOD) |
| 95018 | break; |
| 95019 | id->identifierType = UA_NODEIDTYPE_STRING; |
| 95020 | break; |
| 95021 | } |
| 95022 | case 'g': |
| 95023 | res = parse_guid(guid: &id->identifier.guid, s: (const UA_Byte*)body+2, e: (const UA_Byte*)end); |
| 95024 | if(res == UA_STATUSCODE_GOOD) |
| 95025 | id->identifierType = UA_NODEIDTYPE_GUID; |
| 95026 | break; |
| 95027 | case 'b': |
| 95028 | id->identifier.byteString.data = |
| 95029 | UA_unbase64(src: (const unsigned char*)body+2, len, |
| 95030 | out_len: &id->identifier.byteString.length); |
| 95031 | if(!id->identifier.byteString.data && len > 0) |
| 95032 | return UA_STATUSCODE_BADDECODINGERROR; |
| 95033 | id->identifierType = UA_NODEIDTYPE_BYTESTRING; |
| 95034 | break; |
| 95035 | default: |
| 95036 | return UA_STATUSCODE_BADDECODINGERROR; |
| 95037 | } |
| 95038 | return res; |
| 95039 | } |
| 95040 | |
| 95041 | static UA_StatusCode |
| 95042 | parse_nodeid(UA_NodeId *id, const char *pos, const char *end) { |
| 95043 | *id = UA_NODEID_NULL; /* Reset the NodeId */ |
| 95044 | LexContext context; |
| 95045 | memset(s: &context, c: 0, n: sizeof(LexContext)); |
| 95046 | const char *ns = NULL, *nse= NULL; |
| 95047 | |
| 95048 | |
| 95049 | { |
| 95050 | char yych; |
| 95051 | yych = YYPEEK(); |
| 95052 | switch (yych) { |
| 95053 | case 'b': |
| 95054 | case 'g': |
| 95055 | case 'i': |
| 95056 | case 's': |
| 95057 | YYSTAGN(context.yyt1); |
| 95058 | YYSTAGN(context.yyt2); |
| 95059 | goto yy3; |
| 95060 | case 'n': goto yy4; |
| 95061 | default: goto yy1; |
| 95062 | } |
| 95063 | yy1: |
| 95064 | YYSKIP(); |
| 95065 | yy2: |
| 95066 | { (void)pos; return UA_STATUSCODE_BADDECODINGERROR; } |
| 95067 | yy3: |
| 95068 | YYSKIP(); |
| 95069 | yych = YYPEEK(); |
| 95070 | switch (yych) { |
| 95071 | case '=': goto yy5; |
| 95072 | default: goto yy2; |
| 95073 | } |
| 95074 | yy4: |
| 95075 | YYSKIP(); |
| 95076 | YYBACKUP(); |
| 95077 | yych = YYPEEK(); |
| 95078 | switch (yych) { |
| 95079 | case 's': goto yy6; |
| 95080 | default: goto yy2; |
| 95081 | } |
| 95082 | yy5: |
| 95083 | YYSKIP(); |
| 95084 | ns = context.yyt1; |
| 95085 | nse = context.yyt2; |
| 95086 | { |
| 95087 | (void)pos; // Get rid of a dead store clang-analyzer warning |
| 95088 | if(ns) { |
| 95089 | UA_UInt32 tmp; |
| 95090 | size_t len = (size_t)(nse - ns); |
| 95091 | if(UA_readNumber(buf: (const UA_Byte*)ns, buflen: len, number: &tmp) != len) |
| 95092 | return UA_STATUSCODE_BADDECODINGERROR; |
| 95093 | id->namespaceIndex = (UA_UInt16)tmp; |
| 95094 | } |
| 95095 | |
| 95096 | // From the current position until the end |
| 95097 | return parse_nodeid_body(id, body: &pos[-2], end); |
| 95098 | } |
| 95099 | yy6: |
| 95100 | YYSKIP(); |
| 95101 | yych = YYPEEK(); |
| 95102 | switch (yych) { |
| 95103 | case '=': goto yy8; |
| 95104 | default: goto yy7; |
| 95105 | } |
| 95106 | yy7: |
| 95107 | YYRESTORE(); |
| 95108 | goto yy2; |
| 95109 | yy8: |
| 95110 | YYSKIP(); |
| 95111 | yych = YYPEEK(); |
| 95112 | switch (yych) { |
| 95113 | case '0': |
| 95114 | case '1': |
| 95115 | case '2': |
| 95116 | case '3': |
| 95117 | case '4': |
| 95118 | case '5': |
| 95119 | case '6': |
| 95120 | case '7': |
| 95121 | case '8': |
| 95122 | case '9': |
| 95123 | YYSTAGP(context.yyt1); |
| 95124 | goto yy9; |
| 95125 | default: goto yy7; |
| 95126 | } |
| 95127 | yy9: |
| 95128 | YYSKIP(); |
| 95129 | yych = YYPEEK(); |
| 95130 | switch (yych) { |
| 95131 | case '0': |
| 95132 | case '1': |
| 95133 | case '2': |
| 95134 | case '3': |
| 95135 | case '4': |
| 95136 | case '5': |
| 95137 | case '6': |
| 95138 | case '7': |
| 95139 | case '8': |
| 95140 | case '9': goto yy9; |
| 95141 | case ';': |
| 95142 | YYSTAGP(context.yyt2); |
| 95143 | goto yy10; |
| 95144 | default: goto yy7; |
| 95145 | } |
| 95146 | yy10: |
| 95147 | YYSKIP(); |
| 95148 | yych = YYPEEK(); |
| 95149 | switch (yych) { |
| 95150 | case 'b': |
| 95151 | case 'g': |
| 95152 | case 'i': |
| 95153 | case 's': goto yy11; |
| 95154 | default: goto yy7; |
| 95155 | } |
| 95156 | yy11: |
| 95157 | YYSKIP(); |
| 95158 | yych = YYPEEK(); |
| 95159 | switch (yych) { |
| 95160 | case '=': goto yy5; |
| 95161 | default: goto yy7; |
| 95162 | } |
| 95163 | } |
| 95164 | |
| 95165 | } |
| 95166 | |
| 95167 | UA_StatusCode |
| 95168 | UA_NodeId_parse(UA_NodeId *id, const UA_String str) { |
| 95169 | UA_StatusCode res = |
| 95170 | parse_nodeid(id, pos: (const char*)str.data, end: (const char*)str.data+str.length); |
| 95171 | if(res != UA_STATUSCODE_GOOD) |
| 95172 | UA_NodeId_clear(p: id); |
| 95173 | return res; |
| 95174 | } |
| 95175 | |
| 95176 | static UA_StatusCode |
| 95177 | parse_expandednodeid(UA_ExpandedNodeId *id, const char *pos, const char *end) { |
| 95178 | *id = UA_EXPANDEDNODEID_NULL; /* Reset the NodeId */ |
| 95179 | LexContext context; |
| 95180 | memset(s: &context, c: 0, n: sizeof(LexContext)); |
| 95181 | const char *svr = NULL, *svre = NULL, *nsu = NULL, *ns = NULL, *body = NULL; |
| 95182 | |
| 95183 | |
| 95184 | { |
| 95185 | char yych; |
| 95186 | yych = YYPEEK(); |
| 95187 | switch (yych) { |
| 95188 | case 'b': |
| 95189 | case 'g': |
| 95190 | case 'i': |
| 95191 | YYSTAGN(context.yyt1); |
| 95192 | YYSTAGN(context.yyt2); |
| 95193 | YYSTAGN(context.yyt3); |
| 95194 | YYSTAGN(context.yyt4); |
| 95195 | goto yy15; |
| 95196 | case 'n': |
| 95197 | YYSTAGN(context.yyt1); |
| 95198 | YYSTAGN(context.yyt2); |
| 95199 | goto yy16; |
| 95200 | case 's': |
| 95201 | YYSTAGN(context.yyt1); |
| 95202 | YYSTAGN(context.yyt2); |
| 95203 | YYSTAGN(context.yyt3); |
| 95204 | YYSTAGN(context.yyt4); |
| 95205 | goto yy17; |
| 95206 | default: goto yy13; |
| 95207 | } |
| 95208 | yy13: |
| 95209 | YYSKIP(); |
| 95210 | yy14: |
| 95211 | { (void)pos; return UA_STATUSCODE_BADDECODINGERROR; } |
| 95212 | yy15: |
| 95213 | YYSKIP(); |
| 95214 | yych = YYPEEK(); |
| 95215 | switch (yych) { |
| 95216 | case '=': goto yy18; |
| 95217 | default: goto yy14; |
| 95218 | } |
| 95219 | yy16: |
| 95220 | YYSKIP(); |
| 95221 | YYBACKUP(); |
| 95222 | yych = YYPEEK(); |
| 95223 | switch (yych) { |
| 95224 | case 's': goto yy19; |
| 95225 | default: goto yy14; |
| 95226 | } |
| 95227 | yy17: |
| 95228 | YYSKIP(); |
| 95229 | YYBACKUP(); |
| 95230 | yych = YYPEEK(); |
| 95231 | switch (yych) { |
| 95232 | case '=': goto yy18; |
| 95233 | case 'v': goto yy21; |
| 95234 | default: goto yy14; |
| 95235 | } |
| 95236 | yy18: |
| 95237 | YYSKIP(); |
| 95238 | svr = context.yyt1; |
| 95239 | svre = context.yyt2; |
| 95240 | ns = context.yyt3; |
| 95241 | nsu = context.yyt4; |
| 95242 | YYSTAGP(body); |
| 95243 | YYSHIFTSTAG(body, -2); |
| 95244 | { |
| 95245 | (void)pos; // Get rid of a dead store clang-analyzer warning |
| 95246 | if(svr) { |
| 95247 | size_t len = (size_t)((svre) - svr); |
| 95248 | if(UA_readNumber(buf: (const UA_Byte*)svr, buflen: len, number: &id->serverIndex) != len) |
| 95249 | return UA_STATUSCODE_BADDECODINGERROR; |
| 95250 | } |
| 95251 | |
| 95252 | if(nsu) { |
| 95253 | size_t len = (size_t)((body-1) - nsu); |
| 95254 | UA_String nsuri; |
| 95255 | nsuri.data = (UA_Byte*)(uintptr_t)nsu; |
| 95256 | nsuri.length = len; |
| 95257 | UA_StatusCode res = UA_String_copy(src: &nsuri, dst: &id->namespaceUri); |
| 95258 | if(res != UA_STATUSCODE_GOOD) |
| 95259 | return res; |
| 95260 | } else if(ns) { |
| 95261 | UA_UInt32 tmp; |
| 95262 | size_t len = (size_t)((body-1) - ns); |
| 95263 | if(UA_readNumber(buf: (const UA_Byte*)ns, buflen: len, number: &tmp) != len) |
| 95264 | return UA_STATUSCODE_BADDECODINGERROR; |
| 95265 | id->nodeId.namespaceIndex = (UA_UInt16)tmp; |
| 95266 | } |
| 95267 | |
| 95268 | // From the current position until the end |
| 95269 | return parse_nodeid_body(id: &id->nodeId, body: &pos[-2], end); |
| 95270 | } |
| 95271 | yy19: |
| 95272 | YYSKIP(); |
| 95273 | yych = YYPEEK(); |
| 95274 | switch (yych) { |
| 95275 | case '=': goto yy22; |
| 95276 | case 'u': goto yy23; |
| 95277 | default: goto yy20; |
| 95278 | } |
| 95279 | yy20: |
| 95280 | YYRESTORE(); |
| 95281 | goto yy14; |
| 95282 | yy21: |
| 95283 | YYSKIP(); |
| 95284 | yych = YYPEEK(); |
| 95285 | switch (yych) { |
| 95286 | case 'r': goto yy24; |
| 95287 | default: goto yy20; |
| 95288 | } |
| 95289 | yy22: |
| 95290 | YYSKIP(); |
| 95291 | yych = YYPEEK(); |
| 95292 | switch (yych) { |
| 95293 | case '0': |
| 95294 | case '1': |
| 95295 | case '2': |
| 95296 | case '3': |
| 95297 | case '4': |
| 95298 | case '5': |
| 95299 | case '6': |
| 95300 | case '7': |
| 95301 | case '8': |
| 95302 | case '9': |
| 95303 | YYSTAGP(context.yyt3); |
| 95304 | goto yy25; |
| 95305 | default: goto yy20; |
| 95306 | } |
| 95307 | yy23: |
| 95308 | YYSKIP(); |
| 95309 | yych = YYPEEK(); |
| 95310 | switch (yych) { |
| 95311 | case '=': goto yy26; |
| 95312 | default: goto yy20; |
| 95313 | } |
| 95314 | yy24: |
| 95315 | YYSKIP(); |
| 95316 | yych = YYPEEK(); |
| 95317 | switch (yych) { |
| 95318 | case '=': goto yy27; |
| 95319 | default: goto yy20; |
| 95320 | } |
| 95321 | yy25: |
| 95322 | YYSKIP(); |
| 95323 | yych = YYPEEK(); |
| 95324 | switch (yych) { |
| 95325 | case '0': |
| 95326 | case '1': |
| 95327 | case '2': |
| 95328 | case '3': |
| 95329 | case '4': |
| 95330 | case '5': |
| 95331 | case '6': |
| 95332 | case '7': |
| 95333 | case '8': |
| 95334 | case '9': goto yy25; |
| 95335 | case ';': goto yy28; |
| 95336 | default: goto yy20; |
| 95337 | } |
| 95338 | yy26: |
| 95339 | YYSKIP(); |
| 95340 | yych = YYPEEK(); |
| 95341 | switch (yych) { |
| 95342 | case 0x00: |
| 95343 | case '\n': goto yy20; |
| 95344 | case ';': |
| 95345 | YYSTAGP(context.yyt4); |
| 95346 | goto yy30; |
| 95347 | default: |
| 95348 | YYSTAGP(context.yyt4); |
| 95349 | goto yy29; |
| 95350 | } |
| 95351 | yy27: |
| 95352 | YYSKIP(); |
| 95353 | yych = YYPEEK(); |
| 95354 | switch (yych) { |
| 95355 | case '0': |
| 95356 | case '1': |
| 95357 | case '2': |
| 95358 | case '3': |
| 95359 | case '4': |
| 95360 | case '5': |
| 95361 | case '6': |
| 95362 | case '7': |
| 95363 | case '8': |
| 95364 | case '9': |
| 95365 | YYSTAGP(context.yyt1); |
| 95366 | goto yy31; |
| 95367 | default: goto yy20; |
| 95368 | } |
| 95369 | yy28: |
| 95370 | YYSKIP(); |
| 95371 | yych = YYPEEK(); |
| 95372 | switch (yych) { |
| 95373 | case 'b': |
| 95374 | case 'g': |
| 95375 | case 'i': |
| 95376 | case 's': |
| 95377 | YYSTAGN(context.yyt4); |
| 95378 | goto yy32; |
| 95379 | default: goto yy20; |
| 95380 | } |
| 95381 | yy29: |
| 95382 | YYSKIP(); |
| 95383 | yych = YYPEEK(); |
| 95384 | switch (yych) { |
| 95385 | case 0x00: |
| 95386 | case '\n': goto yy20; |
| 95387 | case ';': goto yy30; |
| 95388 | default: goto yy29; |
| 95389 | } |
| 95390 | yy30: |
| 95391 | YYSKIP(); |
| 95392 | yych = YYPEEK(); |
| 95393 | switch (yych) { |
| 95394 | case 'b': |
| 95395 | case 'g': |
| 95396 | case 'i': |
| 95397 | case 's': |
| 95398 | YYSTAGN(context.yyt3); |
| 95399 | goto yy32; |
| 95400 | default: goto yy20; |
| 95401 | } |
| 95402 | yy31: |
| 95403 | YYSKIP(); |
| 95404 | yych = YYPEEK(); |
| 95405 | switch (yych) { |
| 95406 | case '0': |
| 95407 | case '1': |
| 95408 | case '2': |
| 95409 | case '3': |
| 95410 | case '4': |
| 95411 | case '5': |
| 95412 | case '6': |
| 95413 | case '7': |
| 95414 | case '8': |
| 95415 | case '9': goto yy31; |
| 95416 | case ';': |
| 95417 | YYSTAGP(context.yyt2); |
| 95418 | goto yy33; |
| 95419 | default: goto yy20; |
| 95420 | } |
| 95421 | yy32: |
| 95422 | YYSKIP(); |
| 95423 | yych = YYPEEK(); |
| 95424 | switch (yych) { |
| 95425 | case '=': goto yy18; |
| 95426 | default: goto yy20; |
| 95427 | } |
| 95428 | yy33: |
| 95429 | YYSKIP(); |
| 95430 | yych = YYPEEK(); |
| 95431 | switch (yych) { |
| 95432 | case 'b': |
| 95433 | case 'g': |
| 95434 | case 'i': |
| 95435 | case 's': |
| 95436 | YYSTAGN(context.yyt3); |
| 95437 | YYSTAGN(context.yyt4); |
| 95438 | goto yy32; |
| 95439 | case 'n': goto yy34; |
| 95440 | default: goto yy20; |
| 95441 | } |
| 95442 | yy34: |
| 95443 | YYSKIP(); |
| 95444 | yych = YYPEEK(); |
| 95445 | switch (yych) { |
| 95446 | case 's': goto yy19; |
| 95447 | default: goto yy20; |
| 95448 | } |
| 95449 | } |
| 95450 | |
| 95451 | } |
| 95452 | |
| 95453 | UA_StatusCode |
| 95454 | UA_ExpandedNodeId_parse(UA_ExpandedNodeId *id, const UA_String str) { |
| 95455 | UA_StatusCode res = |
| 95456 | parse_expandednodeid(id, pos: (const char*)str.data, end: (const char*)str.data+str.length); |
| 95457 | if(res != UA_STATUSCODE_GOOD) |
| 95458 | UA_ExpandedNodeId_clear(p: id); |
| 95459 | return res; |
| 95460 | } |
| 95461 | |
| 95462 | static UA_StatusCode |
| 95463 | relativepath_addelem(UA_RelativePath *rp, UA_RelativePathElement *el) { |
| 95464 | /* Allocate memory */ |
| 95465 | UA_RelativePathElement *newArray = (UA_RelativePathElement*) |
| 95466 | UA_realloc(ptr: rp->elements, size: sizeof(UA_RelativePathElement) * (rp->elementsSize + 1)); |
| 95467 | if(!newArray) |
| 95468 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 95469 | rp->elements = newArray; |
| 95470 | |
| 95471 | /* Move to the target */ |
| 95472 | rp->elements[rp->elementsSize] = *el; |
| 95473 | rp->elementsSize++; |
| 95474 | return UA_STATUSCODE_GOOD; |
| 95475 | } |
| 95476 | |
| 95477 | /* Parse name string with '&' as the escape character */ |
| 95478 | static UA_StatusCode |
| 95479 | parse_refpath_qn_name(UA_QualifiedName *qn, const char **pos, const char *end) { |
| 95480 | /* Allocate the max length the name can have */ |
| 95481 | size_t maxlen = (size_t)(end - *pos); |
| 95482 | if(maxlen == 0) { |
| 95483 | qn->name.data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL; |
| 95484 | return UA_STATUSCODE_GOOD; |
| 95485 | } |
| 95486 | char *name = (char*)UA_malloc(size: maxlen); |
| 95487 | if(!name) |
| 95488 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 95489 | |
| 95490 | size_t index = 0; |
| 95491 | for(; *pos < end; (*pos)++) { |
| 95492 | char c = **pos; |
| 95493 | /* Unescaped special characer: The end of the QualifiedName */ |
| 95494 | if(c == '/' || c == '.' || c == '<' || c == '>' || |
| 95495 | c == ':' || c == '#' || c == '!') |
| 95496 | break; |
| 95497 | |
| 95498 | /* Escaped character */ |
| 95499 | if(c == '&') { |
| 95500 | (*pos)++; |
| 95501 | if(*pos >= end || |
| 95502 | (**pos != '/' && **pos != '.' && **pos != '<' && **pos != '>' && |
| 95503 | **pos != ':' && **pos != '#' && **pos != '!' && **pos != '&')) { |
| 95504 | UA_free(ptr: name); |
| 95505 | return UA_STATUSCODE_BADDECODINGERROR; |
| 95506 | } |
| 95507 | c = **pos; |
| 95508 | } |
| 95509 | |
| 95510 | /* Unescaped normal character */ |
| 95511 | name[index] = c; |
| 95512 | index++; |
| 95513 | } |
| 95514 | |
| 95515 | if(index > 0) { |
| 95516 | qn->name.data = (UA_Byte*)name; |
| 95517 | qn->name.length = index; |
| 95518 | } else { |
| 95519 | qn->name.data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL; |
| 95520 | UA_free(ptr: name); |
| 95521 | } |
| 95522 | return UA_STATUSCODE_GOOD; |
| 95523 | } |
| 95524 | |
| 95525 | static UA_StatusCode |
| 95526 | parse_refpath_qn(UA_QualifiedName *qn, const char *pos, const char *end) { |
| 95527 | LexContext context; |
| 95528 | memset(s: &context, c: 0, n: sizeof(LexContext)); |
| 95529 | const char *ns = NULL, *nse = NULL; |
| 95530 | UA_QualifiedName_init(p: qn); |
| 95531 | |
| 95532 | |
| 95533 | { |
| 95534 | char yych; |
| 95535 | yych = YYPEEK(); |
| 95536 | switch (yych) { |
| 95537 | case '0': |
| 95538 | case '1': |
| 95539 | case '2': |
| 95540 | case '3': |
| 95541 | case '4': |
| 95542 | case '5': |
| 95543 | case '6': |
| 95544 | case '7': |
| 95545 | case '8': |
| 95546 | case '9': |
| 95547 | YYSTAGP(context.yyt1); |
| 95548 | goto yy38; |
| 95549 | default: goto yy36; |
| 95550 | } |
| 95551 | yy36: |
| 95552 | YYSKIP(); |
| 95553 | yy37: |
| 95554 | { pos--; goto parse_qn_name; } |
| 95555 | yy38: |
| 95556 | YYSKIP(); |
| 95557 | YYBACKUP(); |
| 95558 | yych = YYPEEK(); |
| 95559 | switch (yych) { |
| 95560 | case '0': |
| 95561 | case '1': |
| 95562 | case '2': |
| 95563 | case '3': |
| 95564 | case '4': |
| 95565 | case '5': |
| 95566 | case '6': |
| 95567 | case '7': |
| 95568 | case '8': |
| 95569 | case '9': |
| 95570 | case ':': goto yy40; |
| 95571 | default: goto yy37; |
| 95572 | } |
| 95573 | yy39: |
| 95574 | YYSKIP(); |
| 95575 | yych = YYPEEK(); |
| 95576 | yy40: |
| 95577 | switch (yych) { |
| 95578 | case '0': |
| 95579 | case '1': |
| 95580 | case '2': |
| 95581 | case '3': |
| 95582 | case '4': |
| 95583 | case '5': |
| 95584 | case '6': |
| 95585 | case '7': |
| 95586 | case '8': |
| 95587 | case '9': goto yy39; |
| 95588 | case ':': goto yy42; |
| 95589 | default: goto yy41; |
| 95590 | } |
| 95591 | yy41: |
| 95592 | YYRESTORE(); |
| 95593 | goto yy37; |
| 95594 | yy42: |
| 95595 | YYSKIP(); |
| 95596 | ns = context.yyt1; |
| 95597 | YYSTAGP(nse); |
| 95598 | YYSHIFTSTAG(nse, -1); |
| 95599 | { |
| 95600 | UA_UInt32 tmp; |
| 95601 | size_t len = (size_t)(nse - ns); |
| 95602 | if(UA_readNumber(buf: (const UA_Byte*)ns, buflen: len, number: &tmp) != len) |
| 95603 | return UA_STATUSCODE_BADDECODINGERROR; |
| 95604 | qn->namespaceIndex = (UA_UInt16)tmp; |
| 95605 | goto parse_qn_name; |
| 95606 | } |
| 95607 | } |
| 95608 | |
| 95609 | |
| 95610 | parse_qn_name: |
| 95611 | return parse_refpath_qn_name(qn, pos: &pos, end); |
| 95612 | } |
| 95613 | |
| 95614 | /* List of well-known ReferenceTypes that don't require lookup in the server */ |
| 95615 | |
| 95616 | typedef struct { |
| 95617 | char *browseName; |
| 95618 | UA_UInt32 identifier; |
| 95619 | } RefTypeNames; |
| 95620 | |
| 95621 | #define KNOWNREFTYPES 17 |
| 95622 | static const RefTypeNames knownRefTypes[KNOWNREFTYPES] = { |
| 95623 | {"References", UA_NS0ID_REFERENCES}, |
| 95624 | {"HierachicalReferences", UA_NS0ID_HIERARCHICALREFERENCES}, |
| 95625 | {"NonHierachicalReferences", UA_NS0ID_NONHIERARCHICALREFERENCES}, |
| 95626 | {"HasChild", UA_NS0ID_HASCHILD}, |
| 95627 | {"Aggregates", UA_NS0ID_AGGREGATES}, |
| 95628 | {"HasComponent", UA_NS0ID_HASCOMPONENT}, |
| 95629 | {"HasProperty", UA_NS0ID_HASPROPERTY}, |
| 95630 | {"HasOrderedComponent", UA_NS0ID_HASORDEREDCOMPONENT}, |
| 95631 | {"HasSubtype", UA_NS0ID_HASSUBTYPE}, |
| 95632 | {"Organizes", UA_NS0ID_ORGANIZES}, |
| 95633 | {"HasModellingRule", UA_NS0ID_HASMODELLINGRULE}, |
| 95634 | {"HasTypeDefinition", UA_NS0ID_HASTYPEDEFINITION}, |
| 95635 | {"HasEncoding", UA_NS0ID_HASENCODING}, |
| 95636 | {"GeneratesEvent", UA_NS0ID_GENERATESEVENT}, |
| 95637 | {"AlwaysGeneratesEvent", UA_NS0ID_ALWAYSGENERATESEVENT}, |
| 95638 | {"HasEventSource", UA_NS0ID_HASEVENTSOURCE}, |
| 95639 | {"HasNotifier", UA_NS0ID_HASNOTIFIER} |
| 95640 | }; |
| 95641 | |
| 95642 | static UA_StatusCode |
| 95643 | lookup_reftype(UA_NodeId *refTypeId, UA_QualifiedName *qn) { |
| 95644 | if(qn->namespaceIndex != 0) |
| 95645 | return UA_STATUSCODE_BADNOTFOUND; |
| 95646 | |
| 95647 | for(size_t i = 0; i < KNOWNREFTYPES; i++) { |
| 95648 | UA_String tmp = UA_STRING(chars: knownRefTypes[i].browseName); |
| 95649 | if(UA_String_equal(p1: &qn->name, p2: &tmp)) { |
| 95650 | *refTypeId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: knownRefTypes[i].identifier); |
| 95651 | return UA_STATUSCODE_GOOD; |
| 95652 | } |
| 95653 | } |
| 95654 | |
| 95655 | return UA_STATUSCODE_BADNOTFOUND; |
| 95656 | } |
| 95657 | |
| 95658 | static UA_StatusCode |
| 95659 | parse_relativepath(UA_RelativePath *rp, const char *pos, const char *end) { |
| 95660 | LexContext context; |
| 95661 | memset(s: &context, c: 0, n: sizeof(LexContext)); |
| 95662 | const char *begin = NULL, *finish = NULL; |
| 95663 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 95664 | UA_RelativePath_init(p: rp); /* Reset the BrowsePath */ |
| 95665 | |
| 95666 | /* Add one element to the path in every iteration */ |
| 95667 | UA_RelativePathElement current; |
| 95668 | loop: |
| 95669 | UA_RelativePathElement_init(p: ¤t); |
| 95670 | current.includeSubtypes = true; /* Follow subtypes by default */ |
| 95671 | |
| 95672 | /* Get the ReferenceType and its modifiers */ |
| 95673 | |
| 95674 | { |
| 95675 | char yych; |
| 95676 | unsigned int yyaccept = 0; |
| 95677 | yych = YYPEEK(); |
| 95678 | switch (yych) { |
| 95679 | case 0x00: goto yy44; |
| 95680 | case '.': goto yy47; |
| 95681 | case '/': goto yy48; |
| 95682 | case '<': goto yy49; |
| 95683 | default: goto yy45; |
| 95684 | } |
| 95685 | yy44: |
| 95686 | YYSKIP(); |
| 95687 | { (void)pos; return UA_STATUSCODE_GOOD; } |
| 95688 | yy45: |
| 95689 | YYSKIP(); |
| 95690 | yy46: |
| 95691 | { (void)pos; return UA_STATUSCODE_BADDECODINGERROR; } |
| 95692 | yy47: |
| 95693 | YYSKIP(); |
| 95694 | { |
| 95695 | current.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_AGGREGATES); |
| 95696 | goto reftype_target; |
| 95697 | } |
| 95698 | yy48: |
| 95699 | YYSKIP(); |
| 95700 | { |
| 95701 | current.referenceTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_HIERARCHICALREFERENCES); |
| 95702 | goto reftype_target; |
| 95703 | } |
| 95704 | yy49: |
| 95705 | yyaccept = 0; |
| 95706 | YYSKIP(); |
| 95707 | YYBACKUP(); |
| 95708 | yych = YYPEEK(); |
| 95709 | switch (yych) { |
| 95710 | case 0x00: |
| 95711 | case '>': goto yy46; |
| 95712 | case '&': |
| 95713 | YYSTAGP(context.yyt1); |
| 95714 | goto yy52; |
| 95715 | default: |
| 95716 | YYSTAGP(context.yyt1); |
| 95717 | goto yy50; |
| 95718 | } |
| 95719 | yy50: |
| 95720 | YYSKIP(); |
| 95721 | yych = YYPEEK(); |
| 95722 | switch (yych) { |
| 95723 | case 0x00: goto yy51; |
| 95724 | case '&': goto yy52; |
| 95725 | case '>': goto yy53; |
| 95726 | default: goto yy50; |
| 95727 | } |
| 95728 | yy51: |
| 95729 | YYRESTORE(); |
| 95730 | if (yyaccept == 0) { |
| 95731 | goto yy46; |
| 95732 | } else { |
| 95733 | goto yy54; |
| 95734 | } |
| 95735 | yy52: |
| 95736 | YYSKIP(); |
| 95737 | yych = YYPEEK(); |
| 95738 | switch (yych) { |
| 95739 | case 0x00: goto yy51; |
| 95740 | case '&': goto yy52; |
| 95741 | case '>': goto yy55; |
| 95742 | default: goto yy50; |
| 95743 | } |
| 95744 | yy53: |
| 95745 | YYSKIP(); |
| 95746 | yy54: |
| 95747 | begin = context.yyt1; |
| 95748 | YYSTAGP(finish); |
| 95749 | YYSHIFTSTAG(finish, -1); |
| 95750 | { |
| 95751 | for(; begin < finish; begin++) { |
| 95752 | if(*begin== '#') |
| 95753 | current.includeSubtypes = false; |
| 95754 | else if(*begin == '!') |
| 95755 | current.isInverse = true; |
| 95756 | else |
| 95757 | break; |
| 95758 | } |
| 95759 | UA_QualifiedName refqn; |
| 95760 | res |= parse_refpath_qn(qn: &refqn, pos: begin, end: finish); |
| 95761 | res |= lookup_reftype(refTypeId: ¤t.referenceTypeId, qn: &refqn); |
| 95762 | UA_QualifiedName_clear(p: &refqn); |
| 95763 | goto reftype_target; |
| 95764 | } |
| 95765 | yy55: |
| 95766 | yyaccept = 1; |
| 95767 | YYSKIP(); |
| 95768 | YYBACKUP(); |
| 95769 | yych = YYPEEK(); |
| 95770 | switch (yych) { |
| 95771 | case 0x00: goto yy54; |
| 95772 | case '&': goto yy52; |
| 95773 | case '>': goto yy53; |
| 95774 | default: goto yy50; |
| 95775 | } |
| 95776 | } |
| 95777 | |
| 95778 | |
| 95779 | /* Get the TargetName component */ |
| 95780 | reftype_target: |
| 95781 | if(res != UA_STATUSCODE_GOOD) |
| 95782 | return res; |
| 95783 | |
| 95784 | |
| 95785 | { |
| 95786 | char yych; |
| 95787 | yych = YYPEEK(); |
| 95788 | switch (yych) { |
| 95789 | case 0x00: |
| 95790 | case '.': |
| 95791 | case '/': |
| 95792 | case '<': goto yy57; |
| 95793 | case '&': |
| 95794 | YYSTAGP(context.yyt1); |
| 95795 | goto yy60; |
| 95796 | default: |
| 95797 | YYSTAGP(context.yyt1); |
| 95798 | goto yy58; |
| 95799 | } |
| 95800 | yy57: |
| 95801 | YYSKIP(); |
| 95802 | { pos--; goto add_element; } |
| 95803 | yy58: |
| 95804 | YYSKIP(); |
| 95805 | yych = YYPEEK(); |
| 95806 | switch (yych) { |
| 95807 | case 0x00: |
| 95808 | case '.': |
| 95809 | case '/': |
| 95810 | case '<': goto yy59; |
| 95811 | case '&': goto yy60; |
| 95812 | default: goto yy58; |
| 95813 | } |
| 95814 | yy59: |
| 95815 | begin = context.yyt1; |
| 95816 | { |
| 95817 | res = parse_refpath_qn(qn: ¤t.targetName, pos: begin, end: pos); |
| 95818 | goto add_element; |
| 95819 | } |
| 95820 | yy60: |
| 95821 | YYSKIP(); |
| 95822 | yych = YYPEEK(); |
| 95823 | switch (yych) { |
| 95824 | case 0x00: goto yy59; |
| 95825 | case '&': goto yy60; |
| 95826 | default: goto yy58; |
| 95827 | } |
| 95828 | } |
| 95829 | |
| 95830 | |
| 95831 | /* Add the current element to the path and continue to the next element */ |
| 95832 | add_element: |
| 95833 | res |= relativepath_addelem(rp, el: ¤t); |
| 95834 | if(res != UA_STATUSCODE_GOOD) { |
| 95835 | UA_RelativePathElement_clear(p: ¤t); |
| 95836 | return res; |
| 95837 | } |
| 95838 | goto loop; |
| 95839 | } |
| 95840 | |
| 95841 | UA_StatusCode |
| 95842 | UA_RelativePath_parse(UA_RelativePath *rp, const UA_String str) { |
| 95843 | UA_StatusCode res = |
| 95844 | parse_relativepath(rp, pos: (const char*)str.data, end: (const char*)str.data+str.length); |
| 95845 | if(res != UA_STATUSCODE_GOOD) |
| 95846 | UA_RelativePath_clear(p: rp); |
| 95847 | return res; |
| 95848 | } |
| 95849 | |
| 95850 | /**** amalgamated original file "/src/pubsub/ua_pubsub_networkmessage_json.c" ****/ |
| 95851 | |
| 95852 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 95853 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 95854 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 95855 | * |
| 95856 | * Copyright (c) 2019 Fraunhofer IOSB (Author: Lukas Meling) |
| 95857 | */ |
| 95858 | |
| 95859 | |
| 95860 | |
| 95861 | /* Json keys for dsm */ |
| 95862 | const char * UA_DECODEKEY_MESSAGES = "Messages"; |
| 95863 | const char * UA_DECODEKEY_MESSAGETYPE = "MessageType"; |
| 95864 | const char * UA_DECODEKEY_MESSAGEID = "MessageId"; |
| 95865 | const char * UA_DECODEKEY_PUBLISHERID = "PublisherId"; |
| 95866 | const char * UA_DECODEKEY_DATASETCLASSID = "DataSetClassId"; |
| 95867 | |
| 95868 | /* Json keys for dsm */ |
| 95869 | const char * UA_DECODEKEY_DATASETWRITERID = "DataSetWriterId"; |
| 95870 | const char * UA_DECODEKEY_SEQUENCENUMBER = "SequenceNumber"; |
| 95871 | const char * UA_DECODEKEY_METADATAVERSION = "MetaDataVersion"; |
| 95872 | const char * UA_DECODEKEY_TIMESTAMP = "Timestamp"; |
| 95873 | const char * UA_DECODEKEY_DSM_STATUS = "Status"; |
| 95874 | const char * UA_DECODEKEY_PAYLOAD = "Payload"; |
| 95875 | const char * UA_DECODEKEY_DS_TYPE = "Type"; |
| 95876 | |
| 95877 | /* -- json encoding/decoding -- */ |
| 95878 | static UA_StatusCode writeJsonKey_UA_String(CtxJson *ctx, UA_String *in) { |
| 95879 | UA_STACKARRAY(char, out, in->length + 1); |
| 95880 | memcpy(dest: out, src: in->data, n: in->length); |
| 95881 | out[in->length] = 0; |
| 95882 | return writeJsonKey(ctx, key: out); |
| 95883 | } |
| 95884 | |
| 95885 | static UA_StatusCode |
| 95886 | UA_DataSetMessage_encodeJson_internal(const UA_DataSetMessage* src, |
| 95887 | UA_UInt16 dataSetWriterId, |
| 95888 | CtxJson *ctx) { |
| 95889 | status rv = writeJsonObjStart(ctx); |
| 95890 | |
| 95891 | /* DataSetWriterId */ |
| 95892 | rv |= writeJsonObjElm(ctx, key: UA_DECODEKEY_DATASETWRITERID, |
| 95893 | value: &dataSetWriterId, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 95894 | if(rv != UA_STATUSCODE_GOOD) |
| 95895 | return rv; |
| 95896 | |
| 95897 | /* DataSetMessageSequenceNr */ |
| 95898 | if(src->header.dataSetMessageSequenceNrEnabled) { |
| 95899 | rv |= writeJsonObjElm(ctx, key: UA_DECODEKEY_SEQUENCENUMBER, |
| 95900 | value: &src->header.dataSetMessageSequenceNr, |
| 95901 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 95902 | if(rv != UA_STATUSCODE_GOOD) |
| 95903 | return rv; |
| 95904 | } |
| 95905 | |
| 95906 | /* MetaDataVersion */ |
| 95907 | if(src->header.configVersionMajorVersionEnabled || |
| 95908 | src->header.configVersionMinorVersionEnabled) { |
| 95909 | UA_ConfigurationVersionDataType cvd; |
| 95910 | cvd.majorVersion = src->header.configVersionMajorVersion; |
| 95911 | cvd.minorVersion = src->header.configVersionMinorVersion; |
| 95912 | rv |= writeJsonObjElm(ctx, key: UA_DECODEKEY_METADATAVERSION, value: &cvd, |
| 95913 | type: &UA_TYPES[UA_TYPES_CONFIGURATIONVERSIONDATATYPE]); |
| 95914 | if(rv != UA_STATUSCODE_GOOD) |
| 95915 | return rv; |
| 95916 | } |
| 95917 | |
| 95918 | /* Timestamp */ |
| 95919 | if(src->header.timestampEnabled) { |
| 95920 | rv |= writeJsonObjElm(ctx, key: UA_DECODEKEY_TIMESTAMP, value: &src->header.timestamp, |
| 95921 | type: &UA_TYPES[UA_TYPES_DATETIME]); |
| 95922 | if(rv != UA_STATUSCODE_GOOD) |
| 95923 | return rv; |
| 95924 | } |
| 95925 | |
| 95926 | /* Status */ |
| 95927 | if(src->header.statusEnabled) { |
| 95928 | rv |= writeJsonObjElm(ctx, key: UA_DECODEKEY_DSM_STATUS, |
| 95929 | value: &src->header.status, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 95930 | if(rv != UA_STATUSCODE_GOOD) |
| 95931 | return rv; |
| 95932 | } |
| 95933 | |
| 95934 | rv |= writeJsonKey(ctx, key: UA_DECODEKEY_PAYLOAD); |
| 95935 | rv |= writeJsonObjStart(ctx); |
| 95936 | |
| 95937 | /* TODO: currently no difference between delta and key frames. Own |
| 95938 | * dataSetMessageType for json?. If the field names are not defined, write |
| 95939 | * out empty field names. */ |
| 95940 | if(src->header.dataSetMessageType != UA_DATASETMESSAGE_DATAKEYFRAME) |
| 95941 | return UA_STATUSCODE_BADNOTSUPPORTED; /* Delta frames not supported */ |
| 95942 | |
| 95943 | if(src->header.fieldEncoding == UA_FIELDENCODING_VARIANT) { |
| 95944 | /* KEYFRAME VARIANT */ |
| 95945 | for(UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) { |
| 95946 | if(src->data.keyFrameData.fieldNames) |
| 95947 | rv |= writeJsonKey_UA_String(ctx, in: &src->data.keyFrameData.fieldNames[i]); |
| 95948 | else |
| 95949 | rv |= writeJsonKey(ctx, key: ""); |
| 95950 | rv |= encodeJsonJumpTable[UA_DATATYPEKIND_VARIANT] |
| 95951 | (ctx, &src->data.keyFrameData.dataSetFields[i].value, NULL); |
| 95952 | if(rv != UA_STATUSCODE_GOOD) |
| 95953 | return rv; |
| 95954 | } |
| 95955 | } else if(src->header.fieldEncoding == UA_FIELDENCODING_DATAVALUE) { |
| 95956 | /* KEYFRAME DATAVALUE */ |
| 95957 | for(UA_UInt16 i = 0; i < src->data.keyFrameData.fieldCount; i++) { |
| 95958 | if(src->data.keyFrameData.fieldNames) |
| 95959 | rv |= writeJsonKey_UA_String(ctx, in: &src->data.keyFrameData.fieldNames[i]); |
| 95960 | else |
| 95961 | rv |= writeJsonKey(ctx, key: ""); |
| 95962 | rv |= encodeJsonJumpTable[UA_DATATYPEKIND_DATAVALUE] |
| 95963 | (ctx, &src->data.keyFrameData.dataSetFields[i], NULL); |
| 95964 | if(rv != UA_STATUSCODE_GOOD) |
| 95965 | return rv; |
| 95966 | } |
| 95967 | } else { |
| 95968 | /* RawData */ |
| 95969 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 95970 | } |
| 95971 | rv |= writeJsonObjEnd(ctx); /* Payload */ |
| 95972 | rv |= writeJsonObjEnd(ctx); /* DataSetMessage */ |
| 95973 | return rv; |
| 95974 | } |
| 95975 | |
| 95976 | static UA_StatusCode |
| 95977 | UA_NetworkMessage_encodeJson_internal(const UA_NetworkMessage* src, CtxJson *ctx) { |
| 95978 | status rv = UA_STATUSCODE_GOOD; |
| 95979 | const UA_DataType *publisherIdType; |
| 95980 | /* currently only ua-data is supported, no discovery message implemented */ |
| 95981 | if(src->networkMessageType != UA_NETWORKMESSAGE_DATASET) |
| 95982 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 95983 | |
| 95984 | writeJsonObjStart(ctx); |
| 95985 | |
| 95986 | /* Table 91 – JSON NetworkMessage Definition |
| 95987 | * MessageId | String | A globally unique identifier for the message. |
| 95988 | * This value is mandatory. But we don't check uniqueness in the |
| 95989 | * encoding layer. */ |
| 95990 | rv |= writeJsonObjElm(ctx, key: UA_DECODEKEY_MESSAGEID, |
| 95991 | value: &src->messageId, type: &UA_TYPES[UA_TYPES_STRING]); |
| 95992 | |
| 95993 | /* MessageType */ |
| 95994 | UA_String s = UA_STRING(chars: "ua-data"); |
| 95995 | rv |= writeJsonObjElm(ctx, key: UA_DECODEKEY_MESSAGETYPE, |
| 95996 | value: &s, type: &UA_TYPES[UA_TYPES_STRING]); |
| 95997 | |
| 95998 | /* PublisherId */ |
| 95999 | if(src->publisherIdEnabled) { |
| 96000 | rv = writeJsonKey(ctx, key: UA_DECODEKEY_PUBLISHERID); |
| 96001 | switch (src->publisherIdType) { |
| 96002 | case UA_PUBLISHERIDTYPE_BYTE: |
| 96003 | publisherIdType = &UA_TYPES[UA_TYPES_BYTE]; |
| 96004 | break; |
| 96005 | case UA_PUBLISHERIDTYPE_UINT16: |
| 96006 | publisherIdType = &UA_TYPES[UA_TYPES_UINT16]; |
| 96007 | break; |
| 96008 | case UA_PUBLISHERIDTYPE_UINT32: |
| 96009 | publisherIdType = &UA_TYPES[UA_TYPES_UINT32]; |
| 96010 | break; |
| 96011 | case UA_PUBLISHERIDTYPE_UINT64: |
| 96012 | publisherIdType = &UA_TYPES[UA_TYPES_UINT64]; |
| 96013 | break; |
| 96014 | case UA_PUBLISHERIDTYPE_STRING: |
| 96015 | publisherIdType = &UA_TYPES[UA_TYPES_STRING]; |
| 96016 | break; |
| 96017 | } |
| 96018 | rv |= encodeJsonJumpTable[publisherIdType->typeKind] |
| 96019 | (ctx, &src->publisherId, publisherIdType); |
| 96020 | } |
| 96021 | if(rv != UA_STATUSCODE_GOOD) |
| 96022 | return rv; |
| 96023 | |
| 96024 | /* DataSetClassId */ |
| 96025 | if(src->dataSetClassIdEnabled) { |
| 96026 | rv |= writeJsonObjElm(ctx, key: UA_DECODEKEY_DATASETCLASSID, |
| 96027 | value: &src->dataSetClassId, type: &UA_TYPES[UA_TYPES_GUID]); |
| 96028 | if(rv != UA_STATUSCODE_GOOD) |
| 96029 | return rv; |
| 96030 | } |
| 96031 | |
| 96032 | /* Payload: DataSetMessages */ |
| 96033 | UA_Byte count = src->payloadHeader.dataSetPayloadHeader.count; |
| 96034 | if(count > 0) { |
| 96035 | UA_UInt16 *dataSetWriterIds = |
| 96036 | src->payloadHeader.dataSetPayloadHeader.dataSetWriterIds; |
| 96037 | if(!dataSetWriterIds) |
| 96038 | return UA_STATUSCODE_BADENCODINGERROR; |
| 96039 | |
| 96040 | rv |= writeJsonKey(ctx, key: UA_DECODEKEY_MESSAGES); |
| 96041 | rv |= writeJsonArrStart(ctx); /* start array */ |
| 96042 | |
| 96043 | const UA_DataSetMessage *dataSetMessages = |
| 96044 | src->payload.dataSetPayload.dataSetMessages; |
| 96045 | for(UA_UInt16 i = 0; i < count; i++) { |
| 96046 | rv |= writeJsonBeforeElement(ctx, true); |
| 96047 | rv |= UA_DataSetMessage_encodeJson_internal(src: &dataSetMessages[i], |
| 96048 | dataSetWriterId: dataSetWriterIds[i], ctx); |
| 96049 | if(rv != UA_STATUSCODE_GOOD) |
| 96050 | return rv; |
| 96051 | /* comma is needed if more dsm are present */ |
| 96052 | ctx->commaNeeded[ctx->depth] = true; |
| 96053 | } |
| 96054 | rv |= writeJsonArrEnd(ctx); /* end array */ |
| 96055 | } |
| 96056 | |
| 96057 | rv |= writeJsonObjEnd(ctx); |
| 96058 | return rv; |
| 96059 | } |
| 96060 | |
| 96061 | UA_StatusCode |
| 96062 | UA_NetworkMessage_encodeJson(const UA_NetworkMessage *src, |
| 96063 | UA_Byte **bufPos, const UA_Byte **bufEnd, |
| 96064 | UA_String *namespaces, size_t namespaceSize, |
| 96065 | UA_String *serverUris, size_t serverUriSize, |
| 96066 | UA_Boolean useReversible) { |
| 96067 | /* Set up the context */ |
| 96068 | CtxJson ctx; |
| 96069 | memset(s: &ctx, c: 0, n: sizeof(ctx)); |
| 96070 | ctx.pos = *bufPos; |
| 96071 | ctx.end = *bufEnd; |
| 96072 | ctx.depth = 0; |
| 96073 | ctx.namespaces = namespaces; |
| 96074 | ctx.namespacesSize = namespaceSize; |
| 96075 | ctx.serverUris = serverUris; |
| 96076 | ctx.serverUrisSize = serverUriSize; |
| 96077 | ctx.useReversible = useReversible; |
| 96078 | ctx.calcOnly = false; |
| 96079 | |
| 96080 | status ret = UA_NetworkMessage_encodeJson_internal(src, ctx: &ctx); |
| 96081 | |
| 96082 | *bufPos = ctx.pos; |
| 96083 | *bufEnd = ctx.end; |
| 96084 | return ret; |
| 96085 | } |
| 96086 | |
| 96087 | size_t |
| 96088 | UA_NetworkMessage_calcSizeJson(const UA_NetworkMessage *src, |
| 96089 | UA_String *namespaces, size_t namespaceSize, |
| 96090 | UA_String *serverUris, size_t serverUriSize, |
| 96091 | UA_Boolean useReversible){ |
| 96092 | /* Set up the context */ |
| 96093 | CtxJson ctx; |
| 96094 | memset(s: &ctx, c: 0, n: sizeof(ctx)); |
| 96095 | ctx.pos = 0; |
| 96096 | ctx.end = (const UA_Byte*)(uintptr_t)SIZE_MAX; |
| 96097 | ctx.depth = 0; |
| 96098 | ctx.namespaces = namespaces; |
| 96099 | ctx.namespacesSize = namespaceSize; |
| 96100 | ctx.serverUris = serverUris; |
| 96101 | ctx.serverUrisSize = serverUriSize; |
| 96102 | ctx.useReversible = useReversible; |
| 96103 | ctx.calcOnly = true; |
| 96104 | |
| 96105 | status ret = UA_NetworkMessage_encodeJson_internal(src, ctx: &ctx); |
| 96106 | if(ret != UA_STATUSCODE_GOOD) |
| 96107 | return 0; |
| 96108 | return (size_t)ctx.pos; |
| 96109 | } |
| 96110 | |
| 96111 | /* decode json */ |
| 96112 | static status |
| 96113 | MetaDataVersion_decodeJsonInternal(ParseCtx *ctx, void* cvd, const UA_DataType *type) { |
| 96114 | return decodeJsonJumpTable[UA_DATATYPEKIND_STRUCTURE] |
| 96115 | (ctx, cvd, &UA_TYPES[UA_TYPES_CONFIGURATIONVERSIONDATATYPE]); |
| 96116 | } |
| 96117 | |
| 96118 | static status |
| 96119 | DataSetPayload_decodeJsonInternal(ParseCtx *ctx, void* dsmP, const UA_DataType *type) { |
| 96120 | UA_DataSetMessage* dsm = (UA_DataSetMessage*)dsmP; |
| 96121 | dsm->header.dataSetMessageValid = true; |
| 96122 | if(currentTokenType(ctx) == CJ5_TOKEN_NULL) { |
| 96123 | ctx->index++; |
| 96124 | return UA_STATUSCODE_GOOD; |
| 96125 | } |
| 96126 | |
| 96127 | if(currentTokenType(ctx) != CJ5_TOKEN_OBJECT) |
| 96128 | return UA_STATUSCODE_BADDECODINGERROR; |
| 96129 | |
| 96130 | /* The number of key-value pairs */ |
| 96131 | UA_assert(ctx->tokens[ctx->index].size % 2 == 0); |
| 96132 | size_t length = (size_t)(ctx->tokens[ctx->index].size) / 2; |
| 96133 | |
| 96134 | UA_String *fieldNames = (UA_String*)UA_calloc(nmemb: length, size: sizeof(UA_String)); |
| 96135 | if(!fieldNames) |
| 96136 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 96137 | dsm->data.keyFrameData.fieldNames = fieldNames; |
| 96138 | dsm->data.keyFrameData.fieldCount = (UA_UInt16)length; |
| 96139 | |
| 96140 | dsm->data.keyFrameData.dataSetFields = (UA_DataValue *) |
| 96141 | UA_Array_new(size: dsm->data.keyFrameData.fieldCount, type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 96142 | if(!dsm->data.keyFrameData.dataSetFields) |
| 96143 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 96144 | |
| 96145 | ctx->index++; /* Go to the first key */ |
| 96146 | |
| 96147 | /* Iterate over the key/value pairs in the object. Keys are stored in fieldnames. */ |
| 96148 | status ret = UA_STATUSCODE_GOOD; |
| 96149 | for(size_t i = 0; i < length; ++i) { |
| 96150 | UA_assert(currentTokenType(ctx) == CJ5_TOKEN_STRING); |
| 96151 | ret = decodeJsonJumpTable[UA_DATATYPEKIND_STRING](ctx, &fieldNames[i], type); |
| 96152 | if(ret != UA_STATUSCODE_GOOD) |
| 96153 | return ret; |
| 96154 | |
| 96155 | /* TODO: Is field value a variant or datavalue? Current check if type and body present. */ |
| 96156 | size_t searchResult = 0; |
| 96157 | status foundType = lookAheadForKey(ctx, search: "Type", resultIndex: &searchResult); |
| 96158 | status foundBody = lookAheadForKey(ctx, search: "Body", resultIndex: &searchResult); |
| 96159 | if(foundType == UA_STATUSCODE_GOOD && foundBody == UA_STATUSCODE_GOOD) { |
| 96160 | dsm->header.fieldEncoding = UA_FIELDENCODING_VARIANT; |
| 96161 | ret = decodeJsonJumpTable[UA_DATATYPEKIND_VARIANT] |
| 96162 | (ctx, &dsm->data.keyFrameData.dataSetFields[i].value, type); |
| 96163 | dsm->data.keyFrameData.dataSetFields[i].hasValue = true; |
| 96164 | } else { |
| 96165 | dsm->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE; |
| 96166 | ret = decodeJsonJumpTable[UA_DATATYPEKIND_DATAVALUE] |
| 96167 | (ctx, &dsm->data.keyFrameData.dataSetFields[i], type); |
| 96168 | dsm->data.keyFrameData.dataSetFields[i].hasValue = true; |
| 96169 | } |
| 96170 | |
| 96171 | if(ret != UA_STATUSCODE_GOOD) |
| 96172 | return ret; |
| 96173 | } |
| 96174 | |
| 96175 | return ret; |
| 96176 | } |
| 96177 | |
| 96178 | static status |
| 96179 | DatasetMessage_Payload_decodeJsonInternal(ParseCtx *ctx, UA_DataSetMessage* dsm, |
| 96180 | const UA_DataType *type) { |
| 96181 | UA_ConfigurationVersionDataType cvd; |
| 96182 | UA_UInt16 dataSetWriterId; |
| 96183 | |
| 96184 | dsm->header.fieldEncoding = UA_FIELDENCODING_DATAVALUE; |
| 96185 | |
| 96186 | DecodeEntry entries[6] = { |
| 96187 | {UA_DECODEKEY_DATASETWRITERID, &dataSetWriterId, NULL, false, &UA_TYPES[UA_TYPES_UINT16]}, |
| 96188 | {UA_DECODEKEY_SEQUENCENUMBER, &dsm->header.dataSetMessageSequenceNr, NULL, false, &UA_TYPES[UA_TYPES_UINT16]}, |
| 96189 | {UA_DECODEKEY_METADATAVERSION, &cvd, &MetaDataVersion_decodeJsonInternal, false, NULL}, |
| 96190 | {UA_DECODEKEY_TIMESTAMP, &dsm->header.timestamp, NULL, false, &UA_TYPES[UA_TYPES_DATETIME]}, |
| 96191 | {UA_DECODEKEY_DSM_STATUS, &dsm->header.status, NULL, false, &UA_TYPES[UA_TYPES_UINT16]}, |
| 96192 | {UA_DECODEKEY_PAYLOAD, dsm, &DataSetPayload_decodeJsonInternal, false, NULL} |
| 96193 | }; |
| 96194 | status ret = decodeFields(ctx, entries, entryCount: 6); |
| 96195 | |
| 96196 | /* Error or no DatasetWriterId found or no payload found */ |
| 96197 | if(ret != UA_STATUSCODE_GOOD || !entries[0].found || !entries[5].found) |
| 96198 | return UA_STATUSCODE_BADDECODINGERROR; |
| 96199 | |
| 96200 | /* Set the DatasetWriterId in the context */ |
| 96201 | if(!ctx->custom) |
| 96202 | return UA_STATUSCODE_BADDECODINGERROR; |
| 96203 | if(ctx->currentCustomIndex >= ctx->numCustom) |
| 96204 | return UA_STATUSCODE_BADDECODINGERROR; |
| 96205 | UA_UInt16* dataSetWriterIdsArray = (UA_UInt16*)ctx->custom; |
| 96206 | dataSetWriterIdsArray[ctx->currentCustomIndex] = dataSetWriterId; |
| 96207 | ctx->currentCustomIndex++; |
| 96208 | |
| 96209 | dsm->header.dataSetMessageSequenceNrEnabled = entries[1].found; |
| 96210 | dsm->header.configVersionMajorVersion = cvd.majorVersion; |
| 96211 | dsm->header.configVersionMinorVersion = cvd.minorVersion; |
| 96212 | dsm->header.configVersionMajorVersionEnabled = entries[2].found; |
| 96213 | dsm->header.configVersionMinorVersionEnabled = entries[2].found; |
| 96214 | dsm->header.timestampEnabled = entries[3].found; |
| 96215 | dsm->header.statusEnabled = entries[4].found; |
| 96216 | |
| 96217 | dsm->header.dataSetMessageType = UA_DATASETMESSAGE_DATAKEYFRAME; |
| 96218 | dsm->header.picoSecondsIncluded = false; |
| 96219 | dsm->header.dataSetMessageValid = true; |
| 96220 | dsm->header.fieldEncoding = UA_FIELDENCODING_VARIANT; |
| 96221 | return UA_STATUSCODE_GOOD; |
| 96222 | } |
| 96223 | |
| 96224 | static status |
| 96225 | DatasetMessage_Array_decodeJsonInternal(ParseCtx *ctx, void *UA_RESTRICT dst, |
| 96226 | const UA_DataType *type) { |
| 96227 | /* Array! */ |
| 96228 | if(currentTokenType(ctx) != CJ5_TOKEN_ARRAY) |
| 96229 | return UA_STATUSCODE_BADDECODINGERROR; |
| 96230 | size_t length = (size_t)ctx->tokens[ctx->index].size; |
| 96231 | |
| 96232 | /* Return early for empty arrays */ |
| 96233 | if(length == 0) |
| 96234 | return UA_STATUSCODE_GOOD; |
| 96235 | |
| 96236 | /* Allocate memory */ |
| 96237 | UA_DataSetMessage *dsm = (UA_DataSetMessage*) |
| 96238 | UA_calloc(nmemb: length, size: sizeof(UA_DataSetMessage)); |
| 96239 | if(!dsm) |
| 96240 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 96241 | |
| 96242 | /* Copy new Pointer do dest */ |
| 96243 | memcpy(dest: dst, src: &dsm, n: sizeof(void*)); |
| 96244 | |
| 96245 | /* We go to first Array member! */ |
| 96246 | ctx->index++; |
| 96247 | |
| 96248 | status ret = UA_STATUSCODE_BADDECODINGERROR; |
| 96249 | /* Decode array members */ |
| 96250 | for(size_t i = 0; i < length; ++i) { |
| 96251 | ret = DatasetMessage_Payload_decodeJsonInternal(ctx, dsm: &dsm[i], NULL); |
| 96252 | if(ret != UA_STATUSCODE_GOOD) |
| 96253 | return ret; |
| 96254 | } |
| 96255 | |
| 96256 | return ret; |
| 96257 | } |
| 96258 | |
| 96259 | static status |
| 96260 | NetworkMessage_decodeJsonInternal(ParseCtx *ctx, UA_NetworkMessage *dst) { |
| 96261 | memset(s: dst, c: 0, n: sizeof(UA_NetworkMessage)); |
| 96262 | dst->chunkMessage = false; |
| 96263 | dst->groupHeaderEnabled = false; |
| 96264 | dst->payloadHeaderEnabled = false; |
| 96265 | dst->picosecondsEnabled = false; |
| 96266 | dst->promotedFieldsEnabled = false; |
| 96267 | |
| 96268 | /* Look forward for publisheId, if present check if type if primitve (Number) or String. */ |
| 96269 | const UA_DataType *pubIdType = &UA_TYPES[UA_TYPES_STRING]; |
| 96270 | size_t searchResultPublishIdType = 0; |
| 96271 | status found = lookAheadForKey(ctx, search: UA_DECODEKEY_PUBLISHERID, resultIndex: &searchResultPublishIdType); |
| 96272 | if(found == UA_STATUSCODE_GOOD) { |
| 96273 | cj5_token *publishIdToken = &ctx->tokens[searchResultPublishIdType]; |
| 96274 | if(publishIdToken->type == CJ5_TOKEN_NUMBER) { |
| 96275 | // store in biggest possible. The problem is that with a UInt64 a |
| 96276 | // string is expected in the json. Therefore, the maximum value is |
| 96277 | // set to UInt32. |
| 96278 | pubIdType = &UA_TYPES[UA_TYPES_UINT32]; |
| 96279 | dst->publisherIdType = UA_PUBLISHERIDTYPE_UINT32; |
| 96280 | } else if(publishIdToken->type == CJ5_TOKEN_STRING) { |
| 96281 | dst->publisherIdType = UA_PUBLISHERIDTYPE_STRING; |
| 96282 | } else { |
| 96283 | return UA_STATUSCODE_BADDECODINGERROR; |
| 96284 | } |
| 96285 | } |
| 96286 | |
| 96287 | /* Is Messages an Array? How big? */ |
| 96288 | size_t searchResultMessages = 0; |
| 96289 | found = lookAheadForKey(ctx, search: UA_DECODEKEY_MESSAGES, resultIndex: &searchResultMessages); |
| 96290 | if(found != UA_STATUSCODE_GOOD) |
| 96291 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 96292 | const cj5_token *bodyToken = &ctx->tokens[searchResultMessages]; |
| 96293 | if(bodyToken->type != CJ5_TOKEN_ARRAY) |
| 96294 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 96295 | size_t messageCount = (size_t)ctx->tokens[searchResultMessages].size; |
| 96296 | |
| 96297 | /* Set up custom context for the dataSetwriterId */ |
| 96298 | ctx->custom = (void*)UA_calloc(nmemb: messageCount, size: sizeof(UA_UInt16)); |
| 96299 | ctx->currentCustomIndex = 0; |
| 96300 | ctx->numCustom = messageCount; |
| 96301 | |
| 96302 | /* MessageType */ |
| 96303 | UA_Boolean isUaData = true; |
| 96304 | size_t searchResultMessageType = 0; |
| 96305 | found = lookAheadForKey(ctx, search: UA_DECODEKEY_MESSAGETYPE, resultIndex: &searchResultMessageType); |
| 96306 | if(found != UA_STATUSCODE_GOOD) |
| 96307 | return UA_STATUSCODE_BADDECODINGERROR; |
| 96308 | size_t size = getTokenLength(t: &ctx->tokens[searchResultMessageType]); |
| 96309 | const char* msgType = &ctx->json5[ctx->tokens[searchResultMessageType].start]; |
| 96310 | if(size == 7) { //ua-data |
| 96311 | if(strncmp(s1: msgType, s2: "ua-data", n: size) != 0) |
| 96312 | return UA_STATUSCODE_BADDECODINGERROR; |
| 96313 | isUaData = true; |
| 96314 | } else if(size == 11) { //ua-metadata |
| 96315 | if(strncmp(s1: msgType, s2: "ua-metadata", n: size) != 0) |
| 96316 | return UA_STATUSCODE_BADDECODINGERROR; |
| 96317 | isUaData = false; |
| 96318 | } else { |
| 96319 | return UA_STATUSCODE_BADDECODINGERROR; |
| 96320 | } |
| 96321 | |
| 96322 | //TODO: MetaData |
| 96323 | if(!isUaData) |
| 96324 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 96325 | |
| 96326 | /* Network Message */ |
| 96327 | UA_String messageType; |
| 96328 | DecodeEntry entries[5] = { |
| 96329 | {UA_DECODEKEY_MESSAGEID, &dst->messageId, NULL, false, &UA_TYPES[UA_TYPES_STRING]}, |
| 96330 | {UA_DECODEKEY_MESSAGETYPE, &messageType, NULL, false, NULL}, |
| 96331 | {UA_DECODEKEY_PUBLISHERID, &dst->publisherId, NULL, false, pubIdType}, |
| 96332 | {UA_DECODEKEY_DATASETCLASSID, &dst->dataSetClassId, NULL, false, &UA_TYPES[UA_TYPES_GUID]}, |
| 96333 | {UA_DECODEKEY_MESSAGES, &dst->payload.dataSetPayload.dataSetMessages, &DatasetMessage_Array_decodeJsonInternal, false, NULL} |
| 96334 | }; |
| 96335 | |
| 96336 | status ret = decodeFields(ctx, entries, entryCount: 5); |
| 96337 | if(ret != UA_STATUSCODE_GOOD) |
| 96338 | return ret; |
| 96339 | |
| 96340 | dst->messageIdEnabled = entries[0].found; |
| 96341 | dst->publisherIdEnabled = entries[2].found; |
| 96342 | if(dst->publisherIdEnabled) { |
| 96343 | if(pubIdType == &UA_TYPES[UA_TYPES_UINT32]) { |
| 96344 | dst->publisherIdType = UA_PUBLISHERIDTYPE_UINT32; |
| 96345 | } else { |
| 96346 | dst->publisherIdType = UA_PUBLISHERIDTYPE_STRING; |
| 96347 | } |
| 96348 | } |
| 96349 | dst->dataSetClassIdEnabled = entries[3].found; |
| 96350 | dst->payloadHeaderEnabled = true; |
| 96351 | dst->payloadHeader.dataSetPayloadHeader.count = (UA_Byte)messageCount; |
| 96352 | |
| 96353 | /* Set the dataSetWriterIds. They are filled in the dataSet decoding. */ |
| 96354 | dst->payloadHeader.dataSetPayloadHeader.dataSetWriterIds = (UA_UInt16*)ctx->custom; |
| 96355 | return ret; |
| 96356 | } |
| 96357 | |
| 96358 | status |
| 96359 | UA_NetworkMessage_decodeJson(UA_NetworkMessage *dst, const UA_ByteString *src) { |
| 96360 | /* Set up the context */ |
| 96361 | cj5_token tokens[UA_JSON_MAXTOKENCOUNT]; |
| 96362 | ParseCtx ctx; |
| 96363 | memset(s: &ctx, c: 0, n: sizeof(ParseCtx)); |
| 96364 | ctx.tokens = tokens; |
| 96365 | status ret = tokenize(ctx: &ctx, src, UA_JSON_MAXTOKENCOUNT); |
| 96366 | if(ret != UA_STATUSCODE_GOOD) |
| 96367 | goto cleanup; |
| 96368 | |
| 96369 | ret = NetworkMessage_decodeJsonInternal(ctx: &ctx, dst); |
| 96370 | |
| 96371 | cleanup: |
| 96372 | /* Free token array on the heap */ |
| 96373 | if(ctx.tokens != tokens) |
| 96374 | UA_free(ptr: (void*)(uintptr_t)ctx.tokens); |
| 96375 | return ret; |
| 96376 | } |
| 96377 | |
| 96378 | /**** amalgamated original file "/deps/cj5.c" ****/ |
| 96379 | |
| 96380 | // MIT License |
| 96381 | // |
| 96382 | // Copyright (c) 2020 Sepehr Taghdisian |
| 96383 | // Copyright (c) 2022 Julius Pfrommer |
| 96384 | // |
| 96385 | // Permission is hereby granted, free of charge, to any person obtaining a copy |
| 96386 | // of this software and associated documentation files (the "Software"), to deal |
| 96387 | // in the Software without restriction, including without limitation the rights |
| 96388 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 96389 | // copies of the Software, and to permit persons to whom the Software is |
| 96390 | // furnished to do so, subject to the following conditions: |
| 96391 | // |
| 96392 | // The above copyright notice and this permission notice shall be included in all |
| 96393 | // copies or substantial portions of the Software. |
| 96394 | // |
| 96395 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 96396 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 96397 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 96398 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 96399 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 96400 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 96401 | // SOFTWARE. |
| 96402 | |
| 96403 | |
| 96404 | #include <math.h> |
| 96405 | #include <float.h> |
| 96406 | #include <string.h> |
| 96407 | |
| 96408 | #if defined(_MSC_VER) |
| 96409 | # define CJ5_INLINE __inline |
| 96410 | #else |
| 96411 | # define CJ5_INLINE inline |
| 96412 | #endif |
| 96413 | |
| 96414 | /* vs2008 does not have INFINITY and NAN defined */ |
| 96415 | #ifndef INFINITY |
| 96416 | # define INFINITY ((double)(DBL_MAX+DBL_MAX)) |
| 96417 | #endif |
| 96418 | #ifndef NAN |
| 96419 | # define NAN ((double)(INFINITY-INFINITY)) |
| 96420 | #endif |
| 96421 | |
| 96422 | #if defined(_MSC_VER) |
| 96423 | # pragma warning(disable: 4056) |
| 96424 | # pragma warning(disable: 4756) |
| 96425 | #endif |
| 96426 | |
| 96427 | /* Max nesting depth of objects and arrays */ |
| 96428 | #define CJ5_MAX_NESTING 32 |
| 96429 | |
| 96430 | #define CJ5__FOURCC(_a, _b, _c, _d) \ |
| 96431 | (((uint32_t)(_a) | ((uint32_t)(_b) << 8) | \ |
| 96432 | ((uint32_t)(_c) << 16) | ((uint32_t)(_d) << 24))) |
| 96433 | |
| 96434 | static const uint32_t CJ5__NULL_FOURCC = CJ5__FOURCC('n', 'u', 'l', 'l'); |
| 96435 | static const uint32_t CJ5__TRUE_FOURCC = CJ5__FOURCC('t', 'r', 'u', 'e'); |
| 96436 | static const uint32_t CJ5__FALSE_FOURCC = CJ5__FOURCC('f', 'a', 'l', 's'); |
| 96437 | |
| 96438 | typedef struct { |
| 96439 | unsigned int pos; |
| 96440 | unsigned int line_start; |
| 96441 | unsigned int line; |
| 96442 | cj5_error_code error; |
| 96443 | |
| 96444 | const char *json5; |
| 96445 | unsigned int len; |
| 96446 | |
| 96447 | unsigned int curr_tok_idx; |
| 96448 | |
| 96449 | cj5_token *tokens; |
| 96450 | unsigned int token_count; |
| 96451 | unsigned int max_tokens; |
| 96452 | |
| 96453 | bool stop_early; |
| 96454 | } cj5__parser; |
| 96455 | |
| 96456 | static CJ5_INLINE bool |
| 96457 | cj5__isrange(char ch, char from, char to) { |
| 96458 | return (uint8_t)(ch - from) <= (uint8_t)(to - from); |
| 96459 | } |
| 96460 | |
| 96461 | #define cj5__isupperchar(ch) cj5__isrange(ch, 'A', 'Z') |
| 96462 | #define cj5__islowerchar(ch) cj5__isrange(ch, 'a', 'z') |
| 96463 | #define cj5__isnum(ch) cj5__isrange(ch, '0', '9') |
| 96464 | |
| 96465 | static cj5_token * |
| 96466 | cj5__alloc_token(cj5__parser *parser) { |
| 96467 | cj5_token* token = NULL; |
| 96468 | if(parser->token_count < parser->max_tokens) { |
| 96469 | token = &parser->tokens[parser->token_count]; |
| 96470 | memset(s: token, c: 0x0, n: sizeof(cj5_token)); |
| 96471 | } else { |
| 96472 | parser->error = CJ5_ERROR_OVERFLOW; |
| 96473 | } |
| 96474 | |
| 96475 | // Always increase the index. So we know eventually how many token would be |
| 96476 | // required (if there are not enough). |
| 96477 | parser->token_count++; |
| 96478 | return token; |
| 96479 | } |
| 96480 | |
| 96481 | static void |
| 96482 | cj5__parse_string(cj5__parser *parser) { |
| 96483 | const char *json5 = parser->json5; |
| 96484 | unsigned int len = parser->len; |
| 96485 | unsigned int start = parser->pos; |
| 96486 | char str_open = json5[start]; |
| 96487 | |
| 96488 | parser->pos++; |
| 96489 | for(; parser->pos < len; parser->pos++) { |
| 96490 | char c = json5[parser->pos]; |
| 96491 | |
| 96492 | // End of string |
| 96493 | if(str_open == c) { |
| 96494 | cj5_token *token = cj5__alloc_token(parser); |
| 96495 | if(token) { |
| 96496 | token->type = CJ5_TOKEN_STRING; |
| 96497 | token->start = start + 1; |
| 96498 | token->end = parser->pos - 1; |
| 96499 | token->size = token->end - token->start + 1; |
| 96500 | token->parent_id = parser->curr_tok_idx; |
| 96501 | } |
| 96502 | return; |
| 96503 | } |
| 96504 | |
| 96505 | // Unescaped newlines are forbidden |
| 96506 | if(c == '\n') { |
| 96507 | parser->error = CJ5_ERROR_INVALID; |
| 96508 | return; |
| 96509 | } |
| 96510 | |
| 96511 | // Escape char |
| 96512 | if(c == '\\') { |
| 96513 | if(parser->pos + 1 >= len) { |
| 96514 | parser->error = CJ5_ERROR_INCOMPLETE; |
| 96515 | return; |
| 96516 | } |
| 96517 | parser->pos++; |
| 96518 | switch(json5[parser->pos]) { |
| 96519 | case '\"': |
| 96520 | case '/': |
| 96521 | case '\\': |
| 96522 | case 'b': |
| 96523 | case 'f': |
| 96524 | case 'r': |
| 96525 | case 'n': |
| 96526 | case 't': |
| 96527 | break; |
| 96528 | case 'u': // The next four characters are an utf8 code |
| 96529 | parser->pos++; |
| 96530 | if(parser->pos + 4 >= len) { |
| 96531 | parser->error = CJ5_ERROR_INVALID; |
| 96532 | return; |
| 96533 | } |
| 96534 | for(unsigned int i = 0; i < 4; i++) { |
| 96535 | // If it isn't a hex character we have an error |
| 96536 | if(!(json5[parser->pos] >= 48 && json5[parser->pos] <= 57) && /* 0-9 */ |
| 96537 | !(json5[parser->pos] >= 65 && json5[parser->pos] <= 70) && /* A-F */ |
| 96538 | !(json5[parser->pos] >= 97 && json5[parser->pos] <= 102)) /* a-f */ |
| 96539 | { |
| 96540 | parser->error = CJ5_ERROR_INVALID; |
| 96541 | return; |
| 96542 | } |
| 96543 | parser->pos++; |
| 96544 | } |
| 96545 | parser->pos--; |
| 96546 | break; |
| 96547 | case '\n': // Escape break line |
| 96548 | parser->line++; |
| 96549 | parser->line_start = parser->pos; |
| 96550 | break; |
| 96551 | default: |
| 96552 | parser->error = CJ5_ERROR_INVALID; |
| 96553 | return; |
| 96554 | } |
| 96555 | } |
| 96556 | } |
| 96557 | |
| 96558 | // The file has ended before the string terminates |
| 96559 | parser->error = CJ5_ERROR_INCOMPLETE; |
| 96560 | } |
| 96561 | |
| 96562 | // parser->pos is advanced a last time in the next iteration of the main |
| 96563 | // parse-loop. So we leave parse-primitive in a state where parse->pos points to |
| 96564 | // the last character of the primitive value (or the quote-character of the |
| 96565 | // string). |
| 96566 | static void |
| 96567 | cj5__parse_primitive(cj5__parser* parser) { |
| 96568 | const char* json5 = parser->json5; |
| 96569 | unsigned int len = parser->len; |
| 96570 | unsigned int start = parser->pos; |
| 96571 | |
| 96572 | // String value |
| 96573 | if(json5[start] == '\"' || |
| 96574 | json5[start] == '\'') { |
| 96575 | cj5__parse_string(parser); |
| 96576 | return; |
| 96577 | } |
| 96578 | |
| 96579 | // Fast comparison of bool, and null. |
| 96580 | // We have to use memcpy here or we can get unaligned accesses |
| 96581 | uint32_t fourcc = 0; |
| 96582 | if(start + 4 < len) |
| 96583 | memcpy(dest: &fourcc, src: &json5[start], n: 4); |
| 96584 | |
| 96585 | cj5_token_type type; |
| 96586 | if(fourcc == CJ5__NULL_FOURCC) { |
| 96587 | type = CJ5_TOKEN_NULL; |
| 96588 | parser->pos += 3; |
| 96589 | } else if(fourcc == CJ5__TRUE_FOURCC) { |
| 96590 | type = CJ5_TOKEN_BOOL; |
| 96591 | parser->pos += 3; |
| 96592 | } else if(fourcc == CJ5__FALSE_FOURCC) { |
| 96593 | // "false" has five characters |
| 96594 | type = CJ5_TOKEN_BOOL; |
| 96595 | if(start + 4 >= len || json5[start+4] != 'e') { |
| 96596 | parser->error = CJ5_ERROR_INVALID; |
| 96597 | return; |
| 96598 | } |
| 96599 | parser->pos += 4; |
| 96600 | } else { |
| 96601 | // Numbers are checked for basic compatibility. |
| 96602 | // But they are fully parsed only in the cj5_get_XXX functions. |
| 96603 | type = CJ5_TOKEN_NUMBER; |
| 96604 | for(; parser->pos < len; parser->pos++) { |
| 96605 | if(!cj5__isnum(json5[parser->pos]) && |
| 96606 | !(json5[parser->pos] == '.') && |
| 96607 | !cj5__islowerchar(json5[parser->pos]) && |
| 96608 | !cj5__isupperchar(json5[parser->pos]) && |
| 96609 | !(json5[parser->pos] == '+') && !(json5[parser->pos] == '-')) { |
| 96610 | break; |
| 96611 | } |
| 96612 | } |
| 96613 | parser->pos--; // Point to the last character that is still inside the |
| 96614 | // primitive value |
| 96615 | } |
| 96616 | |
| 96617 | cj5_token *token = cj5__alloc_token(parser); |
| 96618 | if(token) { |
| 96619 | token->type = type; |
| 96620 | token->start = start; |
| 96621 | token->end = parser->pos; |
| 96622 | token->size = parser->pos - start + 1; |
| 96623 | token->parent_id = parser->curr_tok_idx; |
| 96624 | } |
| 96625 | } |
| 96626 | |
| 96627 | static void |
| 96628 | cj5__parse_key(cj5__parser* parser) { |
| 96629 | const char* json5 = parser->json5; |
| 96630 | unsigned int start = parser->pos; |
| 96631 | cj5_token* token; |
| 96632 | |
| 96633 | // Key is a a normal string |
| 96634 | if(json5[start] == '\"' || json5[start] == '\'') { |
| 96635 | cj5__parse_string(parser); |
| 96636 | return; |
| 96637 | } |
| 96638 | |
| 96639 | // An unquoted key. Must start with a-ZA-Z_$. Can contain numbers later on. |
| 96640 | unsigned int len = parser->len; |
| 96641 | for(; parser->pos < len; parser->pos++) { |
| 96642 | if(cj5__islowerchar(json5[parser->pos]) || |
| 96643 | cj5__isupperchar(json5[parser->pos]) || |
| 96644 | json5[parser->pos] == '_' || json5[parser->pos] == '$') |
| 96645 | continue; |
| 96646 | if(cj5__isnum(json5[parser->pos]) && parser->pos != start) |
| 96647 | continue; |
| 96648 | break; |
| 96649 | } |
| 96650 | |
| 96651 | // An empty key is not allowed |
| 96652 | if(parser->pos <= start) { |
| 96653 | parser->error = CJ5_ERROR_INVALID; |
| 96654 | return; |
| 96655 | } |
| 96656 | |
| 96657 | // Move pos to the last character within the unquoted key |
| 96658 | parser->pos--; |
| 96659 | |
| 96660 | token = cj5__alloc_token(parser); |
| 96661 | if(token) { |
| 96662 | token->type = CJ5_TOKEN_STRING; |
| 96663 | token->start = start; |
| 96664 | token->end = parser->pos; |
| 96665 | token->size = parser->pos - start + 1; |
| 96666 | token->parent_id = parser->curr_tok_idx; |
| 96667 | } |
| 96668 | } |
| 96669 | |
| 96670 | static void |
| 96671 | cj5__skip_comment(cj5__parser* parser) { |
| 96672 | const char* json5 = parser->json5; |
| 96673 | |
| 96674 | // Single-line comment |
| 96675 | if(json5[parser->pos] == '#') { |
| 96676 | skip_line: |
| 96677 | while(parser->pos < parser->len) { |
| 96678 | if(json5[parser->pos] == '\n') { |
| 96679 | parser->pos--; // Reparse the newline in the main parse loop |
| 96680 | return; |
| 96681 | } |
| 96682 | parser->pos++; |
| 96683 | } |
| 96684 | return; |
| 96685 | } |
| 96686 | |
| 96687 | // Comment begins with '/' but not enough space for another character |
| 96688 | if(parser->pos + 1 >= parser->len) { |
| 96689 | parser->error = CJ5_ERROR_INVALID; |
| 96690 | return; |
| 96691 | } |
| 96692 | parser->pos++; |
| 96693 | |
| 96694 | // Comment begins with '//' -> single-line comment |
| 96695 | if(json5[parser->pos] == '/') |
| 96696 | goto skip_line; |
| 96697 | |
| 96698 | // Multi-line comments begin with '/*' and end with '*/' |
| 96699 | if(json5[parser->pos] == '*') { |
| 96700 | parser->pos++; |
| 96701 | for(; parser->pos + 1 < parser->len; parser->pos++) { |
| 96702 | if(json5[parser->pos] == '*' && json5[parser->pos + 1] == '/') { |
| 96703 | parser->pos++; |
| 96704 | return; |
| 96705 | } |
| 96706 | // Remember we passed a newline |
| 96707 | if(json5[parser->pos] == '\n') { |
| 96708 | parser->line++; |
| 96709 | parser->line_start = parser->pos; |
| 96710 | } |
| 96711 | } |
| 96712 | } |
| 96713 | |
| 96714 | // Unknown comment type or the multi-line comment is not terminated |
| 96715 | parser->error = CJ5_ERROR_INCOMPLETE; |
| 96716 | } |
| 96717 | |
| 96718 | cj5_result |
| 96719 | cj5_parse(const char *json5, unsigned int len, |
| 96720 | cj5_token *tokens, unsigned int max_tokens, |
| 96721 | cj5_options *options) { |
| 96722 | cj5_result r; |
| 96723 | cj5__parser parser; |
| 96724 | memset(s: &parser, c: 0x0, n: sizeof(parser)); |
| 96725 | parser.curr_tok_idx = 0; |
| 96726 | parser.json5 = json5; |
| 96727 | parser.len = len; |
| 96728 | parser.tokens = tokens; |
| 96729 | parser.max_tokens = max_tokens; |
| 96730 | |
| 96731 | if(options) |
| 96732 | parser.stop_early = options->stop_early; |
| 96733 | |
| 96734 | unsigned short depth = 0; // Nesting depth zero means "outside the root object" |
| 96735 | char nesting[CJ5_MAX_NESTING]; // Contains either '\0', '{' or '[' for the |
| 96736 | // type of nesting at each depth. '\0' |
| 96737 | // indicates we are out of the root object. |
| 96738 | char next[CJ5_MAX_NESTING]; // Next content to parse: 'k' (key), ':', 'v' |
| 96739 | // (value) or ',' (comma). |
| 96740 | next[0] = 'v'; // The root is a "value" (object, array or primitive). If we |
| 96741 | // detect a colon after the first value then everything is |
| 96742 | // wrapped into a "virtual root object" and the parsing is |
| 96743 | // restarted. |
| 96744 | nesting[0] = 0; // Becomes '{' if there is a virtual root object |
| 96745 | |
| 96746 | cj5_token *token = NULL; // The current token |
| 96747 | |
| 96748 | start_parsing: |
| 96749 | for(; parser.pos < len; parser.pos++) { |
| 96750 | char c = json5[parser.pos]; |
| 96751 | switch(c) { |
| 96752 | case '\n': // Skip newline |
| 96753 | parser.line++; |
| 96754 | parser.line_start = parser.pos; |
| 96755 | break; |
| 96756 | |
| 96757 | case '\r': // Skip whitespace |
| 96758 | case '\t': |
| 96759 | case ' ': |
| 96760 | break; |
| 96761 | |
| 96762 | case '#': // Skip comment |
| 96763 | case '/': |
| 96764 | cj5__skip_comment(parser: &parser); |
| 96765 | if(parser.error != CJ5_ERROR_NONE && |
| 96766 | parser.error != CJ5_ERROR_OVERFLOW) |
| 96767 | goto finish; |
| 96768 | break; |
| 96769 | |
| 96770 | case '{': // Open an object or array |
| 96771 | case '[': |
| 96772 | // Check the nesting depth |
| 96773 | if(depth + 1 >= CJ5_MAX_NESTING) { |
| 96774 | parser.error = CJ5_ERROR_INVALID; |
| 96775 | goto finish; |
| 96776 | } |
| 96777 | |
| 96778 | // Correct next? |
| 96779 | if(next[depth] != 'v') { |
| 96780 | parser.error = CJ5_ERROR_INVALID; |
| 96781 | goto finish; |
| 96782 | } |
| 96783 | |
| 96784 | depth++; // Increase the nesting depth |
| 96785 | nesting[depth] = c; // Set the nesting type |
| 96786 | next[depth] = (c == '{') ? 'k' : 'v'; // next is either a key or a value |
| 96787 | |
| 96788 | // Create a token for the object or array |
| 96789 | token = cj5__alloc_token(parser: &parser); |
| 96790 | if(token) { |
| 96791 | token->parent_id = parser.curr_tok_idx; |
| 96792 | token->type = (c == '{') ? CJ5_TOKEN_OBJECT : CJ5_TOKEN_ARRAY; |
| 96793 | token->start = parser.pos; |
| 96794 | token->size = 0; |
| 96795 | parser.curr_tok_idx = parser.token_count - 1; // The new curr_tok_idx |
| 96796 | // is for this token |
| 96797 | } |
| 96798 | break; |
| 96799 | |
| 96800 | case '}': // Close an object or array |
| 96801 | case ']': |
| 96802 | // Check the nesting depth. Note that a "virtual root object" at |
| 96803 | // depth zero must not be closed. |
| 96804 | if(depth == 0) { |
| 96805 | parser.error = CJ5_ERROR_INVALID; |
| 96806 | goto finish; |
| 96807 | } |
| 96808 | |
| 96809 | // Check and adjust the nesting. Note that ']' - '[' == 2 and '}' - |
| 96810 | // '{' == 2. Arrays can always be closed. Objects can only close |
| 96811 | // when a key or a comma is expected. |
| 96812 | if(c - nesting[depth] != 2 || |
| 96813 | (c == '}' && next[depth] != 'k' && next[depth] != ',')) { |
| 96814 | parser.error = CJ5_ERROR_INVALID; |
| 96815 | goto finish; |
| 96816 | } |
| 96817 | |
| 96818 | if(token) { |
| 96819 | // Finalize the current token |
| 96820 | token->end = parser.pos; |
| 96821 | |
| 96822 | // Move to the parent and increase the parent size. Omit this |
| 96823 | // when we leave the root (parent the same as the current |
| 96824 | // token). |
| 96825 | if(parser.curr_tok_idx != token->parent_id) { |
| 96826 | parser.curr_tok_idx = token->parent_id; |
| 96827 | token = &tokens[token->parent_id]; |
| 96828 | token->size++; |
| 96829 | } |
| 96830 | } |
| 96831 | |
| 96832 | // Step one level up |
| 96833 | depth--; |
| 96834 | next[depth] = (depth == 0) ? 0 : ','; // zero if we step out the root |
| 96835 | // object. then we do not look for |
| 96836 | // another element. |
| 96837 | |
| 96838 | // The first element was successfully parsed. Stop early or try to |
| 96839 | // parse the full input string? |
| 96840 | if(depth == 0 && parser.stop_early) |
| 96841 | goto finish; |
| 96842 | |
| 96843 | break; |
| 96844 | |
| 96845 | case ':': // Colon (between key and value) |
| 96846 | if(next[depth] != ':') { |
| 96847 | parser.error = CJ5_ERROR_INVALID; |
| 96848 | goto finish; |
| 96849 | } |
| 96850 | next[depth] = 'v'; |
| 96851 | break; |
| 96852 | |
| 96853 | case ',': // Comma |
| 96854 | if(next[depth] != ',') { |
| 96855 | parser.error = CJ5_ERROR_INVALID; |
| 96856 | goto finish; |
| 96857 | } |
| 96858 | next[depth] = (nesting[depth] == '{') ? 'k' : 'v'; |
| 96859 | break; |
| 96860 | |
| 96861 | default: // Value or key |
| 96862 | if(next[depth] == 'v') { |
| 96863 | cj5__parse_primitive(parser: &parser); // Parse primitive value |
| 96864 | if(nesting[depth] != 0) { |
| 96865 | // Parent is object or array |
| 96866 | if(token) |
| 96867 | token->size++; |
| 96868 | next[depth] = ','; |
| 96869 | } else { |
| 96870 | // The current value was the root element. Don't look for |
| 96871 | // any next element. |
| 96872 | next[depth] = 0; |
| 96873 | |
| 96874 | // The first element was successfully parsed. Stop early or try to |
| 96875 | // parse the full input string? |
| 96876 | if(parser.stop_early) |
| 96877 | goto finish; |
| 96878 | } |
| 96879 | } else if(next[depth] == 'k') { |
| 96880 | cj5__parse_key(parser: &parser); |
| 96881 | if(token) |
| 96882 | token->size++; // Keys count towards the length |
| 96883 | next[depth] = ':'; |
| 96884 | } else { |
| 96885 | parser.error = CJ5_ERROR_INVALID; |
| 96886 | } |
| 96887 | |
| 96888 | if(parser.error && parser.error != CJ5_ERROR_OVERFLOW) |
| 96889 | goto finish; |
| 96890 | |
| 96891 | break; |
| 96892 | } |
| 96893 | } |
| 96894 | |
| 96895 | // Are we back to the initial nesting depth? |
| 96896 | if(depth != 0) { |
| 96897 | parser.error = CJ5_ERROR_INCOMPLETE; |
| 96898 | goto finish; |
| 96899 | } |
| 96900 | |
| 96901 | // Close the virtual root object if there is one |
| 96902 | if(nesting[0] == '{' && parser.error != CJ5_ERROR_OVERFLOW) { |
| 96903 | // Check the we end after a complete key-value pair (or dangling comma) |
| 96904 | if(next[0] != 'k' && next[0] != ',') |
| 96905 | parser.error = CJ5_ERROR_INVALID; |
| 96906 | tokens[0].end = parser.pos - 1; |
| 96907 | } |
| 96908 | |
| 96909 | finish: |
| 96910 | // If parsing failed at the initial nesting depth, create a virtual root object |
| 96911 | // and restart parsing. |
| 96912 | if(parser.error != CJ5_ERROR_NONE && |
| 96913 | parser.error != CJ5_ERROR_OVERFLOW && |
| 96914 | depth == 0 && nesting[0] != '{') { |
| 96915 | parser.token_count = 0; |
| 96916 | token = cj5__alloc_token(parser: &parser); |
| 96917 | if(token) { |
| 96918 | token->parent_id = 0; |
| 96919 | token->type = CJ5_TOKEN_OBJECT; |
| 96920 | token->start = 0; |
| 96921 | token->size = 0; |
| 96922 | |
| 96923 | nesting[0] = '{'; |
| 96924 | next[0] = 'k'; |
| 96925 | |
| 96926 | parser.curr_tok_idx = 0; |
| 96927 | parser.pos = 0; |
| 96928 | parser.error = CJ5_ERROR_NONE; |
| 96929 | goto start_parsing; |
| 96930 | } |
| 96931 | } |
| 96932 | |
| 96933 | memset(s: &r, c: 0x0, n: sizeof(r)); |
| 96934 | r.error = parser.error; |
| 96935 | r.error_line = parser.line; |
| 96936 | r.error_col = parser.pos - parser.line_start; |
| 96937 | r.num_tokens = parser.token_count; // How many tokens (would) have been |
| 96938 | // consumed by the parser? |
| 96939 | |
| 96940 | // Not a single token was parsed -> return an error |
| 96941 | if(r.num_tokens == 0) |
| 96942 | r.error = CJ5_ERROR_INCOMPLETE; |
| 96943 | |
| 96944 | // Set the tokens and original string only if successfully parsed |
| 96945 | if(r.error == CJ5_ERROR_NONE) { |
| 96946 | r.tokens = tokens; |
| 96947 | r.json5 = json5; |
| 96948 | } |
| 96949 | |
| 96950 | return r; |
| 96951 | } |
| 96952 | |
| 96953 | cj5_error_code |
| 96954 | cj5_get_bool(const cj5_result *r, unsigned int tok_index, bool *out) { |
| 96955 | const cj5_token *token = &r->tokens[tok_index]; |
| 96956 | if(token->type != CJ5_TOKEN_BOOL) |
| 96957 | return CJ5_ERROR_INVALID; |
| 96958 | *out = (r->json5[token->start] == 't'); |
| 96959 | return CJ5_ERROR_NONE; |
| 96960 | } |
| 96961 | |
| 96962 | cj5_error_code |
| 96963 | cj5_get_float(const cj5_result *r, unsigned int tok_index, double *out) { |
| 96964 | const cj5_token *token = &r->tokens[tok_index]; |
| 96965 | if(token->type != CJ5_TOKEN_NUMBER) |
| 96966 | return CJ5_ERROR_INVALID; |
| 96967 | |
| 96968 | const char *tokstr = &r->json5[token->start]; |
| 96969 | size_t toksize = token->end - token->start + 1; |
| 96970 | if(toksize == 0) |
| 96971 | return CJ5_ERROR_INVALID; |
| 96972 | |
| 96973 | // Skip prefixed +/- |
| 96974 | bool neg = false; |
| 96975 | if(tokstr[0] == '+' || tokstr[0] == '-') { |
| 96976 | neg = (tokstr[0] == '-'); |
| 96977 | tokstr++; |
| 96978 | toksize--; |
| 96979 | } |
| 96980 | |
| 96981 | // Detect prefixed inf/nan |
| 96982 | if(strncmp(s1: tokstr, s2: "Infinity", n: toksize) == 0) { |
| 96983 | *out = neg ? -INFINITY : INFINITY; |
| 96984 | return CJ5_ERROR_NONE; |
| 96985 | } else if(strncmp(s1: tokstr, s2: "NaN", n: toksize) == 0) { |
| 96986 | *out = NAN; |
| 96987 | return CJ5_ERROR_NONE; |
| 96988 | } |
| 96989 | |
| 96990 | // reset the +/- detection and parse |
| 96991 | tokstr = &r->json5[token->start]; |
| 96992 | toksize = token->end - token->start + 1; |
| 96993 | size_t parsed = parseDouble(str: tokstr, size: toksize, result: out); |
| 96994 | |
| 96995 | // There must only be whitespace between the end of the parsed number and |
| 96996 | // the end of the token |
| 96997 | for(size_t i = parsed; i < toksize; i++) { |
| 96998 | if(tokstr[i] != ' ' && tokstr[i] -'\t' >= 5) |
| 96999 | return CJ5_ERROR_INVALID; |
| 97000 | } |
| 97001 | |
| 97002 | return (parsed != 0) ? CJ5_ERROR_NONE : CJ5_ERROR_INVALID; |
| 97003 | } |
| 97004 | |
| 97005 | cj5_error_code |
| 97006 | cj5_get_int(const cj5_result *r, unsigned int tok_index, |
| 97007 | int64_t *out) { |
| 97008 | const cj5_token *token = &r->tokens[tok_index]; |
| 97009 | if(token->type != CJ5_TOKEN_NUMBER) |
| 97010 | return CJ5_ERROR_INVALID; |
| 97011 | size_t parsed = parseInt64(str: &r->json5[token->start], size: token->size, result: out); |
| 97012 | return (parsed != 0) ? CJ5_ERROR_NONE : CJ5_ERROR_INVALID; |
| 97013 | } |
| 97014 | |
| 97015 | cj5_error_code |
| 97016 | cj5_get_uint(const cj5_result *r, unsigned int tok_index, |
| 97017 | uint64_t *out) { |
| 97018 | const cj5_token *token = &r->tokens[tok_index]; |
| 97019 | if(token->type != CJ5_TOKEN_NUMBER) |
| 97020 | return CJ5_ERROR_INVALID; |
| 97021 | size_t parsed = parseUInt64(str: &r->json5[token->start], size: token->size, result: out); |
| 97022 | return (parsed != 0) ? CJ5_ERROR_NONE : CJ5_ERROR_INVALID; |
| 97023 | } |
| 97024 | |
| 97025 | static const uint32_t SURROGATE_OFFSET = 0x10000u - (0xD800u << 10) - 0xDC00; |
| 97026 | |
| 97027 | static cj5_error_code |
| 97028 | parse_codepoint(const char *pos, uint32_t *out_utf) { |
| 97029 | uint32_t utf = 0; |
| 97030 | for(unsigned int i = 0; i < 4; i++) { |
| 97031 | char byte = pos[i]; |
| 97032 | if(cj5__isnum(byte)) { |
| 97033 | byte = (char)(byte - '0'); |
| 97034 | } else if(cj5__isrange(ch: byte, from: 'a', to: 'f')) { |
| 97035 | byte = (char)(byte - ('a' - 10)); |
| 97036 | } else if(cj5__isrange(ch: byte, from: 'A', to: 'F')) { |
| 97037 | byte = (char)(byte - ('A' - 10)); |
| 97038 | } else { |
| 97039 | return CJ5_ERROR_INVALID; |
| 97040 | } |
| 97041 | utf = (utf << 4) | ((uint8_t)byte & 0xF); |
| 97042 | } |
| 97043 | *out_utf = utf; |
| 97044 | return CJ5_ERROR_NONE; |
| 97045 | } |
| 97046 | |
| 97047 | cj5_error_code |
| 97048 | cj5_get_str(const cj5_result *r, unsigned int tok_index, |
| 97049 | char *buf, unsigned int *buflen) { |
| 97050 | const cj5_token *token = &r->tokens[tok_index]; |
| 97051 | if(token->type != CJ5_TOKEN_STRING) |
| 97052 | return CJ5_ERROR_INVALID; |
| 97053 | |
| 97054 | const char *pos = &r->json5[token->start]; |
| 97055 | const char *end = &r->json5[token->end + 1]; |
| 97056 | unsigned int outpos = 0; |
| 97057 | for(; pos < end; pos++) { |
| 97058 | uint8_t c = (uint8_t)*pos; |
| 97059 | |
| 97060 | // Process an escape character |
| 97061 | if(c == '\\') { |
| 97062 | if(pos + 1 >= end) |
| 97063 | return CJ5_ERROR_INCOMPLETE; |
| 97064 | pos++; |
| 97065 | c = (uint8_t)*pos; |
| 97066 | switch(c) { |
| 97067 | case '\"': buf[outpos++] = '\"'; break; |
| 97068 | case '\\': buf[outpos++] = '\\'; break; |
| 97069 | case '\n': buf[outpos++] = '\n'; break; // escape newline |
| 97070 | case '/': buf[outpos++] = '/'; break; |
| 97071 | case 'b': buf[outpos++] = '\b'; break; |
| 97072 | case 'f': buf[outpos++] = '\f'; break; |
| 97073 | case 'r': buf[outpos++] = '\r'; break; |
| 97074 | case 'n': buf[outpos++] = '\n'; break; |
| 97075 | case 't': buf[outpos++] = '\t'; break; |
| 97076 | case 'u': { |
| 97077 | // Parse the unicode code point |
| 97078 | if(pos + 4 >= end) |
| 97079 | return CJ5_ERROR_INCOMPLETE; |
| 97080 | pos++; |
| 97081 | uint32_t utf; |
| 97082 | cj5_error_code err = parse_codepoint(pos, out_utf: &utf); |
| 97083 | if(err != CJ5_ERROR_NONE) |
| 97084 | return err; |
| 97085 | pos += 3; |
| 97086 | |
| 97087 | if(0xD800 <= utf && utf <= 0xDBFF) { |
| 97088 | // Parse a surrogate pair |
| 97089 | if(pos + 6 >= end) |
| 97090 | return CJ5_ERROR_INVALID; |
| 97091 | if(pos[1] != '\\' && pos[3] != 'u') |
| 97092 | return CJ5_ERROR_INVALID; |
| 97093 | pos += 3; |
| 97094 | uint32_t trail; |
| 97095 | err = parse_codepoint(pos, out_utf: &trail); |
| 97096 | if(err != CJ5_ERROR_NONE) |
| 97097 | return err; |
| 97098 | pos += 3; |
| 97099 | utf = (utf << 10) + trail + SURROGATE_OFFSET; |
| 97100 | } else if(0xDC00 <= utf && utf <= 0xDFFF) { |
| 97101 | // Invalid Unicode '\\u%04X' |
| 97102 | return CJ5_ERROR_INVALID; |
| 97103 | } |
| 97104 | |
| 97105 | // Write the utf8 bytes of the code point |
| 97106 | if(utf <= 0x7F) { // Plain ASCII |
| 97107 | buf[outpos++] = (char)utf; |
| 97108 | } else if(utf <= 0x07FF) { // 2-byte unicode |
| 97109 | buf[outpos++] = (char)(((utf >> 6) & 0x1F) | 0xC0); |
| 97110 | buf[outpos++] = (char)(((utf >> 0) & 0x3F) | 0x80); |
| 97111 | } else if(utf <= 0xFFFF) { // 3-byte unicode |
| 97112 | buf[outpos++] = (char)(((utf >> 12) & 0x0F) | 0xE0); |
| 97113 | buf[outpos++] = (char)(((utf >> 6) & 0x3F) | 0x80); |
| 97114 | buf[outpos++] = (char)(((utf >> 0) & 0x3F) | 0x80); |
| 97115 | } else if(utf <= 0x10FFFF) { // 4-byte unicode |
| 97116 | buf[outpos++] = (char)(((utf >> 18) & 0x07) | 0xF0); |
| 97117 | buf[outpos++] = (char)(((utf >> 12) & 0x3F) | 0x80); |
| 97118 | buf[outpos++] = (char)(((utf >> 6) & 0x3F) | 0x80); |
| 97119 | buf[outpos++] = (char)(((utf >> 0) & 0x3F) | 0x80); |
| 97120 | } else { |
| 97121 | return CJ5_ERROR_INVALID; // Not a utf8 string |
| 97122 | } |
| 97123 | break; |
| 97124 | } |
| 97125 | default: |
| 97126 | return CJ5_ERROR_INVALID; |
| 97127 | } |
| 97128 | continue; |
| 97129 | } |
| 97130 | |
| 97131 | // Unprintable ascii characters must be escaped. JSON5 allows nested |
| 97132 | // quotes if the quote character is not the same as the surrounding |
| 97133 | // quote character, e.g. 'this is my "quote"'. This logic is in the |
| 97134 | // token parsing code and not in this "string extraction" method. |
| 97135 | if(c < ' ' || c == 127) |
| 97136 | return CJ5_ERROR_INVALID; |
| 97137 | |
| 97138 | // Ascii character or utf8 byte |
| 97139 | buf[outpos++] = (char)c; |
| 97140 | } |
| 97141 | |
| 97142 | // Terminate with \0 |
| 97143 | buf[outpos] = 0; |
| 97144 | |
| 97145 | // Set the output length |
| 97146 | if(buflen) |
| 97147 | *buflen = outpos; |
| 97148 | return CJ5_ERROR_NONE; |
| 97149 | } |
| 97150 | |
| 97151 | void |
| 97152 | cj5_skip(const cj5_result *r, unsigned int *tok_index) { |
| 97153 | unsigned int idx = *tok_index; |
| 97154 | unsigned int end = r->tokens[idx].end; |
| 97155 | do { idx++; } while(idx < r->num_tokens && |
| 97156 | r->tokens[idx].start < end); |
| 97157 | *tok_index = idx; |
| 97158 | } |
| 97159 | |
| 97160 | cj5_error_code |
| 97161 | cj5_find(const cj5_result *r, unsigned int *tok_index, |
| 97162 | const char *key) { |
| 97163 | // It has to be an object |
| 97164 | unsigned int idx = *tok_index; |
| 97165 | if(r->tokens[idx].type != CJ5_TOKEN_OBJECT) |
| 97166 | return CJ5_ERROR_INVALID; |
| 97167 | unsigned int size = r->tokens[idx].size; |
| 97168 | |
| 97169 | // Skip to the first key |
| 97170 | idx++; |
| 97171 | |
| 97172 | // Size is number of keys + number of values |
| 97173 | for(unsigned int i = 0; i < size; i += 2) { |
| 97174 | // Key has to be a string |
| 97175 | if(r->tokens[idx].type != CJ5_TOKEN_STRING) |
| 97176 | return CJ5_ERROR_INVALID; |
| 97177 | |
| 97178 | // Return the index to the value if the key matches |
| 97179 | const char *keystart = &r->json5[r->tokens[idx].start]; |
| 97180 | size_t keysize = r->tokens[idx].end - r->tokens[idx].start + 1; |
| 97181 | if(strncmp(s1: key, s2: keystart, n: keysize) == 0) { |
| 97182 | *tok_index = idx + 1; |
| 97183 | return CJ5_ERROR_NONE; |
| 97184 | } |
| 97185 | |
| 97186 | // Skip over the value |
| 97187 | idx++; |
| 97188 | cj5_skip(r, tok_index: &idx); |
| 97189 | } |
| 97190 | return CJ5_ERROR_NOTFOUND; |
| 97191 | } |
| 97192 | |
| 97193 | /**** amalgamated original file "/deps/parse_num.c" ****/ |
| 97194 | |
| 97195 | /* Originally released by the musl project (http://www.musl-libc.org/) under the |
| 97196 | * MIT license. Taken and adapted from the file src/stdlib/atoi.c |
| 97197 | * |
| 97198 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 97199 | * of this software and associated documentation files (the "Software"), to deal |
| 97200 | * in the Software without restriction, including without limitation the rights |
| 97201 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 97202 | * copies of the Software, and to permit persons to whom the Software is |
| 97203 | * furnished to do so, subject to the following conditions: |
| 97204 | * |
| 97205 | * The above copyright notice and this permission notice shall be included in |
| 97206 | * all copies or substantial portions of the Software. |
| 97207 | * |
| 97208 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 97209 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 97210 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 97211 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 97212 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 97213 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 97214 | * THE SOFTWARE. |
| 97215 | */ |
| 97216 | |
| 97217 | |
| 97218 | #include <string.h> |
| 97219 | #include <stdlib.h> |
| 97220 | #include <errno.h> |
| 97221 | |
| 97222 | size_t |
| 97223 | parseUInt64(const char *str, size_t size, uint64_t *result) { |
| 97224 | size_t i = 0; |
| 97225 | uint64_t n = 0, prev = 0; |
| 97226 | |
| 97227 | /* Hex */ |
| 97228 | if(size > 2 && str[0] == '0' && (str[1] | 32) == 'x') { |
| 97229 | i = 2; |
| 97230 | for(; i < size; i++) { |
| 97231 | uint8_t c = (uint8_t)str[i] | 32; |
| 97232 | if(c >= '0' && c <= '9') |
| 97233 | c = (uint8_t)(c - '0'); |
| 97234 | else if(c >= 'a' && c <='f') |
| 97235 | c = (uint8_t)(c - 'a' + 10); |
| 97236 | else if(c >= 'A' && c <='F') |
| 97237 | c = (uint8_t)(c - 'A' + 10); |
| 97238 | else |
| 97239 | break; |
| 97240 | n = (n << 4) | (c & 0xF); |
| 97241 | if(n < prev) /* Check for overflow */ |
| 97242 | return 0; |
| 97243 | prev = n; |
| 97244 | } |
| 97245 | *result = n; |
| 97246 | return (i > 2) ? i : 0; /* 2 -> No digit was parsed */ |
| 97247 | } |
| 97248 | |
| 97249 | /* Decimal */ |
| 97250 | for(; i < size; i++) { |
| 97251 | if(str[i] < '0' || str[i] > '9') |
| 97252 | break; |
| 97253 | /* Fast multiplication: n*10 == (n*8) + (n*2) */ |
| 97254 | n = (n << 3) + (n << 1) + (uint8_t)(str[i] - '0'); |
| 97255 | if(n < prev) /* Check for overflow */ |
| 97256 | return 0; |
| 97257 | prev = n; |
| 97258 | } |
| 97259 | *result = n; |
| 97260 | return i; |
| 97261 | } |
| 97262 | |
| 97263 | size_t |
| 97264 | parseInt64(const char *str, size_t size, int64_t *result) { |
| 97265 | /* Negative value? */ |
| 97266 | size_t i = 0; |
| 97267 | bool neg = false; |
| 97268 | if(*str == '-' || *str == '+') { |
| 97269 | neg = (*str == '-'); |
| 97270 | i++; |
| 97271 | } |
| 97272 | |
| 97273 | /* Parse as unsigned */ |
| 97274 | uint64_t n = 0; |
| 97275 | size_t len = parseUInt64(str: &str[i], size: size - i, result: &n); |
| 97276 | if(len == 0) |
| 97277 | return 0; |
| 97278 | |
| 97279 | /* Check for overflow, adjust and return */ |
| 97280 | if(!neg) { |
| 97281 | if(n > 9223372036854775807UL) |
| 97282 | return 0; |
| 97283 | *result = (int64_t)n; |
| 97284 | } else { |
| 97285 | if(n > 9223372036854775808UL) |
| 97286 | return 0; |
| 97287 | *result = -(int64_t)n; |
| 97288 | } |
| 97289 | return len + i; |
| 97290 | } |
| 97291 | |
| 97292 | size_t parseDouble(const char *str, size_t size, double *result) { |
| 97293 | char buf[2000]; |
| 97294 | if(size >= 2000) |
| 97295 | return 0; |
| 97296 | memcpy(dest: buf, src: str, n: size); |
| 97297 | buf[size] = 0; |
| 97298 | errno = 0; |
| 97299 | char *endptr; |
| 97300 | *result = strtod(nptr: str, endptr: &endptr); |
| 97301 | if(errno != 0 && errno != ERANGE) |
| 97302 | return 0; |
| 97303 | return (uintptr_t)endptr - (uintptr_t)str; |
| 97304 | } |
| 97305 | |
| 97306 | /**** amalgamated original file "/src/ua_types_encoding_json.c" ****/ |
| 97307 | |
| 97308 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 97309 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 97310 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 97311 | * |
| 97312 | * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 97313 | * Copyright 2018 (c) Fraunhofer IOSB (Author: Lukas Meling) |
| 97314 | */ |
| 97315 | |
| 97316 | |
| 97317 | #ifdef UA_ENABLE_JSON_ENCODING |
| 97318 | |
| 97319 | |
| 97320 | #include <float.h> |
| 97321 | #include <math.h> |
| 97322 | |
| 97323 | |
| 97324 | #ifndef UA_ENABLE_PARSING |
| 97325 | #error UA_ENABLE_PARSING required for JSON encoding |
| 97326 | #endif |
| 97327 | |
| 97328 | #ifndef UA_ENABLE_TYPEDESCRIPTION |
| 97329 | #error UA_ENABLE_TYPEDESCRIPTION required for JSON encoding |
| 97330 | #endif |
| 97331 | |
| 97332 | /* vs2008 does not have INFINITY and NAN defined */ |
| 97333 | #ifndef INFINITY |
| 97334 | # define INFINITY ((UA_Double)(DBL_MAX+DBL_MAX)) |
| 97335 | #endif |
| 97336 | #ifndef NAN |
| 97337 | # define NAN ((UA_Double)(INFINITY-INFINITY)) |
| 97338 | #endif |
| 97339 | |
| 97340 | #if defined(_MSC_VER) |
| 97341 | # pragma warning(disable: 4756) |
| 97342 | # pragma warning(disable: 4056) |
| 97343 | #endif |
| 97344 | |
| 97345 | /* Have some slack at the end. E.g. for negative and very long years. */ |
| 97346 | #define UA_JSON_DATETIME_LENGTH 40 |
| 97347 | |
| 97348 | /************/ |
| 97349 | /* Encoding */ |
| 97350 | /************/ |
| 97351 | |
| 97352 | #define ENCODE_JSON(TYPE) static status \ |
| 97353 | TYPE##_encodeJson(CtxJson *ctx, const UA_##TYPE *src, const UA_DataType *type) |
| 97354 | |
| 97355 | #define ENCODE_DIRECT_JSON(SRC, TYPE) \ |
| 97356 | TYPE##_encodeJson(ctx, (const UA_##TYPE*)SRC, NULL) |
| 97357 | |
| 97358 | static status UA_FUNC_ATTR_WARN_UNUSED_RESULT |
| 97359 | writeChar(CtxJson *ctx, char c) { |
| 97360 | if(ctx->pos >= ctx->end) |
| 97361 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97362 | if(!ctx->calcOnly) |
| 97363 | *ctx->pos = (UA_Byte)c; |
| 97364 | ctx->pos++; |
| 97365 | return UA_STATUSCODE_GOOD; |
| 97366 | } |
| 97367 | |
| 97368 | static status UA_FUNC_ATTR_WARN_UNUSED_RESULT |
| 97369 | writeChars(CtxJson *ctx, const char *c, size_t len) { |
| 97370 | if(ctx->pos + len > ctx->end) |
| 97371 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97372 | if(!ctx->calcOnly) |
| 97373 | memcpy(dest: ctx->pos, src: c, n: len); |
| 97374 | ctx->pos += len; |
| 97375 | return UA_STATUSCODE_GOOD; |
| 97376 | } |
| 97377 | |
| 97378 | #define WRITE_JSON_ELEMENT(ELEM) \ |
| 97379 | UA_FUNC_ATTR_WARN_UNUSED_RESULT status \ |
| 97380 | writeJson##ELEM(CtxJson *ctx) |
| 97381 | |
| 97382 | static WRITE_JSON_ELEMENT(Quote) { |
| 97383 | return writeChar(ctx, c: '\"'); |
| 97384 | } |
| 97385 | |
| 97386 | UA_StatusCode |
| 97387 | writeJsonBeforeElement(CtxJson *ctx, UA_Boolean distinct) { |
| 97388 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 97389 | /* Comma if needed */ |
| 97390 | if(ctx->commaNeeded[ctx->depth]) |
| 97391 | res |= writeChar(ctx, c: ','); |
| 97392 | if(ctx->prettyPrint) { |
| 97393 | if(distinct) { |
| 97394 | /* Newline and indent if needed */ |
| 97395 | res |= writeChar(ctx, c: '\n'); |
| 97396 | for(size_t i = 0; i < ctx->depth; i++) |
| 97397 | res |= writeChar(ctx, c: '\t'); |
| 97398 | } else if(ctx->commaNeeded[ctx->depth]) { |
| 97399 | /* Space after the comma if no newline */ |
| 97400 | res |= writeChar(ctx, c: ' '); |
| 97401 | } |
| 97402 | } |
| 97403 | return res; |
| 97404 | } |
| 97405 | |
| 97406 | WRITE_JSON_ELEMENT(ObjStart) { |
| 97407 | /* increase depth, save: before first key-value no comma needed. */ |
| 97408 | if(ctx->depth >= UA_JSON_ENCODING_MAX_RECURSION - 1) |
| 97409 | return UA_STATUSCODE_BADENCODINGERROR; |
| 97410 | ctx->depth++; |
| 97411 | ctx->commaNeeded[ctx->depth] = false; |
| 97412 | return writeChar(ctx, c: '{'); |
| 97413 | } |
| 97414 | |
| 97415 | WRITE_JSON_ELEMENT(ObjEnd) { |
| 97416 | if(ctx->depth == 0) |
| 97417 | return UA_STATUSCODE_BADENCODINGERROR; |
| 97418 | |
| 97419 | UA_Boolean have_elem = ctx->commaNeeded[ctx->depth]; |
| 97420 | ctx->depth--; |
| 97421 | ctx->commaNeeded[ctx->depth] = true; |
| 97422 | |
| 97423 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 97424 | if(ctx->prettyPrint && have_elem) { |
| 97425 | res |= writeChar(ctx, c: '\n'); |
| 97426 | for(size_t i = 0; i < ctx->depth; i++) |
| 97427 | res |= writeChar(ctx, c: '\t'); |
| 97428 | } |
| 97429 | return res | writeChar(ctx, c: '}'); |
| 97430 | } |
| 97431 | |
| 97432 | WRITE_JSON_ELEMENT(ArrStart) { |
| 97433 | /* increase depth, save: before first array entry no comma needed. */ |
| 97434 | if(ctx->depth >= UA_JSON_ENCODING_MAX_RECURSION - 1) |
| 97435 | return UA_STATUSCODE_BADENCODINGERROR; |
| 97436 | ctx->depth++; |
| 97437 | ctx->commaNeeded[ctx->depth] = false; |
| 97438 | return writeChar(ctx, c: '['); |
| 97439 | } |
| 97440 | |
| 97441 | WRITE_JSON_ELEMENT(ArrEnd) { |
| 97442 | if(ctx->depth == 0) |
| 97443 | return UA_STATUSCODE_BADENCODINGERROR; |
| 97444 | UA_Boolean have_elem = ctx->commaNeeded[ctx->depth]; |
| 97445 | ctx->depth--; |
| 97446 | ctx->commaNeeded[ctx->depth] = true; |
| 97447 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 97448 | if(ctx->prettyPrint && have_elem) { |
| 97449 | res |= writeChar(ctx, c: '\n'); |
| 97450 | for(size_t i = 0; i < ctx->depth; i++) |
| 97451 | res |= writeChar(ctx, c: '\t'); |
| 97452 | } |
| 97453 | return res | writeChar(ctx, c: ']'); |
| 97454 | } |
| 97455 | |
| 97456 | status |
| 97457 | writeJsonArrElm(CtxJson *ctx, const void *value, |
| 97458 | const UA_DataType *type) { |
| 97459 | UA_Boolean distinct = (type->typeKind > UA_DATATYPEKIND_DOUBLE); |
| 97460 | status ret = writeJsonBeforeElement(ctx, distinct); |
| 97461 | ctx->commaNeeded[ctx->depth] = true; |
| 97462 | return ret | encodeJsonJumpTable[type->typeKind](ctx, value, type); |
| 97463 | } |
| 97464 | |
| 97465 | status |
| 97466 | writeJsonObjElm(CtxJson *ctx, const char *key, |
| 97467 | const void *value, const UA_DataType *type) { |
| 97468 | return writeJsonKey(ctx, key) | encodeJsonJumpTable[type->typeKind](ctx, value, type); |
| 97469 | } |
| 97470 | |
| 97471 | /* Keys for JSON */ |
| 97472 | |
| 97473 | /* LocalizedText */ |
| 97474 | static const char* UA_JSONKEY_LOCALE = "Locale"; |
| 97475 | static const char* UA_JSONKEY_TEXT = "Text"; |
| 97476 | |
| 97477 | /* QualifiedName */ |
| 97478 | static const char* UA_JSONKEY_NAME = "Name"; |
| 97479 | static const char* UA_JSONKEY_URI = "Uri"; |
| 97480 | |
| 97481 | /* NodeId */ |
| 97482 | static const char* UA_JSONKEY_ID = "Id"; |
| 97483 | static const char* UA_JSONKEY_IDTYPE = "IdType"; |
| 97484 | static const char* UA_JSONKEY_NAMESPACE = "Namespace"; |
| 97485 | |
| 97486 | /* ExpandedNodeId */ |
| 97487 | static const char* UA_JSONKEY_SERVERURI = "ServerUri"; |
| 97488 | |
| 97489 | /* Variant */ |
| 97490 | static const char* UA_JSONKEY_TYPE = "Type"; |
| 97491 | static const char* UA_JSONKEY_BODY = "Body"; |
| 97492 | static const char* UA_JSONKEY_DIMENSION = "Dimension"; |
| 97493 | |
| 97494 | /* DataValue */ |
| 97495 | static const char* UA_JSONKEY_VALUE = "Value"; |
| 97496 | static const char* UA_JSONKEY_STATUS = "Status"; |
| 97497 | static const char* UA_JSONKEY_SOURCETIMESTAMP = "SourceTimestamp"; |
| 97498 | static const char* UA_JSONKEY_SOURCEPICOSECONDS = "SourcePicoseconds"; |
| 97499 | static const char* UA_JSONKEY_SERVERTIMESTAMP = "ServerTimestamp"; |
| 97500 | static const char* UA_JSONKEY_SERVERPICOSECONDS = "ServerPicoseconds"; |
| 97501 | |
| 97502 | /* ExtensionObject */ |
| 97503 | static const char* UA_JSONKEY_ENCODING = "Encoding"; |
| 97504 | static const char* UA_JSONKEY_TYPEID = "TypeId"; |
| 97505 | |
| 97506 | /* StatusCode */ |
| 97507 | static const char* UA_JSONKEY_CODE = "Code"; |
| 97508 | static const char* UA_JSONKEY_SYMBOL = "Symbol"; |
| 97509 | |
| 97510 | /* DiagnosticInfo */ |
| 97511 | static const char* UA_JSONKEY_SYMBOLICID = "SymbolicId"; |
| 97512 | static const char* UA_JSONKEY_NAMESPACEURI = "NamespaceUri"; |
| 97513 | static const char* UA_JSONKEY_LOCALIZEDTEXT = "LocalizedText"; |
| 97514 | static const char* UA_JSONKEY_ADDITIONALINFO = "AdditionalInfo"; |
| 97515 | static const char* UA_JSONKEY_INNERSTATUSCODE = "InnerStatusCode"; |
| 97516 | static const char* UA_JSONKEY_INNERDIAGNOSTICINFO = "InnerDiagnosticInfo"; |
| 97517 | |
| 97518 | /* Writes null terminated string to output buffer (current ctx->pos). Writes |
| 97519 | * comma in front of key if needed. Encapsulates key in quotes. */ |
| 97520 | status UA_FUNC_ATTR_WARN_UNUSED_RESULT |
| 97521 | writeJsonKey(CtxJson *ctx, const char* key) { |
| 97522 | status ret = writeJsonBeforeElement(ctx, true); |
| 97523 | ctx->commaNeeded[ctx->depth] = true; |
| 97524 | if(!ctx->unquotedKeys) |
| 97525 | ret |= writeChar(ctx, c: '\"'); |
| 97526 | ret |= writeChars(ctx, c: key, len: strlen(s: key)); |
| 97527 | if(!ctx->unquotedKeys) |
| 97528 | ret |= writeChar(ctx, c: '\"'); |
| 97529 | if(!ctx->unquotedKeys) |
| 97530 | ret |= writeChar(ctx, c: ':'); |
| 97531 | if(ctx->prettyPrint) |
| 97532 | ret |= writeChar(ctx, c: ' '); |
| 97533 | return ret; |
| 97534 | } |
| 97535 | |
| 97536 | static bool |
| 97537 | isNull(const void *p, const UA_DataType *type) { |
| 97538 | if(UA_DataType_isNumeric(type) || type->typeKind == UA_DATATYPEKIND_BOOLEAN) |
| 97539 | return false; |
| 97540 | UA_STACKARRAY(char, buf, type->memSize); |
| 97541 | memset(s: buf, c: 0, n: type->memSize); |
| 97542 | return UA_equal(p1: buf, p2: p, type); |
| 97543 | } |
| 97544 | |
| 97545 | /* Boolean */ |
| 97546 | ENCODE_JSON(Boolean) { |
| 97547 | if(*src == true) |
| 97548 | return writeChars(ctx, c: "true", len: 4); |
| 97549 | return writeChars(ctx, c: "false", len: 5); |
| 97550 | } |
| 97551 | |
| 97552 | /* Byte */ |
| 97553 | ENCODE_JSON(Byte) { |
| 97554 | char buf[4]; |
| 97555 | UA_UInt16 digits = itoaUnsigned(value: *src, buffer: buf, base: 10); |
| 97556 | |
| 97557 | /* Ensure destination can hold the data- */ |
| 97558 | if(ctx->pos + digits > ctx->end) |
| 97559 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97560 | |
| 97561 | /* Copy digits to the output string/buffer. */ |
| 97562 | if(!ctx->calcOnly) |
| 97563 | memcpy(dest: ctx->pos, src: buf, n: digits); |
| 97564 | ctx->pos += digits; |
| 97565 | return UA_STATUSCODE_GOOD; |
| 97566 | } |
| 97567 | |
| 97568 | /* signed Byte */ |
| 97569 | ENCODE_JSON(SByte) { |
| 97570 | char buf[5]; |
| 97571 | UA_UInt16 digits = itoaSigned(value: *src, buffer: buf); |
| 97572 | if(ctx->pos + digits > ctx->end) |
| 97573 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97574 | if(!ctx->calcOnly) |
| 97575 | memcpy(dest: ctx->pos, src: buf, n: digits); |
| 97576 | ctx->pos += digits; |
| 97577 | return UA_STATUSCODE_GOOD; |
| 97578 | } |
| 97579 | |
| 97580 | /* UInt16 */ |
| 97581 | ENCODE_JSON(UInt16) { |
| 97582 | char buf[6]; |
| 97583 | UA_UInt16 digits = itoaUnsigned(value: *src, buffer: buf, base: 10); |
| 97584 | |
| 97585 | if(ctx->pos + digits > ctx->end) |
| 97586 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97587 | |
| 97588 | if(!ctx->calcOnly) |
| 97589 | memcpy(dest: ctx->pos, src: buf, n: digits); |
| 97590 | ctx->pos += digits; |
| 97591 | return UA_STATUSCODE_GOOD; |
| 97592 | } |
| 97593 | |
| 97594 | /* Int16 */ |
| 97595 | ENCODE_JSON(Int16) { |
| 97596 | char buf[7]; |
| 97597 | UA_UInt16 digits = itoaSigned(value: *src, buffer: buf); |
| 97598 | |
| 97599 | if(ctx->pos + digits > ctx->end) |
| 97600 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97601 | |
| 97602 | if(!ctx->calcOnly) |
| 97603 | memcpy(dest: ctx->pos, src: buf, n: digits); |
| 97604 | ctx->pos += digits; |
| 97605 | return UA_STATUSCODE_GOOD; |
| 97606 | } |
| 97607 | |
| 97608 | /* UInt32 */ |
| 97609 | ENCODE_JSON(UInt32) { |
| 97610 | char buf[11]; |
| 97611 | UA_UInt16 digits = itoaUnsigned(value: *src, buffer: buf, base: 10); |
| 97612 | |
| 97613 | if(ctx->pos + digits > ctx->end) |
| 97614 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97615 | |
| 97616 | if(!ctx->calcOnly) |
| 97617 | memcpy(dest: ctx->pos, src: buf, n: digits); |
| 97618 | ctx->pos += digits; |
| 97619 | return UA_STATUSCODE_GOOD; |
| 97620 | } |
| 97621 | |
| 97622 | /* Int32 */ |
| 97623 | ENCODE_JSON(Int32) { |
| 97624 | char buf[12]; |
| 97625 | UA_UInt16 digits = itoaSigned(value: *src, buffer: buf); |
| 97626 | |
| 97627 | if(ctx->pos + digits > ctx->end) |
| 97628 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97629 | |
| 97630 | if(!ctx->calcOnly) |
| 97631 | memcpy(dest: ctx->pos, src: buf, n: digits); |
| 97632 | ctx->pos += digits; |
| 97633 | return UA_STATUSCODE_GOOD; |
| 97634 | } |
| 97635 | |
| 97636 | /* UInt64 */ |
| 97637 | ENCODE_JSON(UInt64) { |
| 97638 | char buf[23]; |
| 97639 | buf[0] = '\"'; |
| 97640 | UA_UInt16 digits = itoaUnsigned(value: *src, buffer: buf + 1, base: 10); |
| 97641 | buf[digits + 1] = '\"'; |
| 97642 | UA_UInt16 length = (UA_UInt16)(digits + 2); |
| 97643 | |
| 97644 | if(ctx->pos + length > ctx->end) |
| 97645 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97646 | |
| 97647 | if(!ctx->calcOnly) |
| 97648 | memcpy(dest: ctx->pos, src: buf, n: length); |
| 97649 | ctx->pos += length; |
| 97650 | return UA_STATUSCODE_GOOD; |
| 97651 | } |
| 97652 | |
| 97653 | /* Int64 */ |
| 97654 | ENCODE_JSON(Int64) { |
| 97655 | char buf[23]; |
| 97656 | buf[0] = '\"'; |
| 97657 | UA_UInt16 digits = itoaSigned(value: *src, buffer: buf + 1); |
| 97658 | buf[digits + 1] = '\"'; |
| 97659 | UA_UInt16 length = (UA_UInt16)(digits + 2); |
| 97660 | |
| 97661 | if(ctx->pos + length > ctx->end) |
| 97662 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97663 | |
| 97664 | if(!ctx->calcOnly) |
| 97665 | memcpy(dest: ctx->pos, src: buf, n: length); |
| 97666 | ctx->pos += length; |
| 97667 | return UA_STATUSCODE_GOOD; |
| 97668 | } |
| 97669 | |
| 97670 | ENCODE_JSON(Float) { |
| 97671 | char buffer[32]; |
| 97672 | size_t len; |
| 97673 | if(*src != *src) { |
| 97674 | strcpy(dest: buffer, src: "\"NaN\""); |
| 97675 | len = strlen(s: buffer); |
| 97676 | } else if(*src == INFINITY) { |
| 97677 | strcpy(dest: buffer, src: "\"Infinity\""); |
| 97678 | len = strlen(s: buffer); |
| 97679 | } else if(*src == -INFINITY) { |
| 97680 | strcpy(dest: buffer, src: "\"-Infinity\""); |
| 97681 | len = strlen(s: buffer); |
| 97682 | } else { |
| 97683 | len = dtoa(d: (UA_Double)*src, buffer); |
| 97684 | } |
| 97685 | |
| 97686 | if(ctx->pos + len > ctx->end) |
| 97687 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97688 | |
| 97689 | if(!ctx->calcOnly) |
| 97690 | memcpy(dest: ctx->pos, src: buffer, n: len); |
| 97691 | ctx->pos += len; |
| 97692 | return UA_STATUSCODE_GOOD; |
| 97693 | } |
| 97694 | |
| 97695 | ENCODE_JSON(Double) { |
| 97696 | char buffer[32]; |
| 97697 | size_t len; |
| 97698 | if(*src != *src) { |
| 97699 | strcpy(dest: buffer, src: "\"NaN\""); |
| 97700 | len = strlen(s: buffer); |
| 97701 | } else if(*src == INFINITY) { |
| 97702 | strcpy(dest: buffer, src: "\"Infinity\""); |
| 97703 | len = strlen(s: buffer); |
| 97704 | } else if(*src == -INFINITY) { |
| 97705 | strcpy(dest: buffer, src: "\"-Infinity\""); |
| 97706 | len = strlen(s: buffer); |
| 97707 | } else { |
| 97708 | len = dtoa(d: *src, buffer); |
| 97709 | } |
| 97710 | |
| 97711 | if(ctx->pos + len > ctx->end) |
| 97712 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97713 | |
| 97714 | if(!ctx->calcOnly) |
| 97715 | memcpy(dest: ctx->pos, src: buffer, n: len); |
| 97716 | ctx->pos += len; |
| 97717 | return UA_STATUSCODE_GOOD; |
| 97718 | } |
| 97719 | |
| 97720 | static status |
| 97721 | encodeJsonArray(CtxJson *ctx, const void *ptr, size_t length, |
| 97722 | const UA_DataType *type) { |
| 97723 | /* Null-arrays (length -1) are written as empty arrays '[]'. |
| 97724 | * TODO: Clarify the difference between length -1 and length 0 in JSON. */ |
| 97725 | status ret = writeJsonArrStart(ctx); |
| 97726 | if(!ptr) |
| 97727 | return ret | writeJsonArrEnd(ctx); |
| 97728 | |
| 97729 | uintptr_t uptr = (uintptr_t)ptr; |
| 97730 | encodeJsonSignature encodeType = encodeJsonJumpTable[type->typeKind]; |
| 97731 | UA_Boolean distinct = (type->typeKind > UA_DATATYPEKIND_DOUBLE); |
| 97732 | for(size_t i = 0; i < length && ret == UA_STATUSCODE_GOOD; ++i) { |
| 97733 | ret |= writeJsonBeforeElement(ctx, distinct); |
| 97734 | if(isNull(p: (const void*)uptr, type)) |
| 97735 | ret |= writeChars(ctx, c: "null", len: 4); |
| 97736 | else |
| 97737 | ret |= encodeType(ctx, (const void*)uptr, type); |
| 97738 | ctx->commaNeeded[ctx->depth] = true; |
| 97739 | uptr += type->memSize; |
| 97740 | } |
| 97741 | return ret | writeJsonArrEnd(ctx); |
| 97742 | } |
| 97743 | |
| 97744 | static const uint32_t min_codepoints[5] = {0x00, 0x00, 0x80, 0x800, 0x10000}; |
| 97745 | static const u8 hexmap[16] = |
| 97746 | {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; |
| 97747 | |
| 97748 | /* Extract the next utf8 codepoint from the buffer. Return the next position in |
| 97749 | * the buffer or NULL upon an error. */ |
| 97750 | static const unsigned char * |
| 97751 | extract_codepoint(const unsigned char *pos, size_t len, uint32_t *codepoint) { |
| 97752 | UA_assert(len > 0); |
| 97753 | |
| 97754 | *codepoint = pos[0]; |
| 97755 | if(UA_LIKELY(*codepoint < 0x80)) |
| 97756 | return pos + 1; /* Normal ASCII */ |
| 97757 | |
| 97758 | if(UA_UNLIKELY(*codepoint <= 0xC1)) |
| 97759 | return NULL; /* Continuation byte not allowed here */ |
| 97760 | |
| 97761 | unsigned char count; |
| 97762 | if(*codepoint <= 0xDF) { |
| 97763 | count = 2; /* 2-byte sequence */ |
| 97764 | *codepoint &= 0x1F; |
| 97765 | } else if(*codepoint <= 0xEF) { |
| 97766 | count = 3; /* 3-byte sequence */ |
| 97767 | *codepoint &= 0xF; |
| 97768 | } else if(*codepoint <= 0xF4) { |
| 97769 | count = 4; /* 4-byte sequence */ |
| 97770 | *codepoint &= 0x7; |
| 97771 | } else { |
| 97772 | return NULL; /* invalid utf8 */ |
| 97773 | } |
| 97774 | |
| 97775 | if(UA_UNLIKELY(count > len)) |
| 97776 | return NULL; /* Not enough bytes left */ |
| 97777 | |
| 97778 | for(unsigned char i = 1; i < count; i++) { |
| 97779 | unsigned char byte = pos[i]; |
| 97780 | if(UA_UNLIKELY(byte < 0x80 || byte > 0xBF)) |
| 97781 | return NULL; /* Not a continuation byte */ |
| 97782 | *codepoint = (*codepoint << 6) + (byte & 0x3F); |
| 97783 | } |
| 97784 | |
| 97785 | /* Not in Unicode range or too small for the encoding length */ |
| 97786 | if(UA_UNLIKELY(*codepoint > 0x10FFFF || *codepoint < min_codepoints[count])) |
| 97787 | return NULL; |
| 97788 | |
| 97789 | return pos + count; /* Return the new position in the pos */ |
| 97790 | } |
| 97791 | |
| 97792 | ENCODE_JSON(String) { |
| 97793 | if(!src->data) |
| 97794 | return writeChars(ctx, c: "null", len: 4); |
| 97795 | |
| 97796 | if(src->length == 0) |
| 97797 | return writeJsonQuote(ctx) | writeJsonQuote(ctx); |
| 97798 | |
| 97799 | UA_StatusCode ret = writeJsonQuote(ctx); |
| 97800 | |
| 97801 | const unsigned char *str = src->data; |
| 97802 | const unsigned char *pos = str; |
| 97803 | const unsigned char *end = str; |
| 97804 | const unsigned char *lim = str + src->length; |
| 97805 | uint32_t codepoint = 0; |
| 97806 | while(1) { |
| 97807 | /* Iterate over codepoints in the utf8 encoding. Until the first |
| 97808 | * character that needs to be escaped. */ |
| 97809 | while(end < lim) { |
| 97810 | end = extract_codepoint(pos, len: (size_t)(lim - pos), codepoint: &codepoint); |
| 97811 | if(!end) { |
| 97812 | /* A malformed utf8 character. Print anyway and let the |
| 97813 | * receiving side choose how to handle it. */ |
| 97814 | pos++; |
| 97815 | end = pos; |
| 97816 | continue; |
| 97817 | } |
| 97818 | |
| 97819 | /* Escape unprintable ASCII and escape characters */ |
| 97820 | if(codepoint < ' ' || codepoint == 127 || |
| 97821 | codepoint == '\\' || codepoint == '\"') |
| 97822 | break; |
| 97823 | |
| 97824 | pos = end; |
| 97825 | } |
| 97826 | |
| 97827 | /* Write out the characters that don't need escaping */ |
| 97828 | if(pos != str) { |
| 97829 | if(ctx->pos + (pos - str) > ctx->end) |
| 97830 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97831 | if(!ctx->calcOnly) |
| 97832 | memcpy(dest: ctx->pos, src: str, n: (size_t)(pos - str)); |
| 97833 | ctx->pos += pos - str; |
| 97834 | } |
| 97835 | |
| 97836 | /* Reached the end of the utf8 encoding */ |
| 97837 | if(end == pos) |
| 97838 | break; |
| 97839 | |
| 97840 | /* Handle an escaped character */ |
| 97841 | size_t length = 2; |
| 97842 | u8 seq[13]; |
| 97843 | const char *text; |
| 97844 | |
| 97845 | switch(codepoint) { |
| 97846 | case '\\': text = "\\\\"; break; |
| 97847 | case '\"': text = "\\\""; break; |
| 97848 | case '\b': text = "\\b"; break; |
| 97849 | case '\f': text = "\\f"; break; |
| 97850 | case '\n': text = "\\n"; break; |
| 97851 | case '\r': text = "\\r"; break; |
| 97852 | case '\t': text = "\\t"; break; |
| 97853 | default: |
| 97854 | text = (char*)seq; |
| 97855 | if(codepoint < 0x10000) { |
| 97856 | /* codepoint is in BMP */ |
| 97857 | seq[0] = '\\'; |
| 97858 | seq[1] = 'u'; |
| 97859 | UA_Byte b1 = (UA_Byte)(codepoint >> 8u); |
| 97860 | UA_Byte b2 = (UA_Byte)(codepoint >> 0u); |
| 97861 | seq[2] = hexmap[(b1 & 0xF0u) >> 4u]; |
| 97862 | seq[3] = hexmap[b1 & 0x0Fu]; |
| 97863 | seq[4] = hexmap[(b2 & 0xF0u) >> 4u]; |
| 97864 | seq[5] = hexmap[b2 & 0x0Fu]; |
| 97865 | length = 6; |
| 97866 | } else { |
| 97867 | /* not in BMP -> construct a UTF-16 surrogate pair */ |
| 97868 | codepoint -= 0x10000; |
| 97869 | UA_UInt32 first = 0xD800u | ((codepoint & 0xffc00u) >> 10u); |
| 97870 | UA_UInt32 last = 0xDC00u | (codepoint & 0x003ffu); |
| 97871 | UA_Byte fb1 = (UA_Byte)(first >> 8u); |
| 97872 | UA_Byte fb2 = (UA_Byte)(first >> 0u); |
| 97873 | UA_Byte lb1 = (UA_Byte)(last >> 8u); |
| 97874 | UA_Byte lb2 = (UA_Byte)(last >> 0u); |
| 97875 | seq[0] = '\\'; |
| 97876 | seq[1] = 'u'; |
| 97877 | seq[2] = hexmap[(fb1 & 0xF0u) >> 4u]; |
| 97878 | seq[3] = hexmap[fb1 & 0x0Fu]; |
| 97879 | seq[4] = hexmap[(fb2 & 0xF0u) >> 4u]; |
| 97880 | seq[5] = hexmap[fb2 & 0x0Fu]; |
| 97881 | seq[6] = '\\'; |
| 97882 | seq[7] = 'u'; |
| 97883 | seq[8] = hexmap[(lb1 & 0xF0u) >> 4u]; |
| 97884 | seq[9] = hexmap[lb1 & 0x0Fu]; |
| 97885 | seq[10] = hexmap[(lb2 & 0xF0u) >> 4u]; |
| 97886 | seq[11] = hexmap[lb2 & 0x0Fu]; |
| 97887 | length = 12; |
| 97888 | } |
| 97889 | break; |
| 97890 | } |
| 97891 | if(ctx->pos + length > ctx->end) |
| 97892 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97893 | if(!ctx->calcOnly) |
| 97894 | memcpy(dest: ctx->pos, src: text, n: length); |
| 97895 | ctx->pos += length; |
| 97896 | str = pos = end; |
| 97897 | } |
| 97898 | |
| 97899 | return ret | writeJsonQuote(ctx); |
| 97900 | } |
| 97901 | |
| 97902 | ENCODE_JSON(ByteString) { |
| 97903 | if(!src->data) |
| 97904 | return writeChars(ctx, c: "null", len: 4); |
| 97905 | |
| 97906 | if(src->length == 0) { |
| 97907 | status retval = writeJsonQuote(ctx); |
| 97908 | retval |= writeJsonQuote(ctx); |
| 97909 | return retval; |
| 97910 | } |
| 97911 | |
| 97912 | status ret = writeJsonQuote(ctx); |
| 97913 | size_t flen = 0; |
| 97914 | unsigned char *ba64 = UA_base64(src: src->data, len: src->length, out_len: &flen); |
| 97915 | |
| 97916 | /* Not converted, no mem */ |
| 97917 | if(!ba64) |
| 97918 | return UA_STATUSCODE_BADENCODINGERROR; |
| 97919 | |
| 97920 | if(ctx->pos + flen > ctx->end) { |
| 97921 | UA_free(ptr: ba64); |
| 97922 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97923 | } |
| 97924 | |
| 97925 | /* Copy flen bytes to output stream. */ |
| 97926 | if(!ctx->calcOnly) |
| 97927 | memcpy(dest: ctx->pos, src: ba64, n: flen); |
| 97928 | ctx->pos += flen; |
| 97929 | |
| 97930 | /* Base64 result no longer needed */ |
| 97931 | UA_free(ptr: ba64); |
| 97932 | |
| 97933 | return ret | writeJsonQuote(ctx); |
| 97934 | } |
| 97935 | |
| 97936 | /* Guid */ |
| 97937 | ENCODE_JSON(Guid) { |
| 97938 | if(ctx->pos + 38 > ctx->end) /* 36 + 2 (") */ |
| 97939 | return UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED; |
| 97940 | status ret = writeJsonQuote(ctx); |
| 97941 | if(!ctx->calcOnly) |
| 97942 | UA_Guid_to_hex(guid: src, out: ctx->pos, false); |
| 97943 | ctx->pos += 36; |
| 97944 | return ret | writeJsonQuote(ctx); |
| 97945 | } |
| 97946 | |
| 97947 | static u8 |
| 97948 | printNumber(i32 n, char *pos, u8 min_digits) { |
| 97949 | char digits[10]; |
| 97950 | u8 len = 0; |
| 97951 | /* Handle negative values */ |
| 97952 | if(n < 0) { |
| 97953 | pos[len++] = '-'; |
| 97954 | n = -n; |
| 97955 | } |
| 97956 | |
| 97957 | /* Extract the digits */ |
| 97958 | u8 i = 0; |
| 97959 | for(; i < min_digits || n > 0; i++) { |
| 97960 | digits[i] = (char)((n % 10) + '0'); |
| 97961 | n /= 10; |
| 97962 | } |
| 97963 | |
| 97964 | /* Print in reverse order and return */ |
| 97965 | for(; i > 0; i--) |
| 97966 | pos[len++] = digits[i-1]; |
| 97967 | return len; |
| 97968 | } |
| 97969 | |
| 97970 | ENCODE_JSON(DateTime) { |
| 97971 | UA_DateTimeStruct tSt = UA_DateTime_toStruct(t: *src); |
| 97972 | |
| 97973 | /* Format: -yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS'Z' is used. max 31 bytes. |
| 97974 | * Note the optional minus for negative years. */ |
| 97975 | char buffer[UA_JSON_DATETIME_LENGTH]; |
| 97976 | char *pos = buffer; |
| 97977 | pos += printNumber(n: tSt.year, pos, min_digits: 4); |
| 97978 | *(pos++) = '-'; |
| 97979 | pos += printNumber(n: tSt.month, pos, min_digits: 2); |
| 97980 | *(pos++) = '-'; |
| 97981 | pos += printNumber(n: tSt.day, pos, min_digits: 2); |
| 97982 | *(pos++) = 'T'; |
| 97983 | pos += printNumber(n: tSt.hour, pos, min_digits: 2); |
| 97984 | *(pos++) = ':'; |
| 97985 | pos += printNumber(n: tSt.min, pos, min_digits: 2); |
| 97986 | *(pos++) = ':'; |
| 97987 | pos += printNumber(n: tSt.sec, pos, min_digits: 2); |
| 97988 | *(pos++) = '.'; |
| 97989 | pos += printNumber(n: tSt.milliSec, pos, min_digits: 3); |
| 97990 | pos += printNumber(n: tSt.microSec, pos, min_digits: 3); |
| 97991 | pos += printNumber(n: tSt.nanoSec, pos, min_digits: 3); |
| 97992 | |
| 97993 | UA_assert(pos <= &buffer[UA_JSON_DATETIME_LENGTH]); |
| 97994 | |
| 97995 | /* Remove trailing zeros */ |
| 97996 | pos--; |
| 97997 | while(*pos == '0') |
| 97998 | pos--; |
| 97999 | if(*pos == '.') |
| 98000 | pos--; |
| 98001 | |
| 98002 | *(++pos) = 'Z'; |
| 98003 | UA_String str = {((uintptr_t)pos - (uintptr_t)buffer)+1, (UA_Byte*)buffer}; |
| 98004 | return ENCODE_DIRECT_JSON(&str, String); |
| 98005 | } |
| 98006 | |
| 98007 | /* NodeId */ |
| 98008 | static status |
| 98009 | NodeId_encodeJsonInternal(CtxJson *ctx, UA_NodeId const *src) { |
| 98010 | status ret = UA_STATUSCODE_GOOD; |
| 98011 | switch(src->identifierType) { |
| 98012 | case UA_NODEIDTYPE_NUMERIC: |
| 98013 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_ID); |
| 98014 | ret |= ENCODE_DIRECT_JSON(&src->identifier.numeric, UInt32); |
| 98015 | break; |
| 98016 | case UA_NODEIDTYPE_STRING: |
| 98017 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_IDTYPE); |
| 98018 | ret |= writeChar(ctx, c: '1'); |
| 98019 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_ID); |
| 98020 | ret |= ENCODE_DIRECT_JSON(&src->identifier.string, String); |
| 98021 | break; |
| 98022 | case UA_NODEIDTYPE_GUID: |
| 98023 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_IDTYPE); |
| 98024 | ret |= writeChar(ctx, c: '2'); |
| 98025 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_ID); /* Id */ |
| 98026 | ret |= ENCODE_DIRECT_JSON(&src->identifier.guid, Guid); |
| 98027 | break; |
| 98028 | case UA_NODEIDTYPE_BYTESTRING: |
| 98029 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_IDTYPE); |
| 98030 | ret |= writeChar(ctx, c: '3'); |
| 98031 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_ID); /* Id */ |
| 98032 | ret |= ENCODE_DIRECT_JSON(&src->identifier.byteString, ByteString); |
| 98033 | break; |
| 98034 | default: |
| 98035 | return UA_STATUSCODE_BADINTERNALERROR; |
| 98036 | } |
| 98037 | return ret; |
| 98038 | } |
| 98039 | |
| 98040 | ENCODE_JSON(NodeId) { |
| 98041 | /* Encode as string (non-standard). Encode with the standard utf8 escaping. |
| 98042 | * As the NodeId can contain quote characters, etc. */ |
| 98043 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 98044 | if(ctx->stringNodeIds) { |
| 98045 | UA_String out = UA_STRING_NULL; |
| 98046 | ret |= UA_NodeId_print(id: src, output: &out); |
| 98047 | ret |= encodeJsonJumpTable[UA_DATATYPEKIND_STRING](ctx, &out, NULL); |
| 98048 | UA_String_clear(p: &out); |
| 98049 | return ret; |
| 98050 | } |
| 98051 | |
| 98052 | /* Encode as object */ |
| 98053 | ret |= writeJsonObjStart(ctx); |
| 98054 | ret |= NodeId_encodeJsonInternal(ctx, src); |
| 98055 | if(ctx->useReversible) { |
| 98056 | if(src->namespaceIndex > 0) { |
| 98057 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_NAMESPACE); |
| 98058 | ret |= ENCODE_DIRECT_JSON(&src->namespaceIndex, UInt16); |
| 98059 | } |
| 98060 | } else { |
| 98061 | /* For the non-reversible encoding, the field is the NamespaceUri |
| 98062 | * associated with the NamespaceIndex, encoded as a JSON string. |
| 98063 | * A NamespaceIndex of 1 is always encoded as a JSON number. */ |
| 98064 | if(src->namespaceIndex == 1) { |
| 98065 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_NAMESPACE); |
| 98066 | ret |= ENCODE_DIRECT_JSON(&src->namespaceIndex, UInt16); |
| 98067 | } else { |
| 98068 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_NAMESPACE); |
| 98069 | |
| 98070 | /* Check if Namespace given and in range */ |
| 98071 | if(src->namespaceIndex < ctx->namespacesSize && ctx->namespaces != NULL) { |
| 98072 | UA_String namespaceEntry = ctx->namespaces[src->namespaceIndex]; |
| 98073 | ret |= ENCODE_DIRECT_JSON(&namespaceEntry, String); |
| 98074 | } else { |
| 98075 | return UA_STATUSCODE_BADNOTFOUND; |
| 98076 | } |
| 98077 | } |
| 98078 | } |
| 98079 | |
| 98080 | return ret | writeJsonObjEnd(ctx); |
| 98081 | } |
| 98082 | |
| 98083 | /* ExpandedNodeId */ |
| 98084 | ENCODE_JSON(ExpandedNodeId) { |
| 98085 | /* Encode as string (non-standard). Encode with utf8 escaping as the NodeId |
| 98086 | * can contain quote characters, etc. */ |
| 98087 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 98088 | if(ctx->stringNodeIds) { |
| 98089 | UA_String out = UA_STRING_NULL; |
| 98090 | ret |= UA_ExpandedNodeId_print(eid: src, output: &out); |
| 98091 | ret |= encodeJsonJumpTable[UA_DATATYPEKIND_STRING](ctx, &out, NULL); |
| 98092 | UA_String_clear(p: &out); |
| 98093 | return ret; |
| 98094 | } |
| 98095 | |
| 98096 | /* Encode as object */ |
| 98097 | ret |= writeJsonObjStart(ctx); |
| 98098 | |
| 98099 | /* Encode the identifier portion */ |
| 98100 | ret |= NodeId_encodeJsonInternal(ctx, src: &src->nodeId); |
| 98101 | |
| 98102 | if(ctx->useReversible) { |
| 98103 | /* Reversible Case */ |
| 98104 | |
| 98105 | if(src->namespaceUri.data) { |
| 98106 | /* If the NamespaceUri is specified it is encoded as a JSON string |
| 98107 | * in this field */ |
| 98108 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_NAMESPACE); |
| 98109 | ret |= ENCODE_DIRECT_JSON(&src->namespaceUri, String); |
| 98110 | } else if(src->nodeId.namespaceIndex > 0) { |
| 98111 | /* If the NamespaceUri is not specified, the NamespaceIndex is |
| 98112 | * encoded. Encoded as a JSON number for the reversible encoding. |
| 98113 | * Omitted if the NamespaceIndex equals 0. */ |
| 98114 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_NAMESPACE); |
| 98115 | ret |= ENCODE_DIRECT_JSON(&src->nodeId.namespaceIndex, UInt16); |
| 98116 | } |
| 98117 | |
| 98118 | /* Encode the serverIndex/Url. As a JSON number for the reversible |
| 98119 | * encoding. Omitted if the ServerIndex equals 0. */ |
| 98120 | if(src->serverIndex > 0) { |
| 98121 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_SERVERURI); |
| 98122 | ret |= ENCODE_DIRECT_JSON(&src->serverIndex, UInt32); |
| 98123 | } |
| 98124 | } else { |
| 98125 | /* Non-Reversible Case */ |
| 98126 | |
| 98127 | /* If the NamespaceUri is not specified, the NamespaceIndex is encoded |
| 98128 | * with these rules: For the non-reversible encoding the field is the |
| 98129 | * NamespaceUri associated with the NamespaceIndex encoded as a JSON |
| 98130 | * string. A NamespaceIndex of 1 is always encoded as a JSON number. */ |
| 98131 | |
| 98132 | if(src->namespaceUri.data) { |
| 98133 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_NAMESPACE); |
| 98134 | ret |= ENCODE_DIRECT_JSON(&src->namespaceUri, String); |
| 98135 | } else { |
| 98136 | if(src->nodeId.namespaceIndex == 1) { |
| 98137 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_NAMESPACE); |
| 98138 | ret |= ENCODE_DIRECT_JSON(&src->nodeId.namespaceIndex, UInt16); |
| 98139 | } else { |
| 98140 | /* Check if Namespace given and in range */ |
| 98141 | if(src->nodeId.namespaceIndex >= ctx->namespacesSize || !ctx->namespaces) |
| 98142 | return UA_STATUSCODE_BADNOTFOUND; |
| 98143 | UA_String namespaceEntry = ctx->namespaces[src->nodeId.namespaceIndex]; |
| 98144 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_NAMESPACE); |
| 98145 | ret |= ENCODE_DIRECT_JSON(&namespaceEntry, String); |
| 98146 | } |
| 98147 | } |
| 98148 | |
| 98149 | /* For the non-reversible encoding, this field is the ServerUri |
| 98150 | * associated with the ServerIndex portion of the ExpandedNodeId, |
| 98151 | * encoded as a JSON string. */ |
| 98152 | |
| 98153 | /* Check if server given and in range */ |
| 98154 | if(src->serverIndex >= ctx->serverUrisSize || !ctx->serverUris) |
| 98155 | return UA_STATUSCODE_BADNOTFOUND; |
| 98156 | |
| 98157 | UA_String serverUriEntry = ctx->serverUris[src->serverIndex]; |
| 98158 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_SERVERURI); |
| 98159 | ret |= ENCODE_DIRECT_JSON(&serverUriEntry, String); |
| 98160 | } |
| 98161 | |
| 98162 | return ret | writeJsonObjEnd(ctx); |
| 98163 | } |
| 98164 | |
| 98165 | /* LocalizedText */ |
| 98166 | ENCODE_JSON(LocalizedText) { |
| 98167 | if(ctx->useReversible) { |
| 98168 | status ret = writeJsonObjStart(ctx); |
| 98169 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_LOCALE); |
| 98170 | ret |= ENCODE_DIRECT_JSON(&src->locale, String); |
| 98171 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_TEXT); |
| 98172 | ret |= ENCODE_DIRECT_JSON(&src->text, String); |
| 98173 | return ret | writeJsonObjEnd(ctx); |
| 98174 | } |
| 98175 | |
| 98176 | /* For the non-reversible form, LocalizedText value shall be encoded as a |
| 98177 | * JSON string containing the Text component.*/ |
| 98178 | return ENCODE_DIRECT_JSON(&src->text, String); |
| 98179 | } |
| 98180 | |
| 98181 | ENCODE_JSON(QualifiedName) { |
| 98182 | status ret = writeJsonObjStart(ctx); |
| 98183 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_NAME); |
| 98184 | ret |= ENCODE_DIRECT_JSON(&src->name, String); |
| 98185 | |
| 98186 | if(ctx->useReversible) { |
| 98187 | if(src->namespaceIndex != 0) { |
| 98188 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_URI); |
| 98189 | ret |= ENCODE_DIRECT_JSON(&src->namespaceIndex, UInt16); |
| 98190 | } |
| 98191 | } else { |
| 98192 | /* For the non-reversible form, the NamespaceUri associated with the |
| 98193 | * NamespaceIndex portion of the QualifiedName is encoded as JSON string |
| 98194 | * unless the NamespaceIndex is 1 or if NamespaceUri is unknown. In |
| 98195 | * these cases, the NamespaceIndex is encoded as a JSON number. */ |
| 98196 | if(src->namespaceIndex == 1) { |
| 98197 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_URI); |
| 98198 | ret |= ENCODE_DIRECT_JSON(&src->namespaceIndex, UInt16); |
| 98199 | } else { |
| 98200 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_URI); |
| 98201 | |
| 98202 | /* Check if Namespace given and in range */ |
| 98203 | if(src->namespaceIndex < ctx->namespacesSize && ctx->namespaces != NULL) { |
| 98204 | UA_String namespaceEntry = ctx->namespaces[src->namespaceIndex]; |
| 98205 | ret |= ENCODE_DIRECT_JSON(&namespaceEntry, String); |
| 98206 | } else { |
| 98207 | /* If not encode as number */ |
| 98208 | ret |= ENCODE_DIRECT_JSON(&src->namespaceIndex, UInt16); |
| 98209 | } |
| 98210 | } |
| 98211 | } |
| 98212 | |
| 98213 | return ret | writeJsonObjEnd(ctx); |
| 98214 | } |
| 98215 | |
| 98216 | ENCODE_JSON(StatusCode) { |
| 98217 | if(ctx->useReversible) |
| 98218 | return ENCODE_DIRECT_JSON(src, UInt32); |
| 98219 | |
| 98220 | const char *codename = UA_StatusCode_name(code: *src); |
| 98221 | UA_String statusDescription = UA_STRING(chars: (char*)(uintptr_t)codename); |
| 98222 | |
| 98223 | status ret = UA_STATUSCODE_GOOD; |
| 98224 | ret |= writeJsonObjStart(ctx); |
| 98225 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_CODE); |
| 98226 | ret |= ENCODE_DIRECT_JSON(src, UInt32); |
| 98227 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_SYMBOL); |
| 98228 | ret |= ENCODE_DIRECT_JSON(&statusDescription, String); |
| 98229 | ret |= writeJsonObjEnd(ctx); |
| 98230 | return ret; |
| 98231 | } |
| 98232 | |
| 98233 | /* ExtensionObject */ |
| 98234 | ENCODE_JSON(ExtensionObject) { |
| 98235 | if(src->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) |
| 98236 | return writeChars(ctx, c: "null", len: 4); |
| 98237 | |
| 98238 | /* Must have a type set if data is decoded */ |
| 98239 | if(src->encoding >= UA_EXTENSIONOBJECT_DECODED && !src->content.decoded.type) |
| 98240 | return UA_STATUSCODE_BADENCODINGERROR; |
| 98241 | |
| 98242 | status ret = writeJsonObjStart(ctx); |
| 98243 | |
| 98244 | /* Reversible encoding */ |
| 98245 | if(ctx->useReversible) { |
| 98246 | /* Write the type NodeId */ |
| 98247 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_TYPEID); |
| 98248 | if(src->encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING || |
| 98249 | src->encoding == UA_EXTENSIONOBJECT_ENCODED_XML) |
| 98250 | ret |= ENCODE_DIRECT_JSON(&src->content.encoded.typeId, NodeId); |
| 98251 | else |
| 98252 | ret |= ENCODE_DIRECT_JSON(&src->content.decoded.type->typeId, NodeId); |
| 98253 | |
| 98254 | /* Write the encoding */ |
| 98255 | if(src->encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING) { |
| 98256 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_ENCODING); |
| 98257 | ret |= writeChar(ctx, c: '1'); |
| 98258 | } else if(src->encoding == UA_EXTENSIONOBJECT_ENCODED_XML) { |
| 98259 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_ENCODING); |
| 98260 | ret |= writeChar(ctx, c: '2'); |
| 98261 | } |
| 98262 | } |
| 98263 | |
| 98264 | /* Write the body */ |
| 98265 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_BODY); |
| 98266 | if(src->encoding == UA_EXTENSIONOBJECT_ENCODED_BYTESTRING || |
| 98267 | src->encoding == UA_EXTENSIONOBJECT_ENCODED_XML) { |
| 98268 | ret |= ENCODE_DIRECT_JSON(&src->content.encoded.body, String); |
| 98269 | } else { |
| 98270 | const UA_DataType *t = src->content.decoded.type; |
| 98271 | ret |= encodeJsonJumpTable[t->typeKind] |
| 98272 | (ctx, src->content.decoded.data, t); |
| 98273 | } |
| 98274 | |
| 98275 | return ret | writeJsonObjEnd(ctx); |
| 98276 | } |
| 98277 | |
| 98278 | /* Non-builtin types get wrapped in an ExtensionObject */ |
| 98279 | static status |
| 98280 | encodeScalarJsonWrapExtensionObject(CtxJson *ctx, const UA_Variant *src) { |
| 98281 | const UA_Boolean isBuiltin = (src->type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO); |
| 98282 | const void *ptr = src->data; |
| 98283 | const UA_DataType *type = src->type; |
| 98284 | |
| 98285 | /* Set up a temporary ExtensionObject to wrap the data */ |
| 98286 | UA_ExtensionObject eo; |
| 98287 | if(!isBuiltin) { |
| 98288 | UA_ExtensionObject_init(p: &eo); |
| 98289 | eo.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 98290 | eo.content.decoded.type = src->type; |
| 98291 | eo.content.decoded.data = src->data; |
| 98292 | ptr = &eo; |
| 98293 | type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]; |
| 98294 | } |
| 98295 | |
| 98296 | return encodeJsonJumpTable[type->typeKind](ctx, ptr, type); |
| 98297 | } |
| 98298 | |
| 98299 | /* Non-builtin types get wrapped in an ExtensionObject */ |
| 98300 | static status |
| 98301 | encodeArrayJsonWrapExtensionObject(CtxJson *ctx, const void *data, |
| 98302 | size_t size, const UA_DataType *type) { |
| 98303 | if(size > UA_INT32_MAX) |
| 98304 | return UA_STATUSCODE_BADENCODINGERROR; |
| 98305 | |
| 98306 | status ret = writeJsonArrStart(ctx); |
| 98307 | |
| 98308 | u16 memSize = type->memSize; |
| 98309 | const UA_Boolean isBuiltin = (type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO); |
| 98310 | if(isBuiltin) { |
| 98311 | uintptr_t ptr = (uintptr_t)data; |
| 98312 | for(size_t i = 0; i < size && ret == UA_STATUSCODE_GOOD; ++i) { |
| 98313 | ret |= writeJsonArrElm(ctx, value: (const void*)ptr, type); |
| 98314 | ptr += memSize; |
| 98315 | } |
| 98316 | } else { |
| 98317 | /* Set up a temporary ExtensionObject to wrap the data */ |
| 98318 | UA_ExtensionObject eo; |
| 98319 | UA_ExtensionObject_init(p: &eo); |
| 98320 | eo.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 98321 | eo.content.decoded.type = type; |
| 98322 | eo.content.decoded.data = (void*)(uintptr_t)data; |
| 98323 | for(size_t i = 0; i < size && ret == UA_STATUSCODE_GOOD; ++i) { |
| 98324 | ret |= writeJsonArrElm(ctx, value: &eo, type: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]); |
| 98325 | eo.content.decoded.data = (void*) |
| 98326 | ((uintptr_t)eo.content.decoded.data + memSize); |
| 98327 | } |
| 98328 | } |
| 98329 | |
| 98330 | return ret | writeJsonArrEnd(ctx); |
| 98331 | } |
| 98332 | |
| 98333 | static status |
| 98334 | addMultiArrayContentJSON(CtxJson *ctx, void* array, const UA_DataType *type, |
| 98335 | size_t *index, UA_UInt32 *arrayDimensions, size_t dimensionIndex, |
| 98336 | size_t dimensionSize) { |
| 98337 | /* Stop recursion: The inner arrays are written */ |
| 98338 | status ret; |
| 98339 | if(dimensionIndex == (dimensionSize - 1)) { |
| 98340 | u8 *ptr = ((u8 *)array) + (type->memSize * *index); |
| 98341 | u32 size = arrayDimensions[dimensionIndex]; |
| 98342 | (*index) += arrayDimensions[dimensionIndex]; |
| 98343 | return encodeArrayJsonWrapExtensionObject(ctx, data: ptr, size, type); |
| 98344 | } |
| 98345 | |
| 98346 | /* Recurse to the next dimension */ |
| 98347 | ret = writeJsonArrStart(ctx); |
| 98348 | for(size_t i = 0; i < arrayDimensions[dimensionIndex]; i++) { |
| 98349 | ret |= writeJsonBeforeElement(ctx, true); |
| 98350 | ret |= addMultiArrayContentJSON(ctx, array, type, index, arrayDimensions, |
| 98351 | dimensionIndex: dimensionIndex + 1, dimensionSize); |
| 98352 | ctx->commaNeeded[ctx->depth] = true; |
| 98353 | } |
| 98354 | return ret | writeJsonArrEnd(ctx); |
| 98355 | } |
| 98356 | |
| 98357 | ENCODE_JSON(Variant) { |
| 98358 | /* If type is 0 (NULL) the Variant contains a NULL value and the containing |
| 98359 | * JSON object shall be omitted or replaced by the JSON literal ‘null’ (when |
| 98360 | * an element of a JSON array). */ |
| 98361 | if(!src->type) |
| 98362 | return writeJsonObjStart(ctx) | writeJsonObjEnd(ctx); |
| 98363 | |
| 98364 | /* Set the content type in the encoding mask */ |
| 98365 | const UA_Boolean isBuiltin = (src->type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO); |
| 98366 | |
| 98367 | /* Set the array type in the encoding mask */ |
| 98368 | const bool isArray = src->arrayLength > 0 || src->data <= UA_EMPTY_ARRAY_SENTINEL; |
| 98369 | const bool hasDimensions = isArray && src->arrayDimensionsSize > 0; |
| 98370 | |
| 98371 | /* We cannot directly encode a variant inside a variant (but arrays of |
| 98372 | * variant are possible) */ |
| 98373 | UA_Boolean wrapEO = !isBuiltin; |
| 98374 | if(src->type == &UA_TYPES[UA_TYPES_VARIANT] && !isArray) |
| 98375 | wrapEO = true; |
| 98376 | |
| 98377 | status ret = writeJsonObjStart(ctx); |
| 98378 | |
| 98379 | /* Write the type NodeId */ |
| 98380 | if(ctx->useReversible) { |
| 98381 | UA_UInt32 typeId = src->type->typeId.identifier.numeric; |
| 98382 | if(wrapEO) |
| 98383 | typeId = UA_TYPES[UA_TYPES_EXTENSIONOBJECT].typeId.identifier.numeric; |
| 98384 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_TYPE); |
| 98385 | ret |= ENCODE_DIRECT_JSON(&typeId, UInt32); |
| 98386 | } |
| 98387 | |
| 98388 | /* Write the Variant body */ |
| 98389 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_BODY); |
| 98390 | |
| 98391 | if(!isArray) { |
| 98392 | encodeScalarJsonWrapExtensionObject(ctx, src); |
| 98393 | } else { |
| 98394 | if(ctx->useReversible || !hasDimensions) { |
| 98395 | ret |= encodeArrayJsonWrapExtensionObject(ctx, data: src->data, |
| 98396 | size: src->arrayLength, type: src->type); |
| 98397 | if(hasDimensions) { |
| 98398 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_DIMENSION); |
| 98399 | ret |= encodeJsonArray(ctx, ptr: src->arrayDimensions, length: src->arrayDimensionsSize, |
| 98400 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 98401 | } |
| 98402 | } else { |
| 98403 | /* Special case of non-reversible array with dimensions */ |
| 98404 | size_t index = 0; |
| 98405 | ret |= addMultiArrayContentJSON(ctx, array: src->data, type: src->type, index: &index, |
| 98406 | arrayDimensions: src->arrayDimensions, dimensionIndex: 0, |
| 98407 | dimensionSize: src->arrayDimensionsSize); |
| 98408 | } |
| 98409 | } |
| 98410 | |
| 98411 | return ret | writeJsonObjEnd(ctx); |
| 98412 | } |
| 98413 | |
| 98414 | /* DataValue */ |
| 98415 | ENCODE_JSON(DataValue) { |
| 98416 | UA_Boolean hasValue = src->hasValue; |
| 98417 | UA_Boolean hasStatus = src->hasStatus; |
| 98418 | UA_Boolean hasSourceTimestamp = src->hasSourceTimestamp; |
| 98419 | UA_Boolean hasSourcePicoseconds = src->hasSourcePicoseconds; |
| 98420 | UA_Boolean hasServerTimestamp = src->hasServerTimestamp; |
| 98421 | UA_Boolean hasServerPicoseconds = src->hasServerPicoseconds; |
| 98422 | |
| 98423 | status ret = writeJsonObjStart(ctx); |
| 98424 | |
| 98425 | if(hasValue) { |
| 98426 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_VALUE); |
| 98427 | ret |= ENCODE_DIRECT_JSON(&src->value, Variant); |
| 98428 | } |
| 98429 | |
| 98430 | if(hasStatus) { |
| 98431 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_STATUS); |
| 98432 | ret |= ENCODE_DIRECT_JSON(&src->status, StatusCode); |
| 98433 | } |
| 98434 | |
| 98435 | if(hasSourceTimestamp) { |
| 98436 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_SOURCETIMESTAMP); |
| 98437 | ret |= ENCODE_DIRECT_JSON(&src->sourceTimestamp, DateTime); |
| 98438 | } |
| 98439 | |
| 98440 | if(hasSourcePicoseconds) { |
| 98441 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_SOURCEPICOSECONDS); |
| 98442 | ret |= ENCODE_DIRECT_JSON(&src->sourcePicoseconds, UInt16); |
| 98443 | } |
| 98444 | |
| 98445 | if(hasServerTimestamp) { |
| 98446 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_SERVERTIMESTAMP); |
| 98447 | ret |= ENCODE_DIRECT_JSON(&src->serverTimestamp, DateTime); |
| 98448 | } |
| 98449 | |
| 98450 | if(hasServerPicoseconds) { |
| 98451 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_SERVERPICOSECONDS); |
| 98452 | ret |= ENCODE_DIRECT_JSON(&src->serverPicoseconds, UInt16); |
| 98453 | } |
| 98454 | |
| 98455 | return ret | writeJsonObjEnd(ctx); |
| 98456 | } |
| 98457 | |
| 98458 | /* DiagnosticInfo */ |
| 98459 | ENCODE_JSON(DiagnosticInfo) { |
| 98460 | status ret = writeJsonObjStart(ctx); |
| 98461 | |
| 98462 | if(src->hasSymbolicId) { |
| 98463 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_SYMBOLICID); |
| 98464 | ret |= ENCODE_DIRECT_JSON(&src->symbolicId, Int32); |
| 98465 | } |
| 98466 | |
| 98467 | if(src->hasNamespaceUri) { |
| 98468 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_NAMESPACEURI); |
| 98469 | ret |= ENCODE_DIRECT_JSON(&src->namespaceUri, Int32); |
| 98470 | } |
| 98471 | |
| 98472 | if(src->hasLocalizedText) { |
| 98473 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_LOCALIZEDTEXT); |
| 98474 | ret |= ENCODE_DIRECT_JSON(&src->localizedText, Int32); |
| 98475 | } |
| 98476 | |
| 98477 | if(src->hasLocale) { |
| 98478 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_LOCALE); |
| 98479 | ret |= ENCODE_DIRECT_JSON(&src->locale, Int32); |
| 98480 | } |
| 98481 | |
| 98482 | if(src->hasAdditionalInfo) { |
| 98483 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_ADDITIONALINFO); |
| 98484 | ret |= ENCODE_DIRECT_JSON(&src->additionalInfo, String); |
| 98485 | } |
| 98486 | |
| 98487 | if(src->hasInnerStatusCode) { |
| 98488 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_INNERSTATUSCODE); |
| 98489 | ret |= ENCODE_DIRECT_JSON(&src->innerStatusCode, StatusCode); |
| 98490 | } |
| 98491 | |
| 98492 | if(src->hasInnerDiagnosticInfo && src->innerDiagnosticInfo) { |
| 98493 | ret |= writeJsonKey(ctx, key: UA_JSONKEY_INNERDIAGNOSTICINFO); |
| 98494 | ret |= encodeJsonJumpTable[UA_DATATYPEKIND_DIAGNOSTICINFO] |
| 98495 | (ctx, src->innerDiagnosticInfo, NULL); |
| 98496 | } |
| 98497 | |
| 98498 | return ret | writeJsonObjEnd(ctx); |
| 98499 | } |
| 98500 | |
| 98501 | static status |
| 98502 | encodeJsonStructure(CtxJson *ctx, const void *src, const UA_DataType *type) { |
| 98503 | status ret = writeJsonObjStart(ctx); |
| 98504 | if(ret != UA_STATUSCODE_GOOD) |
| 98505 | return ret; |
| 98506 | |
| 98507 | uintptr_t ptr = (uintptr_t) src; |
| 98508 | u8 membersSize = type->membersSize; |
| 98509 | for(size_t i = 0; i < membersSize && ret == UA_STATUSCODE_GOOD; ++i) { |
| 98510 | const UA_DataTypeMember *m = &type->members[i]; |
| 98511 | const UA_DataType *mt = m->memberType; |
| 98512 | |
| 98513 | if(m->memberName != NULL && *m->memberName != 0) |
| 98514 | ret |= writeJsonKey(ctx, key: m->memberName); |
| 98515 | |
| 98516 | if(!m->isArray) { |
| 98517 | ptr += m->padding; |
| 98518 | size_t memSize = mt->memSize; |
| 98519 | ret |= encodeJsonJumpTable[mt->typeKind](ctx, (const void*) ptr, mt); |
| 98520 | ptr += memSize; |
| 98521 | } else { |
| 98522 | ptr += m->padding; |
| 98523 | const size_t length = *((const size_t*) ptr); |
| 98524 | ptr += sizeof (size_t); |
| 98525 | ret |= encodeJsonArray(ctx, ptr: *(void * const *)ptr, length, type: mt); |
| 98526 | ptr += sizeof (void*); |
| 98527 | } |
| 98528 | } |
| 98529 | |
| 98530 | return ret | writeJsonObjEnd(ctx); |
| 98531 | } |
| 98532 | |
| 98533 | static status |
| 98534 | encodeJsonNotImplemented(const void *src, const UA_DataType *type, CtxJson *ctx) { |
| 98535 | (void) src, (void) type, (void)ctx; |
| 98536 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 98537 | } |
| 98538 | |
| 98539 | const encodeJsonSignature encodeJsonJumpTable[UA_DATATYPEKINDS] = { |
| 98540 | (encodeJsonSignature)Boolean_encodeJson, |
| 98541 | (encodeJsonSignature)SByte_encodeJson, /* SByte */ |
| 98542 | (encodeJsonSignature)Byte_encodeJson, |
| 98543 | (encodeJsonSignature)Int16_encodeJson, /* Int16 */ |
| 98544 | (encodeJsonSignature)UInt16_encodeJson, |
| 98545 | (encodeJsonSignature)Int32_encodeJson, /* Int32 */ |
| 98546 | (encodeJsonSignature)UInt32_encodeJson, |
| 98547 | (encodeJsonSignature)Int64_encodeJson, /* Int64 */ |
| 98548 | (encodeJsonSignature)UInt64_encodeJson, |
| 98549 | (encodeJsonSignature)Float_encodeJson, |
| 98550 | (encodeJsonSignature)Double_encodeJson, |
| 98551 | (encodeJsonSignature)String_encodeJson, |
| 98552 | (encodeJsonSignature)DateTime_encodeJson, /* DateTime */ |
| 98553 | (encodeJsonSignature)Guid_encodeJson, |
| 98554 | (encodeJsonSignature)ByteString_encodeJson, /* ByteString */ |
| 98555 | (encodeJsonSignature)String_encodeJson, /* XmlElement */ |
| 98556 | (encodeJsonSignature)NodeId_encodeJson, |
| 98557 | (encodeJsonSignature)ExpandedNodeId_encodeJson, |
| 98558 | (encodeJsonSignature)StatusCode_encodeJson, /* StatusCode */ |
| 98559 | (encodeJsonSignature)QualifiedName_encodeJson, /* QualifiedName */ |
| 98560 | (encodeJsonSignature)LocalizedText_encodeJson, |
| 98561 | (encodeJsonSignature)ExtensionObject_encodeJson, |
| 98562 | (encodeJsonSignature)DataValue_encodeJson, |
| 98563 | (encodeJsonSignature)Variant_encodeJson, |
| 98564 | (encodeJsonSignature)DiagnosticInfo_encodeJson, |
| 98565 | (encodeJsonSignature)encodeJsonNotImplemented, /* Decimal */ |
| 98566 | (encodeJsonSignature)Int32_encodeJson, /* Enum */ |
| 98567 | (encodeJsonSignature)encodeJsonStructure, |
| 98568 | (encodeJsonSignature)encodeJsonNotImplemented, /* Structure with optional fields */ |
| 98569 | (encodeJsonSignature)encodeJsonNotImplemented, /* Union */ |
| 98570 | (encodeJsonSignature)encodeJsonNotImplemented /* BitfieldCluster */ |
| 98571 | }; |
| 98572 | |
| 98573 | UA_StatusCode |
| 98574 | UA_encodeJson(const void *src, const UA_DataType *type, UA_ByteString *outBuf, |
| 98575 | const UA_EncodeJsonOptions *options) { |
| 98576 | if(!src || !type) |
| 98577 | return UA_STATUSCODE_BADINTERNALERROR; |
| 98578 | |
| 98579 | /* Allocate buffer */ |
| 98580 | UA_Boolean allocated = false; |
| 98581 | status res = UA_STATUSCODE_GOOD; |
| 98582 | if(outBuf->length == 0) { |
| 98583 | size_t len = UA_calcSizeJson(src, type, options); |
| 98584 | res = UA_ByteString_allocBuffer(bs: outBuf, length: len); |
| 98585 | if(res != UA_STATUSCODE_GOOD) |
| 98586 | return res; |
| 98587 | allocated = true; |
| 98588 | } |
| 98589 | |
| 98590 | /* Set up the context */ |
| 98591 | CtxJson ctx; |
| 98592 | memset(s: &ctx, c: 0, n: sizeof(ctx)); |
| 98593 | ctx.pos = outBuf->data; |
| 98594 | ctx.end = &outBuf->data[outBuf->length]; |
| 98595 | ctx.depth = 0; |
| 98596 | ctx.calcOnly = false; |
| 98597 | ctx.useReversible = true; /* default */ |
| 98598 | if(options) { |
| 98599 | ctx.namespaces = options->namespaces; |
| 98600 | ctx.namespacesSize = options->namespacesSize; |
| 98601 | ctx.serverUris = options->serverUris; |
| 98602 | ctx.serverUrisSize = options->serverUrisSize; |
| 98603 | ctx.useReversible = options->useReversible; |
| 98604 | ctx.prettyPrint = options->prettyPrint; |
| 98605 | ctx.unquotedKeys = options->unquotedKeys; |
| 98606 | ctx.stringNodeIds = options->stringNodeIds; |
| 98607 | } |
| 98608 | |
| 98609 | /* Encode */ |
| 98610 | res = encodeJsonJumpTable[type->typeKind](&ctx, src, type); |
| 98611 | |
| 98612 | /* Clean up */ |
| 98613 | if(res == UA_STATUSCODE_GOOD) |
| 98614 | outBuf->length = (size_t)((uintptr_t)ctx.pos - (uintptr_t)outBuf->data); |
| 98615 | else if(allocated) |
| 98616 | UA_ByteString_clear(p: outBuf); |
| 98617 | return res; |
| 98618 | } |
| 98619 | |
| 98620 | UA_StatusCode |
| 98621 | UA_print(const void *p, const UA_DataType *type, UA_String *output) { |
| 98622 | if(!p || !type || !output) |
| 98623 | return UA_STATUSCODE_BADINTERNALERROR; |
| 98624 | |
| 98625 | UA_EncodeJsonOptions options; |
| 98626 | memset(s: &options, c: 0, n: sizeof(UA_EncodeJsonOptions)); |
| 98627 | options.useReversible = true; |
| 98628 | options.prettyPrint = true; |
| 98629 | options.unquotedKeys = true; |
| 98630 | options.stringNodeIds = true; |
| 98631 | return UA_encodeJson(src: p, type, outBuf: output, options: &options); |
| 98632 | } |
| 98633 | |
| 98634 | /************/ |
| 98635 | /* CalcSize */ |
| 98636 | /************/ |
| 98637 | |
| 98638 | size_t |
| 98639 | UA_calcSizeJson(const void *src, const UA_DataType *type, |
| 98640 | const UA_EncodeJsonOptions *options) { |
| 98641 | if(!src || !type) |
| 98642 | return UA_STATUSCODE_BADINTERNALERROR; |
| 98643 | |
| 98644 | /* Set up the context */ |
| 98645 | CtxJson ctx; |
| 98646 | memset(s: &ctx, c: 0, n: sizeof(ctx)); |
| 98647 | ctx.pos = NULL; |
| 98648 | ctx.end = (const UA_Byte*)(uintptr_t)SIZE_MAX; |
| 98649 | ctx.depth = 0; |
| 98650 | ctx.useReversible = true; /* default */ |
| 98651 | if(options) { |
| 98652 | ctx.namespaces = options->namespaces; |
| 98653 | ctx.namespacesSize = options->namespacesSize; |
| 98654 | ctx.serverUris = options->serverUris; |
| 98655 | ctx.serverUrisSize = options->serverUrisSize; |
| 98656 | ctx.useReversible = options->useReversible; |
| 98657 | ctx.prettyPrint = options->prettyPrint; |
| 98658 | ctx.unquotedKeys = options->unquotedKeys; |
| 98659 | ctx.stringNodeIds = options->stringNodeIds; |
| 98660 | } |
| 98661 | |
| 98662 | ctx.calcOnly = true; |
| 98663 | |
| 98664 | /* Encode */ |
| 98665 | status ret = encodeJsonJumpTable[type->typeKind](&ctx, src, type); |
| 98666 | if(ret != UA_STATUSCODE_GOOD) |
| 98667 | return 0; |
| 98668 | return (size_t)ctx.pos; |
| 98669 | } |
| 98670 | |
| 98671 | /**********/ |
| 98672 | /* Decode */ |
| 98673 | /**********/ |
| 98674 | |
| 98675 | #define GET_TOKEN \ |
| 98676 | size_t tokenSize = getTokenLength(&ctx->tokens[ctx->index]); \ |
| 98677 | const char* tokenData = &ctx->json5[ctx->tokens[ctx->index].start]; \ |
| 98678 | do {} while(0) |
| 98679 | |
| 98680 | #define CHECK_TOKEN_BOUNDS do { \ |
| 98681 | if(ctx->index >= ctx->tokensSize) \ |
| 98682 | return UA_STATUSCODE_BADDECODINGERROR; \ |
| 98683 | } while(0) |
| 98684 | |
| 98685 | #define CHECK_NUMBER do { \ |
| 98686 | if(currentTokenType(ctx) != CJ5_TOKEN_NUMBER) { \ |
| 98687 | return UA_STATUSCODE_BADDECODINGERROR; \ |
| 98688 | }} while(0) |
| 98689 | |
| 98690 | #define CHECK_BOOL do { \ |
| 98691 | if(currentTokenType(ctx) != CJ5_TOKEN_BOOL) { \ |
| 98692 | return UA_STATUSCODE_BADDECODINGERROR; \ |
| 98693 | }} while(0) |
| 98694 | |
| 98695 | #define CHECK_STRING do { \ |
| 98696 | if(currentTokenType(ctx) != CJ5_TOKEN_STRING) { \ |
| 98697 | return UA_STATUSCODE_BADDECODINGERROR; \ |
| 98698 | }} while(0) |
| 98699 | |
| 98700 | #define CHECK_OBJECT do { \ |
| 98701 | if(currentTokenType(ctx) != CJ5_TOKEN_OBJECT) { \ |
| 98702 | return UA_STATUSCODE_BADDECODINGERROR; \ |
| 98703 | }} while(0) |
| 98704 | |
| 98705 | #define CHECK_NULL_SKIP do { \ |
| 98706 | if(currentTokenType(ctx) == CJ5_TOKEN_NULL) { \ |
| 98707 | ctx->index++; \ |
| 98708 | return UA_STATUSCODE_GOOD; \ |
| 98709 | }} while(0) |
| 98710 | |
| 98711 | /* Forward declarations*/ |
| 98712 | #define DECODE_JSON(TYPE) static status \ |
| 98713 | TYPE##_decodeJson(ParseCtx *ctx, UA_##TYPE *dst, \ |
| 98714 | const UA_DataType *type) |
| 98715 | |
| 98716 | /* If ctx->index points to the beginning of an object, move the index to the |
| 98717 | * next token after this object. Attention! The index can be moved after the |
| 98718 | * last parsed token. So the array length has to be checked afterwards. */ |
| 98719 | static void |
| 98720 | skipObject(ParseCtx *ctx) { |
| 98721 | unsigned int end = ctx->tokens[ctx->index].end; |
| 98722 | do { |
| 98723 | ctx->index++; |
| 98724 | } while(ctx->index < ctx->tokensSize && |
| 98725 | ctx->tokens[ctx->index].start < end); |
| 98726 | } |
| 98727 | |
| 98728 | static status |
| 98729 | Array_decodeJson(ParseCtx *ctx, void **dst, const UA_DataType *type); |
| 98730 | |
| 98731 | static status |
| 98732 | Variant_decodeJsonUnwrapExtensionObject(ParseCtx *ctx, void *p, const UA_DataType *type); |
| 98733 | |
| 98734 | static UA_SByte |
| 98735 | jsoneq(const char *json, const cj5_token *tok, const char *searchKey) { |
| 98736 | /* TODO: necessary? |
| 98737 | if(json == NULL |
| 98738 | || tok == NULL |
| 98739 | || searchKey == NULL) { |
| 98740 | return -1; |
| 98741 | } */ |
| 98742 | |
| 98743 | size_t len = getTokenLength(t: tok); |
| 98744 | if(tok->type == CJ5_TOKEN_STRING && |
| 98745 | strlen(s: searchKey) == len && |
| 98746 | strncmp(s1: json + tok->start, s2: (const char*)searchKey, n: len) == 0) |
| 98747 | return 0; |
| 98748 | |
| 98749 | return -1; |
| 98750 | } |
| 98751 | |
| 98752 | DECODE_JSON(Boolean) { |
| 98753 | CHECK_TOKEN_BOUNDS; |
| 98754 | CHECK_BOOL; |
| 98755 | GET_TOKEN; |
| 98756 | |
| 98757 | if(tokenSize == 4 && |
| 98758 | tokenData[0] == 't' && tokenData[1] == 'r' && |
| 98759 | tokenData[2] == 'u' && tokenData[3] == 'e') { |
| 98760 | *dst = true; |
| 98761 | } else if(tokenSize == 5 && |
| 98762 | tokenData[0] == 'f' && tokenData[1] == 'a' && |
| 98763 | tokenData[2] == 'l' && tokenData[3] == 's' && |
| 98764 | tokenData[4] == 'e') { |
| 98765 | *dst = false; |
| 98766 | } else { |
| 98767 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98768 | } |
| 98769 | |
| 98770 | ctx->index++; |
| 98771 | return UA_STATUSCODE_GOOD; |
| 98772 | } |
| 98773 | |
| 98774 | static UA_StatusCode |
| 98775 | parseUnsignedInteger(const char *tokenData, size_t tokenSize, UA_UInt64 *dst) { |
| 98776 | size_t len = parseUInt64(str: tokenData, size: tokenSize, result: dst); |
| 98777 | if(len == 0) |
| 98778 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98779 | |
| 98780 | /* There must only be whitespace between the end of the parsed number and |
| 98781 | * the end of the token */ |
| 98782 | for(size_t i = len; i < tokenSize; i++) { |
| 98783 | if(tokenData[i] != ' ' && tokenData[i] -'\t' >= 5) |
| 98784 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98785 | } |
| 98786 | |
| 98787 | return UA_STATUSCODE_GOOD; |
| 98788 | } |
| 98789 | |
| 98790 | static UA_StatusCode |
| 98791 | parseSignedInteger(const char *tokenData, size_t tokenSize, UA_Int64 *dst) { |
| 98792 | size_t len = parseInt64(str: tokenData, size: tokenSize, result: dst); |
| 98793 | if(len == 0) |
| 98794 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98795 | |
| 98796 | /* There must only be whitespace between the end of the parsed number and |
| 98797 | * the end of the token */ |
| 98798 | for(size_t i = len; i < tokenSize; i++) { |
| 98799 | if(tokenData[i] != ' ' && tokenData[i] -'\t' >= 5) |
| 98800 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98801 | } |
| 98802 | |
| 98803 | return UA_STATUSCODE_GOOD; |
| 98804 | } |
| 98805 | |
| 98806 | DECODE_JSON(Byte) { |
| 98807 | CHECK_TOKEN_BOUNDS; |
| 98808 | CHECK_NUMBER; |
| 98809 | GET_TOKEN; |
| 98810 | |
| 98811 | UA_UInt64 out = 0; |
| 98812 | UA_StatusCode s = parseUnsignedInteger(tokenData, tokenSize, dst: &out); |
| 98813 | if(s != UA_STATUSCODE_GOOD || out > UA_BYTE_MAX) |
| 98814 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98815 | *dst = (UA_Byte)out; |
| 98816 | ctx->index++; |
| 98817 | return UA_STATUSCODE_GOOD; |
| 98818 | } |
| 98819 | |
| 98820 | DECODE_JSON(UInt16) { |
| 98821 | CHECK_TOKEN_BOUNDS; |
| 98822 | CHECK_NUMBER; |
| 98823 | GET_TOKEN; |
| 98824 | |
| 98825 | UA_UInt64 out = 0; |
| 98826 | UA_StatusCode s = parseUnsignedInteger(tokenData, tokenSize, dst: &out); |
| 98827 | if(s != UA_STATUSCODE_GOOD || out > UA_UINT16_MAX) |
| 98828 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98829 | *dst = (UA_UInt16)out; |
| 98830 | ctx->index++; |
| 98831 | return UA_STATUSCODE_GOOD; |
| 98832 | } |
| 98833 | |
| 98834 | DECODE_JSON(UInt32) { |
| 98835 | CHECK_TOKEN_BOUNDS; |
| 98836 | CHECK_NUMBER; |
| 98837 | GET_TOKEN; |
| 98838 | |
| 98839 | UA_UInt64 out = 0; |
| 98840 | UA_StatusCode s = parseUnsignedInteger(tokenData, tokenSize, dst: &out); |
| 98841 | if(s != UA_STATUSCODE_GOOD || out > UA_UINT32_MAX) |
| 98842 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98843 | *dst = (UA_UInt32)out; |
| 98844 | ctx->index++; |
| 98845 | return UA_STATUSCODE_GOOD; |
| 98846 | } |
| 98847 | |
| 98848 | DECODE_JSON(UInt64) { |
| 98849 | CHECK_TOKEN_BOUNDS; |
| 98850 | GET_TOKEN; |
| 98851 | |
| 98852 | UA_StatusCode s = parseUnsignedInteger(tokenData, tokenSize, dst); |
| 98853 | if(s != UA_STATUSCODE_GOOD) |
| 98854 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98855 | ctx->index++; |
| 98856 | return UA_STATUSCODE_GOOD; |
| 98857 | } |
| 98858 | |
| 98859 | DECODE_JSON(SByte) { |
| 98860 | CHECK_TOKEN_BOUNDS; |
| 98861 | CHECK_NUMBER; |
| 98862 | GET_TOKEN; |
| 98863 | |
| 98864 | UA_Int64 out = 0; |
| 98865 | UA_StatusCode s = parseSignedInteger(tokenData, tokenSize, dst: &out); |
| 98866 | if(s != UA_STATUSCODE_GOOD || out < UA_SBYTE_MIN || out > UA_SBYTE_MAX) |
| 98867 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98868 | *dst = (UA_SByte)out; |
| 98869 | ctx->index++; |
| 98870 | return UA_STATUSCODE_GOOD; |
| 98871 | } |
| 98872 | |
| 98873 | DECODE_JSON(Int16) { |
| 98874 | CHECK_TOKEN_BOUNDS; |
| 98875 | CHECK_NUMBER; |
| 98876 | GET_TOKEN; |
| 98877 | |
| 98878 | UA_Int64 out = 0; |
| 98879 | UA_StatusCode s = parseSignedInteger(tokenData, tokenSize, dst: &out); |
| 98880 | if(s != UA_STATUSCODE_GOOD || out < UA_INT16_MIN || out > UA_INT16_MAX) |
| 98881 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98882 | *dst = (UA_Int16)out; |
| 98883 | ctx->index++; |
| 98884 | return UA_STATUSCODE_GOOD; |
| 98885 | } |
| 98886 | |
| 98887 | DECODE_JSON(Int32) { |
| 98888 | CHECK_TOKEN_BOUNDS; |
| 98889 | CHECK_NUMBER; |
| 98890 | GET_TOKEN; |
| 98891 | |
| 98892 | UA_Int64 out = 0; |
| 98893 | UA_StatusCode s = parseSignedInteger(tokenData, tokenSize, dst: &out); |
| 98894 | if(s != UA_STATUSCODE_GOOD || out < UA_INT32_MIN || out > UA_INT32_MAX) |
| 98895 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98896 | *dst = (UA_Int32)out; |
| 98897 | ctx->index++; |
| 98898 | return UA_STATUSCODE_GOOD; |
| 98899 | } |
| 98900 | |
| 98901 | DECODE_JSON(Int64) { |
| 98902 | CHECK_TOKEN_BOUNDS; |
| 98903 | GET_TOKEN; |
| 98904 | |
| 98905 | UA_StatusCode s = parseSignedInteger(tokenData, tokenSize, dst); |
| 98906 | if(s != UA_STATUSCODE_GOOD) |
| 98907 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98908 | ctx->index++; |
| 98909 | return UA_STATUSCODE_GOOD; |
| 98910 | } |
| 98911 | |
| 98912 | /* Either a STRING or NUMBER token */ |
| 98913 | DECODE_JSON(Double) { |
| 98914 | CHECK_TOKEN_BOUNDS; |
| 98915 | GET_TOKEN; |
| 98916 | |
| 98917 | /* https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/ |
| 98918 | * Maximum digit counts for select IEEE floating-point formats: 1074 |
| 98919 | * Sanity check. |
| 98920 | */ |
| 98921 | if(tokenSize > 2000) |
| 98922 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98923 | |
| 98924 | cj5_token_type tokenType = currentTokenType(ctx); |
| 98925 | |
| 98926 | /* It could be a String with Nan, Infinity */ |
| 98927 | if(tokenType == CJ5_TOKEN_STRING) { |
| 98928 | ctx->index++; |
| 98929 | |
| 98930 | if(tokenSize == 8 && memcmp(s1: tokenData, s2: "Infinity", n: 8) == 0) { |
| 98931 | *dst = INFINITY; |
| 98932 | return UA_STATUSCODE_GOOD; |
| 98933 | } |
| 98934 | |
| 98935 | if(tokenSize == 9 && memcmp(s1: tokenData, s2: "-Infinity", n: 9) == 0) { |
| 98936 | /* workaround an MSVC 2013 issue */ |
| 98937 | *dst = -INFINITY; |
| 98938 | return UA_STATUSCODE_GOOD; |
| 98939 | } |
| 98940 | |
| 98941 | if(tokenSize == 3 && memcmp(s1: tokenData, s2: "NaN", n: 3) == 0) { |
| 98942 | *dst = NAN; |
| 98943 | return UA_STATUSCODE_GOOD; |
| 98944 | } |
| 98945 | |
| 98946 | if(tokenSize == 4 && memcmp(s1: tokenData, s2: "-NaN", n: 4) == 0) { |
| 98947 | *dst = NAN; |
| 98948 | return UA_STATUSCODE_GOOD; |
| 98949 | } |
| 98950 | |
| 98951 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98952 | } |
| 98953 | |
| 98954 | if(tokenType != CJ5_TOKEN_NUMBER) |
| 98955 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98956 | |
| 98957 | size_t len = parseDouble(str: tokenData, size: tokenSize, result: dst); |
| 98958 | if(len == 0) |
| 98959 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98960 | |
| 98961 | /* There must only be whitespace between the end of the parsed number and |
| 98962 | * the end of the token */ |
| 98963 | for(size_t i = len; i < tokenSize; i++) { |
| 98964 | if(tokenData[i] != ' ' && tokenData[i] -'\t' >= 5) |
| 98965 | return UA_STATUSCODE_BADDECODINGERROR; |
| 98966 | } |
| 98967 | |
| 98968 | ctx->index++; |
| 98969 | return UA_STATUSCODE_GOOD; |
| 98970 | } |
| 98971 | |
| 98972 | DECODE_JSON(Float) { |
| 98973 | UA_Double v = 0.0; |
| 98974 | UA_StatusCode res = Double_decodeJson(ctx, dst: &v, NULL); |
| 98975 | *dst = (UA_Float)v; |
| 98976 | return res; |
| 98977 | } |
| 98978 | |
| 98979 | DECODE_JSON(Guid) { |
| 98980 | CHECK_TOKEN_BOUNDS; |
| 98981 | CHECK_STRING; |
| 98982 | GET_TOKEN; |
| 98983 | |
| 98984 | /* Use the existing parsing routine if available */ |
| 98985 | UA_String str = {tokenSize, (UA_Byte*)(uintptr_t)tokenData}; |
| 98986 | ctx->index++; |
| 98987 | return UA_Guid_parse(guid: dst, str); |
| 98988 | } |
| 98989 | |
| 98990 | DECODE_JSON(String) { |
| 98991 | CHECK_TOKEN_BOUNDS; |
| 98992 | CHECK_STRING; |
| 98993 | GET_TOKEN; |
| 98994 | (void)tokenData; |
| 98995 | |
| 98996 | /* Empty string? */ |
| 98997 | if(tokenSize == 0) { |
| 98998 | dst->data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL; |
| 98999 | dst->length = 0; |
| 99000 | ctx->index++; |
| 99001 | return UA_STATUSCODE_GOOD; |
| 99002 | } |
| 99003 | |
| 99004 | /* The decoded utf8 is at most of the same length as the source string */ |
| 99005 | char *outBuf = (char*)UA_malloc(size: tokenSize+1); |
| 99006 | if(!outBuf) |
| 99007 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 99008 | |
| 99009 | /* Decode the string */ |
| 99010 | cj5_result r; |
| 99011 | r.tokens = ctx->tokens; |
| 99012 | r.num_tokens = (unsigned int)ctx->tokensSize; |
| 99013 | r.json5 = ctx->json5; |
| 99014 | unsigned int len = 0; |
| 99015 | cj5_error_code err = cj5_get_str(r: &r, tok_index: (unsigned int)ctx->index, buf: outBuf, buflen: &len); |
| 99016 | if(err != CJ5_ERROR_NONE) { |
| 99017 | UA_free(ptr: outBuf); |
| 99018 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99019 | } |
| 99020 | |
| 99021 | /* Set the output */ |
| 99022 | dst->length = len; |
| 99023 | if(dst->length > 0) { |
| 99024 | dst->data = (UA_Byte*)outBuf; |
| 99025 | } else { |
| 99026 | dst->data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL; |
| 99027 | UA_free(ptr: outBuf); |
| 99028 | } |
| 99029 | |
| 99030 | ctx->index++; |
| 99031 | return UA_STATUSCODE_GOOD; |
| 99032 | } |
| 99033 | |
| 99034 | DECODE_JSON(ByteString) { |
| 99035 | CHECK_TOKEN_BOUNDS; |
| 99036 | CHECK_STRING; |
| 99037 | GET_TOKEN; |
| 99038 | |
| 99039 | /* Empty bytestring? */ |
| 99040 | if(tokenSize == 0) { |
| 99041 | dst->data = (UA_Byte*)UA_EMPTY_ARRAY_SENTINEL; |
| 99042 | dst->length = 0; |
| 99043 | } else { |
| 99044 | size_t flen = 0; |
| 99045 | unsigned char* unB64 = |
| 99046 | UA_unbase64(src: (const unsigned char*)tokenData, len: tokenSize, out_len: &flen); |
| 99047 | if(unB64 == 0) |
| 99048 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99049 | dst->data = (u8*)unB64; |
| 99050 | dst->length = flen; |
| 99051 | } |
| 99052 | |
| 99053 | ctx->index++; |
| 99054 | return UA_STATUSCODE_GOOD; |
| 99055 | } |
| 99056 | |
| 99057 | DECODE_JSON(LocalizedText) { |
| 99058 | CHECK_OBJECT; |
| 99059 | |
| 99060 | DecodeEntry entries[2] = { |
| 99061 | {UA_JSONKEY_LOCALE, &dst->locale, NULL, false, &UA_TYPES[UA_TYPES_STRING]}, |
| 99062 | {UA_JSONKEY_TEXT, &dst->text, NULL, false, &UA_TYPES[UA_TYPES_STRING]} |
| 99063 | }; |
| 99064 | |
| 99065 | return decodeFields(ctx, entries, entryCount: 2); |
| 99066 | } |
| 99067 | |
| 99068 | DECODE_JSON(QualifiedName) { |
| 99069 | CHECK_OBJECT; |
| 99070 | |
| 99071 | DecodeEntry entries[2] = { |
| 99072 | {UA_JSONKEY_NAME, &dst->name, NULL, false, &UA_TYPES[UA_TYPES_STRING]}, |
| 99073 | {UA_JSONKEY_URI, &dst->namespaceIndex, NULL, false, &UA_TYPES[UA_TYPES_UINT16]} |
| 99074 | }; |
| 99075 | |
| 99076 | return decodeFields(ctx, entries, entryCount: 2); |
| 99077 | } |
| 99078 | |
| 99079 | UA_FUNC_ATTR_WARN_UNUSED_RESULT status |
| 99080 | lookAheadForKey(ParseCtx *ctx, const char *key, size_t *resultIndex) { |
| 99081 | /* The current index must point to the beginning of an object. |
| 99082 | * This has to be ensured by the caller. */ |
| 99083 | UA_assert(currentTokenType(ctx) == CJ5_TOKEN_OBJECT); |
| 99084 | |
| 99085 | status ret = UA_STATUSCODE_BADNOTFOUND; |
| 99086 | size_t oldIndex = ctx->index; /* Save index for later restore */ |
| 99087 | unsigned int end = ctx->tokens[ctx->index].end; |
| 99088 | ctx->index++; /* Move to the first key */ |
| 99089 | while(ctx->index < ctx->tokensSize && |
| 99090 | ctx->tokens[ctx->index].start < end) { |
| 99091 | /* Key must be a string */ |
| 99092 | UA_assert(currentTokenType(ctx) == CJ5_TOKEN_STRING); |
| 99093 | |
| 99094 | /* Move index to the value */ |
| 99095 | ctx->index++; |
| 99096 | |
| 99097 | /* Value for the key must exist */ |
| 99098 | UA_assert(ctx->index < ctx->tokensSize); |
| 99099 | |
| 99100 | /* Compare the key (previous index) */ |
| 99101 | if(jsoneq(json: ctx->json5, tok: &ctx->tokens[ctx->index-1], searchKey: key) == 0) { |
| 99102 | *resultIndex = ctx->index; /* Point result to the current index */ |
| 99103 | ret = UA_STATUSCODE_GOOD; |
| 99104 | break; |
| 99105 | } |
| 99106 | |
| 99107 | skipObject(ctx); /* Jump over the value (can also be an array or object) */ |
| 99108 | } |
| 99109 | ctx->index = oldIndex; /* Restore the old index */ |
| 99110 | return ret; |
| 99111 | } |
| 99112 | |
| 99113 | static status |
| 99114 | prepareDecodeNodeIdJson(ParseCtx *ctx, UA_NodeId *dst, |
| 99115 | u8 *fieldCount, DecodeEntry *entries) { |
| 99116 | UA_assert(currentTokenType(ctx) == CJ5_TOKEN_OBJECT); |
| 99117 | |
| 99118 | /* possible keys: Id, IdType, NamespaceIndex */ |
| 99119 | /* Id must always be present */ |
| 99120 | entries[*fieldCount].fieldName = UA_JSONKEY_ID; |
| 99121 | entries[*fieldCount].found = false; |
| 99122 | entries[*fieldCount].type = NULL; |
| 99123 | entries[*fieldCount].function = NULL; |
| 99124 | |
| 99125 | /* IdType */ |
| 99126 | size_t idIndex = 0; |
| 99127 | status ret = lookAheadForKey(ctx, key: UA_JSONKEY_IDTYPE, resultIndex: &idIndex); |
| 99128 | if(ret == UA_STATUSCODE_GOOD) { |
| 99129 | size_t size = getTokenLength(t: &ctx->tokens[idIndex]); |
| 99130 | if(size < 1) |
| 99131 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99132 | |
| 99133 | const char *idType = &ctx->json5[ctx->tokens[idIndex].start]; |
| 99134 | |
| 99135 | if(idType[0] == '2') { |
| 99136 | dst->identifierType = UA_NODEIDTYPE_GUID; |
| 99137 | entries[*fieldCount].fieldPointer = &dst->identifier.guid; |
| 99138 | entries[*fieldCount].type = &UA_TYPES[UA_TYPES_GUID]; |
| 99139 | } else if(idType[0] == '1') { |
| 99140 | dst->identifierType = UA_NODEIDTYPE_STRING; |
| 99141 | entries[*fieldCount].fieldPointer = &dst->identifier.string; |
| 99142 | entries[*fieldCount].type = &UA_TYPES[UA_TYPES_STRING]; |
| 99143 | } else if(idType[0] == '3') { |
| 99144 | dst->identifierType = UA_NODEIDTYPE_BYTESTRING; |
| 99145 | entries[*fieldCount].fieldPointer = &dst->identifier.byteString; |
| 99146 | entries[*fieldCount].type = &UA_TYPES[UA_TYPES_BYTESTRING]; |
| 99147 | } else { |
| 99148 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99149 | } |
| 99150 | |
| 99151 | /* Id always present */ |
| 99152 | (*fieldCount)++; |
| 99153 | |
| 99154 | entries[*fieldCount].fieldName = UA_JSONKEY_IDTYPE; |
| 99155 | entries[*fieldCount].fieldPointer = NULL; |
| 99156 | entries[*fieldCount].function = NULL; |
| 99157 | entries[*fieldCount].found = false; |
| 99158 | entries[*fieldCount].type = NULL; |
| 99159 | |
| 99160 | /* IdType */ |
| 99161 | (*fieldCount)++; |
| 99162 | } else { |
| 99163 | dst->identifierType = UA_NODEIDTYPE_NUMERIC; |
| 99164 | entries[*fieldCount].fieldPointer = &dst->identifier.numeric; |
| 99165 | entries[*fieldCount].function = NULL; |
| 99166 | entries[*fieldCount].found = false; |
| 99167 | entries[*fieldCount].type = &UA_TYPES[UA_TYPES_UINT32]; |
| 99168 | (*fieldCount)++; |
| 99169 | } |
| 99170 | |
| 99171 | /* NodeId has a NamespaceIndex (the ExpandedNodeId specialization may |
| 99172 | * overwrite this) */ |
| 99173 | entries[*fieldCount].fieldName = UA_JSONKEY_NAMESPACE; |
| 99174 | entries[*fieldCount].fieldPointer = &dst->namespaceIndex; |
| 99175 | entries[*fieldCount].function = NULL; |
| 99176 | entries[*fieldCount].found = false; |
| 99177 | entries[*fieldCount].type = &UA_TYPES[UA_TYPES_UINT16]; |
| 99178 | (*fieldCount)++; |
| 99179 | |
| 99180 | return UA_STATUSCODE_GOOD; |
| 99181 | } |
| 99182 | |
| 99183 | DECODE_JSON(NodeId) { |
| 99184 | /* Non-standard decoding of NodeIds from the string representation */ |
| 99185 | if(currentTokenType(ctx) == CJ5_TOKEN_STRING) { |
| 99186 | GET_TOKEN; |
| 99187 | UA_String str = {tokenSize, (UA_Byte*)(uintptr_t)tokenData}; |
| 99188 | ctx->index++; |
| 99189 | return UA_NodeId_parse(id: dst, str); |
| 99190 | } |
| 99191 | |
| 99192 | /* Object representation */ |
| 99193 | CHECK_OBJECT; |
| 99194 | |
| 99195 | u8 fieldCount = 0; |
| 99196 | DecodeEntry entries[3]; |
| 99197 | status ret = prepareDecodeNodeIdJson(ctx, dst, fieldCount: &fieldCount, entries); |
| 99198 | if(ret != UA_STATUSCODE_GOOD) |
| 99199 | return ret; |
| 99200 | return decodeFields(ctx, entries, entryCount: fieldCount); |
| 99201 | } |
| 99202 | |
| 99203 | static status |
| 99204 | decodeExpandedNodeIdNamespace(ParseCtx *ctx, void *dst, const UA_DataType *type) { |
| 99205 | UA_ExpandedNodeId *en = (UA_ExpandedNodeId*)dst; |
| 99206 | |
| 99207 | /* Parse as a number */ |
| 99208 | size_t oldIndex = ctx->index; |
| 99209 | status ret = UInt16_decodeJson(ctx, dst: &en->nodeId.namespaceIndex, NULL); |
| 99210 | if(ret == UA_STATUSCODE_GOOD) |
| 99211 | return ret; |
| 99212 | |
| 99213 | /* Parse as a string */ |
| 99214 | ctx->index = oldIndex; /* Reset the index */ |
| 99215 | ret = String_decodeJson(ctx, dst: &en->namespaceUri, NULL); |
| 99216 | if(ret != UA_STATUSCODE_GOOD) |
| 99217 | return ret; |
| 99218 | |
| 99219 | /* Replace with the index if the URI is found. Otherwise keep the string. */ |
| 99220 | for(size_t i = 0; i < ctx->namespacesSize; i++) { |
| 99221 | if(UA_String_equal(p1: &en->namespaceUri, p2: &ctx->namespaces[i])) { |
| 99222 | UA_String_clear(p: &en->namespaceUri); |
| 99223 | en->nodeId.namespaceIndex = (UA_UInt16)i; |
| 99224 | break; |
| 99225 | } |
| 99226 | } |
| 99227 | |
| 99228 | return UA_STATUSCODE_GOOD; |
| 99229 | } |
| 99230 | |
| 99231 | static status |
| 99232 | decodeExpandedNodeIdServerUri(ParseCtx *ctx, void *dst, const UA_DataType *type) { |
| 99233 | UA_ExpandedNodeId *en = (UA_ExpandedNodeId*)dst; |
| 99234 | |
| 99235 | /* Parse as a number */ |
| 99236 | size_t oldIndex = ctx->index; |
| 99237 | status ret = UInt32_decodeJson(ctx, dst: &en->serverIndex, NULL); |
| 99238 | if(ret == UA_STATUSCODE_GOOD) |
| 99239 | return ret; |
| 99240 | |
| 99241 | /* Parse as a string */ |
| 99242 | UA_String uri = UA_STRING_NULL; |
| 99243 | ctx->index = oldIndex; /* Reset the index */ |
| 99244 | ret = String_decodeJson(ctx, dst: &uri, NULL); |
| 99245 | if(ret != UA_STATUSCODE_GOOD) |
| 99246 | return ret; |
| 99247 | |
| 99248 | /* Try to translate the URI into an index */ |
| 99249 | ret = UA_STATUSCODE_BADDECODINGERROR; |
| 99250 | for(size_t i = 0; i < ctx->serverUrisSize; i++) { |
| 99251 | if(UA_String_equal(p1: &uri, p2: &ctx->serverUris[i])) { |
| 99252 | en->serverIndex = (UA_UInt32)i; |
| 99253 | ret = UA_STATUSCODE_GOOD; |
| 99254 | break; |
| 99255 | } |
| 99256 | } |
| 99257 | |
| 99258 | UA_String_clear(p: &uri); |
| 99259 | return ret; |
| 99260 | } |
| 99261 | |
| 99262 | DECODE_JSON(ExpandedNodeId) { |
| 99263 | /* Non-standard decoding of ExpandedNodeIds from the string representation */ |
| 99264 | if(currentTokenType(ctx) == CJ5_TOKEN_STRING) { |
| 99265 | GET_TOKEN; |
| 99266 | UA_String str = {tokenSize, (UA_Byte*)(uintptr_t)tokenData}; |
| 99267 | ctx->index++; |
| 99268 | return UA_ExpandedNodeId_parse(id: dst, str); |
| 99269 | } |
| 99270 | |
| 99271 | /* Object representation */ |
| 99272 | CHECK_OBJECT; |
| 99273 | |
| 99274 | u8 fieldCount = 0; |
| 99275 | DecodeEntry entries[4]; |
| 99276 | status ret = prepareDecodeNodeIdJson(ctx, dst: &dst->nodeId, fieldCount: &fieldCount, entries); |
| 99277 | if(ret != UA_STATUSCODE_GOOD) |
| 99278 | return ret; |
| 99279 | |
| 99280 | /* Overwrite the namespace entry */ |
| 99281 | fieldCount--; |
| 99282 | entries[fieldCount].fieldPointer = dst; |
| 99283 | entries[fieldCount].function = decodeExpandedNodeIdNamespace; |
| 99284 | entries[fieldCount].type = NULL; |
| 99285 | fieldCount++; |
| 99286 | |
| 99287 | entries[fieldCount].fieldName = UA_JSONKEY_SERVERURI; |
| 99288 | entries[fieldCount].fieldPointer = dst; |
| 99289 | entries[fieldCount].function = decodeExpandedNodeIdServerUri; |
| 99290 | entries[fieldCount].found = false; |
| 99291 | entries[fieldCount].type = NULL; |
| 99292 | fieldCount++; |
| 99293 | |
| 99294 | return decodeFields(ctx, entries, entryCount: fieldCount); |
| 99295 | } |
| 99296 | |
| 99297 | DECODE_JSON(DateTime) { |
| 99298 | CHECK_TOKEN_BOUNDS; |
| 99299 | CHECK_STRING; |
| 99300 | GET_TOKEN; |
| 99301 | |
| 99302 | /* The last character has to be 'Z'. We can omit some length checks later on |
| 99303 | * because we know the atoi functions stop before the 'Z'. */ |
| 99304 | if(tokenSize == 0 || tokenData[tokenSize-1] != 'Z') |
| 99305 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99306 | |
| 99307 | struct musl_tm dts; |
| 99308 | memset(s: &dts, c: 0, n: sizeof(dts)); |
| 99309 | |
| 99310 | size_t pos = 0; |
| 99311 | size_t len; |
| 99312 | |
| 99313 | /* Parse the year. The ISO standard asks for four digits. But we accept up |
| 99314 | * to five with an optional plus or minus in front due to the range of the |
| 99315 | * DateTime 64bit integer. But in that case we require the year and the |
| 99316 | * month to be separated by a '-'. Otherwise we cannot know where the month |
| 99317 | * starts. */ |
| 99318 | if(tokenData[0] == '-' || tokenData[0] == '+') |
| 99319 | pos++; |
| 99320 | UA_Int64 year = 0; |
| 99321 | len = parseInt64(str: &tokenData[pos], size: 5, result: &year); |
| 99322 | pos += len; |
| 99323 | if(len != 4 && tokenData[pos] != '-') |
| 99324 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99325 | if(tokenData[0] == '-') |
| 99326 | year = -year; |
| 99327 | dts.tm_year = (UA_Int16)year - 1900; |
| 99328 | if(tokenData[pos] == '-') |
| 99329 | pos++; |
| 99330 | |
| 99331 | /* Parse the month */ |
| 99332 | UA_UInt64 month = 0; |
| 99333 | len = parseUInt64(str: &tokenData[pos], size: 2, result: &month); |
| 99334 | pos += len; |
| 99335 | UA_CHECK(len == 2, return UA_STATUSCODE_BADDECODINGERROR); |
| 99336 | dts.tm_mon = (UA_UInt16)month - 1; |
| 99337 | if(tokenData[pos] == '-') |
| 99338 | pos++; |
| 99339 | |
| 99340 | /* Parse the day and check the T between date and time */ |
| 99341 | UA_UInt64 day = 0; |
| 99342 | len = parseUInt64(str: &tokenData[pos], size: 2, result: &day); |
| 99343 | pos += len; |
| 99344 | UA_CHECK(len == 2 || tokenData[pos] != 'T', |
| 99345 | return UA_STATUSCODE_BADDECODINGERROR); |
| 99346 | dts.tm_mday = (UA_UInt16)day; |
| 99347 | pos++; |
| 99348 | |
| 99349 | /* Parse the hour */ |
| 99350 | UA_UInt64 hour = 0; |
| 99351 | len = parseUInt64(str: &tokenData[pos], size: 2, result: &hour); |
| 99352 | pos += len; |
| 99353 | UA_CHECK(len == 2, return UA_STATUSCODE_BADDECODINGERROR); |
| 99354 | dts.tm_hour = (UA_UInt16)hour; |
| 99355 | if(tokenData[pos] == ':') |
| 99356 | pos++; |
| 99357 | |
| 99358 | /* Parse the minute */ |
| 99359 | UA_UInt64 min = 0; |
| 99360 | len = parseUInt64(str: &tokenData[pos], size: 2, result: &min); |
| 99361 | pos += len; |
| 99362 | UA_CHECK(len == 2, return UA_STATUSCODE_BADDECODINGERROR); |
| 99363 | dts.tm_min = (UA_UInt16)min; |
| 99364 | if(tokenData[pos] == ':') |
| 99365 | pos++; |
| 99366 | |
| 99367 | /* Parse the second */ |
| 99368 | UA_UInt64 sec = 0; |
| 99369 | len = parseUInt64(str: &tokenData[pos], size: 2, result: &sec); |
| 99370 | pos += len; |
| 99371 | UA_CHECK(len == 2, return UA_STATUSCODE_BADDECODINGERROR); |
| 99372 | dts.tm_sec = (UA_UInt16)sec; |
| 99373 | |
| 99374 | /* Compute the seconds since the Unix epoch */ |
| 99375 | long long sinceunix = musl_tm_to_secs(tm: &dts); |
| 99376 | |
| 99377 | /* Are we within the range that can be represented? */ |
| 99378 | long long sinceunix_min = |
| 99379 | (long long)(UA_INT64_MIN / UA_DATETIME_SEC) - |
| 99380 | (long long)(UA_DATETIME_UNIX_EPOCH / UA_DATETIME_SEC) - |
| 99381 | (long long)1; /* manual correction due to rounding */ |
| 99382 | long long sinceunix_max = (long long) |
| 99383 | ((UA_INT64_MAX - UA_DATETIME_UNIX_EPOCH) / UA_DATETIME_SEC); |
| 99384 | if(sinceunix < sinceunix_min || sinceunix > sinceunix_max) |
| 99385 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99386 | |
| 99387 | /* Convert to DateTime. Add or subtract one extra second here to prevent |
| 99388 | * underflow/overflow. This is reverted once the fractional part has been |
| 99389 | * added. */ |
| 99390 | sinceunix -= (sinceunix > 0) ? 1 : -1; |
| 99391 | UA_DateTime dt = (UA_DateTime) |
| 99392 | (sinceunix + (UA_DATETIME_UNIX_EPOCH / UA_DATETIME_SEC)) * UA_DATETIME_SEC; |
| 99393 | |
| 99394 | /* Parse the fraction of the second if defined */ |
| 99395 | if(tokenData[pos] == ',' || tokenData[pos] == '.') { |
| 99396 | pos++; |
| 99397 | double frac = 0.0; |
| 99398 | double denom = 0.1; |
| 99399 | while(pos < tokenSize && |
| 99400 | tokenData[pos] >= '0' && tokenData[pos] <= '9') { |
| 99401 | frac += denom * (tokenData[pos] - '0'); |
| 99402 | denom *= 0.1; |
| 99403 | pos++; |
| 99404 | } |
| 99405 | frac += 0.00000005; /* Correct rounding when converting to integer */ |
| 99406 | dt += (UA_DateTime)(frac * UA_DATETIME_SEC); |
| 99407 | } |
| 99408 | |
| 99409 | /* Remove the underflow/overflow protection (see above) */ |
| 99410 | if(sinceunix > 0) { |
| 99411 | if(dt > UA_INT64_MAX - UA_DATETIME_SEC) |
| 99412 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99413 | dt += UA_DATETIME_SEC; |
| 99414 | } else { |
| 99415 | if(dt < UA_INT64_MIN + UA_DATETIME_SEC) |
| 99416 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99417 | dt -= UA_DATETIME_SEC; |
| 99418 | } |
| 99419 | |
| 99420 | /* We must be at the end of the string (ending with 'Z' as checked above) */ |
| 99421 | if(pos != tokenSize - 1) |
| 99422 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99423 | |
| 99424 | *dst = dt; |
| 99425 | |
| 99426 | ctx->index++; |
| 99427 | return UA_STATUSCODE_GOOD; |
| 99428 | } |
| 99429 | |
| 99430 | DECODE_JSON(StatusCode) { |
| 99431 | return UInt32_decodeJson(ctx, dst, NULL); |
| 99432 | } |
| 99433 | |
| 99434 | static status |
| 99435 | VariantDimension_decodeJson(ParseCtx *ctx, void *dst, const UA_DataType *type) { |
| 99436 | (void) type; |
| 99437 | const UA_DataType *dimType = &UA_TYPES[UA_TYPES_UINT32]; |
| 99438 | return Array_decodeJson(ctx, dst: (void**)dst, type: dimType); |
| 99439 | } |
| 99440 | |
| 99441 | /* Get type type encoded by the ExtensionObject at ctx->index. |
| 99442 | * Returns NULL if that fails (type unknown or otherwise). */ |
| 99443 | static const UA_DataType * |
| 99444 | getExtensionObjectType(ParseCtx *ctx) { |
| 99445 | if(currentTokenType(ctx) != CJ5_TOKEN_OBJECT) |
| 99446 | return NULL; |
| 99447 | |
| 99448 | /* Get the type NodeId index */ |
| 99449 | size_t typeIdIndex = 0; |
| 99450 | UA_StatusCode ret = lookAheadForKey(ctx, key: UA_JSONKEY_TYPEID, resultIndex: &typeIdIndex); |
| 99451 | if(ret != UA_STATUSCODE_GOOD) |
| 99452 | return NULL; |
| 99453 | |
| 99454 | size_t oldIndex = ctx->index; |
| 99455 | ctx->index = typeIdIndex; |
| 99456 | |
| 99457 | /* Decode the type NodeId */ |
| 99458 | UA_NodeId typeId; |
| 99459 | UA_NodeId_init(p: &typeId); |
| 99460 | ret = NodeId_decodeJson(ctx, dst: &typeId, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 99461 | ctx->index = oldIndex; |
| 99462 | if(ret != UA_STATUSCODE_GOOD) { |
| 99463 | UA_NodeId_clear(p: &typeId); /* We don't have the global cleanup */ |
| 99464 | return NULL; |
| 99465 | } |
| 99466 | |
| 99467 | /* Lookup an return */ |
| 99468 | const UA_DataType *type = UA_findDataTypeWithCustom(typeId: &typeId, customTypes: ctx->customTypes); |
| 99469 | UA_NodeId_clear(p: &typeId); |
| 99470 | return type; |
| 99471 | } |
| 99472 | |
| 99473 | /* Check if all array members are ExtensionObjects of the same type. Return this |
| 99474 | * type or NULL. */ |
| 99475 | static const UA_DataType * |
| 99476 | getArrayUnwrapType(ParseCtx *ctx, size_t arrayIndex) { |
| 99477 | UA_assert(ctx->tokens[arrayIndex].type == CJ5_TOKEN_ARRAY); |
| 99478 | |
| 99479 | /* Save index to restore later */ |
| 99480 | size_t oldIndex = ctx->index; |
| 99481 | ctx->index = arrayIndex; |
| 99482 | |
| 99483 | /* Return early for empty arrays */ |
| 99484 | size_t length = (size_t)ctx->tokens[ctx->index].size; |
| 99485 | if(length == 0) { |
| 99486 | ctx->index = oldIndex; /* Restore the index */ |
| 99487 | return NULL; |
| 99488 | } |
| 99489 | |
| 99490 | /* Go to first array member */ |
| 99491 | ctx->index++; |
| 99492 | |
| 99493 | /* Lookup the type for the first array member */ |
| 99494 | UA_NodeId typeId; |
| 99495 | UA_NodeId_init(p: &typeId); |
| 99496 | const UA_DataType *typeOfBody = getExtensionObjectType(ctx); |
| 99497 | if(!typeOfBody) { |
| 99498 | ctx->index = oldIndex; /* Restore the index */ |
| 99499 | return NULL; |
| 99500 | } |
| 99501 | |
| 99502 | /* The content is a builtin type that could have been directly encoded in |
| 99503 | * the Variant, there was no need to wrap in an ExtensionObject. But this |
| 99504 | * means for us, that somebody made an extra effort to explicitly get an |
| 99505 | * ExtensionObject. So we keep it. As an added advantage we will generate |
| 99506 | * the same JSON again when encoding again. */ |
| 99507 | UA_Boolean isBuiltin = (typeOfBody->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO); |
| 99508 | if(isBuiltin) { |
| 99509 | ctx->index = oldIndex; /* Restore the index */ |
| 99510 | return NULL; |
| 99511 | } |
| 99512 | |
| 99513 | /* Get the typeId index for faster comparison below. |
| 99514 | * Cannot fail as getExtensionObjectType already looked this up. */ |
| 99515 | size_t typeIdIndex = 0; |
| 99516 | UA_StatusCode ret = lookAheadForKey(ctx, key: UA_JSONKEY_TYPEID, resultIndex: &typeIdIndex); |
| 99517 | (void)ret; |
| 99518 | UA_assert(ret == UA_STATUSCODE_GOOD); |
| 99519 | const char* typeIdData = &ctx->json5[ctx->tokens[typeIdIndex].start]; |
| 99520 | size_t typeIdSize = getTokenLength(t: &ctx->tokens[typeIdIndex]); |
| 99521 | |
| 99522 | /* Loop over all members and check whether they can be unwrapped */ |
| 99523 | for(size_t i = 0; i < length; i++) { |
| 99524 | /* Array element must be an object */ |
| 99525 | if(currentTokenType(ctx) != CJ5_TOKEN_OBJECT) { |
| 99526 | ctx->index = oldIndex; /* Restore the index */ |
| 99527 | return NULL; |
| 99528 | } |
| 99529 | |
| 99530 | /* Check for non-JSON encoding */ |
| 99531 | size_t encIndex = 0; |
| 99532 | ret = lookAheadForKey(ctx, key: UA_JSONKEY_ENCODING, resultIndex: &encIndex); |
| 99533 | if(ret == UA_STATUSCODE_GOOD) { |
| 99534 | ctx->index = oldIndex; /* Restore the index */ |
| 99535 | return NULL; |
| 99536 | } |
| 99537 | |
| 99538 | /* Get the type NodeId index */ |
| 99539 | size_t memberTypeIdIndex = 0; |
| 99540 | ret = lookAheadForKey(ctx, key: UA_JSONKEY_TYPEID, resultIndex: &memberTypeIdIndex); |
| 99541 | if(ret != UA_STATUSCODE_GOOD) { |
| 99542 | ctx->index = oldIndex; /* Restore the index */ |
| 99543 | return NULL; |
| 99544 | } |
| 99545 | |
| 99546 | /* Is it the same type? Compare raw NodeId string */ |
| 99547 | const char* memberTypeIdData = &ctx->json5[ctx->tokens[memberTypeIdIndex].start]; |
| 99548 | size_t memberTypeIdSize = getTokenLength(t: &ctx->tokens[memberTypeIdIndex]); |
| 99549 | if(typeIdSize != memberTypeIdSize || |
| 99550 | memcmp(s1: typeIdData, s2: memberTypeIdData, n: typeIdSize) != 0) { |
| 99551 | ctx->index = oldIndex; /* Restore the index */ |
| 99552 | return NULL; |
| 99553 | } |
| 99554 | |
| 99555 | /* Skip to the next array member */ |
| 99556 | skipObject(ctx); |
| 99557 | } |
| 99558 | |
| 99559 | ctx->index = oldIndex; /* Restore the index */ |
| 99560 | return typeOfBody; |
| 99561 | } |
| 99562 | |
| 99563 | static status |
| 99564 | Array_decodeJsonUnwrapExtensionObject(ParseCtx *ctx, void **dst, const UA_DataType *type) { |
| 99565 | size_t *size_ptr = (size_t*) dst - 1; /* Save the length pointer of the array */ |
| 99566 | size_t length = (size_t)ctx->tokens[ctx->index].size; |
| 99567 | |
| 99568 | /* Known from the previous unwrapping-check */ |
| 99569 | UA_assert(currentTokenType(ctx) == CJ5_TOKEN_ARRAY); |
| 99570 | UA_assert(length > 0); |
| 99571 | |
| 99572 | ctx->index++; /* Go to first array member */ |
| 99573 | |
| 99574 | /* Allocate memory */ |
| 99575 | *dst = UA_calloc(nmemb: length, size: type->memSize); |
| 99576 | if(*dst == NULL) |
| 99577 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 99578 | |
| 99579 | /* Decode array members */ |
| 99580 | uintptr_t ptr = (uintptr_t)*dst; |
| 99581 | for(size_t i = 0; i < length; i++) { |
| 99582 | UA_assert(ctx->tokens[ctx->index].type == CJ5_TOKEN_OBJECT); |
| 99583 | |
| 99584 | /* Get the body field and decode it */ |
| 99585 | DecodeEntry entries[3] = { |
| 99586 | {UA_JSONKEY_TYPEID, NULL, NULL, false, NULL}, |
| 99587 | {UA_JSONKEY_BODY, (void*)ptr, NULL, false, type}, |
| 99588 | {UA_JSONKEY_ENCODING, NULL, NULL, false, NULL} |
| 99589 | }; |
| 99590 | status ret = decodeFields(ctx, entries, entryCount: 3); /* Also skips to the next object */ |
| 99591 | if(ret != UA_STATUSCODE_GOOD) { |
| 99592 | UA_Array_delete(p: *dst, size: i+1, type); |
| 99593 | *dst = NULL; |
| 99594 | return ret; |
| 99595 | } |
| 99596 | ptr += type->memSize; |
| 99597 | } |
| 99598 | |
| 99599 | *size_ptr = length; /* All good, set the size */ |
| 99600 | return UA_STATUSCODE_GOOD; |
| 99601 | } |
| 99602 | |
| 99603 | DECODE_JSON(Variant) { |
| 99604 | CHECK_NULL_SKIP; /* Treat null as an empty variant */ |
| 99605 | CHECK_OBJECT; |
| 99606 | |
| 99607 | /* First search for the variant type in the json object. */ |
| 99608 | size_t typeIndex = 0; |
| 99609 | status ret = lookAheadForKey(ctx, key: UA_JSONKEY_TYPE, resultIndex: &typeIndex); |
| 99610 | if(ret != UA_STATUSCODE_GOOD) { |
| 99611 | skipObject(ctx); |
| 99612 | return UA_STATUSCODE_GOOD; |
| 99613 | } |
| 99614 | |
| 99615 | /* Parse the type */ |
| 99616 | if(ctx->tokens[typeIndex].type != CJ5_TOKEN_NUMBER) |
| 99617 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99618 | UA_UInt64 idType = 0; |
| 99619 | size_t len = parseUInt64(str: &ctx->json5[ctx->tokens[typeIndex].start], |
| 99620 | size: getTokenLength(t: &ctx->tokens[typeIndex]), result: &idType); |
| 99621 | if(len == 0) |
| 99622 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99623 | |
| 99624 | /* A NULL Variant */ |
| 99625 | if(idType == 0) { |
| 99626 | skipObject(ctx); |
| 99627 | return UA_STATUSCODE_GOOD; |
| 99628 | } |
| 99629 | |
| 99630 | /* Set the type */ |
| 99631 | UA_NodeId typeNodeId = UA_NODEID_NUMERIC(nsIndex: 0, identifier: (UA_UInt32)idType); |
| 99632 | dst->type = UA_findDataTypeWithCustom(typeId: &typeNodeId, customTypes: ctx->customTypes); |
| 99633 | if(!dst->type) |
| 99634 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99635 | |
| 99636 | /* Search for body */ |
| 99637 | size_t bodyIndex = 0; |
| 99638 | ret = lookAheadForKey(ctx, key: UA_JSONKEY_BODY, resultIndex: &bodyIndex); |
| 99639 | if(ret != UA_STATUSCODE_GOOD) |
| 99640 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99641 | |
| 99642 | /* Value is an array? */ |
| 99643 | UA_Boolean isArray = (ctx->tokens[bodyIndex].type == CJ5_TOKEN_ARRAY); |
| 99644 | |
| 99645 | /* TODO: Handling of null-arrays (length -1) needs to be clarified |
| 99646 | * |
| 99647 | * if(tokenIsNull(ctx, bodyIndex)) { |
| 99648 | * isArray = true; |
| 99649 | * dst->arrayLength = 0; |
| 99650 | * } */ |
| 99651 | |
| 99652 | /* Has the variant dimension? */ |
| 99653 | UA_Boolean hasDimension = false; |
| 99654 | size_t dimIndex = 0; |
| 99655 | ret = lookAheadForKey(ctx, key: UA_JSONKEY_DIMENSION, resultIndex: &dimIndex); |
| 99656 | if(ret == UA_STATUSCODE_GOOD) |
| 99657 | hasDimension = (ctx->tokens[dimIndex].size > 0); |
| 99658 | |
| 99659 | /* No array but has dimension -> error */ |
| 99660 | if(!isArray && hasDimension) |
| 99661 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99662 | |
| 99663 | /* Get the datatype of the content. The type must be a builtin data type. |
| 99664 | * All not-builtin types are wrapped in an ExtensionObject. */ |
| 99665 | if(dst->type->typeKind > UA_DATATYPEKIND_DIAGNOSTICINFO) |
| 99666 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99667 | |
| 99668 | /* A variant cannot contain a variant. But it can contain an array of |
| 99669 | * variants */ |
| 99670 | if(dst->type->typeKind == UA_DATATYPEKIND_VARIANT && !isArray) |
| 99671 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99672 | |
| 99673 | /* Decode an array */ |
| 99674 | if(isArray) { |
| 99675 | DecodeEntry entries[3] = { |
| 99676 | {UA_JSONKEY_TYPE, NULL, NULL, false, NULL}, |
| 99677 | {UA_JSONKEY_BODY, &dst->data, (decodeJsonSignature)Array_decodeJson, false, dst->type}, |
| 99678 | {UA_JSONKEY_DIMENSION, &dst->arrayDimensions, VariantDimension_decodeJson, false, NULL} |
| 99679 | }; |
| 99680 | |
| 99681 | /* Try to unwrap ExtensionObjects in the array. |
| 99682 | * The members must all have the same type. */ |
| 99683 | if(dst->type == &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]) { |
| 99684 | const UA_DataType *unwrapType = getArrayUnwrapType(ctx, arrayIndex: bodyIndex); |
| 99685 | if(unwrapType) { |
| 99686 | dst->type = unwrapType; |
| 99687 | entries[1].type = unwrapType; |
| 99688 | entries[1].function = (decodeJsonSignature) |
| 99689 | Array_decodeJsonUnwrapExtensionObject; |
| 99690 | } |
| 99691 | } |
| 99692 | |
| 99693 | return decodeFields(ctx, entries, entryCount: (hasDimension) ? 3 : 2); |
| 99694 | } |
| 99695 | |
| 99696 | /* Decode a value wrapped in an ExtensionObject */ |
| 99697 | if(dst->type->typeKind == UA_DATATYPEKIND_EXTENSIONOBJECT) { |
| 99698 | DecodeEntry entries[2] = { |
| 99699 | {UA_JSONKEY_TYPE, NULL, NULL, false, NULL}, |
| 99700 | {UA_JSONKEY_BODY, dst, Variant_decodeJsonUnwrapExtensionObject, false, NULL} |
| 99701 | }; |
| 99702 | return decodeFields(ctx, entries, entryCount: 2); |
| 99703 | } |
| 99704 | |
| 99705 | /* Allocate Memory for Body */ |
| 99706 | dst->data = UA_new(type: dst->type); |
| 99707 | if(!dst->data) |
| 99708 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 99709 | |
| 99710 | DecodeEntry entries[2] = { |
| 99711 | {.fieldName: UA_JSONKEY_TYPE, NULL, NULL, false, NULL}, |
| 99712 | {UA_JSONKEY_BODY, dst->data, NULL, false, dst->type} |
| 99713 | }; |
| 99714 | return decodeFields(ctx, entries, entryCount: 2); |
| 99715 | } |
| 99716 | |
| 99717 | DECODE_JSON(DataValue) { |
| 99718 | CHECK_NULL_SKIP; /* Treat a null value as an empty DataValue */ |
| 99719 | CHECK_OBJECT; |
| 99720 | |
| 99721 | DecodeEntry entries[6] = { |
| 99722 | {UA_JSONKEY_VALUE, &dst->value, NULL, false, &UA_TYPES[UA_TYPES_VARIANT]}, |
| 99723 | {UA_JSONKEY_STATUS, &dst->status, NULL, false, &UA_TYPES[UA_TYPES_STATUSCODE]}, |
| 99724 | {UA_JSONKEY_SOURCETIMESTAMP, &dst->sourceTimestamp, NULL, false, &UA_TYPES[UA_TYPES_DATETIME]}, |
| 99725 | {UA_JSONKEY_SOURCEPICOSECONDS, &dst->sourcePicoseconds, NULL, false, &UA_TYPES[UA_TYPES_UINT16]}, |
| 99726 | {UA_JSONKEY_SERVERTIMESTAMP, &dst->serverTimestamp, NULL, false, &UA_TYPES[UA_TYPES_DATETIME]}, |
| 99727 | {UA_JSONKEY_SERVERPICOSECONDS, &dst->serverPicoseconds, NULL, false, &UA_TYPES[UA_TYPES_UINT16]} |
| 99728 | }; |
| 99729 | |
| 99730 | status ret = decodeFields(ctx, entries, entryCount: 6); |
| 99731 | dst->hasValue = entries[0].found; |
| 99732 | dst->hasStatus = entries[1].found; |
| 99733 | dst->hasSourceTimestamp = entries[2].found; |
| 99734 | dst->hasSourcePicoseconds = entries[3].found; |
| 99735 | dst->hasServerTimestamp = entries[4].found; |
| 99736 | dst->hasServerPicoseconds = entries[5].found; |
| 99737 | return ret; |
| 99738 | } |
| 99739 | |
| 99740 | /* Move the entire current token into the target bytestring */ |
| 99741 | static UA_StatusCode |
| 99742 | tokenToByteString(ParseCtx *ctx, UA_ByteString *p, const UA_DataType *type) { |
| 99743 | GET_TOKEN; |
| 99744 | UA_StatusCode res = UA_ByteString_allocBuffer(bs: p, length: tokenSize); |
| 99745 | if(res != UA_STATUSCODE_GOOD) |
| 99746 | return res; |
| 99747 | memcpy(dest: p->data, src: tokenData, n: tokenSize); |
| 99748 | skipObject(ctx); |
| 99749 | return UA_STATUSCODE_GOOD; |
| 99750 | } |
| 99751 | |
| 99752 | DECODE_JSON(ExtensionObject) { |
| 99753 | CHECK_NULL_SKIP; /* Treat a null value as an empty DataValue */ |
| 99754 | CHECK_OBJECT; |
| 99755 | |
| 99756 | /* Empty object -> Null ExtensionObject */ |
| 99757 | if(ctx->tokens[ctx->index].size == 0) { |
| 99758 | ctx->index++; /* Skip the empty ExtensionObject */ |
| 99759 | return UA_STATUSCODE_GOOD; |
| 99760 | } |
| 99761 | |
| 99762 | /* Search for non-JSON encoding */ |
| 99763 | UA_UInt64 encoding = 0; |
| 99764 | size_t encIndex = 0; |
| 99765 | status ret = lookAheadForKey(ctx, key: UA_JSONKEY_ENCODING, resultIndex: &encIndex); |
| 99766 | if(ret == UA_STATUSCODE_GOOD) { |
| 99767 | const char *extObjEncoding = &ctx->json5[ctx->tokens[encIndex].start]; |
| 99768 | size_t len = parseUInt64(str: extObjEncoding, size: getTokenLength(t: &ctx->tokens[encIndex]), |
| 99769 | result: &encoding); |
| 99770 | if(len == 0) |
| 99771 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99772 | } |
| 99773 | |
| 99774 | /* Lookup the DataType for the ExtensionObject if the body can be decoded */ |
| 99775 | const UA_DataType *typeOfBody = (encoding == 0) ? getExtensionObjectType(ctx) : NULL; |
| 99776 | |
| 99777 | /* Keep the encoded body */ |
| 99778 | if(!typeOfBody) { |
| 99779 | DecodeEntry entries[3] = { |
| 99780 | {UA_JSONKEY_ENCODING, NULL, NULL, false, NULL}, |
| 99781 | {UA_JSONKEY_TYPEID, &dst->content.encoded.typeId, NULL, false, &UA_TYPES[UA_TYPES_NODEID]}, |
| 99782 | {UA_JSONKEY_BODY, &dst->content.encoded.body, NULL, false, &UA_TYPES[UA_TYPES_STRING]} |
| 99783 | }; |
| 99784 | |
| 99785 | if(encoding == 0) { |
| 99786 | entries[2].function = (decodeJsonSignature)tokenToByteString; |
| 99787 | dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING; /* ByteString in Json Body */ |
| 99788 | } else if(encoding == 1) { |
| 99789 | dst->encoding = UA_EXTENSIONOBJECT_ENCODED_BYTESTRING; /* ByteString in Json Body */ |
| 99790 | } else if(encoding == 2) { |
| 99791 | dst->encoding = UA_EXTENSIONOBJECT_ENCODED_XML; /* XmlElement in Json Body */ |
| 99792 | } else { |
| 99793 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99794 | } |
| 99795 | return decodeFields(ctx, entries, entryCount: 3); |
| 99796 | } |
| 99797 | |
| 99798 | /* Allocate memory for the decoded data */ |
| 99799 | dst->content.decoded.data = UA_new(type: typeOfBody); |
| 99800 | if(!dst->content.decoded.data) |
| 99801 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 99802 | |
| 99803 | /* Set type */ |
| 99804 | dst->content.decoded.type = typeOfBody; |
| 99805 | dst->encoding = UA_EXTENSIONOBJECT_DECODED; |
| 99806 | |
| 99807 | /* Decode body */ |
| 99808 | DecodeEntry entries[3] = { |
| 99809 | {UA_JSONKEY_ENCODING, NULL, NULL, false, NULL}, |
| 99810 | {UA_JSONKEY_TYPEID, NULL, NULL, false, NULL}, |
| 99811 | {UA_JSONKEY_BODY, dst->content.decoded.data, NULL, false, typeOfBody} |
| 99812 | }; |
| 99813 | return decodeFields(ctx, entries, entryCount: 3); |
| 99814 | } |
| 99815 | |
| 99816 | static status |
| 99817 | Variant_decodeJsonUnwrapExtensionObject(ParseCtx *ctx, void *p, const UA_DataType *type) { |
| 99818 | (void) type; |
| 99819 | UA_Variant *dst = (UA_Variant*)p; |
| 99820 | |
| 99821 | /* ExtensionObject with null body */ |
| 99822 | if(currentTokenType(ctx) == CJ5_TOKEN_NULL) { |
| 99823 | dst->data = UA_ExtensionObject_new(); |
| 99824 | dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]; |
| 99825 | ctx->index++; |
| 99826 | return UA_STATUSCODE_GOOD; |
| 99827 | } |
| 99828 | |
| 99829 | /* Decode the ExtensionObject */ |
| 99830 | UA_ExtensionObject eo; |
| 99831 | UA_ExtensionObject_init(p: &eo); |
| 99832 | UA_StatusCode ret = ExtensionObject_decodeJson(ctx, dst: &eo, NULL); |
| 99833 | if(ret != UA_STATUSCODE_GOOD) { |
| 99834 | UA_ExtensionObject_clear(p: &eo); /* We don't have the global cleanup */ |
| 99835 | return ret; |
| 99836 | } |
| 99837 | |
| 99838 | /* The content is still encoded, cannot unwrap */ |
| 99839 | if(eo.encoding != UA_EXTENSIONOBJECT_DECODED) |
| 99840 | goto use_eo; |
| 99841 | |
| 99842 | /* The content is a builtin type that could have been directly encoded in |
| 99843 | * the Variant, there was no need to wrap in an ExtensionObject. But this |
| 99844 | * means for us, that somebody made an extra effort to explicitly get an |
| 99845 | * ExtensionObject. So we keep it. As an added advantage we will generate |
| 99846 | * the same JSON again when encoding again. */ |
| 99847 | UA_Boolean isBuiltin = |
| 99848 | (eo.content.decoded.type->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO); |
| 99849 | if(isBuiltin) |
| 99850 | goto use_eo; |
| 99851 | |
| 99852 | /* Unwrap the ExtensionObject */ |
| 99853 | dst->data = eo.content.decoded.data; |
| 99854 | dst->type = eo.content.decoded.type; |
| 99855 | return UA_STATUSCODE_GOOD; |
| 99856 | |
| 99857 | use_eo: |
| 99858 | /* Don't unwrap */ |
| 99859 | dst->data = UA_new(type: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]); |
| 99860 | if(!dst->data) { |
| 99861 | UA_ExtensionObject_clear(p: &eo); |
| 99862 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 99863 | } |
| 99864 | dst->type = &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]; |
| 99865 | *(UA_ExtensionObject*)dst->data = eo; |
| 99866 | return UA_STATUSCODE_GOOD; |
| 99867 | } |
| 99868 | |
| 99869 | status |
| 99870 | DiagnosticInfoInner_decodeJson(ParseCtx* ctx, void* dst, const UA_DataType* type); |
| 99871 | |
| 99872 | DECODE_JSON(DiagnosticInfo) { |
| 99873 | CHECK_NULL_SKIP; /* Treat a null value as an empty DiagnosticInfo */ |
| 99874 | CHECK_OBJECT; |
| 99875 | |
| 99876 | DecodeEntry entries[7] = { |
| 99877 | {UA_JSONKEY_SYMBOLICID, &dst->symbolicId, NULL, false, &UA_TYPES[UA_TYPES_INT32]}, |
| 99878 | {UA_JSONKEY_NAMESPACEURI, &dst->namespaceUri, NULL, false, &UA_TYPES[UA_TYPES_INT32]}, |
| 99879 | {UA_JSONKEY_LOCALIZEDTEXT, &dst->localizedText, NULL, false, &UA_TYPES[UA_TYPES_INT32]}, |
| 99880 | {UA_JSONKEY_LOCALE, &dst->locale, NULL, false, &UA_TYPES[UA_TYPES_INT32]}, |
| 99881 | {UA_JSONKEY_ADDITIONALINFO, &dst->additionalInfo, NULL, false, &UA_TYPES[UA_TYPES_STRING]}, |
| 99882 | {UA_JSONKEY_INNERSTATUSCODE, &dst->innerStatusCode, NULL, false, &UA_TYPES[UA_TYPES_STATUSCODE]}, |
| 99883 | {UA_JSONKEY_INNERDIAGNOSTICINFO, &dst->innerDiagnosticInfo, DiagnosticInfoInner_decodeJson, false, NULL} |
| 99884 | }; |
| 99885 | status ret = decodeFields(ctx, entries, entryCount: 7); |
| 99886 | |
| 99887 | dst->hasSymbolicId = entries[0].found; |
| 99888 | dst->hasNamespaceUri = entries[1].found; |
| 99889 | dst->hasLocalizedText = entries[2].found; |
| 99890 | dst->hasLocale = entries[3].found; |
| 99891 | dst->hasAdditionalInfo = entries[4].found; |
| 99892 | dst->hasInnerStatusCode = entries[5].found; |
| 99893 | dst->hasInnerDiagnosticInfo = entries[6].found; |
| 99894 | return ret; |
| 99895 | } |
| 99896 | |
| 99897 | status |
| 99898 | DiagnosticInfoInner_decodeJson(ParseCtx* ctx, void* dst, const UA_DataType* type) { |
| 99899 | UA_DiagnosticInfo *inner = (UA_DiagnosticInfo*) |
| 99900 | UA_calloc(nmemb: 1, size: sizeof(UA_DiagnosticInfo)); |
| 99901 | if(!inner) |
| 99902 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 99903 | UA_DiagnosticInfo **dst2 = (UA_DiagnosticInfo**)dst; |
| 99904 | *dst2 = inner; /* Copy new Pointer do dest */ |
| 99905 | return DiagnosticInfo_decodeJson(ctx, dst: inner, type); |
| 99906 | } |
| 99907 | |
| 99908 | status |
| 99909 | decodeFields(ParseCtx *ctx, DecodeEntry *entries, size_t entryCount) { |
| 99910 | CHECK_TOKEN_BOUNDS; |
| 99911 | CHECK_NULL_SKIP; /* null is treated like an empty object */ |
| 99912 | |
| 99913 | if(ctx->depth >= UA_JSON_ENCODING_MAX_RECURSION - 1) |
| 99914 | return UA_STATUSCODE_BADENCODINGERROR; |
| 99915 | |
| 99916 | /* Keys and values are counted separately */ |
| 99917 | CHECK_OBJECT; |
| 99918 | UA_assert(ctx->tokens[ctx->index].size % 2 == 0); |
| 99919 | size_t keyCount = (size_t)(ctx->tokens[ctx->index].size) / 2; |
| 99920 | |
| 99921 | ctx->index++; /* Go to first key - or jump after the empty object */ |
| 99922 | ctx->depth++; |
| 99923 | |
| 99924 | status ret = UA_STATUSCODE_GOOD; |
| 99925 | for(size_t key = 0; key < keyCount; key++) { |
| 99926 | /* Key must be a string */ |
| 99927 | UA_assert(ctx->index < ctx->tokensSize); |
| 99928 | UA_assert(currentTokenType(ctx) == CJ5_TOKEN_STRING); |
| 99929 | |
| 99930 | /* Search for the decoding entry matching the key. Start at the key |
| 99931 | * index to speed-up the case where they key-order is the same as the |
| 99932 | * entry-order. */ |
| 99933 | DecodeEntry *entry = NULL; |
| 99934 | for(size_t i = key; i < key + entryCount; i++) { |
| 99935 | size_t ii = i; |
| 99936 | while(ii >= entryCount) |
| 99937 | ii -= entryCount; |
| 99938 | |
| 99939 | /* Compare the key */ |
| 99940 | if(jsoneq(json: ctx->json5, tok: &ctx->tokens[ctx->index], |
| 99941 | searchKey: entries[ii].fieldName) != 0) |
| 99942 | continue; |
| 99943 | |
| 99944 | /* Key was already used -> duplicate, abort */ |
| 99945 | if(entries[ii].found) { |
| 99946 | ctx->depth--; |
| 99947 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99948 | } |
| 99949 | |
| 99950 | /* Found the key */ |
| 99951 | entries[ii].found = true; |
| 99952 | entry = &entries[ii]; |
| 99953 | break; |
| 99954 | } |
| 99955 | |
| 99956 | /* The key is unknown */ |
| 99957 | if(!entry) { |
| 99958 | ret = UA_STATUSCODE_BADDECODINGERROR; |
| 99959 | break; |
| 99960 | } |
| 99961 | |
| 99962 | /* Go from key to value */ |
| 99963 | ctx->index++; |
| 99964 | UA_assert(ctx->index < ctx->tokensSize); |
| 99965 | |
| 99966 | /* An entry that was expected but shall not be decoded. |
| 99967 | * Jump over the value. */ |
| 99968 | if(!entry->function && !entry->type) { |
| 99969 | skipObject(ctx); |
| 99970 | continue; |
| 99971 | } |
| 99972 | |
| 99973 | /* A null-value, skip the decoding (the value is already initialized) */ |
| 99974 | if(currentTokenType(ctx) == CJ5_TOKEN_NULL && !entry->function) { |
| 99975 | ctx->index++; /* skip null value */ |
| 99976 | continue; |
| 99977 | } |
| 99978 | |
| 99979 | /* Decode. This also moves to the next key or right after the object for |
| 99980 | * the last value. */ |
| 99981 | decodeJsonSignature decodeFunc = (entry->function) ? |
| 99982 | entry->function : decodeJsonJumpTable[entry->type->typeKind]; |
| 99983 | ret = decodeFunc(ctx, entry->fieldPointer, entry->type); |
| 99984 | if(ret != UA_STATUSCODE_GOOD) |
| 99985 | break; |
| 99986 | } |
| 99987 | |
| 99988 | ctx->depth--; |
| 99989 | return ret; |
| 99990 | } |
| 99991 | |
| 99992 | static status |
| 99993 | Array_decodeJson(ParseCtx *ctx, void **dst, const UA_DataType *type) { |
| 99994 | /* Save the length of the array */ |
| 99995 | size_t *size_ptr = (size_t*) dst - 1; |
| 99996 | |
| 99997 | if(currentTokenType(ctx) != CJ5_TOKEN_ARRAY) |
| 99998 | return UA_STATUSCODE_BADDECODINGERROR; |
| 99999 | |
| 100000 | size_t length = (size_t)ctx->tokens[ctx->index].size; |
| 100001 | |
| 100002 | ctx->index++; /* Go to first array member or to the first element after |
| 100003 | * the array (if empty) */ |
| 100004 | |
| 100005 | /* Return early for empty arrays */ |
| 100006 | if(length == 0) { |
| 100007 | *size_ptr = length; |
| 100008 | *dst = UA_EMPTY_ARRAY_SENTINEL; |
| 100009 | return UA_STATUSCODE_GOOD; |
| 100010 | } |
| 100011 | |
| 100012 | /* Allocate memory */ |
| 100013 | *dst = UA_calloc(nmemb: length, size: type->memSize); |
| 100014 | if(*dst == NULL) |
| 100015 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 100016 | |
| 100017 | /* Decode array members */ |
| 100018 | uintptr_t ptr = (uintptr_t)*dst; |
| 100019 | for(size_t i = 0; i < length; ++i) { |
| 100020 | if(ctx->tokens[ctx->index].type != CJ5_TOKEN_NULL) { |
| 100021 | status ret = decodeJsonJumpTable[type->typeKind](ctx, (void*)ptr, type); |
| 100022 | if(ret != UA_STATUSCODE_GOOD) { |
| 100023 | UA_Array_delete(p: *dst, size: i+1, type); |
| 100024 | *dst = NULL; |
| 100025 | return ret; |
| 100026 | } |
| 100027 | } else { |
| 100028 | ctx->index++; |
| 100029 | } |
| 100030 | ptr += type->memSize; |
| 100031 | } |
| 100032 | |
| 100033 | *size_ptr = length; /* All good, set the size */ |
| 100034 | return UA_STATUSCODE_GOOD; |
| 100035 | } |
| 100036 | |
| 100037 | static status |
| 100038 | decodeJsonStructure(ParseCtx *ctx, void *dst, const UA_DataType *type) { |
| 100039 | /* Check the recursion limit */ |
| 100040 | if(ctx->depth >= UA_JSON_ENCODING_MAX_RECURSION - 1) |
| 100041 | return UA_STATUSCODE_BADENCODINGERROR; |
| 100042 | ctx->depth++; |
| 100043 | |
| 100044 | uintptr_t ptr = (uintptr_t)dst; |
| 100045 | status ret = UA_STATUSCODE_GOOD; |
| 100046 | u8 membersSize = type->membersSize; |
| 100047 | UA_STACKARRAY(DecodeEntry, entries, membersSize); |
| 100048 | for(size_t i = 0; i < membersSize; ++i) { |
| 100049 | const UA_DataTypeMember *m = &type->members[i]; |
| 100050 | const UA_DataType *mt = m->memberType; |
| 100051 | entries[i].type = mt; |
| 100052 | entries[i].fieldName = m->memberName; |
| 100053 | entries[i].found = false; |
| 100054 | if(!m->isArray) { |
| 100055 | ptr += m->padding; |
| 100056 | entries[i].fieldPointer = (void*)ptr; |
| 100057 | entries[i].function = NULL; |
| 100058 | ptr += mt->memSize; |
| 100059 | } else { |
| 100060 | ptr += m->padding; |
| 100061 | ptr += sizeof(size_t); |
| 100062 | entries[i].fieldPointer = (void*)ptr; |
| 100063 | entries[i].function = (decodeJsonSignature)Array_decodeJson; |
| 100064 | ptr += sizeof(void*); |
| 100065 | } |
| 100066 | } |
| 100067 | |
| 100068 | ret = decodeFields(ctx, entries, entryCount: membersSize); |
| 100069 | |
| 100070 | if(ctx->depth == 0) |
| 100071 | return UA_STATUSCODE_BADENCODINGERROR; |
| 100072 | ctx->depth--; |
| 100073 | return ret; |
| 100074 | } |
| 100075 | |
| 100076 | static status |
| 100077 | decodeJsonNotImplemented(ParseCtx *ctx, void *dst, const UA_DataType *type) { |
| 100078 | (void)dst, (void)type, (void)ctx; |
| 100079 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 100080 | } |
| 100081 | |
| 100082 | const decodeJsonSignature decodeJsonJumpTable[UA_DATATYPEKINDS] = { |
| 100083 | (decodeJsonSignature)Boolean_decodeJson, |
| 100084 | (decodeJsonSignature)SByte_decodeJson, /* SByte */ |
| 100085 | (decodeJsonSignature)Byte_decodeJson, |
| 100086 | (decodeJsonSignature)Int16_decodeJson, /* Int16 */ |
| 100087 | (decodeJsonSignature)UInt16_decodeJson, |
| 100088 | (decodeJsonSignature)Int32_decodeJson, /* Int32 */ |
| 100089 | (decodeJsonSignature)UInt32_decodeJson, |
| 100090 | (decodeJsonSignature)Int64_decodeJson, /* Int64 */ |
| 100091 | (decodeJsonSignature)UInt64_decodeJson, |
| 100092 | (decodeJsonSignature)Float_decodeJson, |
| 100093 | (decodeJsonSignature)Double_decodeJson, |
| 100094 | (decodeJsonSignature)String_decodeJson, |
| 100095 | (decodeJsonSignature)DateTime_decodeJson, /* DateTime */ |
| 100096 | (decodeJsonSignature)Guid_decodeJson, |
| 100097 | (decodeJsonSignature)ByteString_decodeJson, /* ByteString */ |
| 100098 | (decodeJsonSignature)String_decodeJson, /* XmlElement */ |
| 100099 | (decodeJsonSignature)NodeId_decodeJson, |
| 100100 | (decodeJsonSignature)ExpandedNodeId_decodeJson, |
| 100101 | (decodeJsonSignature)StatusCode_decodeJson, /* StatusCode */ |
| 100102 | (decodeJsonSignature)QualifiedName_decodeJson, /* QualifiedName */ |
| 100103 | (decodeJsonSignature)LocalizedText_decodeJson, |
| 100104 | (decodeJsonSignature)ExtensionObject_decodeJson, |
| 100105 | (decodeJsonSignature)DataValue_decodeJson, |
| 100106 | (decodeJsonSignature)Variant_decodeJson, |
| 100107 | (decodeJsonSignature)DiagnosticInfo_decodeJson, |
| 100108 | (decodeJsonSignature)decodeJsonNotImplemented, /* Decimal */ |
| 100109 | (decodeJsonSignature)Int32_decodeJson, /* Enum */ |
| 100110 | (decodeJsonSignature)decodeJsonStructure, |
| 100111 | (decodeJsonSignature)decodeJsonNotImplemented, /* Structure with optional fields */ |
| 100112 | (decodeJsonSignature)decodeJsonNotImplemented, /* Union */ |
| 100113 | (decodeJsonSignature)decodeJsonNotImplemented /* BitfieldCluster */ |
| 100114 | }; |
| 100115 | |
| 100116 | status |
| 100117 | tokenize(ParseCtx *ctx, const UA_ByteString *src, size_t tokensSize) { |
| 100118 | /* Tokenize */ |
| 100119 | cj5_result r = cj5_parse(json5: (char*)src->data, len: (unsigned int)src->length, |
| 100120 | tokens: ctx->tokens, max_tokens: (unsigned int)tokensSize, NULL); |
| 100121 | |
| 100122 | /* Handle overflow error by allocating the number of tokens the parser would |
| 100123 | * have needed */ |
| 100124 | if(r.error == CJ5_ERROR_OVERFLOW && |
| 100125 | tokensSize != r.num_tokens) { |
| 100126 | ctx->tokens = (cj5_token*) |
| 100127 | UA_malloc(size: sizeof(cj5_token) * r.num_tokens); |
| 100128 | if(!ctx->tokens) |
| 100129 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 100130 | return tokenize(ctx, src, tokensSize: r.num_tokens); |
| 100131 | } |
| 100132 | |
| 100133 | /* Cannot recover from other errors */ |
| 100134 | if(r.error != CJ5_ERROR_NONE) |
| 100135 | return UA_STATUSCODE_BADDECODINGERROR; |
| 100136 | |
| 100137 | /* Set up the context */ |
| 100138 | ctx->json5 = (char*)src->data; |
| 100139 | ctx->depth = 0; |
| 100140 | ctx->tokensSize = r.num_tokens; |
| 100141 | ctx->index = 0; |
| 100142 | return UA_STATUSCODE_GOOD; |
| 100143 | } |
| 100144 | |
| 100145 | UA_StatusCode |
| 100146 | UA_decodeJson(const UA_ByteString *src, void *dst, const UA_DataType *type, |
| 100147 | const UA_DecodeJsonOptions *options) { |
| 100148 | if(!dst || !src || !type) |
| 100149 | return UA_STATUSCODE_BADARGUMENTSMISSING; |
| 100150 | |
| 100151 | /* Set up the context */ |
| 100152 | cj5_token tokens[UA_JSON_MAXTOKENCOUNT]; |
| 100153 | ParseCtx ctx; |
| 100154 | memset(s: &ctx, c: 0, n: sizeof(ParseCtx)); |
| 100155 | ctx.tokens = tokens; |
| 100156 | |
| 100157 | if(options) { |
| 100158 | ctx.namespaces = options->namespaces; |
| 100159 | ctx.namespacesSize = options->namespacesSize; |
| 100160 | ctx.serverUris = options->serverUris; |
| 100161 | ctx.serverUrisSize = options->serverUrisSize; |
| 100162 | ctx.customTypes = options->customTypes; |
| 100163 | } |
| 100164 | |
| 100165 | /* Decode */ |
| 100166 | status ret = tokenize(ctx: &ctx, src, UA_JSON_MAXTOKENCOUNT); |
| 100167 | if(ret != UA_STATUSCODE_GOOD) |
| 100168 | goto cleanup; |
| 100169 | |
| 100170 | memset(s: dst, c: 0, n: type->memSize); /* Initialize the value */ |
| 100171 | ret = decodeJsonJumpTable[type->typeKind](&ctx, dst, type); |
| 100172 | |
| 100173 | /* Sanity check if all tokens were processed */ |
| 100174 | if(ctx.index != ctx.tokensSize && |
| 100175 | ctx.index != ctx.tokensSize - 1) |
| 100176 | ret = UA_STATUSCODE_BADDECODINGERROR; |
| 100177 | |
| 100178 | cleanup: |
| 100179 | |
| 100180 | /* Free token array on the heap */ |
| 100181 | if(ctx.tokens != tokens) |
| 100182 | UA_free(ptr: (void*)(uintptr_t)ctx.tokens); |
| 100183 | |
| 100184 | if(ret != UA_STATUSCODE_GOOD) |
| 100185 | UA_clear(p: dst, type); |
| 100186 | return ret; |
| 100187 | } |
| 100188 | |
| 100189 | #endif /* UA_ENABLE_JSON_ENCODING */ |
| 100190 | |
| 100191 | /**** amalgamated original file "/src/server/ua_subscription.c" ****/ |
| 100192 | |
| 100193 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 100194 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 100195 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 100196 | * |
| 100197 | * Copyright 2015-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 100198 | * Copyright 2015 (c) Chris Iatrou |
| 100199 | * Copyright 2015-2016 (c) Sten Grüner |
| 100200 | * Copyright 2017-2018 (c) Thomas Stalder, Blue Time Concept SA |
| 100201 | * Copyright 2015 (c) Joakim L. Gilje |
| 100202 | * Copyright 2016-2017 (c) Florian Palm |
| 100203 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 100204 | * Copyright 2017 (c) frax2222 |
| 100205 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 100206 | * Copyright 2017 (c) Ari Breitkreuz, fortiss GmbH |
| 100207 | * Copyright 2017 (c) Mattias Bornhager |
| 100208 | * Copyright 2018 (c) Hilscher Gesellschaft für Systemautomation mbH (Author: Martin Lang) |
| 100209 | * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 100210 | */ |
| 100211 | |
| 100212 | |
| 100213 | #ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */ |
| 100214 | |
| 100215 | #define UA_MAX_RETRANSMISSIONQUEUESIZE 256 |
| 100216 | |
| 100217 | UA_Subscription * |
| 100218 | UA_Subscription_new(void) { |
| 100219 | /* Allocate the memory */ |
| 100220 | UA_Subscription *newSub = (UA_Subscription*)UA_calloc(nmemb: 1, size: sizeof(UA_Subscription)); |
| 100221 | if(!newSub) |
| 100222 | return NULL; |
| 100223 | |
| 100224 | /* The first publish response is sent immediately */ |
| 100225 | newSub->state = UA_SUBSCRIPTIONSTATE_STOPPED; |
| 100226 | |
| 100227 | /* Even if the first publish response is a keepalive the sequence number is 1. |
| 100228 | * This can happen by a subscription without a monitored item (see CTT test scripts). */ |
| 100229 | newSub->nextSequenceNumber = 1; |
| 100230 | |
| 100231 | TAILQ_INIT(&newSub->retransmissionQueue); |
| 100232 | TAILQ_INIT(&newSub->notificationQueue); |
| 100233 | return newSub; |
| 100234 | } |
| 100235 | |
| 100236 | static void |
| 100237 | delayedFreeSubscription(void *app, void *context) { |
| 100238 | UA_free(ptr: context); |
| 100239 | } |
| 100240 | |
| 100241 | void |
| 100242 | UA_Subscription_delete(UA_Server *server, UA_Subscription *sub) { |
| 100243 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 100244 | |
| 100245 | UA_EventLoop *el = server->config.eventLoop; |
| 100246 | |
| 100247 | /* Unregister the publish callback and possible delayed callback */ |
| 100248 | Subscription_setState(server, sub, state: UA_SUBSCRIPTIONSTATE_REMOVING); |
| 100249 | |
| 100250 | /* Remove delayed callbacks for processing remaining notifications */ |
| 100251 | if(sub->delayedCallbackRegistered) { |
| 100252 | el->removeDelayedCallback(el, &sub->delayedMoreNotifications); |
| 100253 | sub->delayedCallbackRegistered = false; |
| 100254 | } |
| 100255 | |
| 100256 | /* Remove the diagnostics object for the subscription */ |
| 100257 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 100258 | if(!UA_NodeId_isNull(p: &sub->ns0Id)) |
| 100259 | deleteNode(server, nodeId: sub->ns0Id, true); |
| 100260 | UA_NodeId_clear(p: &sub->ns0Id); |
| 100261 | #endif |
| 100262 | |
| 100263 | UA_LOG_INFO_SUBSCRIPTION(server->config.logging, sub, "Subscription deleted"); |
| 100264 | |
| 100265 | /* Detach from the session if necessary */ |
| 100266 | if(sub->session) |
| 100267 | UA_Session_detachSubscription(server, session: sub->session, sub, true); |
| 100268 | |
| 100269 | /* Remove from the server if not previously registered */ |
| 100270 | if(sub->serverListEntry.le_prev) { |
| 100271 | LIST_REMOVE(sub, serverListEntry); |
| 100272 | UA_assert(server->subscriptionsSize > 0); |
| 100273 | server->subscriptionsSize--; |
| 100274 | server->serverDiagnosticsSummary.currentSubscriptionCount--; |
| 100275 | } |
| 100276 | |
| 100277 | /* Delete monitored Items */ |
| 100278 | UA_assert(server->monitoredItemsSize >= sub->monitoredItemsSize); |
| 100279 | UA_MonitoredItem *mon, *tmp_mon; |
| 100280 | LIST_FOREACH_SAFE(mon, &sub->monitoredItems, listEntry, tmp_mon) { |
| 100281 | UA_MonitoredItem_delete(server, mon); |
| 100282 | } |
| 100283 | UA_assert(sub->monitoredItemsSize == 0); |
| 100284 | |
| 100285 | /* Delete Retransmission Queue */ |
| 100286 | UA_NotificationMessageEntry *nme, *nme_tmp; |
| 100287 | TAILQ_FOREACH_SAFE(nme, &sub->retransmissionQueue, listEntry, nme_tmp) { |
| 100288 | TAILQ_REMOVE(&sub->retransmissionQueue, nme, listEntry); |
| 100289 | UA_NotificationMessage_clear(p: &nme->message); |
| 100290 | UA_free(ptr: nme); |
| 100291 | if(sub->session) |
| 100292 | --sub->session->totalRetransmissionQueueSize; |
| 100293 | --sub->retransmissionQueueSize; |
| 100294 | } |
| 100295 | UA_assert(sub->retransmissionQueueSize == 0); |
| 100296 | |
| 100297 | /* Pointers to the subscription may still exist upwards in the call stack. |
| 100298 | * Add a delayed callback to remove the Subscription when the current jobs |
| 100299 | * have completed. */ |
| 100300 | sub->delayedFreePointers.callback = delayedFreeSubscription; |
| 100301 | sub->delayedFreePointers.application = NULL; |
| 100302 | sub->delayedFreePointers.context = sub; |
| 100303 | el->addDelayedCallback(el, &sub->delayedFreePointers); |
| 100304 | } |
| 100305 | |
| 100306 | void |
| 100307 | Subscription_resetLifetime(UA_Subscription *sub) { |
| 100308 | sub->currentLifetimeCount = 0; |
| 100309 | } |
| 100310 | |
| 100311 | UA_MonitoredItem * |
| 100312 | UA_Subscription_getMonitoredItem(UA_Subscription *sub, UA_UInt32 monitoredItemId) { |
| 100313 | UA_MonitoredItem *mon; |
| 100314 | LIST_FOREACH(mon, &sub->monitoredItems, listEntry) { |
| 100315 | if(mon->monitoredItemId == monitoredItemId) |
| 100316 | break; |
| 100317 | } |
| 100318 | return mon; |
| 100319 | } |
| 100320 | |
| 100321 | static void |
| 100322 | removeOldestRetransmissionMessageFromSub(UA_Subscription *sub) { |
| 100323 | UA_NotificationMessageEntry *oldestEntry = |
| 100324 | TAILQ_LAST(&sub->retransmissionQueue, NotificationMessageQueue); |
| 100325 | TAILQ_REMOVE(&sub->retransmissionQueue, oldestEntry, listEntry); |
| 100326 | UA_NotificationMessage_clear(p: &oldestEntry->message); |
| 100327 | UA_free(ptr: oldestEntry); |
| 100328 | --sub->retransmissionQueueSize; |
| 100329 | if(sub->session) |
| 100330 | --sub->session->totalRetransmissionQueueSize; |
| 100331 | |
| 100332 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 100333 | sub->discardedMessageCount++; |
| 100334 | #endif |
| 100335 | } |
| 100336 | |
| 100337 | static void |
| 100338 | removeOldestRetransmissionMessageFromSession(UA_Session *session) { |
| 100339 | UA_NotificationMessageEntry *oldestEntry = NULL; |
| 100340 | UA_Subscription *oldestSub = NULL; |
| 100341 | UA_Subscription *sub; |
| 100342 | TAILQ_FOREACH(sub, &session->subscriptions, sessionListEntry) { |
| 100343 | UA_NotificationMessageEntry *first = |
| 100344 | TAILQ_LAST(&sub->retransmissionQueue, NotificationMessageQueue); |
| 100345 | if(!first) |
| 100346 | continue; |
| 100347 | if(!oldestEntry || oldestEntry->message.publishTime > first->message.publishTime) { |
| 100348 | oldestEntry = first; |
| 100349 | oldestSub = sub; |
| 100350 | } |
| 100351 | } |
| 100352 | UA_assert(oldestEntry); |
| 100353 | UA_assert(oldestSub); |
| 100354 | |
| 100355 | removeOldestRetransmissionMessageFromSub(sub: oldestSub); |
| 100356 | } |
| 100357 | |
| 100358 | static void |
| 100359 | UA_Subscription_addRetransmissionMessage(UA_Server *server, UA_Subscription *sub, |
| 100360 | UA_NotificationMessageEntry *entry) { |
| 100361 | /* Release the oldest entry if there is not enough space */ |
| 100362 | UA_Session *session = sub->session; |
| 100363 | if(sub->retransmissionQueueSize >= UA_MAX_RETRANSMISSIONQUEUESIZE) { |
| 100364 | UA_LOG_WARNING_SUBSCRIPTION(server->config.logging, sub, |
| 100365 | "Subscription retransmission queue overflow"); |
| 100366 | removeOldestRetransmissionMessageFromSub(sub); |
| 100367 | } else if(session && server->config.maxRetransmissionQueueSize > 0 && |
| 100368 | session->totalRetransmissionQueueSize >= |
| 100369 | server->config.maxRetransmissionQueueSize) { |
| 100370 | UA_LOG_WARNING_SUBSCRIPTION(server->config.logging, sub, |
| 100371 | "Session-wide retransmission queue overflow"); |
| 100372 | removeOldestRetransmissionMessageFromSession(session: sub->session); |
| 100373 | } |
| 100374 | |
| 100375 | /* Add entry */ |
| 100376 | TAILQ_INSERT_TAIL(&sub->retransmissionQueue, entry, listEntry); |
| 100377 | ++sub->retransmissionQueueSize; |
| 100378 | if(session) |
| 100379 | ++session->totalRetransmissionQueueSize; |
| 100380 | } |
| 100381 | |
| 100382 | UA_StatusCode |
| 100383 | UA_Subscription_removeRetransmissionMessage(UA_Subscription *sub, UA_UInt32 sequenceNumber) { |
| 100384 | /* Find the retransmission message */ |
| 100385 | UA_NotificationMessageEntry *entry; |
| 100386 | TAILQ_FOREACH(entry, &sub->retransmissionQueue, listEntry) { |
| 100387 | if(entry->message.sequenceNumber == sequenceNumber) |
| 100388 | break; |
| 100389 | } |
| 100390 | if(!entry) |
| 100391 | return UA_STATUSCODE_BADSEQUENCENUMBERUNKNOWN; |
| 100392 | |
| 100393 | /* Remove the retransmission message */ |
| 100394 | TAILQ_REMOVE(&sub->retransmissionQueue, entry, listEntry); |
| 100395 | --sub->retransmissionQueueSize; |
| 100396 | UA_NotificationMessage_clear(p: &entry->message); |
| 100397 | UA_free(ptr: entry); |
| 100398 | |
| 100399 | if(sub->session) |
| 100400 | --sub->session->totalRetransmissionQueueSize; |
| 100401 | |
| 100402 | return UA_STATUSCODE_GOOD; |
| 100403 | } |
| 100404 | |
| 100405 | /* The output counters are only set when the preparation is successful */ |
| 100406 | static UA_StatusCode |
| 100407 | prepareNotificationMessage(UA_Server *server, UA_Subscription *sub, |
| 100408 | UA_NotificationMessage *message, |
| 100409 | size_t maxNotifications) { |
| 100410 | UA_assert(maxNotifications > 0); |
| 100411 | |
| 100412 | /* Allocate an ExtensionObject for Event- and DataChange-Notifications. Also |
| 100413 | * there can be StatusChange-Notifications. The standard says in Part 4, |
| 100414 | * 7.2.1: |
| 100415 | * |
| 100416 | * If a Subscription contains MonitoredItems for events and data, this array |
| 100417 | * should have not more than 2 elements. */ |
| 100418 | message->notificationData = (UA_ExtensionObject*) |
| 100419 | UA_Array_new(size: 2, type: &UA_TYPES[UA_TYPES_EXTENSIONOBJECT]); |
| 100420 | if(!message->notificationData) |
| 100421 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 100422 | message->notificationDataSize = 2; |
| 100423 | |
| 100424 | /* Pre-allocate DataChangeNotifications */ |
| 100425 | size_t notificationDataIdx = 0; |
| 100426 | size_t dcnPos = 0; /* How many DataChangeNotifications? */ |
| 100427 | UA_DataChangeNotification *dcn = NULL; |
| 100428 | if(sub->dataChangeNotifications > 0) { |
| 100429 | dcn = UA_DataChangeNotification_new(); |
| 100430 | if(!dcn) { |
| 100431 | UA_NotificationMessage_clear(p: message); |
| 100432 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 100433 | } |
| 100434 | UA_ExtensionObject_setValue(eo: message->notificationData, p: dcn, |
| 100435 | type: &UA_TYPES[UA_TYPES_DATACHANGENOTIFICATION]); |
| 100436 | size_t dcnSize = sub->dataChangeNotifications; |
| 100437 | if(dcnSize > maxNotifications) |
| 100438 | dcnSize = maxNotifications; |
| 100439 | dcn->monitoredItems = (UA_MonitoredItemNotification*) |
| 100440 | UA_Array_new(size: dcnSize, type: &UA_TYPES[UA_TYPES_MONITOREDITEMNOTIFICATION]); |
| 100441 | if(!dcn->monitoredItems) { |
| 100442 | UA_NotificationMessage_clear(p: message); |
| 100443 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 100444 | } |
| 100445 | dcn->monitoredItemsSize = dcnSize; |
| 100446 | notificationDataIdx++; |
| 100447 | } |
| 100448 | |
| 100449 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 100450 | size_t enlPos = 0; /* How many EventNotifications? */ |
| 100451 | UA_EventNotificationList *enl = NULL; |
| 100452 | if(sub->eventNotifications > 0) { |
| 100453 | enl = UA_EventNotificationList_new(); |
| 100454 | if(!enl) { |
| 100455 | UA_NotificationMessage_clear(p: message); |
| 100456 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 100457 | } |
| 100458 | UA_ExtensionObject_setValue(eo: &message->notificationData[notificationDataIdx], |
| 100459 | p: enl, type: &UA_TYPES[UA_TYPES_EVENTNOTIFICATIONLIST]); |
| 100460 | size_t enlSize = sub->eventNotifications; |
| 100461 | if(enlSize > maxNotifications) |
| 100462 | enlSize = maxNotifications; |
| 100463 | enl->events = (UA_EventFieldList*) |
| 100464 | UA_Array_new(size: enlSize, type: &UA_TYPES[UA_TYPES_EVENTFIELDLIST]); |
| 100465 | if(!enl->events) { |
| 100466 | UA_NotificationMessage_clear(p: message); |
| 100467 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 100468 | } |
| 100469 | enl->eventsSize = enlSize; |
| 100470 | notificationDataIdx++; |
| 100471 | } |
| 100472 | #endif |
| 100473 | |
| 100474 | UA_assert(notificationDataIdx > 0); |
| 100475 | message->notificationDataSize = notificationDataIdx; |
| 100476 | |
| 100477 | /* <-- The point of no return --> */ |
| 100478 | |
| 100479 | /* How many notifications were moved to the response overall? */ |
| 100480 | size_t totalNotifications = 0; |
| 100481 | UA_Notification *notification, *notification_tmp; |
| 100482 | TAILQ_FOREACH_SAFE(notification, &sub->notificationQueue, |
| 100483 | globalEntry, notification_tmp) { |
| 100484 | if(totalNotifications >= maxNotifications) |
| 100485 | break; |
| 100486 | |
| 100487 | /* Move the content to the response */ |
| 100488 | switch(notification->mon->itemToMonitor.attributeId) { |
| 100489 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 100490 | case UA_ATTRIBUTEID_EVENTNOTIFIER: |
| 100491 | UA_assert(enl != NULL); /* Have at least one event notification */ |
| 100492 | enl->events[enlPos] = notification->data.event; |
| 100493 | UA_EventFieldList_init(p: ¬ification->data.event); |
| 100494 | enlPos++; |
| 100495 | break; |
| 100496 | #endif |
| 100497 | default: |
| 100498 | UA_assert(dcn != NULL); /* Have at least one change notification */ |
| 100499 | dcn->monitoredItems[dcnPos] = notification->data.dataChange; |
| 100500 | UA_DataValue_init(p: ¬ification->data.dataChange.value); |
| 100501 | dcnPos++; |
| 100502 | break; |
| 100503 | } |
| 100504 | |
| 100505 | /* If there are Notifications *before this one* in the MonitoredItem- |
| 100506 | * local queue, remove all of them. These are earlier Notifications that |
| 100507 | * are non-reporting. And we don't want them to show up after the |
| 100508 | * current Notification has been sent out. */ |
| 100509 | UA_Notification *prev; |
| 100510 | while((prev = TAILQ_PREV(notification, NotificationQueue, localEntry))) { |
| 100511 | UA_Notification_delete(n: prev); |
| 100512 | } |
| 100513 | |
| 100514 | /* Delete the notification, remove from the queues and decrease the counters */ |
| 100515 | UA_Notification_delete(n: notification); |
| 100516 | |
| 100517 | totalNotifications++; |
| 100518 | } |
| 100519 | |
| 100520 | /* Set sizes */ |
| 100521 | if(dcn) { |
| 100522 | dcn->monitoredItemsSize = dcnPos; |
| 100523 | if(dcnPos == 0) { |
| 100524 | UA_free(ptr: dcn->monitoredItems); |
| 100525 | dcn->monitoredItems = NULL; |
| 100526 | } |
| 100527 | } |
| 100528 | |
| 100529 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 100530 | if(enl) { |
| 100531 | enl->eventsSize = enlPos; |
| 100532 | if(enlPos == 0) { |
| 100533 | UA_free(ptr: enl->events); |
| 100534 | enl->events = NULL; |
| 100535 | } |
| 100536 | } |
| 100537 | #endif |
| 100538 | |
| 100539 | return UA_STATUSCODE_GOOD; |
| 100540 | } |
| 100541 | |
| 100542 | /* According to OPC Unified Architecture, Part 4 5.13.1.1 i) The value 0 is |
| 100543 | * never used for the sequence number */ |
| 100544 | static UA_UInt32 |
| 100545 | UA_Subscription_nextSequenceNumber(UA_UInt32 sequenceNumber) { |
| 100546 | UA_UInt32 nextSequenceNumber = sequenceNumber + 1; |
| 100547 | if(nextSequenceNumber == 0) |
| 100548 | nextSequenceNumber = 1; |
| 100549 | return nextSequenceNumber; |
| 100550 | } |
| 100551 | |
| 100552 | static void |
| 100553 | sendStatusChangeDelete(UA_Server *server, UA_Subscription *sub, |
| 100554 | UA_PublishResponseEntry *pre) { |
| 100555 | /* Cannot send out the StatusChange because no response is queued. |
| 100556 | * Delete the Subscription without sending the StatusChange, if the statusChange is Bad*/ |
| 100557 | if(!pre) { |
| 100558 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, |
| 100559 | "Cannot send the StatusChange notification because no response is queued."); |
| 100560 | if(UA_StatusCode_isBad(code: sub->statusChange)) { |
| 100561 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, "Removing the subscription."); |
| 100562 | UA_Subscription_delete(server, sub); |
| 100563 | } |
| 100564 | return; |
| 100565 | } |
| 100566 | |
| 100567 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, |
| 100568 | "Sending out a StatusChange " |
| 100569 | "notification and removing the subscription"); |
| 100570 | |
| 100571 | /* Populate the response */ |
| 100572 | UA_PublishResponse *response = &pre->response; |
| 100573 | |
| 100574 | UA_StatusChangeNotification scn; |
| 100575 | UA_StatusChangeNotification_init(p: &scn); |
| 100576 | scn.status = sub->statusChange; |
| 100577 | |
| 100578 | UA_ExtensionObject notificationData; |
| 100579 | UA_ExtensionObject_setValue(eo: ¬ificationData, p: &scn, |
| 100580 | type: &UA_TYPES[UA_TYPES_STATUSCHANGENOTIFICATION]); |
| 100581 | |
| 100582 | response->notificationMessage.notificationData = ¬ificationData; |
| 100583 | response->notificationMessage.notificationDataSize = 1; |
| 100584 | response->subscriptionId = sub->subscriptionId; |
| 100585 | response->notificationMessage.publishTime = UA_DateTime_now(); |
| 100586 | response->notificationMessage.sequenceNumber = sub->nextSequenceNumber; |
| 100587 | |
| 100588 | /* Send the response */ |
| 100589 | UA_assert(sub->session); /* Otherwise pre is NULL */ |
| 100590 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, |
| 100591 | "Sending out a publish response"); |
| 100592 | sendResponse(server, session: sub->session, channel: sub->session->header.channel, requestId: pre->requestId, |
| 100593 | response: (UA_Response *)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]); |
| 100594 | |
| 100595 | /* Clean up */ |
| 100596 | response->notificationMessage.notificationData = NULL; |
| 100597 | response->notificationMessage.notificationDataSize = 0; |
| 100598 | UA_PublishResponse_clear(p: &pre->response); |
| 100599 | UA_free(ptr: pre); |
| 100600 | |
| 100601 | /* Delete the subscription */ |
| 100602 | UA_Subscription_delete(server, sub); |
| 100603 | } |
| 100604 | |
| 100605 | static void |
| 100606 | delayedPublishNotifications(UA_Server *server, UA_Subscription *sub) { |
| 100607 | lockServer(server); |
| 100608 | sub->delayedCallbackRegistered = false; |
| 100609 | UA_Subscription_publish(server, sub); |
| 100610 | unlockServer(server); |
| 100611 | } |
| 100612 | |
| 100613 | /* Try to publish now. Enqueue a "next publish" as a delayed callback if not |
| 100614 | * done. */ |
| 100615 | void |
| 100616 | UA_Subscription_publish(UA_Server *server, UA_Subscription *sub) { |
| 100617 | /* Get a response */ |
| 100618 | UA_PublishResponseEntry *pre = NULL; |
| 100619 | if(sub->session) { |
| 100620 | UA_EventLoop *el = server->config.eventLoop; |
| 100621 | UA_DateTime nowMonotonic = el->dateTime_nowMonotonic(el); |
| 100622 | do { |
| 100623 | /* Dequeue the oldest response */ |
| 100624 | pre = UA_Session_dequeuePublishReq(session: sub->session); |
| 100625 | if(!pre) |
| 100626 | break; |
| 100627 | |
| 100628 | /* Check if the TimeoutHint is still valid. Otherwise return with a bad |
| 100629 | * statuscode and continue. */ |
| 100630 | if(pre->maxTime < nowMonotonic) { |
| 100631 | UA_LOG_DEBUG_SESSION(server->config.logging, sub->session, |
| 100632 | "Publish request %u has timed out", pre->requestId); |
| 100633 | pre->response.responseHeader.serviceResult = UA_STATUSCODE_BADTIMEOUT; |
| 100634 | sendResponse(server, session: sub->session, channel: sub->session->header.channel, |
| 100635 | requestId: pre->requestId, response: (UA_Response *)&pre->response, |
| 100636 | responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]); |
| 100637 | UA_PublishResponse_clear(p: &pre->response); |
| 100638 | UA_free(ptr: pre); |
| 100639 | pre = NULL; |
| 100640 | } |
| 100641 | } while(!pre); |
| 100642 | } |
| 100643 | |
| 100644 | /* Update the LifetimeCounter */ |
| 100645 | if(pre) { |
| 100646 | Subscription_resetLifetime(sub); |
| 100647 | } else { |
| 100648 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, |
| 100649 | "The publish queue is empty"); |
| 100650 | ++sub->currentLifetimeCount; |
| 100651 | if(sub->currentLifetimeCount > sub->lifeTimeCount) { |
| 100652 | UA_LOG_WARNING_SUBSCRIPTION(server->config.logging, sub, |
| 100653 | "End of subscription lifetime"); |
| 100654 | /* Set the StatusChange to delete the subscription. */ |
| 100655 | sub->statusChange = UA_STATUSCODE_BADTIMEOUT; |
| 100656 | } |
| 100657 | } |
| 100658 | |
| 100659 | /* Send a StatusChange notification if possible and delete the |
| 100660 | * Subscription */ |
| 100661 | if(sub->statusChange != UA_STATUSCODE_GOOD) { |
| 100662 | sendStatusChangeDelete(server, sub, pre); |
| 100663 | return; |
| 100664 | } |
| 100665 | |
| 100666 | /* Dsiabled subscriptions do not send notifications */ |
| 100667 | UA_UInt32 notifications = (sub->state == UA_SUBSCRIPTIONSTATE_ENABLED) ? |
| 100668 | sub->notificationQueueSize : 0; |
| 100669 | |
| 100670 | /* Limit the number of notifications to the configured maximum */ |
| 100671 | if(notifications > sub->notificationsPerPublish) |
| 100672 | notifications = sub->notificationsPerPublish; |
| 100673 | |
| 100674 | /* Return if no notifications and no keepalive */ |
| 100675 | if(notifications == 0) { |
| 100676 | ++sub->currentKeepAliveCount; |
| 100677 | if(sub->currentKeepAliveCount < sub->maxKeepAliveCount) { |
| 100678 | if(pre) |
| 100679 | UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */ |
| 100680 | return; |
| 100681 | } |
| 100682 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, "Sending a KeepAlive"); |
| 100683 | } |
| 100684 | |
| 100685 | /* We want to send a response, but cannot. Either because there is no queued |
| 100686 | * response or because the Subscription is detached from a Session or because |
| 100687 | * the SecureChannel for the Session is closed. */ |
| 100688 | if(!pre || !sub->session || !sub->session->header.channel) { |
| 100689 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, |
| 100690 | "Want to send a publish response but cannot. " |
| 100691 | "The subscription is late."); |
| 100692 | sub->late = true; |
| 100693 | if(pre) |
| 100694 | UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */ |
| 100695 | return; |
| 100696 | } |
| 100697 | |
| 100698 | UA_assert(pre); |
| 100699 | UA_assert(sub->session); /* Otherwise pre is NULL */ |
| 100700 | |
| 100701 | /* Prepare the response */ |
| 100702 | UA_PublishResponse *response = &pre->response; |
| 100703 | UA_NotificationMessage *message = &response->notificationMessage; |
| 100704 | UA_NotificationMessageEntry *retransmission = NULL; |
| 100705 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 100706 | size_t priorDataChangeNotifications = sub->dataChangeNotifications; |
| 100707 | size_t priorEventNotifications = sub->eventNotifications; |
| 100708 | #endif |
| 100709 | if(notifications > 0) { |
| 100710 | if(server->config.enableRetransmissionQueue) { |
| 100711 | /* Allocate the retransmission entry */ |
| 100712 | retransmission = (UA_NotificationMessageEntry*) |
| 100713 | UA_malloc(size: sizeof(UA_NotificationMessageEntry)); |
| 100714 | if(!retransmission) { |
| 100715 | UA_LOG_WARNING_SUBSCRIPTION(server->config.logging, sub, |
| 100716 | "Could not allocate memory for retransmission. " |
| 100717 | "The subscription is late."); |
| 100718 | sub->late = true; |
| 100719 | UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */ |
| 100720 | return; |
| 100721 | } |
| 100722 | } |
| 100723 | |
| 100724 | /* Prepare the response */ |
| 100725 | UA_StatusCode retval = |
| 100726 | prepareNotificationMessage(server, sub, message, maxNotifications: notifications); |
| 100727 | if(retval != UA_STATUSCODE_GOOD) { |
| 100728 | UA_LOG_WARNING_SUBSCRIPTION(server->config.logging, sub, |
| 100729 | "Could not prepare the notification message. " |
| 100730 | "The subscription is late."); |
| 100731 | /* If the retransmission queue is enabled a retransmission message is allocated */ |
| 100732 | if(retransmission) |
| 100733 | UA_free(ptr: retransmission); |
| 100734 | sub->late = true; |
| 100735 | UA_Session_queuePublishReq(session: sub->session, entry: pre, true); /* Re-enqueue */ |
| 100736 | return; |
| 100737 | } |
| 100738 | } |
| 100739 | |
| 100740 | /* <-- The point of no return --> */ |
| 100741 | |
| 100742 | /* Set up the response */ |
| 100743 | response->subscriptionId = sub->subscriptionId; |
| 100744 | response->moreNotifications = (sub->notificationQueueSize > 0); |
| 100745 | message->publishTime = UA_DateTime_now(); |
| 100746 | |
| 100747 | /* Set sequence number to message. Started at 1 which is given during |
| 100748 | * creating a new subscription. The 1 is required for initial publish |
| 100749 | * response with or without an monitored item. */ |
| 100750 | message->sequenceNumber = sub->nextSequenceNumber; |
| 100751 | |
| 100752 | if(notifications > 0) { |
| 100753 | /* If the retransmission queue is enabled a retransmission message is |
| 100754 | * allocated */ |
| 100755 | if(retransmission) { |
| 100756 | /* Put the notification message into the retransmission queue. This |
| 100757 | * needs to be done here, so that the message itself is included in |
| 100758 | * the available sequence numbers for acknowledgement. */ |
| 100759 | retransmission->message = response->notificationMessage; |
| 100760 | UA_Subscription_addRetransmissionMessage(server, sub, entry: retransmission); |
| 100761 | } |
| 100762 | /* Only if a notification was created, the sequence number must be |
| 100763 | * increased. For a keepalive the sequence number can be reused. */ |
| 100764 | sub->nextSequenceNumber = |
| 100765 | UA_Subscription_nextSequenceNumber(sequenceNumber: sub->nextSequenceNumber); |
| 100766 | } |
| 100767 | |
| 100768 | /* Get the available sequence numbers from the retransmission queue */ |
| 100769 | UA_assert(sub->retransmissionQueueSize <= UA_MAX_RETRANSMISSIONQUEUESIZE); |
| 100770 | UA_UInt32 seqNumbers[UA_MAX_RETRANSMISSIONQUEUESIZE]; |
| 100771 | response->availableSequenceNumbers = seqNumbers; |
| 100772 | response->availableSequenceNumbersSize = sub->retransmissionQueueSize; |
| 100773 | size_t i = 0; |
| 100774 | UA_NotificationMessageEntry *nme; |
| 100775 | TAILQ_FOREACH(nme, &sub->retransmissionQueue, listEntry) { |
| 100776 | response->availableSequenceNumbers[i] = nme->message.sequenceNumber; |
| 100777 | ++i; |
| 100778 | } |
| 100779 | UA_assert(i == sub->retransmissionQueueSize); |
| 100780 | |
| 100781 | /* Send the response */ |
| 100782 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, |
| 100783 | "Sending out a publish response with %"PRIu32 |
| 100784 | " notifications", notifications); |
| 100785 | sendResponse(server, session: sub->session, channel: sub->session->header.channel, requestId: pre->requestId, |
| 100786 | response: (UA_Response*)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]); |
| 100787 | |
| 100788 | /* Reset the Subscription state to NORMAL. But only if all notifications |
| 100789 | * have been sent out. Otherwise keep the Subscription in the LATE state. So |
| 100790 | * we immediately answer incoming Publish requests. |
| 100791 | * |
| 100792 | * (We also check that session->responseQueueSize > 0 in Service_Publish. To |
| 100793 | * avoid answering Publish requests out of order. As we additionally may have |
| 100794 | * scheduled a publish callback as a delayed callback. */ |
| 100795 | if(sub->notificationQueueSize == 0) |
| 100796 | sub->late = false; |
| 100797 | |
| 100798 | /* Reset the KeepAlive after publishing */ |
| 100799 | sub->currentKeepAliveCount = 0; |
| 100800 | |
| 100801 | /* Free the response */ |
| 100802 | if(retransmission) { |
| 100803 | /* NotificationMessage was moved into retransmission queue */ |
| 100804 | UA_NotificationMessage_init(p: &response->notificationMessage); |
| 100805 | } |
| 100806 | response->availableSequenceNumbers = NULL; |
| 100807 | response->availableSequenceNumbersSize = 0; |
| 100808 | UA_PublishResponse_clear(p: &pre->response); |
| 100809 | UA_free(ptr: pre); |
| 100810 | |
| 100811 | /* Update the diagnostics statistics */ |
| 100812 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 100813 | sub->publishRequestCount++; |
| 100814 | |
| 100815 | UA_UInt32 sentDCN = (UA_UInt32) |
| 100816 | (priorDataChangeNotifications - sub->dataChangeNotifications); |
| 100817 | UA_UInt32 sentEN = (UA_UInt32)(priorEventNotifications - sub->eventNotifications); |
| 100818 | sub->dataChangeNotificationsCount += sentDCN; |
| 100819 | sub->eventNotificationsCount += sentEN; |
| 100820 | sub->notificationsCount += (sentDCN + sentEN); |
| 100821 | #endif |
| 100822 | |
| 100823 | /* Repeat sending notifications if there are more notifications to send. But |
| 100824 | * only call monitoredItem_sampleCallback in the regular publish |
| 100825 | * callback. */ |
| 100826 | UA_Boolean done = (sub->notificationQueueSize == 0); |
| 100827 | if(!done && !sub->delayedCallbackRegistered) { |
| 100828 | sub->delayedCallbackRegistered = true; |
| 100829 | |
| 100830 | sub->delayedMoreNotifications.callback = (UA_Callback)delayedPublishNotifications; |
| 100831 | sub->delayedMoreNotifications.application = server; |
| 100832 | sub->delayedMoreNotifications.context = sub; |
| 100833 | |
| 100834 | UA_EventLoop *el = server->config.eventLoop; |
| 100835 | el->addDelayedCallback(el, &sub->delayedMoreNotifications); |
| 100836 | } |
| 100837 | } |
| 100838 | |
| 100839 | void |
| 100840 | UA_Subscription_resendData(UA_Server *server, UA_Subscription *sub) { |
| 100841 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 100842 | UA_assert(server); |
| 100843 | UA_assert(sub); |
| 100844 | |
| 100845 | /* Part 4, §6.7: If this Method is called, subsequent Publish responses |
| 100846 | * shall contain the current values of all data MonitoredItems in the |
| 100847 | * Subscription where the MonitoringMode is set to Reporting. If a value is |
| 100848 | * queued for a data MonitoredItem, the next value in the queue is sent in |
| 100849 | * the Publish response. If no value is queued for a data MonitoredItem, the |
| 100850 | * last value sent is repeated in the Publish response. */ |
| 100851 | UA_MonitoredItem *mon; |
| 100852 | LIST_FOREACH(mon, &sub->monitoredItems, listEntry) { |
| 100853 | /* Create only DataChange notifications */ |
| 100854 | if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) |
| 100855 | continue; |
| 100856 | |
| 100857 | /* Only if the mode is monitoring */ |
| 100858 | if(mon->monitoringMode != UA_MONITORINGMODE_REPORTING) |
| 100859 | continue; |
| 100860 | |
| 100861 | /* If a value is queued for a data MonitoredItem, the next value in |
| 100862 | * the queue is sent in the Publish response. */ |
| 100863 | if(mon->queueSize > 0) |
| 100864 | continue; |
| 100865 | |
| 100866 | /* Create a notification with the last sampled value */ |
| 100867 | UA_MonitoredItem_createDataChangeNotification(server, mon, value: &mon->lastValue); |
| 100868 | } |
| 100869 | } |
| 100870 | |
| 100871 | void |
| 100872 | UA_Session_ensurePublishQueueSpace(UA_Server* server, UA_Session* session) { |
| 100873 | if(server->config.maxPublishReqPerSession == 0) |
| 100874 | return; |
| 100875 | |
| 100876 | while(session->responseQueueSize >= server->config.maxPublishReqPerSession) { |
| 100877 | /* Dequeue a response */ |
| 100878 | UA_PublishResponseEntry *pre = UA_Session_dequeuePublishReq(session); |
| 100879 | UA_assert(pre != NULL); /* There must be a pre as session->responseQueueSize > 0 */ |
| 100880 | |
| 100881 | UA_LOG_DEBUG_SESSION(server->config.logging, session, |
| 100882 | "Sending out a publish response triggered by too many publish requests"); |
| 100883 | |
| 100884 | /* Send the response. This response has no related subscription id */ |
| 100885 | UA_PublishResponse *response = &pre->response; |
| 100886 | response->responseHeader.serviceResult = UA_STATUSCODE_BADTOOMANYPUBLISHREQUESTS; |
| 100887 | sendResponse(server, session, channel: session->header.channel, requestId: pre->requestId, |
| 100888 | response: (UA_Response *)response, responseType: &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]); |
| 100889 | |
| 100890 | /* Free the response */ |
| 100891 | UA_PublishResponse_clear(p: response); |
| 100892 | UA_free(ptr: pre); |
| 100893 | } |
| 100894 | } |
| 100895 | |
| 100896 | static void |
| 100897 | sampleAndPublishCallback(UA_Server *server, UA_Subscription *sub) { |
| 100898 | UA_assert(sub); |
| 100899 | |
| 100900 | lockServer(server); |
| 100901 | |
| 100902 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, |
| 100903 | "Sample and Publish Callback"); |
| 100904 | |
| 100905 | /* Sample the MonitoredItems with sampling interval <0 (which implies |
| 100906 | * sampling in the same interval as the subscription) */ |
| 100907 | UA_MonitoredItem *mon; |
| 100908 | LIST_FOREACH(mon, &sub->samplingMonitoredItems, sampling.subscriptionSampling) { |
| 100909 | monitoredItem_sampleCallback(server, mon); |
| 100910 | } |
| 100911 | |
| 100912 | /* Publish the queued notifications */ |
| 100913 | UA_Subscription_publish(server, sub); |
| 100914 | |
| 100915 | unlockServer(server); |
| 100916 | } |
| 100917 | |
| 100918 | UA_StatusCode |
| 100919 | Subscription_setState(UA_Server *server, UA_Subscription *sub, |
| 100920 | UA_SubscriptionState state) { |
| 100921 | if(state <= UA_SUBSCRIPTIONSTATE_REMOVING) { |
| 100922 | if(sub->publishCallbackId != 0) { |
| 100923 | removeCallback(server, callbackId: sub->publishCallbackId); |
| 100924 | sub->publishCallbackId = 0; |
| 100925 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 100926 | sub->disableCount++; |
| 100927 | #endif |
| 100928 | } |
| 100929 | } else if(sub->publishCallbackId == 0) { |
| 100930 | UA_StatusCode res = |
| 100931 | addRepeatedCallback(server, callback: (UA_ServerCallback)sampleAndPublishCallback, |
| 100932 | data: sub, interval_ms: sub->publishingInterval, callbackId: &sub->publishCallbackId); |
| 100933 | if(res != UA_STATUSCODE_GOOD) { |
| 100934 | sub->state = UA_SUBSCRIPTIONSTATE_STOPPED; |
| 100935 | return res; |
| 100936 | } |
| 100937 | |
| 100938 | /* Send (at least a) keepalive after the next publish interval */ |
| 100939 | sub->currentKeepAliveCount = sub->maxKeepAliveCount; |
| 100940 | |
| 100941 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 100942 | sub->enableCount++; |
| 100943 | #endif |
| 100944 | } |
| 100945 | |
| 100946 | sub->state = state; |
| 100947 | return UA_STATUSCODE_GOOD; |
| 100948 | } |
| 100949 | |
| 100950 | #endif /* UA_ENABLE_SUBSCRIPTIONS */ |
| 100951 | |
| 100952 | /**** amalgamated original file "/src/server/ua_subscription_monitoreditem.c" ****/ |
| 100953 | |
| 100954 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 100955 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 100956 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 100957 | * |
| 100958 | * Copyright 2017-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 100959 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 100960 | * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH |
| 100961 | * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA |
| 100962 | * Copyright 2018 (c) Fabian Arndt, Root-Core |
| 100963 | * Copyright 2020-2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 100964 | */ |
| 100965 | |
| 100966 | |
| 100967 | #ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */ |
| 100968 | |
| 100969 | /****************/ |
| 100970 | /* Notification */ |
| 100971 | /****************/ |
| 100972 | |
| 100973 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 100974 | |
| 100975 | static const UA_NodeId eventQueueOverflowEventType = |
| 100976 | {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_EVENTQUEUEOVERFLOWEVENTTYPE}}; |
| 100977 | |
| 100978 | /* The specification states in Part 4 5.12.1.5 that an EventQueueOverflowEvent |
| 100979 | * "is generated when the first Event has to be discarded [...] without |
| 100980 | * discarding any other event". So only generate one for all deleted events. */ |
| 100981 | static UA_StatusCode |
| 100982 | createEventOverflowNotification(UA_Server *server, UA_Subscription *sub, |
| 100983 | UA_MonitoredItem *mon) { |
| 100984 | /* Avoid creating two adjacent overflow events */ |
| 100985 | UA_Notification *indicator = NULL; |
| 100986 | if(mon->parameters.discardOldest) { |
| 100987 | indicator = TAILQ_FIRST(&mon->queue); |
| 100988 | UA_assert(indicator); /* must exist */ |
| 100989 | if(indicator->isOverflowEvent) |
| 100990 | return UA_STATUSCODE_GOOD; |
| 100991 | } else { |
| 100992 | indicator = TAILQ_LAST(&mon->queue, NotificationQueue); |
| 100993 | UA_assert(indicator); /* must exist */ |
| 100994 | /* Skip the last element. It is the recently added notification that |
| 100995 | * shall be kept. We know it is not an OverflowEvent. */ |
| 100996 | UA_Notification *before = TAILQ_PREV(indicator, NotificationQueue, localEntry); |
| 100997 | if(before && before->isOverflowEvent) |
| 100998 | return UA_STATUSCODE_GOOD; |
| 100999 | } |
| 101000 | |
| 101001 | /* A Notification is inserted into the queue which includes only the |
| 101002 | * NodeId of the OverflowEventType. */ |
| 101003 | |
| 101004 | /* Allocate the notification */ |
| 101005 | UA_Notification *overflowNotification = UA_Notification_new(); |
| 101006 | if(!overflowNotification) |
| 101007 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 101008 | |
| 101009 | /* Set the notification fields */ |
| 101010 | overflowNotification->isOverflowEvent = true; |
| 101011 | overflowNotification->mon = mon; |
| 101012 | overflowNotification->data.event.clientHandle = mon->parameters.clientHandle; |
| 101013 | overflowNotification->data.event.eventFields = UA_Variant_new(); |
| 101014 | if(!overflowNotification->data.event.eventFields) { |
| 101015 | UA_free(ptr: overflowNotification); |
| 101016 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 101017 | } |
| 101018 | overflowNotification->data.event.eventFieldsSize = 1; |
| 101019 | UA_StatusCode retval = |
| 101020 | UA_Variant_setScalarCopy(v: overflowNotification->data.event.eventFields, |
| 101021 | p: &eventQueueOverflowEventType, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 101022 | if(retval != UA_STATUSCODE_GOOD) { |
| 101023 | UA_Notification_delete(n: overflowNotification); |
| 101024 | return retval; |
| 101025 | } |
| 101026 | |
| 101027 | /* Insert before the removed notification. This is either first in the |
| 101028 | * queue (if the oldest notification was removed) or before the new event |
| 101029 | * that remains the last element of the queue. |
| 101030 | * |
| 101031 | * Ensure that the following is consistent with UA_Notification_enqueueMon |
| 101032 | * and UA_Notification_enqueueSub! */ |
| 101033 | TAILQ_INSERT_BEFORE(indicator, overflowNotification, localEntry); |
| 101034 | ++mon->eventOverflows; |
| 101035 | ++mon->queueSize; |
| 101036 | |
| 101037 | /* Test for consistency */ |
| 101038 | UA_assert(mon->queueSize >= mon->eventOverflows); |
| 101039 | UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1); |
| 101040 | |
| 101041 | if(TAILQ_NEXT(indicator, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) { |
| 101042 | /* Insert just before the indicator */ |
| 101043 | TAILQ_INSERT_BEFORE(indicator, overflowNotification, globalEntry); |
| 101044 | } else { |
| 101045 | /* The indicator was not reporting or not added yet. */ |
| 101046 | if(!mon->parameters.discardOldest) { |
| 101047 | /* Add last to the per-Subscription queue */ |
| 101048 | TAILQ_INSERT_TAIL(&mon->subscription->notificationQueue, |
| 101049 | overflowNotification, globalEntry); |
| 101050 | } else { |
| 101051 | /* Find the oldest reported element. Add before that. */ |
| 101052 | while(indicator) { |
| 101053 | indicator = TAILQ_PREV(indicator, NotificationQueue, localEntry); |
| 101054 | if(!indicator) { |
| 101055 | TAILQ_INSERT_TAIL(&mon->subscription->notificationQueue, |
| 101056 | overflowNotification, globalEntry); |
| 101057 | break; |
| 101058 | } |
| 101059 | if(TAILQ_NEXT(indicator, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) { |
| 101060 | TAILQ_INSERT_BEFORE(indicator, overflowNotification, globalEntry); |
| 101061 | break; |
| 101062 | } |
| 101063 | } |
| 101064 | } |
| 101065 | } |
| 101066 | |
| 101067 | ++sub->notificationQueueSize; |
| 101068 | ++sub->eventNotifications; |
| 101069 | |
| 101070 | /* Update the diagnostics statistics */ |
| 101071 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 101072 | sub->eventQueueOverFlowCount++; |
| 101073 | #endif |
| 101074 | |
| 101075 | return UA_STATUSCODE_GOOD; |
| 101076 | } |
| 101077 | |
| 101078 | #endif |
| 101079 | |
| 101080 | /* Set the InfoBits that a datachange notification was removed */ |
| 101081 | static void |
| 101082 | setOverflowInfoBits(UA_MonitoredItem *mon) { |
| 101083 | /* Only for queues with more than one element */ |
| 101084 | if(mon->parameters.queueSize == 1) |
| 101085 | return; |
| 101086 | |
| 101087 | UA_Notification *indicator = NULL; |
| 101088 | if(mon->parameters.discardOldest) { |
| 101089 | indicator = TAILQ_FIRST(&mon->queue); |
| 101090 | } else { |
| 101091 | indicator = TAILQ_LAST(&mon->queue, NotificationQueue); |
| 101092 | } |
| 101093 | UA_assert(indicator); /* must exist */ |
| 101094 | |
| 101095 | indicator->data.dataChange.value.hasStatus = true; |
| 101096 | indicator->data.dataChange.value.status |= |
| 101097 | (UA_STATUSCODE_INFOTYPE_DATAVALUE | UA_STATUSCODE_INFOBITS_OVERFLOW); |
| 101098 | } |
| 101099 | |
| 101100 | /* Remove the InfoBits when the queueSize was reduced to 1 */ |
| 101101 | void |
| 101102 | UA_MonitoredItem_removeOverflowInfoBits(UA_MonitoredItem *mon) { |
| 101103 | /* Don't consider queue size > 1 and Event MonitoredItems */ |
| 101104 | if(mon->parameters.queueSize > 1 || |
| 101105 | mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) |
| 101106 | return; |
| 101107 | |
| 101108 | /* Get the first notification */ |
| 101109 | UA_Notification *n = TAILQ_FIRST(&mon->queue); |
| 101110 | if(!n) |
| 101111 | return; |
| 101112 | |
| 101113 | /* Assertion that at most one notification is in the queue */ |
| 101114 | UA_assert(n == TAILQ_LAST(&mon->queue, NotificationQueue)); |
| 101115 | |
| 101116 | /* Remve the Infobits */ |
| 101117 | n->data.dataChange.value.status &= ~(UA_StatusCode) |
| 101118 | (UA_STATUSCODE_INFOTYPE_DATAVALUE | UA_STATUSCODE_INFOBITS_OVERFLOW); |
| 101119 | } |
| 101120 | |
| 101121 | UA_Notification * |
| 101122 | UA_Notification_new(void) { |
| 101123 | UA_Notification *n = (UA_Notification*)UA_calloc(nmemb: 1, size: sizeof(UA_Notification)); |
| 101124 | if(n) { |
| 101125 | /* Set the sentinel for a notification that is not enqueued */ |
| 101126 | TAILQ_NEXT(n, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL; |
| 101127 | TAILQ_NEXT(n, localEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL; |
| 101128 | } |
| 101129 | return n; |
| 101130 | } |
| 101131 | |
| 101132 | static void UA_Notification_dequeueMon(UA_Notification *n); |
| 101133 | static void UA_Notification_enqueueSub(UA_Notification *n); |
| 101134 | static void UA_Notification_dequeueSub(UA_Notification *n); |
| 101135 | |
| 101136 | void |
| 101137 | UA_Notification_delete(UA_Notification *n) { |
| 101138 | UA_assert(n != UA_SUBSCRIPTION_QUEUE_SENTINEL); |
| 101139 | if(n->mon) { |
| 101140 | UA_Notification_dequeueMon(n); |
| 101141 | UA_Notification_dequeueSub(n); |
| 101142 | switch(n->mon->itemToMonitor.attributeId) { |
| 101143 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 101144 | case UA_ATTRIBUTEID_EVENTNOTIFIER: |
| 101145 | UA_EventFieldList_clear(p: &n->data.event); |
| 101146 | break; |
| 101147 | #endif |
| 101148 | default: |
| 101149 | UA_MonitoredItemNotification_clear(p: &n->data.dataChange); |
| 101150 | break; |
| 101151 | } |
| 101152 | } |
| 101153 | UA_free(ptr: n); |
| 101154 | } |
| 101155 | |
| 101156 | /* Add to the MonitoredItem queue, update all counters and then handle overflow */ |
| 101157 | static void |
| 101158 | UA_Notification_enqueueMon(UA_Server *server, UA_Notification *n) { |
| 101159 | UA_MonitoredItem *mon = n->mon; |
| 101160 | UA_assert(mon); |
| 101161 | UA_assert(TAILQ_NEXT(n, localEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL); |
| 101162 | |
| 101163 | /* Add to the MonitoredItem */ |
| 101164 | TAILQ_INSERT_TAIL(&mon->queue, n, localEntry); |
| 101165 | ++mon->queueSize; |
| 101166 | |
| 101167 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 101168 | if(n->isOverflowEvent) |
| 101169 | ++mon->eventOverflows; |
| 101170 | #endif |
| 101171 | |
| 101172 | /* Test for consistency */ |
| 101173 | UA_assert(mon->queueSize >= mon->eventOverflows); |
| 101174 | UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1); |
| 101175 | |
| 101176 | /* Ensure enough space is available in the MonitoredItem. Do this only after |
| 101177 | * adding the new Notification. */ |
| 101178 | UA_MonitoredItem_ensureQueueSpace(server, mon); |
| 101179 | |
| 101180 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, mon->subscription, |
| 101181 | "MonitoredItem %"PRIi32 " | " |
| 101182 | "Notification enqueued (Queue size %lu / %lu)", |
| 101183 | mon->monitoredItemId, |
| 101184 | (long unsigned)mon->queueSize, |
| 101185 | (long unsigned)mon->parameters.queueSize); |
| 101186 | } |
| 101187 | |
| 101188 | static void |
| 101189 | UA_Notification_enqueueSub(UA_Notification *n) { |
| 101190 | UA_MonitoredItem *mon = n->mon; |
| 101191 | UA_assert(mon); |
| 101192 | |
| 101193 | UA_Subscription *sub = mon->subscription; |
| 101194 | UA_assert(sub); |
| 101195 | |
| 101196 | if(TAILQ_NEXT(n, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) |
| 101197 | return; |
| 101198 | |
| 101199 | /* Add to the subscription if reporting is enabled */ |
| 101200 | TAILQ_INSERT_TAIL(&sub->notificationQueue, n, globalEntry); |
| 101201 | ++sub->notificationQueueSize; |
| 101202 | |
| 101203 | switch(mon->itemToMonitor.attributeId) { |
| 101204 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 101205 | case UA_ATTRIBUTEID_EVENTNOTIFIER: |
| 101206 | ++sub->eventNotifications; |
| 101207 | break; |
| 101208 | #endif |
| 101209 | default: |
| 101210 | ++sub->dataChangeNotifications; |
| 101211 | break; |
| 101212 | } |
| 101213 | } |
| 101214 | |
| 101215 | void |
| 101216 | UA_Notification_enqueueAndTrigger(UA_Server *server, UA_Notification *n) { |
| 101217 | UA_MonitoredItem *mon = n->mon; |
| 101218 | UA_Subscription *sub = mon->subscription; |
| 101219 | UA_assert(sub); /* This function is never called for local MonitoredItems */ |
| 101220 | |
| 101221 | /* If reporting or (sampled+triggered), enqueue into the Subscription first |
| 101222 | * and then into the MonitoredItem. UA_MonitoredItem_ensureQueueSpace |
| 101223 | * (called within UA_Notification_enqueueMon) assumes the notification is |
| 101224 | * already in the Subscription's publishing queue. */ |
| 101225 | if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING || |
| 101226 | (mon->monitoringMode == UA_MONITORINGMODE_SAMPLING && |
| 101227 | mon->triggeredUntil > UA_DateTime_nowMonotonic())) { |
| 101228 | UA_Notification_enqueueSub(n); |
| 101229 | mon->triggeredUntil = UA_INT64_MIN; |
| 101230 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, |
| 101231 | "Notification enqueued (Queue size %lu)", |
| 101232 | (long unsigned)sub->notificationQueueSize); |
| 101233 | } |
| 101234 | |
| 101235 | /* Insert into the MonitoredItem. This checks the queue size and |
| 101236 | * handles overflow. */ |
| 101237 | UA_Notification_enqueueMon(server, n); |
| 101238 | |
| 101239 | for(size_t i = mon->triggeringLinksSize - 1; i < mon->triggeringLinksSize; i--) { |
| 101240 | /* Get the triggered MonitoredItem. Remove the link if the MI doesn't exist. */ |
| 101241 | UA_MonitoredItem *triggeredMon = |
| 101242 | UA_Subscription_getMonitoredItem(sub, monitoredItemId: mon->triggeringLinks[i]); |
| 101243 | if(!triggeredMon) { |
| 101244 | UA_MonitoredItem_removeLink(sub, mon, linkId: mon->triggeringLinks[i]); |
| 101245 | continue; |
| 101246 | } |
| 101247 | |
| 101248 | /* Only sampling MonitoredItems receive a trigger. Reporting |
| 101249 | * MonitoredItems send out Notifications anyway and disabled |
| 101250 | * MonitoredItems don't create samples to send. */ |
| 101251 | if(triggeredMon->monitoringMode != UA_MONITORINGMODE_SAMPLING) |
| 101252 | continue; |
| 101253 | |
| 101254 | /* Get the latest sampled Notification from the triggered MonitoredItem. |
| 101255 | * Enqueue for publication. */ |
| 101256 | UA_Notification *n2 = TAILQ_LAST(&triggeredMon->queue, NotificationQueue); |
| 101257 | if(n2) |
| 101258 | UA_Notification_enqueueSub(n: n2); |
| 101259 | |
| 101260 | /* The next Notification within the publishing interval is going to be |
| 101261 | * published as well. (Falsely) assume that the publishing cycle has |
| 101262 | * started right now, so that we don't have to loop over MonitoredItems |
| 101263 | * to deactivate the triggering after the publishing cycle. */ |
| 101264 | triggeredMon->triggeredUntil = UA_DateTime_nowMonotonic() + |
| 101265 | (UA_DateTime)(sub->publishingInterval * (UA_Double)UA_DATETIME_MSEC); |
| 101266 | |
| 101267 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, |
| 101268 | "MonitoredItem %u triggers MonitoredItem %u", |
| 101269 | mon->monitoredItemId, triggeredMon->monitoredItemId); |
| 101270 | } |
| 101271 | } |
| 101272 | |
| 101273 | /* Remove from the MonitoredItem queue and adjust all counters */ |
| 101274 | static void |
| 101275 | UA_Notification_dequeueMon(UA_Notification *n) { |
| 101276 | UA_MonitoredItem *mon = n->mon; |
| 101277 | UA_assert(mon); |
| 101278 | |
| 101279 | if(TAILQ_NEXT(n, localEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL) |
| 101280 | return; |
| 101281 | |
| 101282 | /* Remove from the MonitoredItem queue */ |
| 101283 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 101284 | if(n->isOverflowEvent) |
| 101285 | --mon->eventOverflows; |
| 101286 | #endif |
| 101287 | |
| 101288 | TAILQ_REMOVE(&mon->queue, n, localEntry); |
| 101289 | --mon->queueSize; |
| 101290 | |
| 101291 | /* Test for consistency */ |
| 101292 | UA_assert(mon->queueSize >= mon->eventOverflows); |
| 101293 | UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1); |
| 101294 | |
| 101295 | /* Reset the sentintel */ |
| 101296 | TAILQ_NEXT(n, localEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL; |
| 101297 | } |
| 101298 | |
| 101299 | void |
| 101300 | UA_Notification_dequeueSub(UA_Notification *n) { |
| 101301 | if(TAILQ_NEXT(n, globalEntry) == UA_SUBSCRIPTION_QUEUE_SENTINEL) |
| 101302 | return; |
| 101303 | |
| 101304 | UA_MonitoredItem *mon = n->mon; |
| 101305 | UA_assert(mon); |
| 101306 | UA_Subscription *sub = mon->subscription; |
| 101307 | UA_assert(sub); |
| 101308 | |
| 101309 | switch(mon->itemToMonitor.attributeId) { |
| 101310 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 101311 | case UA_ATTRIBUTEID_EVENTNOTIFIER: |
| 101312 | --sub->eventNotifications; |
| 101313 | break; |
| 101314 | #endif |
| 101315 | default: |
| 101316 | --sub->dataChangeNotifications; |
| 101317 | break; |
| 101318 | } |
| 101319 | |
| 101320 | TAILQ_REMOVE(&sub->notificationQueue, n, globalEntry); |
| 101321 | --sub->notificationQueueSize; |
| 101322 | |
| 101323 | /* Reset the sentinel */ |
| 101324 | TAILQ_NEXT(n, globalEntry) = UA_SUBSCRIPTION_QUEUE_SENTINEL; |
| 101325 | } |
| 101326 | |
| 101327 | /*****************/ |
| 101328 | /* MonitoredItem */ |
| 101329 | /*****************/ |
| 101330 | |
| 101331 | void |
| 101332 | UA_MonitoredItem_init(UA_MonitoredItem *mon) { |
| 101333 | memset(s: mon, c: 0, n: sizeof(UA_MonitoredItem)); |
| 101334 | TAILQ_INIT(&mon->queue); |
| 101335 | mon->triggeredUntil = UA_INT64_MIN; |
| 101336 | } |
| 101337 | |
| 101338 | static UA_StatusCode |
| 101339 | addMonitoredItemBackpointer(UA_Server *server, UA_Session *session, |
| 101340 | UA_Node *node, void *data) { |
| 101341 | UA_MonitoredItem *mon = (UA_MonitoredItem*)data; |
| 101342 | UA_assert(mon != (UA_MonitoredItem*)~0); |
| 101343 | mon->sampling.nodeListNext = node->head.monitoredItems; |
| 101344 | node->head.monitoredItems = mon; |
| 101345 | return UA_STATUSCODE_GOOD; |
| 101346 | } |
| 101347 | |
| 101348 | static UA_StatusCode |
| 101349 | removeMonitoredItemBackPointer(UA_Server *server, UA_Session *session, |
| 101350 | UA_Node *node, void *data) { |
| 101351 | if(!node->head.monitoredItems) |
| 101352 | return UA_STATUSCODE_GOOD; |
| 101353 | |
| 101354 | /* Edge case that it's the first element */ |
| 101355 | UA_MonitoredItem *remove = (UA_MonitoredItem*)data; |
| 101356 | if(node->head.monitoredItems == remove) { |
| 101357 | node->head.monitoredItems = remove->sampling.nodeListNext; |
| 101358 | return UA_STATUSCODE_GOOD; |
| 101359 | } |
| 101360 | |
| 101361 | UA_MonitoredItem *prev = node->head.monitoredItems; |
| 101362 | UA_MonitoredItem *entry = prev->sampling.nodeListNext; |
| 101363 | for(; entry != NULL; prev = entry, entry = entry->sampling.nodeListNext) { |
| 101364 | if(entry == remove) { |
| 101365 | prev->sampling.nodeListNext = entry->sampling.nodeListNext; |
| 101366 | break; |
| 101367 | } |
| 101368 | } |
| 101369 | |
| 101370 | return UA_STATUSCODE_GOOD; |
| 101371 | } |
| 101372 | |
| 101373 | void |
| 101374 | UA_Server_registerMonitoredItem(UA_Server *server, UA_MonitoredItem *mon) { |
| 101375 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 101376 | |
| 101377 | if(mon->registered) |
| 101378 | return; |
| 101379 | |
| 101380 | /* Register in Subscription and Server */ |
| 101381 | UA_Subscription *sub = mon->subscription; |
| 101382 | if(sub) { |
| 101383 | mon->monitoredItemId = ++sub->lastMonitoredItemId; |
| 101384 | sub->monitoredItemsSize++; |
| 101385 | LIST_INSERT_HEAD(&sub->monitoredItems, mon, listEntry); |
| 101386 | } else { |
| 101387 | mon->monitoredItemId = ++server->lastLocalMonitoredItemId; |
| 101388 | LIST_INSERT_HEAD(&server->localMonitoredItems, mon, listEntry); |
| 101389 | } |
| 101390 | server->monitoredItemsSize++; |
| 101391 | |
| 101392 | /* Register the MonitoredItem in userland */ |
| 101393 | if(server->config.monitoredItemRegisterCallback) { |
| 101394 | UA_Session *session = &server->adminSession; |
| 101395 | if(sub) |
| 101396 | session = sub->session; |
| 101397 | |
| 101398 | void *targetContext = NULL; |
| 101399 | getNodeContext(server, nodeId: mon->itemToMonitor.nodeId, nodeContext: &targetContext); |
| 101400 | server->config.monitoredItemRegisterCallback(server, |
| 101401 | session ? &session->sessionId : NULL, |
| 101402 | session ? session->sessionHandle : NULL, |
| 101403 | &mon->itemToMonitor.nodeId, |
| 101404 | targetContext, |
| 101405 | mon->itemToMonitor.attributeId, false); |
| 101406 | } |
| 101407 | |
| 101408 | mon->registered = true; |
| 101409 | } |
| 101410 | |
| 101411 | static void |
| 101412 | UA_Server_unregisterMonitoredItem(UA_Server *server, UA_MonitoredItem *mon) { |
| 101413 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 101414 | |
| 101415 | if(!mon->registered) |
| 101416 | return; |
| 101417 | |
| 101418 | UA_Subscription *sub = mon->subscription; |
| 101419 | UA_LOG_INFO_SUBSCRIPTION(server->config.logging, sub, |
| 101420 | "MonitoredItem %"PRIi32 " | Deleting the MonitoredItem", |
| 101421 | mon->monitoredItemId); |
| 101422 | |
| 101423 | /* Deregister MonitoredItem in userland */ |
| 101424 | if(server->config.monitoredItemRegisterCallback) { |
| 101425 | UA_Session *session = &server->adminSession; |
| 101426 | if(sub) |
| 101427 | session = sub->session; |
| 101428 | |
| 101429 | void *targetContext = NULL; |
| 101430 | getNodeContext(server, nodeId: mon->itemToMonitor.nodeId, nodeContext: &targetContext); |
| 101431 | server->config.monitoredItemRegisterCallback(server, |
| 101432 | session ? &session->sessionId : NULL, |
| 101433 | session ? session->sessionHandle : NULL, |
| 101434 | &mon->itemToMonitor.nodeId, |
| 101435 | targetContext, |
| 101436 | mon->itemToMonitor.attributeId, true); |
| 101437 | } |
| 101438 | |
| 101439 | /* Deregister in Subscription and server */ |
| 101440 | if(sub) |
| 101441 | sub->monitoredItemsSize--; |
| 101442 | LIST_REMOVE(mon, listEntry); /* Also for LocalMonitoredItems */ |
| 101443 | server->monitoredItemsSize--; |
| 101444 | |
| 101445 | mon->registered = false; |
| 101446 | } |
| 101447 | |
| 101448 | UA_StatusCode |
| 101449 | UA_MonitoredItem_setMonitoringMode(UA_Server *server, UA_MonitoredItem *mon, |
| 101450 | UA_MonitoringMode monitoringMode) { |
| 101451 | /* Check if the MonitoringMode is valid or not */ |
| 101452 | if(monitoringMode > UA_MONITORINGMODE_REPORTING) |
| 101453 | return UA_STATUSCODE_BADMONITORINGMODEINVALID; |
| 101454 | |
| 101455 | /* Set the MonitoringMode, store the old mode */ |
| 101456 | UA_MonitoringMode oldMode = mon->monitoringMode; |
| 101457 | mon->monitoringMode = monitoringMode; |
| 101458 | |
| 101459 | UA_Notification *notification; |
| 101460 | /* Reporting is disabled. This causes all Notifications to be dequeued and |
| 101461 | * deleted. Also remove the last samples so that we immediately generate a |
| 101462 | * Notification when re-activated. */ |
| 101463 | if(mon->monitoringMode == UA_MONITORINGMODE_DISABLED) { |
| 101464 | UA_Notification *notification_tmp; |
| 101465 | UA_MonitoredItem_unregisterSampling(server, mon); |
| 101466 | TAILQ_FOREACH_SAFE(notification, &mon->queue, localEntry, notification_tmp) { |
| 101467 | UA_Notification_delete(n: notification); |
| 101468 | } |
| 101469 | UA_DataValue_clear(p: &mon->lastValue); |
| 101470 | return UA_STATUSCODE_GOOD; |
| 101471 | } |
| 101472 | |
| 101473 | /* When reporting is enabled, put all notifications that were already |
| 101474 | * sampled into the global queue of the subscription. When sampling is |
| 101475 | * enabled, remove all notifications from the global queue. !!! This needs |
| 101476 | * to be the same operation as in UA_Notification_enqueue !!! */ |
| 101477 | if(mon->monitoringMode == UA_MONITORINGMODE_REPORTING) { |
| 101478 | /* Make all notifications reporting. Re-enqueue to ensure they have the |
| 101479 | * right order if some notifications are already reported by a trigger |
| 101480 | * link. */ |
| 101481 | TAILQ_FOREACH(notification, &mon->queue, localEntry) { |
| 101482 | UA_Notification_dequeueSub(n: notification); |
| 101483 | UA_Notification_enqueueSub(n: notification); |
| 101484 | } |
| 101485 | } else /* mon->monitoringMode == UA_MONITORINGMODE_SAMPLING */ { |
| 101486 | /* Make all notifications non-reporting */ |
| 101487 | TAILQ_FOREACH(notification, &mon->queue, localEntry) |
| 101488 | UA_Notification_dequeueSub(n: notification); |
| 101489 | } |
| 101490 | |
| 101491 | /* Register the sampling callback with an interval. If registering the |
| 101492 | * sampling callback failed, set to disabled. But don't delete the current |
| 101493 | * notifications. */ |
| 101494 | UA_StatusCode res = UA_MonitoredItem_registerSampling(server, mon); |
| 101495 | if(res != UA_STATUSCODE_GOOD) { |
| 101496 | mon->monitoringMode = UA_MONITORINGMODE_DISABLED; |
| 101497 | return res; |
| 101498 | } |
| 101499 | |
| 101500 | /* Manually create the first sample if the MonitoredItem was disabled, the |
| 101501 | * MonitoredItem is now sampling (or reporting) and it is not an |
| 101502 | * Event-MonitoredItem */ |
| 101503 | if(oldMode == UA_MONITORINGMODE_DISABLED && |
| 101504 | mon->monitoringMode > UA_MONITORINGMODE_DISABLED && |
| 101505 | mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER) |
| 101506 | monitoredItem_sampleCallback(server, mon); |
| 101507 | |
| 101508 | return UA_STATUSCODE_GOOD; |
| 101509 | } |
| 101510 | |
| 101511 | static void |
| 101512 | delayedFreeMonitoredItem(void *app, void *context) { |
| 101513 | UA_free(ptr: context); |
| 101514 | } |
| 101515 | |
| 101516 | void |
| 101517 | UA_MonitoredItem_delete(UA_Server *server, UA_MonitoredItem *mon) { |
| 101518 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 101519 | |
| 101520 | /* Remove the sampling callback */ |
| 101521 | UA_MonitoredItem_unregisterSampling(server, mon); |
| 101522 | |
| 101523 | /* Deregister in Server and Subscription */ |
| 101524 | if(mon->registered) |
| 101525 | UA_Server_unregisterMonitoredItem(server, mon); |
| 101526 | |
| 101527 | /* Remove the TriggeringLinks */ |
| 101528 | if(mon->triggeringLinksSize > 0) { |
| 101529 | UA_free(ptr: mon->triggeringLinks); |
| 101530 | mon->triggeringLinks = NULL; |
| 101531 | mon->triggeringLinksSize = 0; |
| 101532 | } |
| 101533 | |
| 101534 | /* Remove the queued notifications attached to the subscription */ |
| 101535 | UA_Notification *notification, *notification_tmp; |
| 101536 | TAILQ_FOREACH_SAFE(notification, &mon->queue, localEntry, notification_tmp) { |
| 101537 | UA_Notification_delete(n: notification); |
| 101538 | } |
| 101539 | |
| 101540 | /* Remove the settings */ |
| 101541 | UA_ReadValueId_clear(p: &mon->itemToMonitor); |
| 101542 | UA_MonitoringParameters_clear(p: &mon->parameters); |
| 101543 | |
| 101544 | /* Remove the last samples */ |
| 101545 | UA_DataValue_clear(p: &mon->lastValue); |
| 101546 | |
| 101547 | /* Add a delayed callback to remove the MonitoredItem when the current jobs |
| 101548 | * have completed. This is needed to allow that a local MonitoredItem can |
| 101549 | * remove itself in the callback. */ |
| 101550 | mon->delayedFreePointers.callback = delayedFreeMonitoredItem; |
| 101551 | mon->delayedFreePointers.application = NULL; |
| 101552 | mon->delayedFreePointers.context = mon; |
| 101553 | UA_EventLoop *el = server->config.eventLoop; |
| 101554 | el->addDelayedCallback(el, &mon->delayedFreePointers); |
| 101555 | } |
| 101556 | |
| 101557 | void |
| 101558 | UA_MonitoredItem_ensureQueueSpace(UA_Server *server, UA_MonitoredItem *mon) { |
| 101559 | /* There can be only one EventOverflow more than normal entries. Because |
| 101560 | * EventOverflows are never adjacent. */ |
| 101561 | UA_assert(mon->queueSize >= mon->eventOverflows); |
| 101562 | UA_assert(mon->eventOverflows <= mon->queueSize - mon->eventOverflows + 1); |
| 101563 | |
| 101564 | /* Always attached to a Subscription (no local MonitoredItem) */ |
| 101565 | UA_Subscription *sub = mon->subscription; |
| 101566 | UA_assert(sub); |
| 101567 | |
| 101568 | /* Nothing to do */ |
| 101569 | if(mon->queueSize - mon->eventOverflows <= mon->parameters.queueSize) |
| 101570 | return; |
| 101571 | |
| 101572 | /* Remove notifications until the required queue size is reached */ |
| 101573 | UA_Boolean reporting = false; |
| 101574 | size_t remove = mon->queueSize - mon->eventOverflows - mon->parameters.queueSize; |
| 101575 | while(remove > 0) { |
| 101576 | /* The minimum queue size (without EventOverflows) is 1. At least two |
| 101577 | * notifications that are not EventOverflows are in the queue. */ |
| 101578 | UA_assert(mon->queueSize - mon->eventOverflows >= 2); |
| 101579 | |
| 101580 | /* Select the next notification to delete. Skip over overflow events. */ |
| 101581 | UA_Notification *del = NULL; |
| 101582 | if(mon->parameters.discardOldest) { |
| 101583 | /* Remove the oldest */ |
| 101584 | del = TAILQ_FIRST(&mon->queue); |
| 101585 | #if defined(UA_ENABLE_SUBSCRIPTIONS_EVENTS) && !defined(__clang_analyzer__) |
| 101586 | while(del->isOverflowEvent) |
| 101587 | del = TAILQ_NEXT(del, localEntry); /* skip overflow events */ |
| 101588 | #endif |
| 101589 | } else { |
| 101590 | /* Remove the second newest (to keep the up-to-date notification). |
| 101591 | * The last entry is not an OverflowEvent -- we just added it. */ |
| 101592 | del = TAILQ_LAST(&mon->queue, NotificationQueue); |
| 101593 | del = TAILQ_PREV(del, NotificationQueue, localEntry); |
| 101594 | #if defined(UA_ENABLE_SUBSCRIPTIONS_EVENTS) && !defined(__clang_analyzer__) |
| 101595 | while(del->isOverflowEvent) |
| 101596 | del = TAILQ_PREV(del, NotificationQueue, localEntry); /* skip overflow events */ |
| 101597 | #endif |
| 101598 | } |
| 101599 | |
| 101600 | UA_assert(del); /* There must have been one entry that can be deleted */ |
| 101601 | |
| 101602 | /* Only create OverflowEvents (and set InfoBits) if the notification |
| 101603 | * that is removed is reported */ |
| 101604 | if(TAILQ_NEXT(del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) |
| 101605 | reporting = true; |
| 101606 | |
| 101607 | /* Move the entry after del in the per-MonitoredItem queue right after |
| 101608 | * del in the per-Subscription queue. So we don't starve MonitoredItems |
| 101609 | * with a high sampling interval in the Subscription queue by always |
| 101610 | * removing their first appearance in the per-Subscription queue. |
| 101611 | * |
| 101612 | * With MonitoringMode == SAMPLING, the Notifications are not (all) in |
| 101613 | * the per-Subscription queue. Don't reinsert in that case. |
| 101614 | * |
| 101615 | * For the reinsertion to work, first insert into the per-Subscription |
| 101616 | * queue. */ |
| 101617 | if(TAILQ_NEXT(del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) { |
| 101618 | UA_Notification *after_del = TAILQ_NEXT(del, localEntry); |
| 101619 | UA_assert(after_del); /* There must be one remaining element after del */ |
| 101620 | if(TAILQ_NEXT(after_del, globalEntry) != UA_SUBSCRIPTION_QUEUE_SENTINEL) { |
| 101621 | TAILQ_REMOVE(&sub->notificationQueue, after_del, globalEntry); |
| 101622 | TAILQ_INSERT_AFTER(&sub->notificationQueue, del, after_del, globalEntry); |
| 101623 | } |
| 101624 | } |
| 101625 | |
| 101626 | remove--; |
| 101627 | |
| 101628 | /* Delete the notification and remove it from the queues */ |
| 101629 | UA_Notification_delete(n: del); |
| 101630 | |
| 101631 | /* Update the subscription diagnostics statistics */ |
| 101632 | #ifdef UA_ENABLE_DIAGNOSTICS |
| 101633 | sub->monitoringQueueOverflowCount++; |
| 101634 | #endif |
| 101635 | |
| 101636 | /* Assertions to help Clang's scan-analyzer */ |
| 101637 | UA_assert(del != TAILQ_FIRST(&mon->queue)); |
| 101638 | UA_assert(del != TAILQ_LAST(&mon->queue, NotificationQueue)); |
| 101639 | UA_assert(del != TAILQ_PREV(TAILQ_LAST(&mon->queue, NotificationQueue), |
| 101640 | NotificationQueue, localEntry)); |
| 101641 | } |
| 101642 | |
| 101643 | /* Leave an entry to indicate that notifications were removed */ |
| 101644 | if(reporting) { |
| 101645 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 101646 | if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER) |
| 101647 | createEventOverflowNotification(server, sub, mon); |
| 101648 | else |
| 101649 | #endif |
| 101650 | setOverflowInfoBits(mon); |
| 101651 | } |
| 101652 | } |
| 101653 | |
| 101654 | UA_StatusCode |
| 101655 | UA_MonitoredItem_registerSampling(UA_Server *server, UA_MonitoredItem *mon) { |
| 101656 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 101657 | |
| 101658 | /* Sampling is already registered */ |
| 101659 | if(mon->samplingType != UA_MONITOREDITEMSAMPLINGTYPE_NONE) |
| 101660 | return UA_STATUSCODE_GOOD; |
| 101661 | |
| 101662 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 101663 | UA_Subscription *sub = mon->subscription; |
| 101664 | if(mon->itemToMonitor.attributeId == UA_ATTRIBUTEID_EVENTNOTIFIER || |
| 101665 | mon->parameters.samplingInterval == 0.0) { |
| 101666 | /* Add to the linked list in the node */ |
| 101667 | UA_Session *session = &server->adminSession; |
| 101668 | if(sub) |
| 101669 | session = sub->session; |
| 101670 | res = UA_Server_editNode(server, session, nodeId: &mon->itemToMonitor.nodeId, |
| 101671 | callback: addMonitoredItemBackpointer, data: mon); |
| 101672 | if(res == UA_STATUSCODE_GOOD) |
| 101673 | mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_EVENT; |
| 101674 | return res; |
| 101675 | } else if(sub && mon->parameters.samplingInterval == sub->publishingInterval) { |
| 101676 | /* Add to the subscription for sampling before every publish */ |
| 101677 | LIST_INSERT_HEAD(&sub->samplingMonitoredItems, mon, |
| 101678 | sampling.subscriptionSampling); |
| 101679 | mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_PUBLISH; |
| 101680 | } else { |
| 101681 | /* DataChange MonitoredItems with a positive sampling interval have a |
| 101682 | * repeated callback. Other MonitoredItems are attached to the Node in a |
| 101683 | * linked list of backpointers. */ |
| 101684 | res = addRepeatedCallback(server, |
| 101685 | callback: (UA_ServerCallback)UA_MonitoredItem_sampleCallback, |
| 101686 | data: mon, interval_ms: mon->parameters.samplingInterval, |
| 101687 | callbackId: &mon->sampling.callbackId); |
| 101688 | if(res == UA_STATUSCODE_GOOD) |
| 101689 | mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_CYCLIC; |
| 101690 | } |
| 101691 | |
| 101692 | return res; |
| 101693 | } |
| 101694 | |
| 101695 | void |
| 101696 | UA_MonitoredItem_unregisterSampling(UA_Server *server, UA_MonitoredItem *mon) { |
| 101697 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 101698 | |
| 101699 | switch(mon->samplingType) { |
| 101700 | case UA_MONITOREDITEMSAMPLINGTYPE_CYCLIC: |
| 101701 | /* Remove repeated callback */ |
| 101702 | removeCallback(server, callbackId: mon->sampling.callbackId); |
| 101703 | break; |
| 101704 | |
| 101705 | case UA_MONITOREDITEMSAMPLINGTYPE_EVENT: { |
| 101706 | /* Added to a node */ |
| 101707 | UA_Subscription *sub = mon->subscription; |
| 101708 | UA_Session *session = &server->adminSession; |
| 101709 | if(sub) |
| 101710 | session = sub->session; |
| 101711 | UA_Server_editNode(server, session, nodeId: &mon->itemToMonitor.nodeId, |
| 101712 | callback: removeMonitoredItemBackPointer, data: mon); |
| 101713 | break; |
| 101714 | } |
| 101715 | |
| 101716 | case UA_MONITOREDITEMSAMPLINGTYPE_PUBLISH: |
| 101717 | /* Added to the subscription */ |
| 101718 | LIST_REMOVE(mon, sampling.subscriptionSampling); |
| 101719 | break; |
| 101720 | |
| 101721 | case UA_MONITOREDITEMSAMPLINGTYPE_NONE: |
| 101722 | default: |
| 101723 | /* Sampling is not registered */ |
| 101724 | break; |
| 101725 | } |
| 101726 | |
| 101727 | mon->samplingType = UA_MONITOREDITEMSAMPLINGTYPE_NONE; |
| 101728 | } |
| 101729 | |
| 101730 | UA_StatusCode |
| 101731 | UA_MonitoredItem_removeLink(UA_Subscription *sub, UA_MonitoredItem *mon, UA_UInt32 linkId) { |
| 101732 | /* Find the index */ |
| 101733 | size_t i = 0; |
| 101734 | for(; i < mon->triggeringLinksSize; i++) { |
| 101735 | if(mon->triggeringLinks[i] == linkId) |
| 101736 | break; |
| 101737 | } |
| 101738 | |
| 101739 | /* Not existing / already removed */ |
| 101740 | if(i == mon->triggeringLinksSize) |
| 101741 | return UA_STATUSCODE_BADMONITOREDITEMIDINVALID; |
| 101742 | |
| 101743 | /* Remove the link */ |
| 101744 | mon->triggeringLinksSize--; |
| 101745 | if(mon->triggeringLinksSize == 0) { |
| 101746 | UA_free(ptr: mon->triggeringLinks); |
| 101747 | mon->triggeringLinks = NULL; |
| 101748 | } else { |
| 101749 | mon->triggeringLinks[i] = mon->triggeringLinks[mon->triggeringLinksSize]; |
| 101750 | UA_UInt32 *tmpLinks = (UA_UInt32*) |
| 101751 | UA_realloc(ptr: mon->triggeringLinks, size: mon->triggeringLinksSize * sizeof(UA_UInt32)); |
| 101752 | if(tmpLinks) |
| 101753 | mon->triggeringLinks = tmpLinks; |
| 101754 | } |
| 101755 | |
| 101756 | /* Does the target MonitoredItem exist? This is stupid, but the CTT wants us |
| 101757 | * to to this. We don't auto-remove links together with the target |
| 101758 | * MonitoredItem. Links to removed MonitoredItems are removed when the link |
| 101759 | * triggers and the target no longer exists. */ |
| 101760 | UA_MonitoredItem *mon2 = UA_Subscription_getMonitoredItem(sub, monitoredItemId: linkId); |
| 101761 | if(!mon2) |
| 101762 | return UA_STATUSCODE_BADMONITOREDITEMIDINVALID; |
| 101763 | |
| 101764 | return UA_STATUSCODE_GOOD; |
| 101765 | } |
| 101766 | |
| 101767 | UA_StatusCode |
| 101768 | UA_MonitoredItem_addLink(UA_Subscription *sub, UA_MonitoredItem *mon, UA_UInt32 linkId) { |
| 101769 | /* Does the target MonitoredItem exist? */ |
| 101770 | UA_MonitoredItem *mon2 = UA_Subscription_getMonitoredItem(sub, monitoredItemId: linkId); |
| 101771 | if(!mon2) |
| 101772 | return UA_STATUSCODE_BADMONITOREDITEMIDINVALID; |
| 101773 | |
| 101774 | /* Does the link already exist? */ |
| 101775 | for(size_t i = 0 ; i < mon->triggeringLinksSize; i++) { |
| 101776 | if(mon->triggeringLinks[i] == linkId) |
| 101777 | return UA_STATUSCODE_GOOD; |
| 101778 | } |
| 101779 | |
| 101780 | /* Allocate the memory */ |
| 101781 | UA_UInt32 *tmpLinkIds = (UA_UInt32*) |
| 101782 | UA_realloc(ptr: mon->triggeringLinks, size: (mon->triggeringLinksSize + 1) * sizeof(UA_UInt32)); |
| 101783 | if(!tmpLinkIds) |
| 101784 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 101785 | mon->triggeringLinks = tmpLinkIds; |
| 101786 | |
| 101787 | /* Add the link */ |
| 101788 | mon->triggeringLinks[mon->triggeringLinksSize] = linkId; |
| 101789 | mon->triggeringLinksSize++; |
| 101790 | return UA_STATUSCODE_GOOD; |
| 101791 | } |
| 101792 | |
| 101793 | #endif /* UA_ENABLE_SUBSCRIPTIONS */ |
| 101794 | |
| 101795 | /**** amalgamated original file "/src/server/ua_subscription_datachange.c" ****/ |
| 101796 | |
| 101797 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 101798 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 101799 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 101800 | * |
| 101801 | * Copyright 2017-2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 101802 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 101803 | * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH |
| 101804 | * Copyright 2018 (c) Thomas Stalder, Blue Time Concept SA |
| 101805 | * Copyright 2018 (c) Fabian Arndt, Root-Core |
| 101806 | */ |
| 101807 | |
| 101808 | |
| 101809 | #ifdef UA_ENABLE_SUBSCRIPTIONS /* conditional compilation */ |
| 101810 | |
| 101811 | /* Detect value changes outside the deadband */ |
| 101812 | #define UA_DETECT_DEADBAND(TYPE) do { \ |
| 101813 | TYPE v1 = *(const TYPE*)data1; \ |
| 101814 | TYPE v2 = *(const TYPE*)data2; \ |
| 101815 | TYPE diff = (v1 > v2) ? (TYPE)(v1 - v2) : (TYPE)(v2 - v1); \ |
| 101816 | return ((UA_Double)diff > deadband); \ |
| 101817 | } while(false); |
| 101818 | |
| 101819 | static UA_Boolean |
| 101820 | detectScalarDeadBand(const void *data1, const void *data2, |
| 101821 | const UA_DataType *type, const UA_Double deadband) { |
| 101822 | if(type->typeKind == UA_DATATYPEKIND_SBYTE) { |
| 101823 | UA_DETECT_DEADBAND(UA_SByte); |
| 101824 | } else if(type->typeKind == UA_DATATYPEKIND_BYTE) { |
| 101825 | UA_DETECT_DEADBAND(UA_Byte); |
| 101826 | } else if(type->typeKind == UA_DATATYPEKIND_INT16) { |
| 101827 | UA_DETECT_DEADBAND(UA_Int16); |
| 101828 | } else if(type->typeKind == UA_DATATYPEKIND_UINT16) { |
| 101829 | UA_DETECT_DEADBAND(UA_UInt16); |
| 101830 | } else if(type->typeKind == UA_DATATYPEKIND_INT32) { |
| 101831 | UA_DETECT_DEADBAND(UA_Int32); |
| 101832 | } else if(type->typeKind == UA_DATATYPEKIND_UINT32) { |
| 101833 | UA_DETECT_DEADBAND(UA_UInt32); |
| 101834 | } else if(type->typeKind == UA_DATATYPEKIND_INT64) { |
| 101835 | UA_DETECT_DEADBAND(UA_Int64); |
| 101836 | } else if(type->typeKind == UA_DATATYPEKIND_UINT64) { |
| 101837 | UA_DETECT_DEADBAND(UA_UInt64); |
| 101838 | } else if(type->typeKind == UA_DATATYPEKIND_FLOAT) { |
| 101839 | UA_DETECT_DEADBAND(UA_Float); |
| 101840 | } else if(type->typeKind == UA_DATATYPEKIND_DOUBLE) { |
| 101841 | UA_DETECT_DEADBAND(UA_Double); |
| 101842 | } else { |
| 101843 | return false; /* Not a known numerical type */ |
| 101844 | } |
| 101845 | } |
| 101846 | |
| 101847 | static UA_Boolean |
| 101848 | detectVariantDeadband(const UA_Variant *value, const UA_Variant *oldValue, |
| 101849 | const UA_Double deadbandValue) { |
| 101850 | if(value->arrayLength != oldValue->arrayLength) |
| 101851 | return true; |
| 101852 | if(value->type != oldValue->type) |
| 101853 | return true; |
| 101854 | size_t length = 1; |
| 101855 | if(!UA_Variant_isScalar(v: value)) |
| 101856 | length = value->arrayLength; |
| 101857 | uintptr_t data = (uintptr_t)value->data; |
| 101858 | uintptr_t oldData = (uintptr_t)oldValue->data; |
| 101859 | UA_UInt32 memSize = value->type->memSize; |
| 101860 | for(size_t i = 0; i < length; ++i) { |
| 101861 | if(detectScalarDeadBand(data1: (const void*)data, data2: (const void*)oldData, |
| 101862 | type: value->type, deadband: deadbandValue)) |
| 101863 | return true; |
| 101864 | data += memSize; |
| 101865 | oldData += memSize; |
| 101866 | } |
| 101867 | return false; |
| 101868 | } |
| 101869 | |
| 101870 | static UA_Boolean |
| 101871 | detectValueChange(UA_Server *server, UA_MonitoredItem *mon, const UA_DataValue *dv) { |
| 101872 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 101873 | |
| 101874 | /* Status changes are always reported */ |
| 101875 | if(dv->hasStatus != mon->lastValue.hasStatus || |
| 101876 | dv->status != mon->lastValue.status) { |
| 101877 | return true; |
| 101878 | } |
| 101879 | |
| 101880 | /* Default trigger is Status + Value */ |
| 101881 | UA_DataChangeTrigger trigger = UA_DATACHANGETRIGGER_STATUSVALUE; |
| 101882 | |
| 101883 | /* Use the configured trigger */ |
| 101884 | const UA_DataChangeFilter *dcf = NULL; |
| 101885 | const UA_ExtensionObject *filter = &mon->parameters.filter; |
| 101886 | if(filter->content.decoded.type == &UA_TYPES[UA_TYPES_DATACHANGEFILTER]) { |
| 101887 | dcf = (UA_DataChangeFilter*)filter->content.decoded.data; |
| 101888 | trigger = dcf->trigger; |
| 101889 | } |
| 101890 | |
| 101891 | /* The status was already tested above */ |
| 101892 | if(trigger == UA_DATACHANGETRIGGER_STATUS) |
| 101893 | return false; |
| 101894 | |
| 101895 | UA_assert(trigger == UA_DATACHANGETRIGGER_STATUSVALUE || |
| 101896 | trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP); |
| 101897 | |
| 101898 | /* Test absolute deadband */ |
| 101899 | if(dcf && dcf->deadbandType == UA_DEADBANDTYPE_ABSOLUTE && |
| 101900 | dv->value.type != NULL && UA_DataType_isNumeric(type: dv->value.type)) |
| 101901 | return detectVariantDeadband(value: &dv->value, oldValue: &mon->lastValue.value, |
| 101902 | deadbandValue: dcf->deadbandValue); |
| 101903 | |
| 101904 | /* Compare the source timestamp if the trigger requires that */ |
| 101905 | if(trigger == UA_DATACHANGETRIGGER_STATUSVALUETIMESTAMP) { |
| 101906 | if(dv->hasSourceTimestamp != mon->lastValue.hasSourceTimestamp) |
| 101907 | return true; |
| 101908 | if(dv->hasSourceTimestamp && |
| 101909 | dv->sourceTimestamp != mon->lastValue.sourceTimestamp) |
| 101910 | return true; |
| 101911 | } |
| 101912 | |
| 101913 | /* Has the value changed? */ |
| 101914 | if(dv->hasValue != mon->lastValue.hasValue) |
| 101915 | return true; |
| 101916 | return !UA_equal(p1: &dv->value, p2: &mon->lastValue.value, |
| 101917 | type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 101918 | } |
| 101919 | |
| 101920 | UA_StatusCode |
| 101921 | UA_MonitoredItem_createDataChangeNotification(UA_Server *server, UA_MonitoredItem *mon, |
| 101922 | const UA_DataValue *dv) { |
| 101923 | /* Allocate a new notification */ |
| 101924 | UA_Notification *newNot = UA_Notification_new(); |
| 101925 | if(!newNot) |
| 101926 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 101927 | |
| 101928 | /* Prepare the notification */ |
| 101929 | newNot->mon = mon; |
| 101930 | newNot->data.dataChange.clientHandle = mon->parameters.clientHandle; |
| 101931 | UA_StatusCode retval = UA_DataValue_copy(src: dv, dst: &newNot->data.dataChange.value); |
| 101932 | if(retval != UA_STATUSCODE_GOOD) { |
| 101933 | UA_free(ptr: newNot); |
| 101934 | return retval; |
| 101935 | } |
| 101936 | |
| 101937 | /* Enqueue the notification */ |
| 101938 | UA_Notification_enqueueAndTrigger(server, n: newNot); |
| 101939 | return UA_STATUSCODE_GOOD; |
| 101940 | } |
| 101941 | |
| 101942 | void |
| 101943 | UA_MonitoredItem_processSampledValue(UA_Server *server, UA_MonitoredItem *mon, |
| 101944 | UA_DataValue *value) { |
| 101945 | UA_assert(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER); |
| 101946 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 101947 | |
| 101948 | /* Has the value changed (with the filters applied)? */ |
| 101949 | UA_Boolean changed = detectValueChange(server, mon, dv: value); |
| 101950 | if(!changed) { |
| 101951 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, mon->subscription, |
| 101952 | "MonitoredItem %"PRIi32 " | " |
| 101953 | "The value has not changed", mon->monitoredItemId); |
| 101954 | UA_DataValue_clear(p: value); |
| 101955 | return; |
| 101956 | } |
| 101957 | |
| 101958 | /* The MonitoredItem is attached to a subscription (not server-local). |
| 101959 | * Prepare a notification and enqueue it. */ |
| 101960 | if(mon->subscription) { |
| 101961 | UA_StatusCode res = |
| 101962 | UA_MonitoredItem_createDataChangeNotification(server, mon, dv: value); |
| 101963 | if(res != UA_STATUSCODE_GOOD) { |
| 101964 | UA_LOG_WARNING_SUBSCRIPTION(server->config.logging, mon->subscription, |
| 101965 | "MonitoredItem %"PRIi32 " | " |
| 101966 | "Processing the sample returned the statuscode %s", |
| 101967 | mon->monitoredItemId, UA_StatusCode_name(res)); |
| 101968 | UA_DataValue_clear(p: value); |
| 101969 | return; |
| 101970 | } |
| 101971 | } |
| 101972 | |
| 101973 | /* <-- Point of no return --> */ |
| 101974 | |
| 101975 | /* Move/store the value for filter comparison and TransferSubscription */ |
| 101976 | UA_DataValue_clear(p: &mon->lastValue); |
| 101977 | mon->lastValue = *value; |
| 101978 | |
| 101979 | /* Call the local callback if the MonitoredItem is not attached to a |
| 101980 | * subscription. Do this at the very end. Because the callback might delete |
| 101981 | * the subscription. */ |
| 101982 | if(!mon->subscription) { |
| 101983 | UA_LocalMonitoredItem *localMon = (UA_LocalMonitoredItem*) mon; |
| 101984 | void *nodeContext = NULL; |
| 101985 | getNodeContext(server, nodeId: mon->itemToMonitor.nodeId, nodeContext: &nodeContext); |
| 101986 | localMon->callback.dataChangeCallback(server, |
| 101987 | mon->monitoredItemId, localMon->context, |
| 101988 | &mon->itemToMonitor.nodeId, nodeContext, |
| 101989 | mon->itemToMonitor.attributeId, value); |
| 101990 | } |
| 101991 | } |
| 101992 | |
| 101993 | void |
| 101994 | UA_MonitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *mon) { |
| 101995 | lockServer(server); |
| 101996 | monitoredItem_sampleCallback(server, mon); |
| 101997 | unlockServer(server); |
| 101998 | } |
| 101999 | |
| 102000 | void |
| 102001 | monitoredItem_sampleCallback(UA_Server *server, UA_MonitoredItem *mon) { |
| 102002 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 102003 | UA_assert(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER); |
| 102004 | |
| 102005 | UA_Subscription *sub = mon->subscription; |
| 102006 | UA_LOG_DEBUG_SUBSCRIPTION(server->config.logging, sub, "MonitoredItem %"PRIi32 |
| 102007 | " | Sample callback called", mon->monitoredItemId); |
| 102008 | |
| 102009 | /* Sample the current value */ |
| 102010 | UA_Session *session = (sub) ? sub->session : &server->adminSession; |
| 102011 | UA_DataValue dv = readWithSession(server, session, item: &mon->itemToMonitor, |
| 102012 | timestampsToReturn: mon->timestampsToReturn); |
| 102013 | |
| 102014 | /* Process the sample. This always clears the value. */ |
| 102015 | UA_MonitoredItem_processSampledValue(server, mon, value: &dv); |
| 102016 | } |
| 102017 | |
| 102018 | #endif /* UA_ENABLE_SUBSCRIPTIONS */ |
| 102019 | |
| 102020 | /**** amalgamated original file "/src/server/ua_subscription_events.c" ****/ |
| 102021 | |
| 102022 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 102023 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 102024 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 102025 | * |
| 102026 | * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH |
| 102027 | * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 102028 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
| 102029 | */ |
| 102030 | |
| 102031 | |
| 102032 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 102033 | |
| 102034 | /* We use a 16-Byte ByteString as an identifier */ |
| 102035 | UA_StatusCode |
| 102036 | generateEventId(UA_ByteString *generatedId) { |
| 102037 | /* EventId is a ByteString, which is basically just a string |
| 102038 | * We will use a 16-Byte ByteString as an identifier */ |
| 102039 | UA_StatusCode res = UA_ByteString_allocBuffer(bs: generatedId, length: 16 * sizeof(UA_Byte)); |
| 102040 | if(res != UA_STATUSCODE_GOOD) |
| 102041 | return res; |
| 102042 | UA_UInt32 *ids = (UA_UInt32*)generatedId->data; |
| 102043 | ids[0] = UA_UInt32_random(); |
| 102044 | ids[1] = UA_UInt32_random(); |
| 102045 | ids[2] = UA_UInt32_random(); |
| 102046 | ids[3] = UA_UInt32_random(); |
| 102047 | return UA_STATUSCODE_GOOD; |
| 102048 | } |
| 102049 | |
| 102050 | UA_StatusCode |
| 102051 | createEvent(UA_Server *server, const UA_NodeId eventType, UA_NodeId *outNodeId) { |
| 102052 | if(!outNodeId) { |
| 102053 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 102054 | msg: "outNodeId must not be NULL. The event's NodeId must be returned " |
| 102055 | "so it can be triggered."); |
| 102056 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 102057 | } |
| 102058 | |
| 102059 | /* Make sure the eventType is a subtype of BaseEventType */ |
| 102060 | UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE); |
| 102061 | if(!isNodeInTree_singleRef(server, leafNode: &eventType, nodeToFind: &baseEventTypeId, |
| 102062 | UA_REFERENCETYPEINDEX_HASSUBTYPE)) { |
| 102063 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 102064 | msg: "Event type must be a subtype of BaseEventType!"); |
| 102065 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 102066 | } |
| 102067 | |
| 102068 | /* Create an ObjectNode which represents the event */ |
| 102069 | UA_QualifiedName name; |
| 102070 | /* set a dummy name. This is not used. */ |
| 102071 | name = UA_QUALIFIEDNAME(nsIndex: 0,chars: "E"); |
| 102072 | UA_NodeId newNodeId = UA_NODEID_NULL; |
| 102073 | UA_ObjectAttributes oAttr = UA_ObjectAttributes_default; |
| 102074 | UA_StatusCode retval = addNode(server, nodeClass: UA_NODECLASS_OBJECT, |
| 102075 | requestedNewNodeId: UA_NODEID_NULL, /* Set a random unused NodeId */ |
| 102076 | parentNodeId: UA_NODEID_NULL, /* No parent */ |
| 102077 | referenceTypeId: UA_NODEID_NULL, /* No parent reference */ |
| 102078 | browseName: name, /* an event does not have a name */ |
| 102079 | typeDefinition: eventType, /* the type of the event */ |
| 102080 | attr: &oAttr, /* default attributes are fine */ |
| 102081 | attributeType: &UA_TYPES[UA_TYPES_OBJECTATTRIBUTES], |
| 102082 | NULL, /* no node context */ |
| 102083 | outNewNodeId: &newNodeId); |
| 102084 | if(retval != UA_STATUSCODE_GOOD) { |
| 102085 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 102086 | msg: "Adding event failed. StatusCode %s", UA_StatusCode_name(code: retval)); |
| 102087 | return retval; |
| 102088 | } |
| 102089 | |
| 102090 | /* Find the eventType variable */ |
| 102091 | name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventType"); |
| 102092 | UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin: newNodeId, browsePathSize: 1, browsePath: &name); |
| 102093 | if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { |
| 102094 | retval = bpr.statusCode; |
| 102095 | UA_BrowsePathResult_clear(p: &bpr); |
| 102096 | deleteNode(server, nodeId: newNodeId, true); |
| 102097 | UA_NodeId_clear(p: &newNodeId); |
| 102098 | return retval; |
| 102099 | } |
| 102100 | |
| 102101 | /* Set the EventType */ |
| 102102 | UA_Variant value; |
| 102103 | UA_Variant_init(p: &value); |
| 102104 | UA_Variant_setScalar(v: &value, p: (void*)(uintptr_t)&eventType, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 102105 | retval = writeValueAttribute(server, nodeId: bpr.targets[0].targetId.nodeId, value: &value); |
| 102106 | UA_BrowsePathResult_clear(p: &bpr); |
| 102107 | if(retval != UA_STATUSCODE_GOOD) { |
| 102108 | deleteNode(server, nodeId: newNodeId, true); |
| 102109 | UA_NodeId_clear(p: &newNodeId); |
| 102110 | return retval; |
| 102111 | } |
| 102112 | |
| 102113 | *outNodeId = newNodeId; |
| 102114 | return UA_STATUSCODE_GOOD; |
| 102115 | } |
| 102116 | |
| 102117 | UA_StatusCode |
| 102118 | UA_Server_createEvent(UA_Server *server, const UA_NodeId eventType, |
| 102119 | UA_NodeId *outNodeId) { |
| 102120 | lockServer(server); |
| 102121 | UA_StatusCode res = createEvent(server, eventType, outNodeId); |
| 102122 | unlockServer(server); |
| 102123 | return res; |
| 102124 | } |
| 102125 | |
| 102126 | static UA_StatusCode |
| 102127 | eventSetStandardFields(UA_Server *server, const UA_NodeId *event, |
| 102128 | const UA_NodeId *origin, UA_ByteString *outEventId) { |
| 102129 | /* Set the SourceNode */ |
| 102130 | UA_StatusCode retval; |
| 102131 | UA_QualifiedName name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "SourceNode"); |
| 102132 | UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin: *event, browsePathSize: 1, browsePath: &name); |
| 102133 | if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { |
| 102134 | retval = bpr.statusCode; |
| 102135 | UA_BrowsePathResult_clear(p: &bpr); |
| 102136 | return retval; |
| 102137 | } |
| 102138 | UA_Variant value; |
| 102139 | UA_Variant_init(p: &value); |
| 102140 | UA_Variant_setScalarCopy(v: &value, p: origin, type: &UA_TYPES[UA_TYPES_NODEID]); |
| 102141 | retval = writeValueAttribute(server, nodeId: bpr.targets[0].targetId.nodeId, value: &value); |
| 102142 | UA_Variant_clear(p: &value); |
| 102143 | UA_BrowsePathResult_clear(p: &bpr); |
| 102144 | if(retval != UA_STATUSCODE_GOOD) |
| 102145 | return retval; |
| 102146 | |
| 102147 | /* Set the ReceiveTime */ |
| 102148 | name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "ReceiveTime"); |
| 102149 | bpr = browseSimplifiedBrowsePath(server, origin: *event, browsePathSize: 1, browsePath: &name); |
| 102150 | if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { |
| 102151 | retval = bpr.statusCode; |
| 102152 | UA_BrowsePathResult_clear(p: &bpr); |
| 102153 | return retval; |
| 102154 | } |
| 102155 | UA_DateTime rcvTime = UA_DateTime_now(); |
| 102156 | UA_Variant_setScalar(v: &value, p: &rcvTime, type: &UA_TYPES[UA_TYPES_DATETIME]); |
| 102157 | retval = writeValueAttribute(server, nodeId: bpr.targets[0].targetId.nodeId, value: &value); |
| 102158 | UA_BrowsePathResult_clear(p: &bpr); |
| 102159 | if(retval != UA_STATUSCODE_GOOD) |
| 102160 | return retval; |
| 102161 | |
| 102162 | /* Set the EventId */ |
| 102163 | UA_ByteString eventId = UA_BYTESTRING_NULL; |
| 102164 | retval = generateEventId(generatedId: &eventId); |
| 102165 | if(retval != UA_STATUSCODE_GOOD) |
| 102166 | return retval; |
| 102167 | name = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventId"); |
| 102168 | bpr = browseSimplifiedBrowsePath(server, origin: *event, browsePathSize: 1, browsePath: &name); |
| 102169 | if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { |
| 102170 | retval = bpr.statusCode; |
| 102171 | UA_ByteString_clear(p: &eventId); |
| 102172 | UA_BrowsePathResult_clear(p: &bpr); |
| 102173 | return retval; |
| 102174 | } |
| 102175 | UA_Variant_init(p: &value); |
| 102176 | UA_Variant_setScalar(v: &value, p: &eventId, type: &UA_TYPES[UA_TYPES_BYTESTRING]); |
| 102177 | retval = writeValueAttribute(server, nodeId: bpr.targets[0].targetId.nodeId, value: &value); |
| 102178 | UA_BrowsePathResult_clear(p: &bpr); |
| 102179 | if(retval != UA_STATUSCODE_GOOD) { |
| 102180 | UA_ByteString_clear(p: &eventId); |
| 102181 | return retval; |
| 102182 | } |
| 102183 | |
| 102184 | /* Return the EventId */ |
| 102185 | if(outEventId) |
| 102186 | *outEventId = eventId; |
| 102187 | else |
| 102188 | UA_ByteString_clear(p: &eventId); |
| 102189 | |
| 102190 | return UA_STATUSCODE_GOOD; |
| 102191 | } |
| 102192 | |
| 102193 | /* Filters an event according to the filter specified by mon and then adds it to |
| 102194 | * mons notification queue */ |
| 102195 | UA_StatusCode |
| 102196 | UA_MonitoredItem_addEvent(UA_Server *server, UA_MonitoredItem *mon, |
| 102197 | const UA_NodeId *event) { |
| 102198 | /* Get the filter */ |
| 102199 | if(mon->parameters.filter.content.decoded.type != &UA_TYPES[UA_TYPES_EVENTFILTER]) |
| 102200 | return UA_STATUSCODE_BADFILTERNOTALLOWED; |
| 102201 | UA_EventFilter *eventFilter = (UA_EventFilter*) |
| 102202 | mon->parameters.filter.content.decoded.data; |
| 102203 | |
| 102204 | /* Allocate memory for the notification */ |
| 102205 | UA_Notification *notification = UA_Notification_new(); |
| 102206 | if(!notification) |
| 102207 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 102208 | |
| 102209 | /* The MonitoredItem must be attached to a Subscription. This code path is |
| 102210 | * not taken for local MonitoredItems (once they are enabled for Events). */ |
| 102211 | UA_assert(mon->subscription); |
| 102212 | UA_Subscription *sub = mon->subscription; |
| 102213 | UA_Session *session = sub->session; |
| 102214 | |
| 102215 | UA_EventFilterResult res; /* FilterResult contains only statuscodes. Ignored |
| 102216 | * outside the initial setup/validation. */ |
| 102217 | UA_EventFilterResult_init(p: &res); |
| 102218 | UA_StatusCode retval = filterEvent(server, session, eventNode: event, filter: eventFilter, |
| 102219 | efl: ¬ification->data.event, result: &res); |
| 102220 | UA_EventFilterResult_clear(p: &res); |
| 102221 | if(retval != UA_STATUSCODE_GOOD) { |
| 102222 | UA_Notification_delete(n: notification); |
| 102223 | if(retval == UA_STATUSCODE_BADNOMATCH) |
| 102224 | return UA_STATUSCODE_GOOD; |
| 102225 | return retval; |
| 102226 | } |
| 102227 | |
| 102228 | notification->data.event.clientHandle = mon->parameters.clientHandle; |
| 102229 | notification->mon = mon; |
| 102230 | |
| 102231 | UA_Notification_enqueueAndTrigger(server, n: notification); |
| 102232 | return UA_STATUSCODE_GOOD; |
| 102233 | } |
| 102234 | |
| 102235 | #ifdef UA_ENABLE_HISTORIZING |
| 102236 | static void |
| 102237 | setHistoricalEvent(UA_Server *server, const UA_NodeId *origin, |
| 102238 | const UA_NodeId *emitNodeId, const UA_NodeId *eventNodeId) { |
| 102239 | UA_Variant historicalEventFilterValue; |
| 102240 | UA_Variant_init(p: &historicalEventFilterValue); |
| 102241 | |
| 102242 | /* A HistoricalEventNode that has event history available will provide this property */ |
| 102243 | UA_StatusCode retval = |
| 102244 | readObjectProperty(server, objectId: *emitNodeId, |
| 102245 | propertyName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "HistoricalEventFilter"), |
| 102246 | value: &historicalEventFilterValue); |
| 102247 | if(retval != UA_STATUSCODE_GOOD) { |
| 102248 | /* Do not vex users with no match errors */ |
| 102249 | if(retval != UA_STATUSCODE_BADNOMATCH) |
| 102250 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 102251 | msg: "Cannot read the HistoricalEventFilter property of a " |
| 102252 | "listening node. StatusCode %s", |
| 102253 | UA_StatusCode_name(code: retval)); |
| 102254 | return; |
| 102255 | } |
| 102256 | |
| 102257 | /* If found then check if HistoricalEventFilter property has a valid value */ |
| 102258 | if(UA_Variant_isEmpty(v: &historicalEventFilterValue) || |
| 102259 | !UA_Variant_isScalar(v: &historicalEventFilterValue) || |
| 102260 | historicalEventFilterValue.type != &UA_TYPES[UA_TYPES_EVENTFILTER]) { |
| 102261 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 102262 | msg: "HistoricalEventFilter property of a listening node " |
| 102263 | "does not have a valid value"); |
| 102264 | UA_Variant_clear(p: &historicalEventFilterValue); |
| 102265 | return; |
| 102266 | } |
| 102267 | |
| 102268 | /* Finally, if found and valid then filter */ |
| 102269 | UA_EventFilter *filter = (UA_EventFilter*) historicalEventFilterValue.data; |
| 102270 | UA_EventFieldList efl; |
| 102271 | UA_EventFilterResult result; |
| 102272 | retval = filterEvent(server, session: &server->adminSession, eventNode: eventNodeId, filter, efl: &efl, result: &result); |
| 102273 | if(retval == UA_STATUSCODE_GOOD) |
| 102274 | server->config.historyDatabase.setEvent(server, server->config.historyDatabase.context, |
| 102275 | origin, emitNodeId, filter, &efl); |
| 102276 | UA_EventFilterResult_clear(p: &result); |
| 102277 | UA_Variant_clear(p: &historicalEventFilterValue); |
| 102278 | UA_EventFieldList_clear(p: &efl); |
| 102279 | } |
| 102280 | #endif |
| 102281 | |
| 102282 | static const UA_NodeId objectsFolderId = {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_OBJECTSFOLDER}}; |
| 102283 | #define EMIT_REFS_ROOT_COUNT 4 |
| 102284 | static const UA_NodeId emitReferencesRoots[EMIT_REFS_ROOT_COUNT] = |
| 102285 | {{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}}, |
| 102286 | {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}}, |
| 102287 | {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASEVENTSOURCE}}, |
| 102288 | {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASNOTIFIER}}}; |
| 102289 | |
| 102290 | static const UA_NodeId isInFolderReferences[2] = |
| 102291 | {{0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_ORGANIZES}}, |
| 102292 | {0, UA_NODEIDTYPE_NUMERIC, {UA_NS0ID_HASCOMPONENT}}}; |
| 102293 | |
| 102294 | UA_StatusCode |
| 102295 | triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, |
| 102296 | const UA_NodeId origin, UA_ByteString *outEventId, |
| 102297 | const UA_Boolean deleteEventNode) { |
| 102298 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 102299 | |
| 102300 | UA_LOG_NODEID_DEBUG(&origin, |
| 102301 | UA_LOG_DEBUG(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 102302 | "Events: An event is triggered on node %.*s", |
| 102303 | (int)nodeIdStr.length, nodeIdStr.data)); |
| 102304 | |
| 102305 | #ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS |
| 102306 | UA_Boolean isCallerAC = false; |
| 102307 | if(isConditionOrBranch(server, &eventNodeId, &origin, &isCallerAC)) { |
| 102308 | if(!isCallerAC) { |
| 102309 | UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SERVER, |
| 102310 | "Condition Events: Please use A&C API to trigger Condition Events 0x%08X", |
| 102311 | UA_STATUSCODE_BADINVALIDARGUMENT); |
| 102312 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 102313 | } |
| 102314 | } |
| 102315 | #endif /* UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS */ |
| 102316 | |
| 102317 | /* Check that the origin node exists */ |
| 102318 | const UA_Node *originNode = UA_NODESTORE_GET(server, nodeId: &origin); |
| 102319 | if(!originNode) { |
| 102320 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 102321 | msg: "Origin node for event does not exist."); |
| 102322 | return UA_STATUSCODE_BADNOTFOUND; |
| 102323 | } |
| 102324 | UA_NODESTORE_RELEASE(server, originNode); |
| 102325 | |
| 102326 | /* Make sure the origin is in the ObjectsFolder (TODO: or in the ViewsFolder) */ |
| 102327 | /* Only use Organizes and HasComponent to check if we are below the ObjectsFolder */ |
| 102328 | UA_StatusCode retval; |
| 102329 | UA_ReferenceTypeSet refTypes; |
| 102330 | UA_ReferenceTypeSet_init(set: &refTypes); |
| 102331 | for(int i = 0; i < 2; ++i) { |
| 102332 | UA_ReferenceTypeSet tmpRefTypes; |
| 102333 | retval = referenceTypeIndices(server, refType: &isInFolderReferences[i], indices: &tmpRefTypes, true); |
| 102334 | if(retval != UA_STATUSCODE_GOOD) { |
| 102335 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 102336 | msg: "Events: Could not create the list of references and their subtypes " |
| 102337 | "with StatusCode %s", UA_StatusCode_name(code: retval)); |
| 102338 | } |
| 102339 | refTypes = UA_ReferenceTypeSet_union(setA: refTypes, setB: tmpRefTypes); |
| 102340 | } |
| 102341 | |
| 102342 | if(!isNodeInTree(server, leafNode: &origin, nodeToFind: &objectsFolderId, relevantRefs: &refTypes)) { |
| 102343 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_USERLAND, |
| 102344 | msg: "Node for event must be in ObjectsFolder!"); |
| 102345 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 102346 | } |
| 102347 | |
| 102348 | /* Update the standard fields of the event */ |
| 102349 | retval = eventSetStandardFields(server, event: &eventNodeId, origin: &origin, outEventId); |
| 102350 | if(retval != UA_STATUSCODE_GOOD) { |
| 102351 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 102352 | msg: "Events: Could not set the standard event fields with StatusCode %s", |
| 102353 | UA_StatusCode_name(code: retval)); |
| 102354 | return retval; |
| 102355 | } |
| 102356 | |
| 102357 | /* List of nodes that emit the node. Events propagate upwards (bubble up) in |
| 102358 | * the node hierarchy. */ |
| 102359 | UA_ExpandedNodeId *emitNodes = NULL; |
| 102360 | size_t emitNodesSize = 0; |
| 102361 | |
| 102362 | /* Add the server node to the list of nodes from which the event is emitted. |
| 102363 | * The server node emits all events. |
| 102364 | * |
| 102365 | * Part 3, 7.17: In particular, the root notifier of a Server, the Server |
| 102366 | * Object defined in Part 5, is always capable of supplying all Events from |
| 102367 | * a Server and as such has implied HasEventSource References to every event |
| 102368 | * source in a Server. */ |
| 102369 | UA_NodeId emitStartNodes[2]; |
| 102370 | emitStartNodes[0] = origin; |
| 102371 | emitStartNodes[1] = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER); |
| 102372 | |
| 102373 | /* Get all ReferenceTypes over which the events propagate */ |
| 102374 | UA_ReferenceTypeSet emitRefTypes; |
| 102375 | UA_ReferenceTypeSet_init(set: &emitRefTypes); |
| 102376 | for(size_t i = 0; i < EMIT_REFS_ROOT_COUNT; i++) { |
| 102377 | UA_ReferenceTypeSet tmpRefTypes; |
| 102378 | retval = referenceTypeIndices(server, refType: &emitReferencesRoots[i], indices: &tmpRefTypes, true); |
| 102379 | if(retval != UA_STATUSCODE_GOOD) { |
| 102380 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 102381 | msg: "Events: Could not create the list of references for event " |
| 102382 | "propagation with StatusCode %s", UA_StatusCode_name(code: retval)); |
| 102383 | goto cleanup; |
| 102384 | } |
| 102385 | emitRefTypes = UA_ReferenceTypeSet_union(setA: emitRefTypes, setB: tmpRefTypes); |
| 102386 | } |
| 102387 | |
| 102388 | /* Get the list of nodes in the hierarchy that emits the event. */ |
| 102389 | retval = browseRecursive(server, startNodesSize: 2, startNodes: emitStartNodes, browseDirection: UA_BROWSEDIRECTION_INVERSE, |
| 102390 | refTypes: &emitRefTypes, nodeClassMask: UA_NODECLASS_UNSPECIFIED, true, |
| 102391 | resultsSize: &emitNodesSize, results: &emitNodes); |
| 102392 | if(retval != UA_STATUSCODE_GOOD) { |
| 102393 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 102394 | msg: "Events: Could not create the list of nodes listening on the " |
| 102395 | "event with StatusCode %s", UA_StatusCode_name(code: retval)); |
| 102396 | goto cleanup; |
| 102397 | } |
| 102398 | |
| 102399 | /* Add the event to the listening MonitoredItems at each relevant node */ |
| 102400 | for(size_t i = 0; i < emitNodesSize; i++) { |
| 102401 | /* Get the node */ |
| 102402 | const UA_Node *node = UA_NODESTORE_GET(server, nodeId: &emitNodes[i].nodeId); |
| 102403 | if(!node) |
| 102404 | continue; |
| 102405 | |
| 102406 | /* Only consider objects */ |
| 102407 | if(node->head.nodeClass != UA_NODECLASS_OBJECT) { |
| 102408 | UA_NODESTORE_RELEASE(server, node); |
| 102409 | continue; |
| 102410 | } |
| 102411 | |
| 102412 | /* Add event to monitoreditems */ |
| 102413 | UA_MonitoredItem *mon = node->head.monitoredItems; |
| 102414 | for(; mon != NULL; mon = mon->sampling.nodeListNext) { |
| 102415 | /* Is this an Event-MonitoredItem? */ |
| 102416 | if(mon->itemToMonitor.attributeId != UA_ATTRIBUTEID_EVENTNOTIFIER) |
| 102417 | continue; |
| 102418 | retval = UA_MonitoredItem_addEvent(server, mon, event: &eventNodeId); |
| 102419 | if(retval != UA_STATUSCODE_GOOD) { |
| 102420 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 102421 | msg: "Events: Could not add the event to a listening " |
| 102422 | "node with StatusCode %s", UA_StatusCode_name(code: retval)); |
| 102423 | retval = UA_STATUSCODE_GOOD; /* Only log problems with individual emit nodes */ |
| 102424 | } |
| 102425 | } |
| 102426 | |
| 102427 | UA_NODESTORE_RELEASE(server, node); |
| 102428 | |
| 102429 | /* Add event entry in the historical database */ |
| 102430 | #ifdef UA_ENABLE_HISTORIZING |
| 102431 | if(server->config.historyDatabase.setEvent) |
| 102432 | setHistoricalEvent(server, origin: &origin, emitNodeId: &emitNodes[i].nodeId, eventNodeId: &eventNodeId); |
| 102433 | #endif |
| 102434 | } |
| 102435 | |
| 102436 | /* Delete the node representation of the event */ |
| 102437 | if(deleteEventNode) { |
| 102438 | retval = deleteNode(server, nodeId: eventNodeId, true); |
| 102439 | if(retval != UA_STATUSCODE_GOOD) { |
| 102440 | UA_LOG_WARNING(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 102441 | msg: "Attempt to remove event using deleteNode failed. StatusCode %s", |
| 102442 | UA_StatusCode_name(code: retval)); |
| 102443 | } |
| 102444 | } |
| 102445 | |
| 102446 | cleanup: |
| 102447 | UA_Array_delete(p: emitNodes, size: emitNodesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 102448 | return retval; |
| 102449 | } |
| 102450 | |
| 102451 | UA_StatusCode |
| 102452 | UA_Server_triggerEvent(UA_Server *server, const UA_NodeId eventNodeId, |
| 102453 | const UA_NodeId origin, UA_ByteString *outEventId, |
| 102454 | const UA_Boolean deleteEventNode) { |
| 102455 | lockServer(server); |
| 102456 | UA_StatusCode res = |
| 102457 | triggerEvent(server, eventNodeId, origin, outEventId, deleteEventNode); |
| 102458 | unlockServer(server); |
| 102459 | return res; |
| 102460 | } |
| 102461 | #endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */ |
| 102462 | |
| 102463 | /**** amalgamated original file "/src/server/ua_subscription_events_filter.c" ****/ |
| 102464 | |
| 102465 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 102466 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 102467 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 102468 | * |
| 102469 | * Copyright 2018 (c) Ari Breitkreuz, fortiss GmbH |
| 102470 | * Copyright 2020 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 102471 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Andreas Ebner) |
| 102472 | * Copyright 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 102473 | */ |
| 102474 | |
| 102475 | |
| 102476 | #ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 102477 | |
| 102478 | /* Ternary Logic |
| 102479 | * ------------- |
| 102480 | * Similar to SQL, OPC UA Queries use the K3 - Strong Kleene Logic that |
| 102481 | * considers ternary values true/false/null (unknown). Most operators resolve to |
| 102482 | * a ternary value. Some operators can resolve to a literal value (e.g. CAST). */ |
| 102483 | |
| 102484 | typedef enum { |
| 102485 | UA_TERNARY_FALSE = -1, |
| 102486 | UA_TERNARY_NULL = 0, |
| 102487 | UA_TERNARY_TRUE = 1 |
| 102488 | } UA_Ternary; |
| 102489 | |
| 102490 | static UA_Ternary |
| 102491 | UA_Ternary_and(UA_Ternary first, UA_Ternary second) { |
| 102492 | if(first == UA_TERNARY_FALSE || second == UA_TERNARY_FALSE) |
| 102493 | return UA_TERNARY_FALSE; |
| 102494 | if(first == UA_TERNARY_NULL || second == UA_TERNARY_NULL) |
| 102495 | return UA_TERNARY_NULL; |
| 102496 | return UA_TERNARY_TRUE; |
| 102497 | } |
| 102498 | |
| 102499 | static UA_Ternary |
| 102500 | UA_Ternary_or(UA_Ternary first, UA_Ternary second) { |
| 102501 | if(first == UA_TERNARY_TRUE || second == UA_TERNARY_TRUE) |
| 102502 | return UA_TERNARY_TRUE; |
| 102503 | if(first == UA_TERNARY_NULL || second == UA_TERNARY_NULL) |
| 102504 | return UA_TERNARY_NULL; |
| 102505 | return UA_TERNARY_FALSE; |
| 102506 | } |
| 102507 | |
| 102508 | /* Part 4: The NOT operator always evaluates to NULL if applied to a NULL |
| 102509 | * operand. We simply swap true/false. */ |
| 102510 | static UA_Ternary |
| 102511 | UA_Ternary_not(UA_Ternary v) { |
| 102512 | return (UA_Ternary)((int)v * -1); |
| 102513 | } |
| 102514 | |
| 102515 | static UA_Ternary v2t(const UA_Variant *v) { |
| 102516 | if(UA_Variant_isEmpty(v) || !UA_Variant_hasScalarType(v, type: &UA_TYPES[UA_TYPES_BOOLEAN])) |
| 102517 | return UA_TERNARY_NULL; |
| 102518 | UA_Boolean b = *(UA_Boolean*)v->data; |
| 102519 | return (b) ? UA_TERNARY_TRUE : UA_TERNARY_FALSE; |
| 102520 | } |
| 102521 | |
| 102522 | static const UA_Boolean bFalse = false; |
| 102523 | static const UA_Boolean bTrue = true; |
| 102524 | |
| 102525 | static UA_Variant t2v(UA_Ternary t) { |
| 102526 | UA_Variant v; |
| 102527 | UA_Variant_init(p: &v); |
| 102528 | switch(t) { |
| 102529 | case UA_TERNARY_FALSE: |
| 102530 | UA_Variant_setScalar(v: &v, p: (void*)(uintptr_t)&bFalse, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 102531 | break; |
| 102532 | case UA_TERNARY_TRUE: |
| 102533 | UA_Variant_setScalar(v: &v, p: (void*)(uintptr_t)&bTrue, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 102534 | break; |
| 102535 | default: |
| 102536 | return v; |
| 102537 | } |
| 102538 | v.storageType = UA_VARIANT_DATA_NODELETE; |
| 102539 | return v; |
| 102540 | } |
| 102541 | |
| 102542 | /* Type Casting Rules |
| 102543 | * ------------------ |
| 102544 | * For comparison operations values from different datatypes can be implicitly |
| 102545 | * or explicitly cast. The standard defines rules to selected the target type |
| 102546 | * for casting and when implicit casts are possible. */ |
| 102547 | |
| 102548 | /* Defined in Part 4 Table 123 "Data Precedence Rules". Implicit casting is |
| 102549 | * always to the type of lower precedence value. */ |
| 102550 | static UA_Byte typePrecedence[UA_DATATYPEKINDS] = { |
| 102551 | 12, 10, 11, 8, 9, 5, 6, 3, 4, 2, 1, 14, 255, 13, 255, 255, 16, |
| 102552 | 15, 7, 18, 17, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 |
| 102553 | }; |
| 102554 | |
| 102555 | /* Type conversion table from the standard. |
| 102556 | * 0 -> Same Type, 1 -> Implicit Cast, 2 -> Only explicit Cast, -1 -> cast invalid */ |
| 102557 | static UA_SByte convertLookup[21][21] = { |
| 102558 | { 0, 1,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 1,-1, 2,-1,-1, 1, 1, 1,-1}, |
| 102559 | { 2, 0,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 1,-1, 2,-1,-1, 1, 1, 1,-1}, |
| 102560 | {-1,-1, 0,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}, |
| 102561 | {-1,-1,-1, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1}, |
| 102562 | { 2, 2,-1,-1, 0,-1, 2,-1, 2, 2, 2,-1, 2,-1, 2,-1,-1, 2, 2, 2,-1}, |
| 102563 | {-1,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1, 2,-1,-1, 1,-1,-1,-1,-1,-1,-1}, |
| 102564 | { 2, 2,-1,-1, 1,-1, 0,-1, 2, 2, 2,-1, 2,-1, 2,-1,-1, 2, 2, 2,-1}, |
| 102565 | {-1,-1, 2,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1,-1, 2,-1,-1,-1,-1,-1,-1}, |
| 102566 | { 2, 2,-1,-1, 1,-1, 1,-1, 0, 1, 1,-1, 2,-1, 2,-1,-1, 2, 1, 1,-1}, |
| 102567 | { 2, 2,-1,-1, 1,-1, 1,-1, 2, 0, 1,-1, 2, 2, 2,-1,-1, 2, 2, 1,-1}, |
| 102568 | { 2, 2,-1,-1, 1,-1, 1,-1, 2, 2, 0,-1, 2, 2, 2,-1,-1, 2, 2, 2,-1}, |
| 102569 | {-1,-1,-1,-1,-1, 1,-1,-1,-1,-1,-1, 0,-1,-1, 1,-1,-1,-1,-1,-1,-1}, |
| 102570 | { 2, 2,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 0,-1, 2,-1,-1, 1, 1, 1,-1}, |
| 102571 | {-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1,-1, 0,-1,-1,-1, 2, 1, 1,-1}, |
| 102572 | { 1, 1,-1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 1,-1, 0, 2, 2, 1, 1, 1,-1}, |
| 102573 | {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 0,-1,-1,-1,-1,-1}, |
| 102574 | {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1, 0,-1,-1,-1,-1}, |
| 102575 | { 2, 2,-1,-1, 1,-1, 1,-1, 1, 1, 1,-1, 2, 1, 2,-1,-1, 0, 1, 1,-1}, |
| 102576 | { 2, 2,-1,-1, 1,-1, 1,-1, 2, 1, 1,-1, 2, 2, 2,-1,-1, 2, 0, 1,-1}, |
| 102577 | { 2, 2,-1,-1, 1,-1, 1,-1, 2, 2, 1,-1, 2, 2, 2,-1,-1, 2, 2, 0,-1}, |
| 102578 | {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0} |
| 102579 | }; |
| 102580 | |
| 102581 | /* This array maps the index of the DataType-Kind to the index of the type |
| 102582 | * conversion matrix (255 -> not contained in the matrix) */ |
| 102583 | static UA_Byte convertLookupIndex[UA_DATATYPEKINDS] = { |
| 102584 | 0, 12, 1, 8, 17, 9, 18, 10, 19, 6, 4, 14, 3, 7, 2, |
| 102585 | 20, 11, 5, 13, 16, 15,255,255,255,255,255,255,255,255,255,255 |
| 102586 | }; |
| 102587 | |
| 102588 | /* Returns the target type for implicit cassting or NULL if no implicit casting |
| 102589 | * is possible */ |
| 102590 | static const UA_DataType * |
| 102591 | implicitCastTargetType(const UA_DataType *t1, const UA_DataType *t2) { |
| 102592 | if(!t1 || t1 == t2) |
| 102593 | return t1; |
| 102594 | |
| 102595 | /* Get the type precedence. Return if no implicit casting is possible. */ |
| 102596 | UA_Byte p1 = typePrecedence[t1->typeKind]; |
| 102597 | UA_Byte p2 = typePrecedence[t2->typeKind]; |
| 102598 | if(p1 == UA_BYTE_MAX || p2 == UA_BYTE_MAX) |
| 102599 | return NULL; |
| 102600 | |
| 102601 | /* Which is the target type based on the precedence rules? */ |
| 102602 | const UA_DataType *targetType = (p1 < p2) ? t1 : t2; |
| 102603 | const UA_DataType *sourceType = (p1 < p2) ? t2 : t1; |
| 102604 | |
| 102605 | /* Lookup the casting rule */ |
| 102606 | UA_Byte sourceIndex = convertLookupIndex[sourceType->typeKind]; |
| 102607 | UA_Byte targetIndex = convertLookupIndex[targetType->typeKind]; |
| 102608 | if(sourceIndex == UA_BYTE_MAX || targetIndex == UA_BYTE_MAX) |
| 102609 | return NULL; |
| 102610 | UA_SByte castingRule = convertLookup[sourceIndex][targetIndex]; |
| 102611 | |
| 102612 | /* Is implicit casting allowed? */ |
| 102613 | if(castingRule != 0 && castingRule != 1) |
| 102614 | return NULL; |
| 102615 | return targetType; |
| 102616 | } |
| 102617 | |
| 102618 | /* Cast Numerical |
| 102619 | * -------------- |
| 102620 | * To reduce the number of cases we first "normalize" to either of |
| 102621 | * Int64/UInt64/Double. Then cast from there to the target type. This works for |
| 102622 | * all numericals (not only the implicit conversion). |
| 102623 | * |
| 102624 | * Numerical conversion rules from the standard: |
| 102625 | * |
| 102626 | * - If the conversion fails the result is a null value. |
| 102627 | * - Floating point values are rounded by adding 0.5 and truncating when they |
| 102628 | * are converted to integer values. |
| 102629 | * - Converting a value that is outside the range of the target type causes a |
| 102630 | * conversion error. */ |
| 102631 | |
| 102632 | #define UA_CAST_SIGNED(t, T) \ |
| 102633 | if(i < T##_MIN || (i > 0 && (t)i > T##_MAX)) \ |
| 102634 | return; \ |
| 102635 | *(t*)data = (t)i; \ |
| 102636 | do { } while(0) |
| 102637 | |
| 102638 | #define UA_CAST_UNSIGNED(t, T) \ |
| 102639 | if(u > T##_MAX) \ |
| 102640 | return; \ |
| 102641 | *(t*)data = (t)u; \ |
| 102642 | do { } while(0) |
| 102643 | |
| 102644 | #define UA_CAST_FLOAT(t, T) \ |
| 102645 | if(f + 0.5 < (UA_Double)T##_MIN || f + 0.5 > (UA_Double)T##_MAX) \ |
| 102646 | return; \ |
| 102647 | *(t*)data = (t)(f + 0.5); \ |
| 102648 | do { } while(0) |
| 102649 | |
| 102650 | /* We can cast between any numerical type. So this can be reused for explicit casting. */ |
| 102651 | static void |
| 102652 | castNumerical(const UA_Variant *in, const UA_DataType *type, UA_Variant *out) { |
| 102653 | UA_assert(UA_Variant_isScalar(in)); |
| 102654 | UA_Variant_init(p: out); /* Set to null value */ |
| 102655 | |
| 102656 | UA_Int64 i = 0; |
| 102657 | UA_UInt64 u = 0; |
| 102658 | UA_Double f = 0.0; |
| 102659 | |
| 102660 | const UA_DataTypeKind ink = (UA_DataTypeKind)in->type->typeKind; |
| 102661 | switch(ink) { |
| 102662 | case UA_DATATYPEKIND_SBYTE: i = *(UA_SByte*)in->data; break; |
| 102663 | case UA_DATATYPEKIND_INT16: i = *(UA_Int16*)in->data; break; |
| 102664 | case UA_DATATYPEKIND_INT32: i = *(UA_Int32*)in->data; break; |
| 102665 | case UA_DATATYPEKIND_INT64: i = *(UA_Int64*)in->data; break; |
| 102666 | case UA_DATATYPEKIND_BYTE: /* or */ |
| 102667 | case UA_DATATYPEKIND_BOOLEAN: u = *(UA_Byte*)in->data; break; |
| 102668 | case UA_DATATYPEKIND_UINT16: u = *(UA_UInt16*)in->data; break; |
| 102669 | case UA_DATATYPEKIND_UINT32: /* or */ |
| 102670 | case UA_DATATYPEKIND_STATUSCODE: u = *(UA_UInt32*)in->data; break; |
| 102671 | case UA_DATATYPEKIND_UINT64: u = *(UA_UInt64*)in->data; break; |
| 102672 | case UA_DATATYPEKIND_FLOAT: f = *(UA_Float*)in->data; break; |
| 102673 | case UA_DATATYPEKIND_DOUBLE: f = *(UA_Double*)in->data; break; |
| 102674 | default: return; |
| 102675 | } |
| 102676 | |
| 102677 | void *data = UA_new(type); |
| 102678 | if(!data) |
| 102679 | return; |
| 102680 | |
| 102681 | if(ink == UA_DATATYPEKIND_SBYTE || ink == UA_DATATYPEKIND_INT16 || |
| 102682 | ink == UA_DATATYPEKIND_INT32 || ink == UA_DATATYPEKIND_INT64) { |
| 102683 | /* Cast from signed */ |
| 102684 | switch(type->typeKind) { |
| 102685 | case UA_DATATYPEKIND_SBYTE: UA_CAST_SIGNED(UA_SByte, UA_SBYTE); break; |
| 102686 | case UA_DATATYPEKIND_INT16: UA_CAST_SIGNED(UA_Int16, UA_INT16); break; |
| 102687 | case UA_DATATYPEKIND_INT32: UA_CAST_SIGNED(UA_Int32, UA_INT32); break; |
| 102688 | case UA_DATATYPEKIND_INT64: *(UA_Int64*)data = i; break; |
| 102689 | case UA_DATATYPEKIND_BYTE: UA_CAST_SIGNED(UA_Byte, UA_BYTE); break; |
| 102690 | case UA_DATATYPEKIND_UINT16: UA_CAST_SIGNED(UA_UInt16, UA_UINT16); break; |
| 102691 | case UA_DATATYPEKIND_UINT32: UA_CAST_SIGNED(UA_UInt32, UA_UINT32); break; |
| 102692 | case UA_DATATYPEKIND_UINT64: UA_CAST_SIGNED(UA_UInt64, UA_UINT64); break; |
| 102693 | case UA_DATATYPEKIND_FLOAT: *(UA_Float*)data = (UA_Float)i; break; |
| 102694 | case UA_DATATYPEKIND_DOUBLE: *(UA_Double*)data = (UA_Double)i; break; |
| 102695 | default: |
| 102696 | UA_free(ptr: data); |
| 102697 | return; |
| 102698 | } |
| 102699 | } else if(ink == UA_DATATYPEKIND_BYTE || ink == UA_DATATYPEKIND_UINT16 || |
| 102700 | ink == UA_DATATYPEKIND_UINT32 || ink == UA_DATATYPEKIND_UINT64) { |
| 102701 | /* Cast from unsigned */ |
| 102702 | switch(type->typeKind) { |
| 102703 | case UA_DATATYPEKIND_SBYTE: UA_CAST_UNSIGNED(UA_SByte, UA_SBYTE); break; |
| 102704 | case UA_DATATYPEKIND_INT16: UA_CAST_UNSIGNED(UA_Int16, UA_INT16); break; |
| 102705 | case UA_DATATYPEKIND_INT32: UA_CAST_UNSIGNED(UA_Int32, UA_INT32); break; |
| 102706 | case UA_DATATYPEKIND_INT64: UA_CAST_UNSIGNED(UA_Int64, UA_INT64); break; |
| 102707 | case UA_DATATYPEKIND_BYTE: UA_CAST_UNSIGNED(UA_Byte, UA_BYTE); break; |
| 102708 | case UA_DATATYPEKIND_UINT16: UA_CAST_UNSIGNED(UA_UInt16, UA_UINT16); break; |
| 102709 | case UA_DATATYPEKIND_UINT32: UA_CAST_UNSIGNED(UA_UInt32, UA_UINT32); break; |
| 102710 | case UA_DATATYPEKIND_UINT64: *(UA_UInt64*)data = u; break; |
| 102711 | case UA_DATATYPEKIND_FLOAT: *(UA_Float*)data = (UA_Float)u; break; |
| 102712 | case UA_DATATYPEKIND_DOUBLE: *(UA_Double*)data = (UA_Double)u; break; |
| 102713 | default: |
| 102714 | UA_free(ptr: data); |
| 102715 | return; |
| 102716 | } |
| 102717 | } else { |
| 102718 | /* Cast from float */ |
| 102719 | if(f != f) { |
| 102720 | /* NaN cannot be cast */ |
| 102721 | UA_free(ptr: data); |
| 102722 | return; |
| 102723 | } |
| 102724 | switch(type->typeKind) { |
| 102725 | case UA_DATATYPEKIND_SBYTE: UA_CAST_FLOAT(UA_SByte, UA_SBYTE); break; |
| 102726 | case UA_DATATYPEKIND_INT16: UA_CAST_FLOAT(UA_Int16, UA_INT16); break; |
| 102727 | case UA_DATATYPEKIND_INT32: UA_CAST_FLOAT(UA_Int32, UA_INT32); break; |
| 102728 | case UA_DATATYPEKIND_INT64: UA_CAST_FLOAT(UA_Int64, UA_INT64); break; |
| 102729 | case UA_DATATYPEKIND_BYTE: UA_CAST_FLOAT(UA_Byte, UA_BYTE); break; |
| 102730 | case UA_DATATYPEKIND_UINT16: UA_CAST_FLOAT(UA_UInt16, UA_UINT16); break; |
| 102731 | case UA_DATATYPEKIND_UINT32: UA_CAST_FLOAT(UA_UInt32, UA_UINT32); break; |
| 102732 | case UA_DATATYPEKIND_UINT64: UA_CAST_FLOAT(UA_UInt64, UA_UINT64); break; |
| 102733 | case UA_DATATYPEKIND_FLOAT: *(UA_Float*)data = (UA_Float)f; break; |
| 102734 | case UA_DATATYPEKIND_DOUBLE: *(UA_Double*)data = (UA_Double)f; break; |
| 102735 | default: |
| 102736 | UA_free(ptr: data); |
| 102737 | return; |
| 102738 | } |
| 102739 | } |
| 102740 | |
| 102741 | UA_Variant_setScalar(v: out, p: data, type); |
| 102742 | } |
| 102743 | |
| 102744 | /* Implicit Casting |
| 102745 | * ---------------- */ |
| 102746 | |
| 102747 | static UA_INLINE UA_Byte uppercase(UA_Byte in) { return in | 32; } |
| 102748 | |
| 102749 | static UA_StatusCode |
| 102750 | castImplicitFromString(const UA_Variant *in, const UA_DataType *outType, UA_Variant *out) { |
| 102751 | #if defined(UA_ENABLE_PARSING) || defined(UA_ENABLE_JSON_ENCODING) |
| 102752 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 102753 | #endif |
| 102754 | if(outType == &UA_TYPES[UA_TYPES_BOOLEAN]) { |
| 102755 | /* String -> Boolean |
| 102756 | * |
| 102757 | * Part 4 says: String values containing "true", "false", "1" or "0" |
| 102758 | * can be converted to Boolean values. Other string values cause a |
| 102759 | * conversion error. In this case Strings are case-insensitive. */ |
| 102760 | UA_Boolean b; |
| 102761 | const UA_String *inStr = (const UA_String*)in->data; |
| 102762 | if(inStr->length == 1 && inStr->data[0] == '0') { |
| 102763 | b = false; |
| 102764 | } else if(inStr->length == 1 && inStr->data[0] == '1') { |
| 102765 | b = true; |
| 102766 | } else if(inStr->length == 4 && |
| 102767 | uppercase(in: inStr->data[0])== 'T' && uppercase(in: inStr->data[1])== 'R' && |
| 102768 | uppercase(in: inStr->data[2])== 'U' && uppercase(in: inStr->data[3])== 'E') { |
| 102769 | b = true; |
| 102770 | } else if(inStr->length == 5 && uppercase(in: inStr->data[0])== 'F' && |
| 102771 | uppercase(in: inStr->data[1])== 'A' && uppercase(in: inStr->data[2])== 'L' && |
| 102772 | uppercase(in: inStr->data[3])== 'S' && uppercase(in: inStr->data[4])== 'E') { |
| 102773 | b = false; |
| 102774 | } else { |
| 102775 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 102776 | } |
| 102777 | return UA_Variant_setScalarCopy(v: out, p: &b, type: outType); |
| 102778 | } |
| 102779 | |
| 102780 | #ifdef UA_ENABLE_PARSING |
| 102781 | else if(outType == &UA_TYPES[UA_TYPES_GUID]) { |
| 102782 | /* String -> Guid */ |
| 102783 | UA_Guid guid; |
| 102784 | res = UA_Guid_parse(guid: &guid, str: *(UA_String*)in->data); |
| 102785 | if(res != UA_STATUSCODE_GOOD) |
| 102786 | return res; |
| 102787 | return UA_Variant_setScalarCopy(v: out, p: &guid, type: outType); |
| 102788 | } |
| 102789 | #endif |
| 102790 | |
| 102791 | #ifdef UA_ENABLE_JSON_ENCODING |
| 102792 | /* String -> Numerical, uses the JSON decoding */ |
| 102793 | else if(UA_DataType_isNumeric(type: outType)) { |
| 102794 | void *outData = UA_new(type: outType); |
| 102795 | if(!outData) |
| 102796 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 102797 | res = UA_decodeJson(src: (const UA_ByteString*)in->data, dst: outData, type: outType, NULL); |
| 102798 | if(res != UA_STATUSCODE_GOOD) { |
| 102799 | UA_free(ptr: outData); |
| 102800 | return res; |
| 102801 | } |
| 102802 | UA_Variant_setScalar(v: out, p: outData, type: outType); |
| 102803 | return UA_STATUSCODE_GOOD; |
| 102804 | } |
| 102805 | #endif |
| 102806 | |
| 102807 | /* No implicit casting possible */ |
| 102808 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 102809 | } |
| 102810 | |
| 102811 | static UA_StatusCode |
| 102812 | castImplicit(const UA_Variant *in, const UA_DataType *outType, UA_Variant *out) { |
| 102813 | /* Of the input is empty, casting results in a NULL value */ |
| 102814 | if(UA_Variant_isEmpty(v: in)) { |
| 102815 | UA_Variant_init(p: out); |
| 102816 | return UA_STATUSCODE_GOOD; |
| 102817 | } |
| 102818 | |
| 102819 | /* TODO: We only support scalar values for now */ |
| 102820 | if(!UA_Variant_isScalar(v: in)) |
| 102821 | return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED; |
| 102822 | |
| 102823 | /* No casting necessary */ |
| 102824 | if(in->type == outType) { |
| 102825 | *out = *in; |
| 102826 | out->storageType = UA_VARIANT_DATA_NODELETE; |
| 102827 | return UA_STATUSCODE_GOOD; |
| 102828 | } |
| 102829 | |
| 102830 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 102831 | switch(in->type->typeKind) { |
| 102832 | case UA_DATATYPEKIND_EXPANDEDNODEID: { |
| 102833 | /* ExpandedNodeId -> String */ |
| 102834 | if(outType != &UA_TYPES[UA_TYPES_STRING]) |
| 102835 | break; |
| 102836 | UA_String *outStr = UA_String_new(); |
| 102837 | if(!outStr) |
| 102838 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 102839 | res = UA_ExpandedNodeId_print(eid: (const UA_ExpandedNodeId*)in->data, output: outStr); |
| 102840 | if(res != UA_STATUSCODE_GOOD) { |
| 102841 | UA_free(ptr: outStr); |
| 102842 | break; |
| 102843 | } |
| 102844 | UA_Variant_setScalar(v: out, p: outStr, type: outType); |
| 102845 | break; |
| 102846 | } |
| 102847 | |
| 102848 | case UA_DATATYPEKIND_NODEID: { |
| 102849 | if(outType == &UA_TYPES[UA_TYPES_STRING]) { |
| 102850 | /* NodeId -> String */ |
| 102851 | UA_String *outStr = UA_String_new(); |
| 102852 | if(!outStr) |
| 102853 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 102854 | res = UA_NodeId_print(id: (const UA_NodeId*)in->data, output: outStr); |
| 102855 | if(res != UA_STATUSCODE_GOOD) { |
| 102856 | UA_free(ptr: outStr); |
| 102857 | break; |
| 102858 | } |
| 102859 | UA_Variant_setScalar(v: out, p: outStr, type: outType); |
| 102860 | } else if(outType == &UA_TYPES[UA_TYPES_EXPANDEDNODEID]) { |
| 102861 | /* NodeId -> ExpandedNodeId */ |
| 102862 | UA_ExpandedNodeId *eid = UA_ExpandedNodeId_new(); |
| 102863 | if(!eid) |
| 102864 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 102865 | res = UA_NodeId_copy(src: (const UA_NodeId*)in->data, dst: &eid->nodeId); |
| 102866 | if(res != UA_STATUSCODE_GOOD) { |
| 102867 | UA_free(ptr: eid); |
| 102868 | break; |
| 102869 | } |
| 102870 | UA_Variant_setScalar(v: out, p: eid, type: outType); |
| 102871 | } |
| 102872 | break; |
| 102873 | } |
| 102874 | |
| 102875 | case UA_DATATYPEKIND_STRING: |
| 102876 | res = castImplicitFromString(in, outType, out); |
| 102877 | break; |
| 102878 | |
| 102879 | case UA_DATATYPEKIND_LOCALIZEDTEXT: { |
| 102880 | if(outType != &UA_TYPES[UA_TYPES_STRING]) |
| 102881 | break; |
| 102882 | /* LocalizedText -> String */ |
| 102883 | UA_LocalizedText *inLT = (UA_LocalizedText*)in->data; |
| 102884 | res = UA_Variant_setScalarCopy(v: out, p: &inLT->text, type: outType); |
| 102885 | break; |
| 102886 | } |
| 102887 | |
| 102888 | case UA_DATATYPEKIND_QUALIFIEDNAME: { |
| 102889 | UA_QualifiedName *inQN = (UA_QualifiedName*)in->data; |
| 102890 | if(outType == &UA_TYPES[UA_TYPES_STRING]) { |
| 102891 | /* QualifiedName -> String */ |
| 102892 | res = UA_Variant_setScalarCopy(v: out, p: &inQN->name, type: outType); |
| 102893 | } else if(outType == &UA_TYPES[UA_TYPES_LOCALIZEDTEXT]) { |
| 102894 | /* QualifiedName -> LocalizedText */ |
| 102895 | UA_LocalizedText lt; |
| 102896 | lt.text = inQN->name; |
| 102897 | lt.locale = UA_STRING_NULL; |
| 102898 | res = UA_Variant_setScalarCopy(v: out, p: <, type: outType); |
| 102899 | } |
| 102900 | break; |
| 102901 | } |
| 102902 | |
| 102903 | default: |
| 102904 | /* Try casting between numericals (also works for Boolean and StatusCode |
| 102905 | * input). The conversion can fail if the limits of the output type are |
| 102906 | * exceeded and then results in a NULL value. */ |
| 102907 | castNumerical(in, type: outType, out); |
| 102908 | } |
| 102909 | |
| 102910 | return res; |
| 102911 | } |
| 102912 | |
| 102913 | /* Filter Evaluation |
| 102914 | * ----------------- */ |
| 102915 | |
| 102916 | typedef struct { |
| 102917 | UA_Server *server; |
| 102918 | UA_Session *session; |
| 102919 | const UA_NodeId *eventNode; |
| 102920 | const UA_ContentFilter *filter; |
| 102921 | UA_ContentFilterResult *filterResult; |
| 102922 | UA_Variant results[UA_EVENTFILTER_MAXELEMENTS]; |
| 102923 | |
| 102924 | /* The stack contains temporary variants. Cleaned up after the evaluation of |
| 102925 | * each operator. */ |
| 102926 | size_t top; |
| 102927 | UA_Variant stack[UA_EVENTFILTER_MAXOPERANDS]; |
| 102928 | } UA_FilterEvalContext; |
| 102929 | |
| 102930 | /* Operand Resolving |
| 102931 | * ~~~~~~~~~~~~~~~~~ |
| 102932 | * Methods that all resolve an operator operand to a Variant. */ |
| 102933 | |
| 102934 | /* Part 4, 7.4.4.5 SimpleAttributeOperand: The clause can point to any attribute |
| 102935 | * of nodes. Either a child of the event node and also the event type. */ |
| 102936 | static UA_StatusCode |
| 102937 | resolveSimpleAttributeOperand(UA_Server *server, UA_Session *session, |
| 102938 | const UA_NodeId *origin, |
| 102939 | const UA_SimpleAttributeOperand *sao, |
| 102940 | UA_Variant *value) { |
| 102941 | /* Prepare the ReadValueId */ |
| 102942 | UA_ReadValueId rvi; |
| 102943 | UA_ReadValueId_init(p: &rvi); |
| 102944 | rvi.indexRange = sao->indexRange; |
| 102945 | rvi.attributeId = sao->attributeId; |
| 102946 | |
| 102947 | /* Read the value */ |
| 102948 | UA_DataValue v; |
| 102949 | if(sao->browsePathSize == 0) { |
| 102950 | /* If this list (browsePath) is empty, the Node is the instance of the |
| 102951 | * TypeDefinition. (Part 4, 7.4.4.5) */ |
| 102952 | rvi.nodeId = *origin; |
| 102953 | |
| 102954 | /* A Condition is an indirection. Look up the target node. */ |
| 102955 | /* TODO: check for Branches! One Condition could have multiple Branches */ |
| 102956 | UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_CONDITIONTYPE); |
| 102957 | if(UA_NodeId_equal(p1: &sao->typeDefinitionId, p2: &conditionTypeId)) { |
| 102958 | #ifdef UA_ENABLE_SUBSCRIPTIONS_ALARMS_CONDITIONS |
| 102959 | UA_StatusCode res = UA_getConditionId(server, origin, &rvi.nodeId); |
| 102960 | UA_CHECK_STATUS(res, return res); |
| 102961 | #else |
| 102962 | return UA_STATUSCODE_BADNOTSUPPORTED; |
| 102963 | #endif |
| 102964 | } |
| 102965 | |
| 102966 | v = readWithSession(server, session, item: &rvi, timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER); |
| 102967 | } else { |
| 102968 | /* Resolve the browse path, starting from the event-source (and not the |
| 102969 | * typeDefinitionId). */ |
| 102970 | UA_BrowsePathResult bpr = |
| 102971 | browseSimplifiedBrowsePath(server, origin: *origin, |
| 102972 | browsePathSize: sao->browsePathSize, browsePath: sao->browsePath); |
| 102973 | if(bpr.targetsSize == 0 && bpr.statusCode == UA_STATUSCODE_GOOD) |
| 102974 | bpr.statusCode = UA_STATUSCODE_BADNOTFOUND; |
| 102975 | if(bpr.statusCode != UA_STATUSCODE_GOOD) { |
| 102976 | UA_StatusCode res = bpr.statusCode; |
| 102977 | UA_BrowsePathResult_clear(p: &bpr); |
| 102978 | return res; |
| 102979 | } |
| 102980 | |
| 102981 | /* Use the first match */ |
| 102982 | rvi.nodeId = bpr.targets[0].targetId.nodeId; |
| 102983 | v = readWithSession(server, session, item: &rvi, timestampsToReturn: UA_TIMESTAMPSTORETURN_NEITHER); |
| 102984 | UA_BrowsePathResult_clear(p: &bpr); |
| 102985 | } |
| 102986 | |
| 102987 | /* Validate the result */ |
| 102988 | if(v.status != UA_STATUSCODE_GOOD) { |
| 102989 | UA_Variant_clear(p: &v.value); |
| 102990 | return v.status; |
| 102991 | } |
| 102992 | if(!v.hasValue) |
| 102993 | return UA_STATUSCODE_BADNODATAAVAILABLE; |
| 102994 | |
| 102995 | /* Move the result to the output */ |
| 102996 | *value = v.value; |
| 102997 | return UA_STATUSCODE_GOOD; |
| 102998 | } |
| 102999 | |
| 103000 | static UA_StatusCode |
| 103001 | resolveOperand(UA_FilterEvalContext *ctx, UA_ExtensionObject *op, UA_Variant *out) { |
| 103002 | if(op->encoding != UA_EXTENSIONOBJECT_DECODED && |
| 103003 | op->encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) |
| 103004 | return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED; |
| 103005 | |
| 103006 | /* Result of an operator that was evaluated prior */ |
| 103007 | if(op->content.decoded.type == &UA_TYPES[UA_TYPES_ELEMENTOPERAND]) { |
| 103008 | UA_ElementOperand *eo = (UA_ElementOperand*)op->content.decoded.data; |
| 103009 | *out = ctx->results[eo->index]; |
| 103010 | out->storageType = UA_VARIANT_DATA_NODELETE; |
| 103011 | return UA_STATUSCODE_GOOD; |
| 103012 | } |
| 103013 | |
| 103014 | /* Literal value */ |
| 103015 | if(op->content.decoded.type == &UA_TYPES[UA_TYPES_LITERALOPERAND]) { |
| 103016 | UA_LiteralOperand *lo = (UA_LiteralOperand*)op->content.decoded.data; |
| 103017 | *out = lo->value; |
| 103018 | out->storageType = UA_VARIANT_DATA_NODELETE; |
| 103019 | return UA_STATUSCODE_GOOD; |
| 103020 | } |
| 103021 | |
| 103022 | /* SimpleAttributeOperand with a BrowsePath */ |
| 103023 | if(op->content.decoded.type == &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND]) { |
| 103024 | UA_SimpleAttributeOperand *sao = |
| 103025 | (UA_SimpleAttributeOperand*)op->content.decoded.data; |
| 103026 | return resolveSimpleAttributeOperand(server: ctx->server, session: ctx->session, |
| 103027 | origin: ctx->eventNode, sao, value: out); |
| 103028 | } |
| 103029 | |
| 103030 | return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED; |
| 103031 | } |
| 103032 | |
| 103033 | /* The operandIndex is within the operator arguments, not the operand index for |
| 103034 | * the overall stack */ |
| 103035 | static UA_StatusCode |
| 103036 | setOperandError(UA_FilterEvalContext *ctx, size_t elementIndex, |
| 103037 | size_t operandIndex, UA_StatusCode statusCode) { |
| 103038 | UA_ContentFilterElementResult *res = &ctx->filterResult->elementResults[elementIndex]; |
| 103039 | res->operandStatusCodes[operandIndex] = statusCode; |
| 103040 | /* The operator status is set globally in a single location upwards the call chain |
| 103041 | * res->statusCode = statusCode; */ |
| 103042 | return statusCode; |
| 103043 | } |
| 103044 | |
| 103045 | /* Filter Operators |
| 103046 | * ~~~~~~~~~~~~~~~~ */ |
| 103047 | |
| 103048 | static UA_StatusCode |
| 103049 | ofTypeOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103050 | const UA_ContentFilterElement *elm = &ctx->filter->elements[index]; |
| 103051 | UA_assert(elm->filterOperandsSize == 1); |
| 103052 | |
| 103053 | /* Get the operand. Must be a literal NodeId */ |
| 103054 | UA_Variant *op0 = &ctx->stack[ctx->top++]; |
| 103055 | UA_StatusCode res = resolveOperand(ctx, op: &elm->filterOperands[0], out: op0); |
| 103056 | if(res != UA_STATUSCODE_GOOD || !UA_Variant_hasScalarType(v: op0, type: &UA_TYPES[UA_TYPES_NODEID])) |
| 103057 | return setOperandError(ctx, elementIndex: index, operandIndex: 0, UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED); |
| 103058 | |
| 103059 | /* Read the event type */ |
| 103060 | UA_Variant eventTypeVar; |
| 103061 | UA_Variant_init(p: &eventTypeVar); |
| 103062 | const UA_NodeId *operandTypeId = (const UA_NodeId *)op0->data; |
| 103063 | res = readObjectProperty(server: ctx->server, objectId: *ctx->eventNode, |
| 103064 | propertyName: UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventType"), value: &eventTypeVar); |
| 103065 | UA_CHECK_STATUS(res, return res); |
| 103066 | |
| 103067 | if(!UA_Variant_hasScalarType(v: &eventTypeVar, type: &UA_TYPES[UA_TYPES_NODEID])) { |
| 103068 | UA_LOG_WARNING(logger: ctx->server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 103069 | msg: "EventType has an invalid type."); |
| 103070 | UA_Variant_clear(p: &eventTypeVar); |
| 103071 | return UA_STATUSCODE_BADINTERNALERROR; |
| 103072 | } |
| 103073 | |
| 103074 | /* Check if the eventtype is equal to the operand or a subtype of it */ |
| 103075 | const UA_NodeId *eventTypeId = (UA_NodeId*)eventTypeVar.data; |
| 103076 | UA_Boolean ofType = isNodeInTree_singleRef(server: ctx->server, leafNode: eventTypeId, nodeToFind: operandTypeId, |
| 103077 | UA_REFERENCETYPEINDEX_HASSUBTYPE); |
| 103078 | ctx->results[index] = t2v(t: ofType ? UA_TERNARY_TRUE : UA_TERNARY_FALSE); |
| 103079 | UA_Variant_clear(p: &eventTypeVar); |
| 103080 | return UA_STATUSCODE_GOOD; |
| 103081 | } |
| 103082 | |
| 103083 | static UA_StatusCode |
| 103084 | andOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103085 | const UA_ContentFilterElement *elm = &ctx->filter->elements[index]; |
| 103086 | UA_assert(elm->filterOperandsSize == 2); |
| 103087 | UA_Variant *op0 = &ctx->stack[ctx->top++]; |
| 103088 | UA_StatusCode res = resolveOperand(ctx, op: &elm->filterOperands[0], out: op0); |
| 103089 | UA_CHECK_STATUS(res, return res); |
| 103090 | UA_Variant *op1 = &ctx->stack[ctx->top++]; |
| 103091 | res = resolveOperand(ctx, op: &elm->filterOperands[1], out: op1); |
| 103092 | UA_CHECK_STATUS(res, return res); |
| 103093 | ctx->results[index] = t2v(t: UA_Ternary_and(first: v2t(v: op0), second: v2t(v: op1))); |
| 103094 | return UA_STATUSCODE_GOOD; |
| 103095 | } |
| 103096 | |
| 103097 | static UA_StatusCode |
| 103098 | orOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103099 | const UA_ContentFilterElement *elm = &ctx->filter->elements[index]; |
| 103100 | UA_assert(elm->filterOperandsSize == 2); |
| 103101 | UA_Variant *op0 = &ctx->stack[ctx->top++]; |
| 103102 | UA_StatusCode res = resolveOperand(ctx, op: &elm->filterOperands[0], out: op0); |
| 103103 | UA_CHECK_STATUS(res, return res); |
| 103104 | UA_Variant *op1 = &ctx->stack[ctx->top++]; |
| 103105 | res = resolveOperand(ctx, op: &elm->filterOperands[1], out: op1); |
| 103106 | UA_CHECK_STATUS(res, return res); |
| 103107 | ctx->results[index] = t2v(t: UA_Ternary_or(first: v2t(v: op0), second: v2t(v: op1))); |
| 103108 | return UA_STATUSCODE_GOOD; |
| 103109 | } |
| 103110 | |
| 103111 | static UA_StatusCode |
| 103112 | notOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103113 | const UA_ContentFilterElement *elm = &ctx->filter->elements[index]; |
| 103114 | UA_assert(elm->filterOperandsSize == 1); |
| 103115 | UA_Variant *op0 = &ctx->stack[ctx->top++]; |
| 103116 | UA_StatusCode res = resolveOperand(ctx, op: &elm->filterOperands[0], out: op0); |
| 103117 | UA_CHECK_STATUS(res, return res); |
| 103118 | ctx->results[index] = t2v(t: UA_Ternary_not(v: v2t(v: op0))); |
| 103119 | return UA_STATUSCODE_GOOD; |
| 103120 | } |
| 103121 | |
| 103122 | /* Resolves the operands and casts them implicitly to the same type. |
| 103123 | * The result is set at &ctx->stack[ctx->top] (for the initial value of top). */ |
| 103124 | static UA_StatusCode |
| 103125 | castResolveOperands(UA_FilterEvalContext *ctx, size_t index, UA_Boolean setError) { |
| 103126 | /* Enough space on the stack left? */ |
| 103127 | const UA_ContentFilterElement *elm = &ctx->filter->elements[index]; |
| 103128 | if(ctx->top + elm->filterOperandsSize > UA_EVENTFILTER_MAXOPERANDS) |
| 103129 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 103130 | |
| 103131 | /* Resolve all operands */ |
| 103132 | UA_assert(ctx->top == 0); /* Assume the stack is empty */ |
| 103133 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 103134 | for(size_t i = 0; i < elm->filterOperandsSize; i++) { |
| 103135 | res = resolveOperand(ctx, op: &elm->filterOperands[i], out: &ctx->stack[ctx->top++]); |
| 103136 | UA_CHECK_STATUS(res, return res); |
| 103137 | } |
| 103138 | UA_assert(ctx->top > 0); /* Assume the stack is no longer empty */ |
| 103139 | |
| 103140 | /* Get the datatype for casting */ |
| 103141 | const UA_DataType *targetType = ctx->stack[0].type; |
| 103142 | for(size_t pos = 1; pos < ctx->top; pos++) { |
| 103143 | if(targetType) |
| 103144 | targetType = implicitCastTargetType(t1: targetType, t2: ctx->stack[pos].type); |
| 103145 | if(!targetType) |
| 103146 | return (setError) ? setOperandError(ctx, elementIndex: index, operandIndex: pos, statusCode: res) : res; |
| 103147 | } |
| 103148 | |
| 103149 | /* Cast the operands. Put the result in the same location on the stack. */ |
| 103150 | for(size_t pos = 0; pos < ctx->top; pos++) { |
| 103151 | UA_Variant orig = ctx->stack[pos]; |
| 103152 | res = castImplicit(in: &orig, outType: targetType, out: &ctx->stack[pos]); |
| 103153 | if(res != UA_STATUSCODE_GOOD) |
| 103154 | return (setError) ? setOperandError(ctx, elementIndex: index, operandIndex: pos, statusCode: res) : res; |
| 103155 | if(ctx->stack[pos].data == orig.data) { |
| 103156 | /* Reuse the storage type of the original data if the variant is |
| 103157 | * identical or only the type has changed */ |
| 103158 | ctx->stack[pos].storageType = orig.storageType; |
| 103159 | } else { |
| 103160 | UA_Variant_clear(p: &orig); /* Fresh allocation of the cast variant. Clean up. */ |
| 103161 | } |
| 103162 | } |
| 103163 | |
| 103164 | return UA_STATUSCODE_GOOD; |
| 103165 | } |
| 103166 | |
| 103167 | static UA_StatusCode |
| 103168 | compareOperator(UA_FilterEvalContext *ctx, size_t index, UA_FilterOperator op) { |
| 103169 | UA_assert(ctx->filter->elements[index].filterOperandsSize == 2); |
| 103170 | |
| 103171 | /* Resolve and cast the operands. A failed casting results in FALSE. Note |
| 103172 | * that operands could cast to NULL. */ |
| 103173 | UA_assert(ctx->top == 0); /* Assume the stack is empty */ |
| 103174 | UA_StatusCode res = castResolveOperands(ctx, index, false); |
| 103175 | if(res != UA_STATUSCODE_GOOD || !ctx->stack[0].type || |
| 103176 | ctx->stack[0].type != ctx->stack[1].type) { |
| 103177 | ctx->results[index] = t2v(t: UA_TERNARY_FALSE); |
| 103178 | return UA_STATUSCODE_GOOD; |
| 103179 | } |
| 103180 | UA_assert(ctx->top == 2); /* Assume the stack is no longer empty */ |
| 103181 | |
| 103182 | /* The equals operator is always possible. For the other comparisons it has |
| 103183 | * to be an ordered type: Numerical, Boolean, StatusCode or DateTime. */ |
| 103184 | const UA_DataType *type = ctx->stack[0].type; |
| 103185 | if(op != UA_FILTEROPERATOR_EQUALS && !UA_DataType_isNumeric(type) && |
| 103186 | type->typeKind != UA_DATATYPEKIND_BOOLEAN && |
| 103187 | type->typeKind != UA_DATATYPEKIND_STATUSCODE && |
| 103188 | type->typeKind != UA_DATATYPEKIND_DATETIME) |
| 103189 | return setOperandError(ctx, elementIndex: index, operandIndex: 0, UA_STATUSCODE_BADFILTEROPERANDINVALID); |
| 103190 | |
| 103191 | /* Compute the order */ |
| 103192 | UA_Order eq = UA_order(p1: ctx->stack[0].data, p2: ctx->stack[1].data, type); |
| 103193 | UA_Ternary operatorResult = UA_TERNARY_FALSE; |
| 103194 | switch(op) { |
| 103195 | case UA_FILTEROPERATOR_EQUALS: |
| 103196 | default: |
| 103197 | if(eq == UA_ORDER_EQ) |
| 103198 | operatorResult = UA_TERNARY_TRUE; |
| 103199 | break; |
| 103200 | case UA_FILTEROPERATOR_GREATERTHAN: |
| 103201 | if(eq == UA_ORDER_MORE) |
| 103202 | operatorResult = UA_TERNARY_TRUE; |
| 103203 | break; |
| 103204 | case UA_FILTEROPERATOR_LESSTHAN: |
| 103205 | if(eq == UA_ORDER_LESS) |
| 103206 | operatorResult = UA_TERNARY_TRUE; |
| 103207 | break; |
| 103208 | case UA_FILTEROPERATOR_GREATERTHANOREQUAL: |
| 103209 | if(eq == UA_ORDER_MORE || eq == UA_ORDER_EQ) |
| 103210 | operatorResult = UA_TERNARY_TRUE; |
| 103211 | break; |
| 103212 | case UA_FILTEROPERATOR_LESSTHANOREQUAL: |
| 103213 | if(eq == UA_ORDER_LESS || eq == UA_ORDER_EQ) |
| 103214 | operatorResult = UA_TERNARY_TRUE; |
| 103215 | break; |
| 103216 | } |
| 103217 | |
| 103218 | /* Set result as a literal value */ |
| 103219 | ctx->results[index] = t2v(t: operatorResult); |
| 103220 | return UA_STATUSCODE_GOOD; |
| 103221 | } |
| 103222 | |
| 103223 | static UA_StatusCode |
| 103224 | equalsOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103225 | return compareOperator(ctx, index, op: UA_FILTEROPERATOR_EQUALS); |
| 103226 | } |
| 103227 | |
| 103228 | static UA_StatusCode |
| 103229 | gtOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103230 | return compareOperator(ctx, index, op: UA_FILTEROPERATOR_GREATERTHAN); |
| 103231 | } |
| 103232 | |
| 103233 | static UA_StatusCode |
| 103234 | ltOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103235 | return compareOperator(ctx, index, op: UA_FILTEROPERATOR_LESSTHAN); |
| 103236 | } |
| 103237 | |
| 103238 | static UA_StatusCode |
| 103239 | gteOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103240 | return compareOperator(ctx, index, op: UA_FILTEROPERATOR_GREATERTHANOREQUAL); |
| 103241 | } |
| 103242 | |
| 103243 | static UA_StatusCode |
| 103244 | lteOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103245 | return compareOperator(ctx, index, op: UA_FILTEROPERATOR_LESSTHANOREQUAL); |
| 103246 | } |
| 103247 | |
| 103248 | static UA_StatusCode |
| 103249 | bitwiseOperator(UA_FilterEvalContext *ctx, size_t index, UA_FilterOperator op) { |
| 103250 | UA_assert(ctx->filter->elements[index].filterOperandsSize == 2); |
| 103251 | |
| 103252 | /* Resolve and cast the operands. Note that operands could cast to NULL. */ |
| 103253 | UA_assert(ctx->top == 0); /* Assume the stack is empty */ |
| 103254 | UA_StatusCode res = castResolveOperands(ctx, index, true); |
| 103255 | UA_CHECK_STATUS(res, return res); |
| 103256 | UA_assert(ctx->top == 2); /* Assume we have two elements */ |
| 103257 | |
| 103258 | /* Operands can cast to NULL */ |
| 103259 | const UA_DataType *type = ctx->stack[0].type; |
| 103260 | if(!type || !UA_DataType_isNumeric(type) || |
| 103261 | ctx->stack[0].type != ctx->stack[1].type) |
| 103262 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 103263 | |
| 103264 | /* Copy the casted literal to the result */ |
| 103265 | res = UA_Variant_copy(src: &ctx->stack[0], dst: &ctx->results[index]); |
| 103266 | UA_CHECK_STATUS(res, return res); |
| 103267 | |
| 103268 | /* Do the bitwise operation on the result data */ |
| 103269 | UA_Byte *bytesOut = (UA_Byte*)ctx->results[index].data; |
| 103270 | const UA_Byte *bytes2 = (const UA_Byte*)ctx->stack[1].data; |
| 103271 | for(size_t i = 0; i < type->memSize; i++) { |
| 103272 | if(op == UA_FILTEROPERATOR_BITWISEAND) |
| 103273 | bytesOut[i] = bytesOut[i] & bytes2[i]; |
| 103274 | else |
| 103275 | bytesOut[i] = bytesOut[i] | bytes2[i]; |
| 103276 | } |
| 103277 | return UA_STATUSCODE_GOOD; |
| 103278 | } |
| 103279 | |
| 103280 | static UA_StatusCode |
| 103281 | bitwiseAndOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103282 | return bitwiseOperator(ctx, index, op: UA_FILTEROPERATOR_BITWISEAND); |
| 103283 | } |
| 103284 | |
| 103285 | static UA_StatusCode |
| 103286 | bitwiseOrOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103287 | return bitwiseOperator(ctx, index, op: UA_FILTEROPERATOR_BITWISEOR); |
| 103288 | } |
| 103289 | |
| 103290 | static UA_StatusCode |
| 103291 | betweenOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103292 | UA_assert(ctx->filter->elements[index].filterOperandsSize == 3); |
| 103293 | |
| 103294 | /* If no implicit conversion is available and the operands are of different |
| 103295 | * types, the particular result is FALSE. */ |
| 103296 | UA_assert(ctx->top == 0); /* Assume the stack is empty */ |
| 103297 | UA_StatusCode res = castResolveOperands(ctx, index, false); |
| 103298 | if(res != UA_STATUSCODE_GOOD) { |
| 103299 | ctx->results[index] = t2v(t: UA_TERNARY_FALSE); |
| 103300 | return UA_STATUSCODE_GOOD; |
| 103301 | } |
| 103302 | UA_assert(ctx->top == 3); /* Assume we have three elements */ |
| 103303 | |
| 103304 | /* The casting can result in NULL values or a non-numerical type */ |
| 103305 | const UA_DataType *type = ctx->stack[0].type; |
| 103306 | if(!type || !UA_DataType_isNumeric(type) || |
| 103307 | type != ctx->stack[1].type || type != ctx->stack[2].type) |
| 103308 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 103309 | |
| 103310 | UA_Order o1 = UA_order(p1: ctx->stack[0].data, p2: ctx->stack[1].data, type); |
| 103311 | UA_Order o2 = UA_order(p1: ctx->stack[0].data, p2: ctx->stack[2].data, type); |
| 103312 | UA_Ternary comp = ((o1 == UA_ORDER_MORE || o1 == UA_ORDER_EQ) && |
| 103313 | (o2 == UA_ORDER_LESS || o2 == UA_ORDER_EQ)) ? |
| 103314 | UA_TERNARY_TRUE : UA_TERNARY_FALSE; |
| 103315 | |
| 103316 | ctx->results[index] = t2v(t: comp); |
| 103317 | return UA_STATUSCODE_GOOD; |
| 103318 | } |
| 103319 | |
| 103320 | static UA_StatusCode |
| 103321 | inListOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103322 | const UA_ContentFilterElement *elm = &ctx->filter->elements[index]; |
| 103323 | UA_assert(elm->filterOperandsSize >= 2); |
| 103324 | UA_Boolean found = false; |
| 103325 | UA_Variant *op0 = &ctx->stack[ctx->top++]; |
| 103326 | UA_Variant *op1 = &ctx->stack[ctx->top++]; |
| 103327 | UA_StatusCode res = resolveOperand(ctx, op: &elm->filterOperands[0], out: op0); |
| 103328 | UA_CHECK_STATUS(res, return res); |
| 103329 | for(size_t i = 1; i < elm->filterOperandsSize && !found; i++) { |
| 103330 | res = resolveOperand(ctx, op: &elm->filterOperands[i], out: op1); |
| 103331 | if(res != UA_STATUSCODE_GOOD) |
| 103332 | continue; |
| 103333 | if(op0->type == op1->type && UA_equal(p1: op0->data, p2: op1->data, type: op0->type)) |
| 103334 | found = true; |
| 103335 | UA_Variant_clear(p: op1); |
| 103336 | } |
| 103337 | ctx->results[index] = t2v(t: (found) ? UA_TERNARY_TRUE: UA_TERNARY_FALSE); |
| 103338 | return UA_STATUSCODE_GOOD; |
| 103339 | } |
| 103340 | |
| 103341 | static UA_StatusCode |
| 103342 | isNullOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103343 | const UA_ContentFilterElement *elm = &ctx->filter->elements[index]; |
| 103344 | UA_assert(elm->filterOperandsSize == 1); |
| 103345 | UA_Variant *op0 = &ctx->stack[ctx->top++]; |
| 103346 | UA_StatusCode res = resolveOperand(ctx, op: &elm->filterOperands[0], out: op0); |
| 103347 | UA_CHECK_STATUS(res, return res); |
| 103348 | ctx->results[index] = t2v(t: UA_Variant_isEmpty(v: op0) ? UA_TERNARY_TRUE : UA_TERNARY_FALSE); |
| 103349 | return UA_STATUSCODE_GOOD; |
| 103350 | } |
| 103351 | |
| 103352 | static UA_StatusCode |
| 103353 | notImplementedOperator(UA_FilterEvalContext *ctx, size_t index) { |
| 103354 | return UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED; |
| 103355 | } |
| 103356 | |
| 103357 | /* Filter Evaluation |
| 103358 | * ~~~~~~~~~~~~~~~~~ */ |
| 103359 | |
| 103360 | typedef struct { |
| 103361 | UA_StatusCode (*operatorMethod)(UA_FilterEvalContext *ctx, size_t index); |
| 103362 | UA_Byte minOperatorCount; |
| 103363 | UA_Byte maxOperatorCount; |
| 103364 | } UA_FilterOperatorJumptableElement; |
| 103365 | |
| 103366 | static const UA_FilterOperatorJumptableElement operatorJumptable[18] = { |
| 103367 | {equalsOperator, 2, 2}, |
| 103368 | {isNullOperator, 1, 1}, |
| 103369 | {gtOperator, 2, 2}, |
| 103370 | {ltOperator, 2, 2}, |
| 103371 | {gteOperator, 2, 2}, |
| 103372 | {lteOperator, 2, 2}, |
| 103373 | {notImplementedOperator, 0, UA_EVENTFILTER_MAXOPERANDS}, /* like */ |
| 103374 | {notOperator, 1, 1}, |
| 103375 | {betweenOperator, 3, 3}, |
| 103376 | {inListOperator, 2, UA_EVENTFILTER_MAXOPERANDS}, |
| 103377 | {andOperator, 2, 2}, |
| 103378 | {orOperator, 2, 2}, |
| 103379 | {notImplementedOperator, 0, UA_EVENTFILTER_MAXOPERANDS}, /* cast */ |
| 103380 | {notImplementedOperator, 0, UA_EVENTFILTER_MAXOPERANDS}, /* in view */ |
| 103381 | {ofTypeOperator, 1, 1}, |
| 103382 | {notImplementedOperator, 0, UA_EVENTFILTER_MAXOPERANDS}, /* related to */ |
| 103383 | {bitwiseAndOperator, 2, 2}, |
| 103384 | {bitwiseOrOperator, 2, 2} |
| 103385 | }; |
| 103386 | |
| 103387 | UA_StatusCode |
| 103388 | evaluateWhereClause(UA_Server *server, UA_Session *session, const UA_NodeId *eventNode, |
| 103389 | const UA_ContentFilter *contentFilter, |
| 103390 | UA_ContentFilterResult *contentFilterResult) { |
| 103391 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 103392 | |
| 103393 | /* An empty filter always succeeds */ |
| 103394 | if(contentFilter->elementsSize == 0) |
| 103395 | return UA_STATUSCODE_GOOD; |
| 103396 | |
| 103397 | /* Prepare the context */ |
| 103398 | UA_FilterEvalContext ctx; |
| 103399 | ctx.filterResult = contentFilterResult; |
| 103400 | ctx.filter = contentFilter; |
| 103401 | ctx.server = server; |
| 103402 | ctx.session = session; |
| 103403 | ctx.eventNode = eventNode; |
| 103404 | ctx.top = 0; |
| 103405 | |
| 103406 | /* Pacify some compilers by initializing the first result */ |
| 103407 | UA_Variant_init(p: &ctx.results[0]); |
| 103408 | |
| 103409 | /* Evaluate the filter. Iterate backwards over the filter elements and |
| 103410 | * resolve each. This ensures that all element-index operands point to an |
| 103411 | * evaluated element. */ |
| 103412 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 103413 | int i = (int)contentFilter->elementsSize - 1; |
| 103414 | for(; i >= 0; i--) { |
| 103415 | UA_ContentFilterElement *cfe = &contentFilter->elements[i]; |
| 103416 | res = operatorJumptable[cfe->filterOperator].operatorMethod(&ctx, (size_t)i); |
| 103417 | for(size_t j = 0; j < ctx.top; j++) |
| 103418 | UA_Variant_clear(p: &ctx.stack[j]); /* clean up the stack */ |
| 103419 | ctx.top = 0; |
| 103420 | if(res != UA_STATUSCODE_GOOD) |
| 103421 | break; |
| 103422 | } |
| 103423 | |
| 103424 | /* The filter matches if the operator at the first position evaluates to TRUE */ |
| 103425 | if(res == UA_STATUSCODE_GOOD && v2t(v: &ctx.results[0]) != UA_TERNARY_TRUE) |
| 103426 | res = UA_STATUSCODE_BADNOMATCH; |
| 103427 | |
| 103428 | /* Clean up the element result variants */ |
| 103429 | for(int j = (int)contentFilter->elementsSize - 1; j > i; j--) |
| 103430 | UA_Variant_clear(p: &ctx.results[j]); |
| 103431 | return res; |
| 103432 | } |
| 103433 | |
| 103434 | static UA_Boolean |
| 103435 | isValidEvent(UA_Server *server, const UA_NodeId *validEventParent, |
| 103436 | const UA_NodeId *eventId) { |
| 103437 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 103438 | |
| 103439 | /* Find the eventType variableNode */ |
| 103440 | UA_QualifiedName findName = UA_QUALIFIEDNAME(nsIndex: 0, chars: "EventType"); |
| 103441 | UA_BrowsePathResult bpr = browseSimplifiedBrowsePath(server, origin: *eventId, browsePathSize: 1, browsePath: &findName); |
| 103442 | if(bpr.statusCode != UA_STATUSCODE_GOOD || bpr.targetsSize < 1) { |
| 103443 | UA_BrowsePathResult_clear(p: &bpr); |
| 103444 | return false; |
| 103445 | } |
| 103446 | |
| 103447 | /* Get the EventType Property Node */ |
| 103448 | UA_Variant tOutVariant; |
| 103449 | UA_Variant_init(p: &tOutVariant); |
| 103450 | /* Read the Value of EventType Property Node (the Value should be a NodeId) */ |
| 103451 | UA_StatusCode retval = readWithReadValue(server, nodeId: &bpr.targets[0].targetId.nodeId, |
| 103452 | attributeId: UA_ATTRIBUTEID_VALUE, v: &tOutVariant); |
| 103453 | if(retval != UA_STATUSCODE_GOOD || |
| 103454 | !UA_Variant_hasScalarType(v: &tOutVariant, type: &UA_TYPES[UA_TYPES_NODEID])) { |
| 103455 | UA_BrowsePathResult_clear(p: &bpr); |
| 103456 | return false; |
| 103457 | } |
| 103458 | |
| 103459 | const UA_NodeId *tEventType = (UA_NodeId*)tOutVariant.data; |
| 103460 | |
| 103461 | /* Check whether the EventType is a Subtype of CondtionType (Part 9 first |
| 103462 | * implementation) */ |
| 103463 | UA_NodeId conditionTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_CONDITIONTYPE); |
| 103464 | if(UA_NodeId_equal(p1: validEventParent, p2: &conditionTypeId) && |
| 103465 | isNodeInTree_singleRef(server, leafNode: tEventType, nodeToFind: &conditionTypeId, |
| 103466 | UA_REFERENCETYPEINDEX_HASSUBTYPE)) { |
| 103467 | UA_BrowsePathResult_clear(p: &bpr); |
| 103468 | UA_Variant_clear(p: &tOutVariant); |
| 103469 | return true; |
| 103470 | } |
| 103471 | |
| 103472 | /* EventType is not a Subtype of CondtionType (ConditionId Clause won't be |
| 103473 | * present in Events, which are not Conditions) */ |
| 103474 | /* Check whether Valid Event other than Conditions */ |
| 103475 | UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE); |
| 103476 | UA_Boolean isSubtypeOfBaseEvent = |
| 103477 | isNodeInTree_singleRef(server, leafNode: tEventType, nodeToFind: &baseEventTypeId, |
| 103478 | UA_REFERENCETYPEINDEX_HASSUBTYPE); |
| 103479 | |
| 103480 | UA_BrowsePathResult_clear(p: &bpr); |
| 103481 | UA_Variant_clear(p: &tOutVariant); |
| 103482 | return isSubtypeOfBaseEvent; |
| 103483 | } |
| 103484 | |
| 103485 | UA_StatusCode |
| 103486 | filterEvent(UA_Server *server, UA_Session *session, |
| 103487 | const UA_NodeId *eventNode, UA_EventFilter *filter, |
| 103488 | UA_EventFieldList *efl, UA_EventFilterResult *result) { |
| 103489 | UA_LOCK_ASSERT(&server->serviceMutex, 1); |
| 103490 | |
| 103491 | if(filter->selectClausesSize == 0) |
| 103492 | return UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 103493 | |
| 103494 | UA_EventFieldList_init(p: efl); |
| 103495 | efl->eventFields = (UA_Variant *) |
| 103496 | UA_Array_new(size: filter->selectClausesSize, type: &UA_TYPES[UA_TYPES_VARIANT]); |
| 103497 | if(!efl->eventFields) |
| 103498 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 103499 | efl->eventFieldsSize = filter->selectClausesSize; |
| 103500 | |
| 103501 | /* Empty event filter result */ |
| 103502 | UA_EventFilterResult_init(p: result); |
| 103503 | result->selectClauseResultsSize = filter->selectClausesSize; |
| 103504 | result->selectClauseResults = (UA_StatusCode *) |
| 103505 | UA_Array_new(size: filter->selectClausesSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 103506 | if(!result->selectClauseResults) { |
| 103507 | UA_EventFieldList_clear(p: efl); |
| 103508 | UA_EventFilterResult_clear(p: result); |
| 103509 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 103510 | } |
| 103511 | |
| 103512 | /* Prepare content filter result structure */ |
| 103513 | if(filter->whereClause.elementsSize > 0) { |
| 103514 | result->whereClauseResult.elementResultsSize = filter->whereClause.elementsSize; |
| 103515 | result->whereClauseResult.elementResults = (UA_ContentFilterElementResult *) |
| 103516 | UA_Array_new(size: filter->whereClause.elementsSize, |
| 103517 | type: &UA_TYPES[UA_TYPES_CONTENTFILTERELEMENTRESULT]); |
| 103518 | if(!result->whereClauseResult.elementResults) { |
| 103519 | UA_EventFieldList_clear(p: efl); |
| 103520 | UA_EventFilterResult_clear(p: result); |
| 103521 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 103522 | } |
| 103523 | |
| 103524 | for(size_t i = 0; i < filter->whereClause.elementsSize; ++i) { |
| 103525 | UA_ContentFilterElementResult *er = |
| 103526 | &result->whereClauseResult.elementResults[i]; |
| 103527 | UA_ContentFilterElement *cf = &filter->whereClause.elements[i]; |
| 103528 | er->operandStatusCodesSize = cf->filterOperandsSize; |
| 103529 | er->operandStatusCodes = (UA_StatusCode *) |
| 103530 | UA_Array_new(size: er->operandStatusCodesSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 103531 | if(!er->operandStatusCodes) { |
| 103532 | UA_EventFieldList_clear(p: efl); |
| 103533 | UA_EventFilterResult_clear(p: result); |
| 103534 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 103535 | } |
| 103536 | } |
| 103537 | } |
| 103538 | |
| 103539 | /* Evaluate the where filter. Do we event need to consider the event? */ |
| 103540 | UA_StatusCode res = evaluateWhereClause(server, session, eventNode, |
| 103541 | contentFilter: &filter->whereClause, |
| 103542 | contentFilterResult: &result->whereClauseResult); |
| 103543 | if(res != UA_STATUSCODE_GOOD){ |
| 103544 | UA_EventFieldList_clear(p: efl); |
| 103545 | UA_EventFilterResult_clear(p: result); |
| 103546 | return res; |
| 103547 | } |
| 103548 | |
| 103549 | /* Apply the select filter */ |
| 103550 | UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE); |
| 103551 | for(size_t i = 0; i < filter->selectClausesSize; i++) { |
| 103552 | UA_SimpleAttributeOperand *sc = &filter->selectClauses[i]; |
| 103553 | /* Check if the browsePath is BaseEventType, in which case nothing more |
| 103554 | * needs to be checked */ |
| 103555 | if(!UA_NodeId_equal(p1: &sc->typeDefinitionId, p2: &baseEventTypeId) && |
| 103556 | !isValidEvent(server, validEventParent: &sc->typeDefinitionId, eventId: eventNode)) { |
| 103557 | UA_Variant_init(p: &efl->eventFields[i]); |
| 103558 | /* EventFilterResult currently isn't being used |
| 103559 | notification->result.selectClauseResults[i] = |
| 103560 | UA_STATUSCODE_BADTYPEDEFINITIONINVALID; */ |
| 103561 | continue; |
| 103562 | } |
| 103563 | |
| 103564 | /* Lookup the field. The overall filter can succeed even if a single |
| 103565 | * select-field cannot be resolved. */ |
| 103566 | result->selectClauseResults[i] = |
| 103567 | resolveSimpleAttributeOperand(server, session, origin: eventNode, |
| 103568 | sao: sc, value: &efl->eventFields[i]); |
| 103569 | } |
| 103570 | |
| 103571 | return UA_STATUSCODE_GOOD; |
| 103572 | } |
| 103573 | |
| 103574 | /*****************************************/ |
| 103575 | /* Validation of Filters during Creation */ |
| 103576 | /*****************************************/ |
| 103577 | |
| 103578 | /* Initial select clause validation. The following checks are currently performed: |
| 103579 | * - Check if typedefenitionid or browsepath of any clause is NULL |
| 103580 | * - Check if the eventType is a subtype of BaseEventType |
| 103581 | * - Check if attributeId is valid |
| 103582 | * - Check if browsePath contains null |
| 103583 | * - Check if indexRange is defined and if it is parsable |
| 103584 | * - Check if attributeId is value */ |
| 103585 | UA_StatusCode |
| 103586 | UA_SimpleAttributeOperandValidation(UA_Server *server, |
| 103587 | const UA_SimpleAttributeOperand *sao) { |
| 103588 | /* TypeDefinition is not NULL? */ |
| 103589 | if(UA_NodeId_isNull(p: &sao->typeDefinitionId)) |
| 103590 | return UA_STATUSCODE_BADTYPEDEFINITIONINVALID; |
| 103591 | |
| 103592 | /* EventType is a subtype of BaseEventType? */ |
| 103593 | UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE); |
| 103594 | if(!isNodeInTree_singleRef(server, leafNode: &sao->typeDefinitionId, |
| 103595 | nodeToFind: &baseEventTypeId, UA_REFERENCETYPEINDEX_HASSUBTYPE)) |
| 103596 | return UA_STATUSCODE_BADTYPEDEFINITIONINVALID; |
| 103597 | |
| 103598 | /* AttributeId is valid ? */ |
| 103599 | if(sao->attributeId == 0 || sao->attributeId >= 28) |
| 103600 | return UA_STATUSCODE_BADATTRIBUTEIDINVALID; |
| 103601 | |
| 103602 | /* If the BrowsePath is empty, the Node is the instance of the |
| 103603 | * TypeDefinition. (Part 4, 7.4.4.5) */ |
| 103604 | if(sao->browsePathSize == 0) |
| 103605 | return UA_STATUSCODE_GOOD; |
| 103606 | |
| 103607 | /* BrowsePath contains empty BrowseNames? */ |
| 103608 | for(size_t j = 0; j < sao->browsePathSize; ++j) { |
| 103609 | if(UA_QualifiedName_isNull(q: &sao->browsePath[j])) |
| 103610 | return UA_STATUSCODE_BADBROWSENAMEINVALID; |
| 103611 | } |
| 103612 | |
| 103613 | /* Get the list of subtypes from event type (including the event type itself) */ |
| 103614 | UA_ReferenceTypeSet reftypes_interface = |
| 103615 | UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE); |
| 103616 | UA_ExpandedNodeId *childTypeNodes = NULL; |
| 103617 | size_t childTypeNodesSize = 0; |
| 103618 | UA_StatusCode res = browseRecursive(server, startNodesSize: 1, startNodes: &sao->typeDefinitionId, |
| 103619 | browseDirection: UA_BROWSEDIRECTION_FORWARD, refTypes: &reftypes_interface, |
| 103620 | nodeClassMask: UA_NODECLASS_OBJECTTYPE, true, resultsSize: &childTypeNodesSize, |
| 103621 | results: &childTypeNodes); |
| 103622 | if(res != UA_STATUSCODE_GOOD) |
| 103623 | return UA_STATUSCODE_BADATTRIBUTEIDINVALID; |
| 103624 | |
| 103625 | /* Is the browse path valid for one of them? */ |
| 103626 | UA_Boolean subTypeContainField = false; |
| 103627 | for(size_t j = 0; j < childTypeNodesSize && !subTypeContainField; j++) { |
| 103628 | UA_BrowsePathResult bpr = |
| 103629 | browseSimplifiedBrowsePath(server, origin: childTypeNodes[j].nodeId, |
| 103630 | browsePathSize: sao->browsePathSize, browsePath: sao->browsePath); |
| 103631 | |
| 103632 | if(bpr.statusCode == UA_STATUSCODE_GOOD && bpr.targetsSize > 0) |
| 103633 | subTypeContainField = true; |
| 103634 | UA_BrowsePathResult_clear(p: &bpr); |
| 103635 | } |
| 103636 | |
| 103637 | UA_Array_delete(p: childTypeNodes, size: childTypeNodesSize, type: &UA_TYPES[UA_TYPES_EXPANDEDNODEID]); |
| 103638 | |
| 103639 | if(!subTypeContainField) |
| 103640 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 103641 | |
| 103642 | /* IndexRange is defined ? */ |
| 103643 | if(!UA_String_isEmpty(s: &sao->indexRange)) { |
| 103644 | UA_NumericRange numericRange = UA_NUMERICRANGE(s: ""); |
| 103645 | if(UA_NumericRange_parse(range: &numericRange, str: sao->indexRange) != UA_STATUSCODE_GOOD) |
| 103646 | return UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 103647 | UA_free(ptr: numericRange.dimensions); |
| 103648 | |
| 103649 | /* AttributeId has to be a value if an IndexRange is defined */ |
| 103650 | if(sao->attributeId != UA_ATTRIBUTEID_VALUE) |
| 103651 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 103652 | } |
| 103653 | |
| 103654 | return UA_STATUSCODE_GOOD; |
| 103655 | } |
| 103656 | |
| 103657 | /* Initial content filter (where clause) check. Current checks: |
| 103658 | * - Number of operands for each (supported) operator |
| 103659 | * - ElementOperands point forward only */ |
| 103660 | UA_ContentFilterElementResult |
| 103661 | UA_ContentFilterElementValidation(UA_Server *server, size_t operatorIndex, |
| 103662 | size_t operatorsCount, |
| 103663 | const UA_ContentFilterElement *ef) { |
| 103664 | /* Initialize the result structure */ |
| 103665 | UA_ContentFilterElementResult er; |
| 103666 | UA_ContentFilterElementResult_init(p: &er); |
| 103667 | er.operandStatusCodes = (UA_StatusCode *) |
| 103668 | UA_Array_new(size: ef->filterOperandsSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 103669 | if(!er.operandStatusCodes) { |
| 103670 | er.statusCode = UA_STATUSCODE_BADOUTOFMEMORY; |
| 103671 | return er; |
| 103672 | } |
| 103673 | er.operandStatusCodesSize = ef->filterOperandsSize; |
| 103674 | |
| 103675 | /* Is the operator in the defined range? Test this before the following |
| 103676 | * jumptable lookup. */ |
| 103677 | if(ef->filterOperator < 0 || ef->filterOperator > UA_FILTEROPERATOR_BITWISEOR) { |
| 103678 | er.statusCode = UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 103679 | return er; |
| 103680 | } |
| 103681 | |
| 103682 | /* Number of operands supported for the operator? */ |
| 103683 | if(ef->filterOperandsSize < operatorJumptable[ef->filterOperator].minOperatorCount || |
| 103684 | ef->filterOperandsSize > operatorJumptable[ef->filterOperator].maxOperatorCount) { |
| 103685 | er.statusCode = UA_STATUSCODE_BADFILTEROPERANDCOUNTMISMATCH; |
| 103686 | return er; |
| 103687 | } |
| 103688 | |
| 103689 | /* Generic validation of the operands */ |
| 103690 | for(size_t i = 0; i < ef->filterOperandsSize; i++) { |
| 103691 | /* Must be a decoded ExtensionObject */ |
| 103692 | UA_ExtensionObject *op = &ef->filterOperands[i]; |
| 103693 | if(op->encoding != UA_EXTENSIONOBJECT_DECODED && |
| 103694 | op->encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE) { |
| 103695 | er.operandStatusCodes[i] = UA_STATUSCODE_BADFILTEROPERANDINVALID; |
| 103696 | er.statusCode = UA_STATUSCODE_BADFILTEROPERANDINVALID; |
| 103697 | return er; |
| 103698 | } |
| 103699 | |
| 103700 | /* Supported type and conforming to the rules? */ |
| 103701 | if(op->content.decoded.type == &UA_TYPES[UA_TYPES_ELEMENTOPERAND]) { |
| 103702 | /* Part 4, 7.4.4.2 defines conditions for Element Operands: An index |
| 103703 | * is considered valid if its value is greater than the element |
| 103704 | * index it is part of and it does not Reference a non-existent |
| 103705 | * element. Clients shall construct filters in this way to avoid |
| 103706 | * circular and invalid References. */ |
| 103707 | UA_ElementOperand *eo = (UA_ElementOperand *)op->content.decoded.data; |
| 103708 | if(eo->index <= operatorIndex || eo->index >= operatorsCount) { |
| 103709 | er.operandStatusCodes[i] = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 103710 | er.statusCode = UA_STATUSCODE_BADINDEXRANGEINVALID; |
| 103711 | return er; |
| 103712 | } |
| 103713 | } else if(op->content.decoded.type == &UA_TYPES[UA_TYPES_ATTRIBUTEOPERAND]) { |
| 103714 | er.operandStatusCodes[i] = UA_STATUSCODE_BADNOTSUPPORTED; |
| 103715 | er.statusCode = UA_STATUSCODE_BADFILTERNOTALLOWED; |
| 103716 | return er; |
| 103717 | } else if(op->content.decoded.type != &UA_TYPES[UA_TYPES_SIMPLEATTRIBUTEOPERAND] && |
| 103718 | op->content.decoded.type != &UA_TYPES[UA_TYPES_LITERALOPERAND]) { |
| 103719 | er.operandStatusCodes[i] = UA_STATUSCODE_BADFILTEROPERANDINVALID; |
| 103720 | er.statusCode = UA_STATUSCODE_BADFILTEROPERANDINVALID; |
| 103721 | return er; |
| 103722 | } |
| 103723 | } |
| 103724 | |
| 103725 | /* Specific validations for different operators */ |
| 103726 | switch(ef->filterOperator) { |
| 103727 | case UA_FILTEROPERATOR_INVIEW: |
| 103728 | case UA_FILTEROPERATOR_RELATEDTO: |
| 103729 | /* Not allowed for event WhereClause according to 7.17.3 in Part 4 */ |
| 103730 | er.statusCode = UA_STATUSCODE_BADEVENTFILTERINVALID; |
| 103731 | break; |
| 103732 | |
| 103733 | case UA_FILTEROPERATOR_EQUALS: |
| 103734 | case UA_FILTEROPERATOR_GREATERTHAN: |
| 103735 | case UA_FILTEROPERATOR_LESSTHAN: |
| 103736 | case UA_FILTEROPERATOR_GREATERTHANOREQUAL: |
| 103737 | case UA_FILTEROPERATOR_LESSTHANOREQUAL: |
| 103738 | case UA_FILTEROPERATOR_BITWISEAND: |
| 103739 | case UA_FILTEROPERATOR_BITWISEOR: |
| 103740 | case UA_FILTEROPERATOR_BETWEEN: |
| 103741 | case UA_FILTEROPERATOR_INLIST: |
| 103742 | case UA_FILTEROPERATOR_AND: |
| 103743 | case UA_FILTEROPERATOR_OR: |
| 103744 | case UA_FILTEROPERATOR_ISNULL: |
| 103745 | case UA_FILTEROPERATOR_NOT: |
| 103746 | break; |
| 103747 | |
| 103748 | case UA_FILTEROPERATOR_OFTYPE: { |
| 103749 | /* Make sure the operand is a NodeId literal */ |
| 103750 | UA_ExtensionObject *o = &ef->filterOperands[0]; |
| 103751 | UA_LiteralOperand *lo = (UA_LiteralOperand *)o->content.decoded.data; |
| 103752 | if(o->content.decoded.type != &UA_TYPES[UA_TYPES_LITERALOPERAND] || |
| 103753 | !UA_Variant_hasScalarType(v: &lo->value, type: &UA_TYPES[UA_TYPES_NODEID])) { |
| 103754 | er.operandStatusCodes[0] = UA_STATUSCODE_BADFILTEROPERANDINVALID; |
| 103755 | er.statusCode = UA_STATUSCODE_BADFILTEROPERANDINVALID; |
| 103756 | break; |
| 103757 | } |
| 103758 | |
| 103759 | /* Make sure the operand is a subtype of BaseEventType */ |
| 103760 | UA_NodeId baseEventTypeId = UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_BASEEVENTTYPE); |
| 103761 | if(!isNodeInTree_singleRef(server, leafNode: (UA_NodeId *)lo->value.data, nodeToFind: &baseEventTypeId, |
| 103762 | UA_REFERENCETYPEINDEX_HASSUBTYPE)) { |
| 103763 | er.operandStatusCodes[0] = UA_STATUSCODE_BADFILTEROPERANDINVALID; |
| 103764 | er.statusCode = UA_STATUSCODE_BADFILTEROPERANDINVALID; |
| 103765 | break; |
| 103766 | } |
| 103767 | break; |
| 103768 | } |
| 103769 | |
| 103770 | case UA_FILTEROPERATOR_LIKE: |
| 103771 | case UA_FILTEROPERATOR_CAST: |
| 103772 | er.statusCode = UA_STATUSCODE_BADFILTEROPERATORUNSUPPORTED; |
| 103773 | break; |
| 103774 | |
| 103775 | default: |
| 103776 | er.statusCode = UA_STATUSCODE_BADFILTEROPERATORINVALID; |
| 103777 | break; |
| 103778 | } |
| 103779 | return er; |
| 103780 | } |
| 103781 | |
| 103782 | #endif /* UA_ENABLE_SUBSCRIPTIONS_EVENTS */ |
| 103783 | |
| 103784 | /**** amalgamated original file "/src/server/ua_discovery.c" ****/ |
| 103785 | |
| 103786 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 103787 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 103788 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 103789 | * |
| 103790 | * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 103791 | * Copyright 2014, 2017 (c) Florian Palm |
| 103792 | * Copyright 2015-2016, 2019 (c) Sten Grüner |
| 103793 | * Copyright 2015 (c) Chris Iatrou |
| 103794 | * Copyright 2015-2016 (c) Oleksiy Vasylyev |
| 103795 | * Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH |
| 103796 | * Copyright 2017 (c) Julian Grothoff |
| 103797 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 103798 | * Copyright 2017 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 103799 | */ |
| 103800 | |
| 103801 | |
| 103802 | #ifdef UA_ENABLE_DISCOVERY |
| 103803 | |
| 103804 | void |
| 103805 | UA_DiscoveryManager_setState(UA_Server *server, |
| 103806 | UA_DiscoveryManager *dm, |
| 103807 | UA_LifecycleState state) { |
| 103808 | /* Check if open connections remain */ |
| 103809 | if(state == UA_LIFECYCLESTATE_STOPPING || |
| 103810 | state == UA_LIFECYCLESTATE_STOPPED) { |
| 103811 | state = UA_LIFECYCLESTATE_STOPPED; |
| 103812 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 103813 | if(dm->mdnsRecvConnectionsSize != 0 || dm->mdnsSendConnection != 0) |
| 103814 | state = UA_LIFECYCLESTATE_STOPPING; |
| 103815 | #endif |
| 103816 | |
| 103817 | for(size_t i = 0; i < UA_MAXREGISTERREQUESTS; i++) { |
| 103818 | if(dm->registerRequests[i].client != NULL) |
| 103819 | state = UA_LIFECYCLESTATE_STOPPING; |
| 103820 | } |
| 103821 | } |
| 103822 | |
| 103823 | /* No change */ |
| 103824 | if(state == dm->sc.state) |
| 103825 | return; |
| 103826 | |
| 103827 | /* Set the new state and notify */ |
| 103828 | dm->sc.state = state; |
| 103829 | if(dm->sc.notifyState) |
| 103830 | dm->sc.notifyState(server, &dm->sc, state); |
| 103831 | } |
| 103832 | |
| 103833 | static UA_StatusCode |
| 103834 | UA_DiscoveryManager_free(UA_Server *server, |
| 103835 | struct UA_ServerComponent *sc) { |
| 103836 | UA_DiscoveryManager *dm = (UA_DiscoveryManager*)sc; |
| 103837 | |
| 103838 | if(sc->state != UA_LIFECYCLESTATE_STOPPED) { |
| 103839 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 103840 | msg: "Cannot delete the DiscoveryManager because " |
| 103841 | "it is not stopped"); |
| 103842 | return UA_STATUSCODE_BADINTERNALERROR; |
| 103843 | } |
| 103844 | |
| 103845 | registeredServer_list_entry *rs, *rs_tmp; |
| 103846 | LIST_FOREACH_SAFE(rs, &dm->registeredServers, pointers, rs_tmp) { |
| 103847 | LIST_REMOVE(rs, pointers); |
| 103848 | UA_RegisteredServer_clear(p: &rs->registeredServer); |
| 103849 | UA_free(ptr: rs); |
| 103850 | } |
| 103851 | |
| 103852 | # ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 103853 | serverOnNetwork_list_entry *son, *son_tmp; |
| 103854 | LIST_FOREACH_SAFE(son, &dm->serverOnNetwork, pointers, son_tmp) { |
| 103855 | LIST_REMOVE(son, pointers); |
| 103856 | UA_ServerOnNetwork_clear(&son->serverOnNetwork); |
| 103857 | if(son->pathTmp) |
| 103858 | UA_free(son->pathTmp); |
| 103859 | UA_free(son); |
| 103860 | } |
| 103861 | |
| 103862 | UA_String_clear(&dm->selfFqdnMdnsRecord); |
| 103863 | |
| 103864 | for(size_t i = 0; i < SERVER_ON_NETWORK_HASH_SIZE; i++) { |
| 103865 | serverOnNetwork_hash_entry* currHash = dm->serverOnNetworkHash[i]; |
| 103866 | while(currHash) { |
| 103867 | serverOnNetwork_hash_entry* nextHash = currHash->next; |
| 103868 | UA_free(currHash); |
| 103869 | currHash = nextHash; |
| 103870 | } |
| 103871 | } |
| 103872 | # endif /* UA_ENABLE_DISCOVERY_MULTICAST */ |
| 103873 | |
| 103874 | UA_free(ptr: dm); |
| 103875 | return UA_STATUSCODE_GOOD; |
| 103876 | } |
| 103877 | |
| 103878 | /* Cleanup server registration: If the semaphore file path is set, then it just |
| 103879 | * checks the existence of the file. When it is deleted, the registration is |
| 103880 | * removed. If there is no semaphore file, then the registration will be removed |
| 103881 | * if it is older than 60 minutes. */ |
| 103882 | static void |
| 103883 | UA_DiscoveryManager_cleanupTimedOut(UA_Server *server, |
| 103884 | void *data) { |
| 103885 | UA_DiscoveryManager *dm = (UA_DiscoveryManager*)data; |
| 103886 | |
| 103887 | /* TimedOut gives the last DateTime at which we must have seen the |
| 103888 | * registered server. Otherwise it is timed out. */ |
| 103889 | UA_DateTime timedOut = UA_DateTime_nowMonotonic(); |
| 103890 | if(server->config.discoveryCleanupTimeout) |
| 103891 | timedOut -= server->config.discoveryCleanupTimeout * UA_DATETIME_SEC; |
| 103892 | |
| 103893 | registeredServer_list_entry *current, *temp; |
| 103894 | LIST_FOREACH_SAFE(current, &dm->registeredServers, pointers, temp) { |
| 103895 | UA_Boolean semaphoreDeleted = false; |
| 103896 | |
| 103897 | #ifdef UA_ENABLE_DISCOVERY_SEMAPHORE |
| 103898 | if(current->registeredServer.semaphoreFilePath.length) { |
| 103899 | size_t fpSize = current->registeredServer.semaphoreFilePath.length+1; |
| 103900 | char* filePath = (char *)UA_malloc(size: fpSize); |
| 103901 | if(filePath) { |
| 103902 | memcpy(dest: filePath, src: current->registeredServer.semaphoreFilePath.data, |
| 103903 | n: current->registeredServer.semaphoreFilePath.length ); |
| 103904 | filePath[current->registeredServer.semaphoreFilePath.length] = '\0'; |
| 103905 | semaphoreDeleted = UA_fileExists(filePath) == false; |
| 103906 | UA_free(ptr: filePath); |
| 103907 | } else { |
| 103908 | UA_LOG_ERROR(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 103909 | msg: "Cannot check registration semaphore. Out of memory"); |
| 103910 | } |
| 103911 | } |
| 103912 | #endif |
| 103913 | |
| 103914 | if(semaphoreDeleted || |
| 103915 | (server->config.discoveryCleanupTimeout && |
| 103916 | current->lastSeen < timedOut)) { |
| 103917 | if(semaphoreDeleted) { |
| 103918 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 103919 | msg: "Registration of server with URI %.*s is removed because " |
| 103920 | "the semaphore file '%.*s' was deleted", |
| 103921 | (int)current->registeredServer.serverUri.length, |
| 103922 | current->registeredServer.serverUri.data, |
| 103923 | (int)current->registeredServer.semaphoreFilePath.length, |
| 103924 | current->registeredServer.semaphoreFilePath.data); |
| 103925 | } else { |
| 103926 | // cppcheck-suppress unreadVariable |
| 103927 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 103928 | msg: "Registration of server with URI %.*s has timed out " |
| 103929 | "and is removed", |
| 103930 | (int)current->registeredServer.serverUri.length, |
| 103931 | current->registeredServer.serverUri.data); |
| 103932 | } |
| 103933 | LIST_REMOVE(current, pointers); |
| 103934 | UA_RegisteredServer_clear(p: ¤t->registeredServer); |
| 103935 | UA_free(ptr: current); |
| 103936 | dm->registeredServersSize--; |
| 103937 | } |
| 103938 | } |
| 103939 | |
| 103940 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 103941 | /* Send out multicast */ |
| 103942 | sendMulticastMessages(dm); |
| 103943 | #endif |
| 103944 | } |
| 103945 | |
| 103946 | static UA_StatusCode |
| 103947 | UA_DiscoveryManager_start(UA_Server *server, |
| 103948 | struct UA_ServerComponent *sc) { |
| 103949 | if(sc->state != UA_LIFECYCLESTATE_STOPPED) |
| 103950 | return UA_STATUSCODE_BADINTERNALERROR; |
| 103951 | |
| 103952 | UA_DiscoveryManager *dm = (UA_DiscoveryManager*)sc; |
| 103953 | UA_StatusCode res = addRepeatedCallback(server, callback: UA_DiscoveryManager_cleanupTimedOut, |
| 103954 | data: dm, interval_ms: 1000.0, callbackId: &dm->discoveryCallbackId); |
| 103955 | if(res != UA_STATUSCODE_GOOD) |
| 103956 | return res; |
| 103957 | |
| 103958 | dm->logging = server->config.logging; |
| 103959 | dm->serverConfig = &server->config; |
| 103960 | |
| 103961 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 103962 | if(server->config.mdnsEnabled) |
| 103963 | startMulticastDiscoveryServer(server); |
| 103964 | #endif |
| 103965 | |
| 103966 | UA_DiscoveryManager_setState(server, dm, state: UA_LIFECYCLESTATE_STARTED); |
| 103967 | return UA_STATUSCODE_GOOD; |
| 103968 | } |
| 103969 | |
| 103970 | static void |
| 103971 | UA_DiscoveryManager_stop(UA_Server *server, |
| 103972 | struct UA_ServerComponent *sc) { |
| 103973 | if(sc->state != UA_LIFECYCLESTATE_STARTED) |
| 103974 | return; |
| 103975 | |
| 103976 | UA_DiscoveryManager *dm = (UA_DiscoveryManager*)sc; |
| 103977 | removeCallback(server, callbackId: dm->discoveryCallbackId); |
| 103978 | |
| 103979 | /* Cancel all outstanding register requests */ |
| 103980 | for(size_t i = 0; i < UA_MAXREGISTERREQUESTS; i++) { |
| 103981 | if(dm->registerRequests[i].client == NULL) |
| 103982 | continue; |
| 103983 | UA_Client_disconnectSecureChannelAsync(client: dm->registerRequests[i].client); |
| 103984 | } |
| 103985 | |
| 103986 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 103987 | if(server->config.mdnsEnabled) |
| 103988 | stopMulticastDiscoveryServer(server); |
| 103989 | #endif |
| 103990 | |
| 103991 | UA_DiscoveryManager_setState(server, dm, state: UA_LIFECYCLESTATE_STOPPED); |
| 103992 | } |
| 103993 | |
| 103994 | UA_ServerComponent * |
| 103995 | UA_DiscoveryManager_new(UA_Server *server) { |
| 103996 | UA_DiscoveryManager *dm = (UA_DiscoveryManager*) |
| 103997 | UA_calloc(nmemb: 1, size: sizeof(UA_DiscoveryManager)); |
| 103998 | if(!dm) |
| 103999 | return NULL; |
| 104000 | |
| 104001 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 104002 | dm->serverOnNetworkRecordIdLastReset = UA_DateTime_now(); |
| 104003 | #endif /* UA_ENABLE_DISCOVERY_MULTICAST */ |
| 104004 | |
| 104005 | dm->sc.name = UA_STRING(chars: "discovery"); |
| 104006 | dm->sc.start = UA_DiscoveryManager_start; |
| 104007 | dm->sc.stop = UA_DiscoveryManager_stop; |
| 104008 | dm->sc.free = UA_DiscoveryManager_free; |
| 104009 | return &dm->sc; |
| 104010 | } |
| 104011 | |
| 104012 | /********************************/ |
| 104013 | /* Register at Discovery Server */ |
| 104014 | /********************************/ |
| 104015 | |
| 104016 | static void |
| 104017 | asyncRegisterRequest_clear(void *app, void *context) { |
| 104018 | UA_Server *server = (UA_Server*)app; |
| 104019 | asyncRegisterRequest *ar = (asyncRegisterRequest*)context; |
| 104020 | UA_DiscoveryManager *dm = ar->dm; |
| 104021 | |
| 104022 | UA_String_clear(p: &ar->semaphoreFilePath); |
| 104023 | if(ar->client) |
| 104024 | UA_Client_delete(client: ar->client); |
| 104025 | memset(s: ar, c: 0, n: sizeof(asyncRegisterRequest)); |
| 104026 | |
| 104027 | /* The Discovery manager is fully stopped? */ |
| 104028 | UA_DiscoveryManager_setState(server, dm, state: dm->sc.state); |
| 104029 | } |
| 104030 | |
| 104031 | static void |
| 104032 | asyncRegisterRequest_clearAsync(asyncRegisterRequest *ar) { |
| 104033 | UA_Server *server = ar->server; |
| 104034 | UA_ServerConfig *sc = &server->config; |
| 104035 | UA_EventLoop *el = sc->eventLoop; |
| 104036 | |
| 104037 | ar->cleanupCallback.callback = asyncRegisterRequest_clear; |
| 104038 | ar->cleanupCallback.application = server; |
| 104039 | ar->cleanupCallback.context = ar; |
| 104040 | el->addDelayedCallback(el, &ar->cleanupCallback); |
| 104041 | } |
| 104042 | |
| 104043 | static void |
| 104044 | setupRegisterRequest(asyncRegisterRequest *ar, UA_RequestHeader *rh, |
| 104045 | UA_RegisteredServer *rs) { |
| 104046 | UA_ServerConfig *sc = ar->dm->serverConfig; |
| 104047 | |
| 104048 | rh->timeoutHint = 10000; |
| 104049 | |
| 104050 | rs->isOnline = !ar->unregister; |
| 104051 | rs->serverUri = sc->applicationDescription.applicationUri; |
| 104052 | rs->productUri = sc->applicationDescription.productUri; |
| 104053 | rs->serverType = sc->applicationDescription.applicationType; |
| 104054 | rs->gatewayServerUri = sc->applicationDescription.gatewayServerUri; |
| 104055 | rs->semaphoreFilePath = ar->semaphoreFilePath; |
| 104056 | |
| 104057 | rs->serverNames = &sc->applicationDescription.applicationName; |
| 104058 | rs->serverNamesSize = 1; |
| 104059 | |
| 104060 | /* Mirror the discovery URLs from the server config (includes hostnames from |
| 104061 | * the network layers) */ |
| 104062 | rs->discoveryUrls = sc->applicationDescription.discoveryUrls; |
| 104063 | rs->discoveryUrlsSize = sc->applicationDescription.discoveryUrlsSize; |
| 104064 | } |
| 104065 | |
| 104066 | static void |
| 104067 | registerAsyncResponse(UA_Client *client, void *userdata, |
| 104068 | UA_UInt32 requestId, void *resp) { |
| 104069 | asyncRegisterRequest *ar = (asyncRegisterRequest*)userdata; |
| 104070 | const UA_ServerConfig *sc = ar->dm->serverConfig; |
| 104071 | UA_Response *response = (UA_Response*)resp; |
| 104072 | const char *regtype = (ar->register2) ? "RegisterServer2": "RegisterServer"; |
| 104073 | |
| 104074 | /* Success registering? */ |
| 104075 | if(response->responseHeader.serviceResult == UA_STATUSCODE_GOOD) { |
| 104076 | UA_LOG_INFO(logger: sc->logging, category: UA_LOGCATEGORY_SERVER, msg: "%s succeeded", regtype); |
| 104077 | goto done; |
| 104078 | } |
| 104079 | |
| 104080 | UA_LOG_WARNING(logger: sc->logging, category: UA_LOGCATEGORY_SERVER, |
| 104081 | msg: "%s failed with statuscode %s", regtype, |
| 104082 | UA_StatusCode_name(code: response->responseHeader.serviceResult)); |
| 104083 | |
| 104084 | /* Try RegisterServer next */ |
| 104085 | ar->register2 = false; |
| 104086 | |
| 104087 | /* Try RegisterServer immediately if we can. |
| 104088 | * Otherwise wait for the next state callback. */ |
| 104089 | UA_SecureChannelState ss; |
| 104090 | UA_Client_getState(client, channelState: &ss, NULL, NULL); |
| 104091 | if(!ar->shutdown && ss == UA_SECURECHANNELSTATE_OPEN) { |
| 104092 | UA_RegisterServerRequest request; |
| 104093 | UA_RegisterServerRequest_init(p: &request); |
| 104094 | setupRegisterRequest(ar, rh: &request.requestHeader, rs: &request.server); |
| 104095 | UA_StatusCode res = |
| 104096 | __UA_Client_AsyncService(client, request: &request, |
| 104097 | requestType: &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST], |
| 104098 | callback: registerAsyncResponse, |
| 104099 | responseType: &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE], userdata: ar, NULL); |
| 104100 | if(res != UA_STATUSCODE_GOOD) { |
| 104101 | UA_LOG_ERROR(logger: (const UA_Logger *)&sc->logging, category: UA_LOGCATEGORY_CLIENT, |
| 104102 | msg: "RegisterServer failed with statuscode %s", |
| 104103 | UA_StatusCode_name(code: res)); |
| 104104 | goto done; |
| 104105 | } |
| 104106 | } |
| 104107 | |
| 104108 | return; |
| 104109 | |
| 104110 | done: |
| 104111 | /* Close the client connection, will be cleaned up in the client state |
| 104112 | * callback when closing is complete */ |
| 104113 | ar->shutdown = true; |
| 104114 | UA_Client_disconnectSecureChannelAsync(client: ar->client); |
| 104115 | } |
| 104116 | |
| 104117 | static void |
| 104118 | discoveryClientStateCallback(UA_Client *client, |
| 104119 | UA_SecureChannelState channelState, |
| 104120 | UA_SessionState sessionState, |
| 104121 | UA_StatusCode connectStatus) { |
| 104122 | asyncRegisterRequest *ar = (asyncRegisterRequest*) |
| 104123 | UA_Client_getContext(client); |
| 104124 | UA_ServerConfig *sc = ar->dm->serverConfig; |
| 104125 | |
| 104126 | /* Connection failed */ |
| 104127 | if(connectStatus != UA_STATUSCODE_GOOD) { |
| 104128 | if(connectStatus != UA_STATUSCODE_BADCONNECTIONCLOSED) { |
| 104129 | UA_LOG_ERROR(logger: sc->logging, category: UA_LOGCATEGORY_SERVER, |
| 104130 | msg: "Could not connect to the Discovery server with error %s", |
| 104131 | UA_StatusCode_name(code: connectStatus)); |
| 104132 | } |
| 104133 | |
| 104134 | /* Connection fully closed */ |
| 104135 | if(channelState == UA_SECURECHANNELSTATE_CLOSED) { |
| 104136 | if(!ar->connectSuccess || ar->shutdown) { |
| 104137 | asyncRegisterRequest_clearAsync(ar); /* Clean up */ |
| 104138 | } else { |
| 104139 | ar->connectSuccess = false; |
| 104140 | __UA_Client_connect(client, true); /* Reconnect */ |
| 104141 | } |
| 104142 | } |
| 104143 | return; |
| 104144 | } |
| 104145 | |
| 104146 | /* Wait until the SecureChannel is open */ |
| 104147 | if(channelState != UA_SECURECHANNELSTATE_OPEN) |
| 104148 | return; |
| 104149 | |
| 104150 | /* We have at least succeeded to connect */ |
| 104151 | ar->connectSuccess = true; |
| 104152 | |
| 104153 | /* Is this the encrypted SecureChannel already? (We might have to wait for |
| 104154 | * the second connection after the FindServers handshake */ |
| 104155 | UA_MessageSecurityMode msm = UA_MESSAGESECURITYMODE_INVALID; |
| 104156 | UA_Client_getConnectionAttribute_scalar(client, key: UA_QUALIFIEDNAME(nsIndex: 0, chars: "securityMode"), |
| 104157 | type: &UA_TYPES[UA_TYPES_MESSAGESECURITYMODE], |
| 104158 | outValue: &msm); |
| 104159 | #ifdef UA_ENABLE_ENCRYPTION |
| 104160 | if(msm != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) |
| 104161 | return; |
| 104162 | #endif |
| 104163 | |
| 104164 | const UA_DataType *reqType; |
| 104165 | const UA_DataType *respType; |
| 104166 | UA_RegisterServerRequest reg1; |
| 104167 | UA_RegisterServer2Request reg2; |
| 104168 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 104169 | UA_ExtensionObject mdnsConfig; |
| 104170 | #endif |
| 104171 | void *request; |
| 104172 | |
| 104173 | /* Prepare the request. This does not allocate memory */ |
| 104174 | if(ar->register2) { |
| 104175 | UA_RegisterServer2Request_init(p: ®2); |
| 104176 | setupRegisterRequest(ar, rh: ®2.requestHeader, rs: ®2.server); |
| 104177 | reqType = &UA_TYPES[UA_TYPES_REGISTERSERVER2REQUEST]; |
| 104178 | respType = &UA_TYPES[UA_TYPES_REGISTERSERVER2RESPONSE]; |
| 104179 | request = ®2; |
| 104180 | |
| 104181 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 104182 | /* Set the configuration that is only available for |
| 104183 | * UA_RegisterServer2Request */ |
| 104184 | UA_ExtensionObject_setValueNoDelete(&mdnsConfig, &sc->mdnsConfig, |
| 104185 | &UA_TYPES[UA_TYPES_MDNSDISCOVERYCONFIGURATION]); |
| 104186 | reg2.discoveryConfigurationSize = 1; |
| 104187 | reg2.discoveryConfiguration = &mdnsConfig; |
| 104188 | #endif |
| 104189 | } else { |
| 104190 | UA_RegisterServerRequest_init(p: ®1); |
| 104191 | setupRegisterRequest(ar, rh: ®1.requestHeader, rs: ®1.server); |
| 104192 | reqType = &UA_TYPES[UA_TYPES_REGISTERSERVERREQUEST]; |
| 104193 | respType = &UA_TYPES[UA_TYPES_REGISTERSERVERRESPONSE]; |
| 104194 | request = ®1; |
| 104195 | } |
| 104196 | |
| 104197 | /* Try to call RegisterServer2 */ |
| 104198 | UA_StatusCode res = |
| 104199 | __UA_Client_AsyncService(client, request, requestType: reqType, callback: registerAsyncResponse, |
| 104200 | responseType: respType, userdata: ar, NULL); |
| 104201 | if(res != UA_STATUSCODE_GOOD) { |
| 104202 | /* Close the client connection, will be cleaned up in the client state |
| 104203 | * callback when closing is complete */ |
| 104204 | UA_Client_disconnectSecureChannelAsync(client: ar->client); |
| 104205 | UA_LOG_ERROR(logger: sc->logging, category: UA_LOGCATEGORY_CLIENT, |
| 104206 | msg: "RegisterServer2 failed with statuscode %s", |
| 104207 | UA_StatusCode_name(code: res)); |
| 104208 | } |
| 104209 | } |
| 104210 | |
| 104211 | static UA_StatusCode |
| 104212 | UA_Server_register(UA_Server *server, UA_ClientConfig *cc, UA_Boolean unregister, |
| 104213 | const UA_String discoveryServerUrl, |
| 104214 | const UA_String semaphoreFilePath) { |
| 104215 | /* Get the discovery manager */ |
| 104216 | UA_DiscoveryManager *dm = (UA_DiscoveryManager*) |
| 104217 | getServerComponentByName(server, name: UA_STRING(chars: "discovery")); |
| 104218 | if(!dm) { |
| 104219 | UA_ClientConfig_clear(config: cc); |
| 104220 | return UA_STATUSCODE_BADINTERNALERROR; |
| 104221 | } |
| 104222 | |
| 104223 | /* Check that the discovery manager is running */ |
| 104224 | UA_ServerConfig *sc = &server->config; |
| 104225 | if(dm->sc.state != UA_LIFECYCLESTATE_STARTED) { |
| 104226 | UA_LOG_ERROR(logger: sc->logging, category: UA_LOGCATEGORY_SERVER, |
| 104227 | msg: "The server must be started for registering"); |
| 104228 | UA_ClientConfig_clear(config: cc); |
| 104229 | return UA_STATUSCODE_BADINTERNALERROR; |
| 104230 | } |
| 104231 | |
| 104232 | /* Find a free slot for storing the async request information */ |
| 104233 | asyncRegisterRequest *ar = NULL; |
| 104234 | for(size_t i = 0; i < UA_MAXREGISTERREQUESTS; i++) { |
| 104235 | if(dm->registerRequests[i].client == NULL) { |
| 104236 | ar = &dm->registerRequests[i]; |
| 104237 | break; |
| 104238 | } |
| 104239 | } |
| 104240 | if(!ar) { |
| 104241 | UA_LOG_ERROR(logger: sc->logging, category: UA_LOGCATEGORY_SERVER, |
| 104242 | msg: "Too many outstanding register requests. Cannot proceed."); |
| 104243 | UA_ClientConfig_clear(config: cc); |
| 104244 | return UA_STATUSCODE_BADINTERNALERROR; |
| 104245 | } |
| 104246 | |
| 104247 | /* Use the EventLoop from the server for the client */ |
| 104248 | if(cc->eventLoop && !cc->externalEventLoop) |
| 104249 | cc->eventLoop->free(cc->eventLoop); |
| 104250 | cc->eventLoop = sc->eventLoop; |
| 104251 | cc->externalEventLoop = true; |
| 104252 | |
| 104253 | /* Set the state callback method and context */ |
| 104254 | cc->stateCallback = discoveryClientStateCallback; |
| 104255 | cc->clientContext = ar; |
| 104256 | |
| 104257 | /* Use encryption by default */ |
| 104258 | #ifdef UA_ENABLE_ENCRYPTION |
| 104259 | cc->securityMode = UA_MESSAGESECURITYMODE_SIGNANDENCRYPT; |
| 104260 | #endif |
| 104261 | |
| 104262 | /* Open only a SecureChannel */ |
| 104263 | cc->noSession = true; |
| 104264 | |
| 104265 | /* Move the endpoint url */ |
| 104266 | UA_String_clear(p: &cc->endpointUrl); |
| 104267 | UA_String_copy(src: &discoveryServerUrl, dst: &cc->endpointUrl); |
| 104268 | |
| 104269 | /* Instantiate the client */ |
| 104270 | ar->client = UA_Client_newWithConfig(config: cc); |
| 104271 | if(!ar->client) { |
| 104272 | UA_ClientConfig_clear(config: cc); |
| 104273 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 104274 | } |
| 104275 | |
| 104276 | /* Zero out the supplied config */ |
| 104277 | memset(s: cc, c: 0, n: sizeof(UA_ClientConfig)); |
| 104278 | |
| 104279 | /* Finish setting up the context */ |
| 104280 | ar->server = server; |
| 104281 | ar->dm = dm; |
| 104282 | ar->unregister = unregister; |
| 104283 | ar->register2 = true; /* Try register2 first */ |
| 104284 | UA_String_copy(src: &semaphoreFilePath, dst: &ar->semaphoreFilePath); |
| 104285 | |
| 104286 | /* Connect asynchronously. The register service is called once the |
| 104287 | * connection is open. */ |
| 104288 | ar->connectSuccess = false; |
| 104289 | return __UA_Client_connect(client: ar->client, true); |
| 104290 | } |
| 104291 | |
| 104292 | UA_StatusCode |
| 104293 | UA_Server_registerDiscovery(UA_Server *server, UA_ClientConfig *cc, |
| 104294 | const UA_String discoveryServerUrl, |
| 104295 | const UA_String semaphoreFilePath) { |
| 104296 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 104297 | msg: "Registering at the DiscoveryServer: %.*s", |
| 104298 | (int)discoveryServerUrl.length, discoveryServerUrl.data); |
| 104299 | lockServer(server); |
| 104300 | UA_StatusCode res = |
| 104301 | UA_Server_register(server, cc, false, discoveryServerUrl, semaphoreFilePath); |
| 104302 | unlockServer(server); |
| 104303 | return res; |
| 104304 | } |
| 104305 | |
| 104306 | UA_StatusCode |
| 104307 | UA_Server_deregisterDiscovery(UA_Server *server, UA_ClientConfig *cc, |
| 104308 | const UA_String discoveryServerUrl) { |
| 104309 | UA_LOG_INFO(logger: server->config.logging, category: UA_LOGCATEGORY_SERVER, |
| 104310 | msg: "Deregistering at the DiscoveryServer: %.*s", |
| 104311 | (int)discoveryServerUrl.length, discoveryServerUrl.data); |
| 104312 | lockServer(server); |
| 104313 | UA_StatusCode res = |
| 104314 | UA_Server_register(server, cc, true, discoveryServerUrl, semaphoreFilePath: UA_STRING_NULL); |
| 104315 | unlockServer(server); |
| 104316 | return res; |
| 104317 | } |
| 104318 | |
| 104319 | #endif /* UA_ENABLE_DISCOVERY */ |
| 104320 | |
| 104321 | /**** amalgamated original file "/plugins/crypto/mbedtls/securitypolicy_mbedtls_common.h" ****/ |
| 104322 | |
| 104323 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 104324 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 104325 | * |
| 104326 | * Copyright 2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 104327 | */ |
| 104328 | |
| 104329 | |
| 104330 | |
| 104331 | #if defined(UA_ENABLE_ENCRYPTION_MBEDTLS) || defined(UA_ENABLE_PUBSUB_ENCRYPTION) |
| 104332 | |
| 104333 | #include <mbedtls/md.h> |
| 104334 | #include <mbedtls/x509_crt.h> |
| 104335 | #include <mbedtls/ctr_drbg.h> |
| 104336 | |
| 104337 | // MBEDTLS_ENTROPY_HARDWARE_ALT should be defined if your hardware does not supportd platform entropy |
| 104338 | |
| 104339 | #define UA_SHA1_LENGTH 20 |
| 104340 | |
| 104341 | _UA_BEGIN_DECLS |
| 104342 | |
| 104343 | void |
| 104344 | swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB); |
| 104345 | |
| 104346 | void |
| 104347 | mbedtls_hmac(mbedtls_md_context_t *context, const UA_ByteString *key, |
| 104348 | const UA_ByteString *in, unsigned char *out); |
| 104349 | |
| 104350 | UA_StatusCode |
| 104351 | mbedtls_generateKey(mbedtls_md_context_t *context, |
| 104352 | const UA_ByteString *secret, const UA_ByteString *seed, |
| 104353 | UA_ByteString *out); |
| 104354 | |
| 104355 | UA_StatusCode |
| 104356 | mbedtls_verifySig_sha1(mbedtls_x509_crt *certificate, const UA_ByteString *message, |
| 104357 | const UA_ByteString *signature); |
| 104358 | |
| 104359 | UA_StatusCode |
| 104360 | mbedtls_sign_sha1(mbedtls_pk_context *localPrivateKey, |
| 104361 | mbedtls_ctr_drbg_context *drbgContext, |
| 104362 | const UA_ByteString *message, |
| 104363 | UA_ByteString *signature); |
| 104364 | |
| 104365 | UA_StatusCode |
| 104366 | mbedtls_thumbprint_sha1(const UA_ByteString *certificate, |
| 104367 | UA_ByteString *thumbprint); |
| 104368 | |
| 104369 | /* Set the hashing scheme before calling |
| 104370 | * E.g. mbedtls_rsa_set_padding(context, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1); */ |
| 104371 | UA_StatusCode |
| 104372 | mbedtls_encrypt_rsaOaep(mbedtls_rsa_context *context, |
| 104373 | mbedtls_ctr_drbg_context *drbgContext, |
| 104374 | UA_ByteString *data, const size_t plainTextBlockSize); |
| 104375 | |
| 104376 | UA_StatusCode |
| 104377 | mbedtls_decrypt_rsaOaep(mbedtls_pk_context *localPrivateKey, |
| 104378 | mbedtls_ctr_drbg_context *drbgContext, |
| 104379 | UA_ByteString *data, int hash_id); |
| 104380 | |
| 104381 | int UA_mbedTLS_LoadPrivateKey(const UA_ByteString *key, mbedtls_pk_context *target, void *p_rng); |
| 104382 | |
| 104383 | UA_StatusCode UA_mbedTLS_LoadLocalCertificate(const UA_ByteString *certData, UA_ByteString *target); |
| 104384 | |
| 104385 | UA_ByteString UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data); |
| 104386 | |
| 104387 | _UA_END_DECLS |
| 104388 | |
| 104389 | #endif |
| 104390 | |
| 104391 | |
| 104392 | /**** amalgamated original file "/plugins/crypto/mbedtls/securitypolicy_mbedtls_common.c" ****/ |
| 104393 | |
| 104394 | |
| 104395 | #if defined(UA_ENABLE_ENCRYPTION_MBEDTLS) || defined(UA_ENABLE_PUBSUB_ENCRYPTION) |
| 104396 | |
| 104397 | |
| 104398 | #include <mbedtls/aes.h> |
| 104399 | #include <mbedtls/ctr_drbg.h> |
| 104400 | #include <mbedtls/entropy.h> |
| 104401 | #include <mbedtls/error.h> |
| 104402 | #include <mbedtls/md.h> |
| 104403 | #include <mbedtls/sha1.h> |
| 104404 | #include <mbedtls/version.h> |
| 104405 | #include <mbedtls/x509_crt.h> |
| 104406 | |
| 104407 | void |
| 104408 | swapBuffers(UA_ByteString *const bufA, UA_ByteString *const bufB) { |
| 104409 | UA_ByteString tmp = *bufA; |
| 104410 | *bufA = *bufB; |
| 104411 | *bufB = tmp; |
| 104412 | } |
| 104413 | |
| 104414 | void |
| 104415 | mbedtls_hmac(mbedtls_md_context_t *context, const UA_ByteString *key, |
| 104416 | const UA_ByteString *in, unsigned char *out) { |
| 104417 | mbedtls_md_hmac_starts(context, key->data, key->length); |
| 104418 | mbedtls_md_hmac_update(context, in->data, in->length); |
| 104419 | mbedtls_md_hmac_finish(context, out); |
| 104420 | } |
| 104421 | |
| 104422 | UA_StatusCode |
| 104423 | mbedtls_generateKey(mbedtls_md_context_t *context, |
| 104424 | const UA_ByteString *secret, const UA_ByteString *seed, |
| 104425 | UA_ByteString *out) { |
| 104426 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 104427 | size_t hashLen = (size_t)mbedtls_md_get_size(context->md_info); |
| 104428 | #else |
| 104429 | size_t hashLen = (size_t)mbedtls_md_get_size(context->private_md_info); |
| 104430 | #endif |
| 104431 | |
| 104432 | UA_ByteString A_and_seed; |
| 104433 | UA_ByteString_allocBuffer(&A_and_seed, hashLen + seed->length); |
| 104434 | memcpy(A_and_seed.data + hashLen, seed->data, seed->length); |
| 104435 | |
| 104436 | UA_ByteString ANext_and_seed; |
| 104437 | UA_ByteString_allocBuffer(&ANext_and_seed, hashLen + seed->length); |
| 104438 | memcpy(ANext_and_seed.data + hashLen, seed->data, seed->length); |
| 104439 | |
| 104440 | UA_ByteString A = { |
| 104441 | hashLen, |
| 104442 | A_and_seed.data |
| 104443 | }; |
| 104444 | |
| 104445 | UA_ByteString ANext = { |
| 104446 | hashLen, |
| 104447 | ANext_and_seed.data |
| 104448 | }; |
| 104449 | |
| 104450 | mbedtls_hmac(context, secret, seed, A.data); |
| 104451 | |
| 104452 | UA_StatusCode retval = 0; |
| 104453 | for(size_t offset = 0; offset < out->length; offset += hashLen) { |
| 104454 | UA_ByteString outSegment = { |
| 104455 | hashLen, |
| 104456 | out->data + offset |
| 104457 | }; |
| 104458 | UA_Boolean bufferAllocated = UA_FALSE; |
| 104459 | // Not enough room in out buffer to write the hash. |
| 104460 | if(offset + hashLen > out->length) { |
| 104461 | outSegment.data = NULL; |
| 104462 | outSegment.length = 0; |
| 104463 | retval = UA_ByteString_allocBuffer(&outSegment, hashLen); |
| 104464 | if(retval != UA_STATUSCODE_GOOD) { |
| 104465 | UA_ByteString_clear(&A_and_seed); |
| 104466 | UA_ByteString_clear(&ANext_and_seed); |
| 104467 | return retval; |
| 104468 | } |
| 104469 | bufferAllocated = UA_TRUE; |
| 104470 | } |
| 104471 | |
| 104472 | mbedtls_hmac(context, secret, &A_and_seed, outSegment.data); |
| 104473 | mbedtls_hmac(context, secret, &A, ANext.data); |
| 104474 | |
| 104475 | if(retval != UA_STATUSCODE_GOOD) { |
| 104476 | if(bufferAllocated) |
| 104477 | UA_ByteString_clear(&outSegment); |
| 104478 | UA_ByteString_clear(&A_and_seed); |
| 104479 | UA_ByteString_clear(&ANext_and_seed); |
| 104480 | return retval; |
| 104481 | } |
| 104482 | |
| 104483 | if(bufferAllocated) { |
| 104484 | memcpy(out->data + offset, outSegment.data, out->length - offset); |
| 104485 | UA_ByteString_clear(&outSegment); |
| 104486 | } |
| 104487 | |
| 104488 | swapBuffers(&ANext_and_seed, &A_and_seed); |
| 104489 | swapBuffers(&ANext, &A); |
| 104490 | } |
| 104491 | |
| 104492 | UA_ByteString_clear(&A_and_seed); |
| 104493 | UA_ByteString_clear(&ANext_and_seed); |
| 104494 | return UA_STATUSCODE_GOOD; |
| 104495 | } |
| 104496 | |
| 104497 | UA_StatusCode |
| 104498 | mbedtls_verifySig_sha1(mbedtls_x509_crt *certificate, const UA_ByteString *message, |
| 104499 | const UA_ByteString *signature) { |
| 104500 | /* Compute the sha1 hash */ |
| 104501 | unsigned char hash[UA_SHA1_LENGTH]; |
| 104502 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 104503 | mbedtls_sha1_ret(message->data, message->length, hash); |
| 104504 | #else |
| 104505 | mbedtls_sha1(message->data, message->length, hash); |
| 104506 | #endif |
| 104507 | |
| 104508 | /* Set the RSA settings */ |
| 104509 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(certificate->pk); |
| 104510 | if(!rsaContext) |
| 104511 | return UA_STATUSCODE_BADINTERNALERROR; |
| 104512 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); |
| 104513 | |
| 104514 | /* Verify */ |
| 104515 | int mbedErr = mbedtls_pk_verify(&certificate->pk, |
| 104516 | MBEDTLS_MD_SHA1, hash, UA_SHA1_LENGTH, |
| 104517 | signature->data, signature->length); |
| 104518 | if(mbedErr) |
| 104519 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 104520 | return UA_STATUSCODE_GOOD; |
| 104521 | } |
| 104522 | |
| 104523 | UA_StatusCode |
| 104524 | mbedtls_sign_sha1(mbedtls_pk_context *localPrivateKey, |
| 104525 | mbedtls_ctr_drbg_context *drbgContext, |
| 104526 | const UA_ByteString *message, |
| 104527 | UA_ByteString *signature) { |
| 104528 | unsigned char hash[UA_SHA1_LENGTH]; |
| 104529 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 104530 | mbedtls_sha1_ret(message->data, message->length, hash); |
| 104531 | #else |
| 104532 | mbedtls_sha1(message->data, message->length, hash); |
| 104533 | #endif |
| 104534 | |
| 104535 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(*localPrivateKey); |
| 104536 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); |
| 104537 | |
| 104538 | size_t sigLen = 0; |
| 104539 | int mbedErr = mbedtls_pk_sign(localPrivateKey, MBEDTLS_MD_SHA1, hash, |
| 104540 | UA_SHA1_LENGTH, signature->data, |
| 104541 | #if MBEDTLS_VERSION_NUMBER >= 0x03000000 |
| 104542 | signature->length, |
| 104543 | #endif |
| 104544 | &sigLen, |
| 104545 | mbedtls_ctr_drbg_random, drbgContext); |
| 104546 | if(mbedErr) |
| 104547 | return UA_STATUSCODE_BADINTERNALERROR; |
| 104548 | return UA_STATUSCODE_GOOD; |
| 104549 | } |
| 104550 | |
| 104551 | UA_StatusCode |
| 104552 | mbedtls_thumbprint_sha1(const UA_ByteString *certificate, |
| 104553 | UA_ByteString *thumbprint) { |
| 104554 | if(UA_ByteString_equal(certificate, &UA_BYTESTRING_NULL)) |
| 104555 | return UA_STATUSCODE_BADINTERNALERROR; |
| 104556 | |
| 104557 | if(thumbprint->length != UA_SHA1_LENGTH) |
| 104558 | return UA_STATUSCODE_BADINTERNALERROR; |
| 104559 | |
| 104560 | /* The certificate thumbprint is always a 20 bit sha1 hash, see Part 4 of the Specification. */ |
| 104561 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 104562 | mbedtls_sha1_ret(certificate->data, certificate->length, thumbprint->data); |
| 104563 | #else |
| 104564 | mbedtls_sha1(certificate->data, certificate->length, thumbprint->data); |
| 104565 | #endif |
| 104566 | return UA_STATUSCODE_GOOD; |
| 104567 | } |
| 104568 | |
| 104569 | UA_StatusCode |
| 104570 | mbedtls_encrypt_rsaOaep(mbedtls_rsa_context *context, |
| 104571 | mbedtls_ctr_drbg_context *drbgContext, |
| 104572 | UA_ByteString *data, const size_t plainTextBlockSize) { |
| 104573 | if(data->length % plainTextBlockSize != 0) |
| 104574 | return UA_STATUSCODE_BADINTERNALERROR; |
| 104575 | |
| 104576 | size_t max_blocks = data->length / plainTextBlockSize; |
| 104577 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 104578 | size_t keylen = context->len; |
| 104579 | #else |
| 104580 | size_t keylen = mbedtls_rsa_get_len(context); |
| 104581 | #endif |
| 104582 | |
| 104583 | UA_ByteString encrypted; |
| 104584 | UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, max_blocks * keylen); |
| 104585 | if(retval != UA_STATUSCODE_GOOD) |
| 104586 | return retval; |
| 104587 | |
| 104588 | size_t lenDataToEncrypt = data->length; |
| 104589 | size_t inOffset = 0; |
| 104590 | size_t offset = 0; |
| 104591 | const unsigned char *label = NULL; |
| 104592 | while(lenDataToEncrypt >= plainTextBlockSize) { |
| 104593 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 104594 | int mbedErr = mbedtls_rsa_rsaes_oaep_encrypt(context, mbedtls_ctr_drbg_random, |
| 104595 | drbgContext, MBEDTLS_RSA_PUBLIC, |
| 104596 | label, 0, plainTextBlockSize, |
| 104597 | data->data + inOffset, encrypted.data + offset); |
| 104598 | #else |
| 104599 | int mbedErr = mbedtls_rsa_rsaes_oaep_encrypt(context, mbedtls_ctr_drbg_random, |
| 104600 | drbgContext, label, 0, plainTextBlockSize, |
| 104601 | data->data + inOffset, encrypted.data + offset); |
| 104602 | #endif |
| 104603 | |
| 104604 | if(mbedErr) { |
| 104605 | UA_ByteString_clear(&encrypted); |
| 104606 | return UA_STATUSCODE_BADINTERNALERROR; |
| 104607 | } |
| 104608 | |
| 104609 | inOffset += plainTextBlockSize; |
| 104610 | offset += keylen; |
| 104611 | lenDataToEncrypt -= plainTextBlockSize; |
| 104612 | } |
| 104613 | |
| 104614 | memcpy(data->data, encrypted.data, offset); |
| 104615 | UA_ByteString_clear(&encrypted); |
| 104616 | return UA_STATUSCODE_GOOD; |
| 104617 | } |
| 104618 | |
| 104619 | UA_StatusCode |
| 104620 | mbedtls_decrypt_rsaOaep(mbedtls_pk_context *localPrivateKey, |
| 104621 | mbedtls_ctr_drbg_context *drbgContext, |
| 104622 | UA_ByteString *data, int hash_id) { |
| 104623 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(*localPrivateKey); |
| 104624 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 104625 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V21, hash_id); |
| 104626 | size_t keylen = rsaContext->len; |
| 104627 | #else |
| 104628 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V21, (mbedtls_md_type_t)hash_id); |
| 104629 | size_t keylen = mbedtls_rsa_get_len(rsaContext); |
| 104630 | #endif |
| 104631 | if(data->length % keylen != 0) |
| 104632 | return UA_STATUSCODE_BADINTERNALERROR; |
| 104633 | |
| 104634 | size_t inOffset = 0; |
| 104635 | size_t outOffset = 0; |
| 104636 | size_t outLength = 0; |
| 104637 | unsigned char buf[512]; |
| 104638 | |
| 104639 | while(inOffset < data->length) { |
| 104640 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 104641 | int mbedErr = mbedtls_rsa_rsaes_oaep_decrypt(rsaContext, mbedtls_ctr_drbg_random, |
| 104642 | drbgContext, MBEDTLS_RSA_PRIVATE, |
| 104643 | NULL, 0, &outLength, |
| 104644 | data->data + inOffset, |
| 104645 | buf, 512); |
| 104646 | #else |
| 104647 | int mbedErr = mbedtls_rsa_rsaes_oaep_decrypt(rsaContext, mbedtls_ctr_drbg_random, |
| 104648 | drbgContext, |
| 104649 | NULL, 0, &outLength, |
| 104650 | data->data + inOffset, |
| 104651 | buf, 512); |
| 104652 | #endif |
| 104653 | |
| 104654 | if(mbedErr) |
| 104655 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 104656 | |
| 104657 | memcpy(data->data + outOffset, buf, outLength); |
| 104658 | inOffset += keylen; |
| 104659 | outOffset += outLength; |
| 104660 | } |
| 104661 | |
| 104662 | data->length = outOffset; |
| 104663 | return UA_STATUSCODE_GOOD; |
| 104664 | } |
| 104665 | |
| 104666 | int |
| 104667 | UA_mbedTLS_LoadPrivateKey(const UA_ByteString *key, mbedtls_pk_context *target, void *p_rng) { |
| 104668 | UA_ByteString data = UA_mbedTLS_CopyDataFormatAware(key); |
| 104669 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 104670 | int mbedErr = mbedtls_pk_parse_key(target, data.data, data.length, NULL, 0); |
| 104671 | #else |
| 104672 | int mbedErr = mbedtls_pk_parse_key(target, data.data, data.length, NULL, 0, mbedtls_entropy_func, p_rng); |
| 104673 | #endif |
| 104674 | UA_ByteString_clear(&data); |
| 104675 | return mbedErr; |
| 104676 | } |
| 104677 | |
| 104678 | UA_StatusCode |
| 104679 | UA_mbedTLS_LoadLocalCertificate(const UA_ByteString *certData, |
| 104680 | UA_ByteString *target) { |
| 104681 | UA_ByteString data = UA_mbedTLS_CopyDataFormatAware(certData); |
| 104682 | |
| 104683 | mbedtls_x509_crt cert; |
| 104684 | mbedtls_x509_crt_init(&cert); |
| 104685 | |
| 104686 | int mbedErr = mbedtls_x509_crt_parse(&cert, data.data, data.length); |
| 104687 | |
| 104688 | UA_StatusCode result = UA_STATUSCODE_BADINVALIDARGUMENT; |
| 104689 | |
| 104690 | if (!mbedErr) { |
| 104691 | UA_ByteString tmp; |
| 104692 | tmp.data = cert.raw.p; |
| 104693 | tmp.length = cert.raw.len; |
| 104694 | |
| 104695 | result = UA_ByteString_copy(&tmp, target); |
| 104696 | } else { |
| 104697 | UA_ByteString_init(target); |
| 104698 | } |
| 104699 | |
| 104700 | UA_ByteString_clear(&data); |
| 104701 | mbedtls_x509_crt_free(&cert); |
| 104702 | return result; |
| 104703 | } |
| 104704 | |
| 104705 | // mbedTLS expects PEM data to be null terminated |
| 104706 | // The data length parameter must include the null terminator |
| 104707 | UA_ByteString |
| 104708 | UA_mbedTLS_CopyDataFormatAware(const UA_ByteString *data) { |
| 104709 | UA_ByteString result; |
| 104710 | UA_ByteString_init(&result); |
| 104711 | |
| 104712 | if (!data->length) |
| 104713 | return result; |
| 104714 | |
| 104715 | if (data->length && data->data[0] == '-') { |
| 104716 | UA_ByteString_allocBuffer(&result, data->length + 1); |
| 104717 | memcpy(result.data, data->data, data->length); |
| 104718 | result.data[data->length] = '\0'; |
| 104719 | } else { |
| 104720 | UA_ByteString_copy(data, &result); |
| 104721 | } |
| 104722 | |
| 104723 | return result; |
| 104724 | } |
| 104725 | |
| 104726 | #endif |
| 104727 | |
| 104728 | /**** amalgamated original file "/plugins/ua_log_stdout.c" ****/ |
| 104729 | |
| 104730 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 104731 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 104732 | * |
| 104733 | * Copyright 2016-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 104734 | * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA |
| 104735 | */ |
| 104736 | |
| 104737 | |
| 104738 | #include <stdio.h> |
| 104739 | |
| 104740 | /* ANSI escape sequences for color output taken from here: |
| 104741 | * https://stackoverflow.com/questions/3219393/stdlib-and-colored-output-in-c*/ |
| 104742 | |
| 104743 | #ifdef UA_ARCHITECTURE_POSIX |
| 104744 | # define ANSI_COLOR_RED "\x1b[31m" |
| 104745 | # define ANSI_COLOR_GREEN "\x1b[32m" |
| 104746 | # define ANSI_COLOR_YELLOW "\x1b[33m" |
| 104747 | # define ANSI_COLOR_BLUE "\x1b[34m" |
| 104748 | # define ANSI_COLOR_MAGENTA "\x1b[35m" |
| 104749 | # define ANSI_COLOR_CYAN "\x1b[36m" |
| 104750 | # define ANSI_COLOR_RESET "\x1b[0m" |
| 104751 | #else |
| 104752 | # define ANSI_COLOR_RED "" |
| 104753 | # define ANSI_COLOR_GREEN "" |
| 104754 | # define ANSI_COLOR_YELLOW "" |
| 104755 | # define ANSI_COLOR_BLUE "" |
| 104756 | # define ANSI_COLOR_MAGENTA "" |
| 104757 | # define ANSI_COLOR_CYAN "" |
| 104758 | # define ANSI_COLOR_RESET "" |
| 104759 | #endif |
| 104760 | |
| 104761 | static |
| 104762 | const char *logLevelNames[6] = {"trace", "debug", |
| 104763 | ANSI_COLOR_GREEN "info", |
| 104764 | ANSI_COLOR_YELLOW "warn", |
| 104765 | ANSI_COLOR_RED "error", |
| 104766 | ANSI_COLOR_MAGENTA "fatal"}; |
| 104767 | static const char * |
| 104768 | logCategoryNames[UA_LOGCATEGORIES] = |
| 104769 | {"network", "channel", "session", "server", "client", |
| 104770 | "userland", "securitypolicy", "eventloop", "pubsub", "discovery"}; |
| 104771 | |
| 104772 | /* Protect crosstalk during logging via global lock. Use a spinlock as we cannot |
| 104773 | * statically initialize a global lock across all platforms. */ |
| 104774 | #if UA_MULTITHREADING >= 100 |
| 104775 | void * volatile logSpinLock = NULL; |
| 104776 | static UA_INLINE void spinLock(void) { |
| 104777 | while(UA_atomic_cmpxchg(&logSpinLock, NULL, (void*)0x1) != NULL) {} |
| 104778 | } |
| 104779 | static UA_INLINE void spinUnLock(void) { |
| 104780 | UA_atomic_xchg(&logSpinLock, NULL); |
| 104781 | } |
| 104782 | #endif |
| 104783 | |
| 104784 | #ifdef __clang__ |
| 104785 | __attribute__((__format__(__printf__, 4 , 0))) |
| 104786 | #endif |
| 104787 | static void |
| 104788 | UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category, |
| 104789 | const char *msg, va_list args) { |
| 104790 | /* MinLevel encoded in the context pointer */ |
| 104791 | UA_LogLevel minLevel = (UA_LogLevel)(uintptr_t)context; |
| 104792 | if(minLevel > level) |
| 104793 | return; |
| 104794 | |
| 104795 | UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset(); |
| 104796 | UA_DateTimeStruct dts = UA_DateTime_toStruct(t: UA_DateTime_now() + tOffset); |
| 104797 | |
| 104798 | int logLevelSlot = ((int)level / 100) - 1; |
| 104799 | if(logLevelSlot < 0 || logLevelSlot > 5) |
| 104800 | logLevelSlot = 5; /* Set to fatal if the level is outside the range */ |
| 104801 | |
| 104802 | /* Lock */ |
| 104803 | #if UA_MULTITHREADING >= 100 |
| 104804 | spinLock(); |
| 104805 | #endif |
| 104806 | |
| 104807 | /* Log */ |
| 104808 | printf(format: "[%04u-%02u-%02u %02u:%02u:%02u.%03u (UTC%+05d)] %s/%s"ANSI_COLOR_RESET "\t", |
| 104809 | dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec, |
| 104810 | (int)(tOffset / UA_DATETIME_SEC / 36), logLevelNames[logLevelSlot], |
| 104811 | logCategoryNames[category]); |
| 104812 | vprintf(format: msg, arg: args); |
| 104813 | printf(format: "\n"); |
| 104814 | fflush(stdout); |
| 104815 | |
| 104816 | /* Unlock */ |
| 104817 | #if UA_MULTITHREADING >= 100 |
| 104818 | spinUnLock(); |
| 104819 | #endif |
| 104820 | } |
| 104821 | |
| 104822 | static void |
| 104823 | UA_Log_Stdout_clear(UA_Logger *logger) { |
| 104824 | UA_free(ptr: logger); |
| 104825 | } |
| 104826 | |
| 104827 | const UA_Logger UA_Log_Stdout_ = {UA_Log_Stdout_log, NULL, NULL}; |
| 104828 | const UA_Logger *UA_Log_Stdout = &UA_Log_Stdout_; |
| 104829 | |
| 104830 | UA_Logger |
| 104831 | UA_Log_Stdout_withLevel(UA_LogLevel minlevel) { |
| 104832 | UA_Logger logger = |
| 104833 | {UA_Log_Stdout_log, (void*)(uintptr_t)minlevel, NULL}; |
| 104834 | return logger; |
| 104835 | } |
| 104836 | |
| 104837 | UA_Logger * |
| 104838 | UA_Log_Stdout_new(UA_LogLevel minlevel) { |
| 104839 | UA_Logger *logger = (UA_Logger*)UA_malloc(size: sizeof(UA_Logger)); |
| 104840 | if(!logger) |
| 104841 | return NULL; |
| 104842 | *logger = UA_Log_Stdout_withLevel(minlevel); |
| 104843 | logger->clear = UA_Log_Stdout_clear; |
| 104844 | return logger; |
| 104845 | } |
| 104846 | |
| 104847 | /**** amalgamated original file "/plugins/ua_accesscontrol_default.c" ****/ |
| 104848 | |
| 104849 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 104850 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 104851 | * |
| 104852 | * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 104853 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 104854 | * Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 104855 | */ |
| 104856 | |
| 104857 | |
| 104858 | /* Example access control management. Anonymous and username / password login. |
| 104859 | * The access rights are maximally permissive. |
| 104860 | * |
| 104861 | * FOR PRODUCTION USE, THIS EXAMPLE PLUGIN SHOULD BE REPLACED WITH LESS |
| 104862 | * PERMISSIVE ACCESS CONTROL. |
| 104863 | * |
| 104864 | * For TransferSubscriptions, we check whether the transfer happens between |
| 104865 | * Sessions for the same user. */ |
| 104866 | |
| 104867 | typedef struct { |
| 104868 | UA_Boolean allowAnonymous; |
| 104869 | size_t usernamePasswordLoginSize; |
| 104870 | UA_UsernamePasswordLogin *usernamePasswordLogin; |
| 104871 | UA_UsernamePasswordLoginCallback loginCallback; |
| 104872 | void *loginContext; |
| 104873 | UA_CertificateVerification verifyX509; |
| 104874 | } AccessControlContext; |
| 104875 | |
| 104876 | #define ANONYMOUS_POLICY "open62541-anonymous-policy" |
| 104877 | #define CERTIFICATE_POLICY "open62541-certificate-policy" |
| 104878 | #define USERNAME_POLICY "open62541-username-policy" |
| 104879 | const UA_String anonymous_policy = UA_STRING_STATIC(ANONYMOUS_POLICY); |
| 104880 | const UA_String certificate_policy = UA_STRING_STATIC(CERTIFICATE_POLICY); |
| 104881 | const UA_String username_policy = UA_STRING_STATIC(USERNAME_POLICY); |
| 104882 | |
| 104883 | /************************/ |
| 104884 | /* Access Control Logic */ |
| 104885 | /************************/ |
| 104886 | |
| 104887 | static UA_StatusCode |
| 104888 | activateSession_default(UA_Server *server, UA_AccessControl *ac, |
| 104889 | const UA_EndpointDescription *endpointDescription, |
| 104890 | const UA_ByteString *secureChannelRemoteCertificate, |
| 104891 | const UA_NodeId *sessionId, |
| 104892 | const UA_ExtensionObject *userIdentityToken, |
| 104893 | void **sessionContext) { |
| 104894 | AccessControlContext *context = (AccessControlContext*)ac->context; |
| 104895 | UA_ServerConfig *config = UA_Server_getConfig(server); |
| 104896 | |
| 104897 | /* The empty token is interpreted as anonymous */ |
| 104898 | UA_AnonymousIdentityToken anonToken; |
| 104899 | UA_ExtensionObject tmpIdentity; |
| 104900 | if(userIdentityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) { |
| 104901 | UA_AnonymousIdentityToken_init(p: &anonToken); |
| 104902 | UA_ExtensionObject_init(p: &tmpIdentity); |
| 104903 | UA_ExtensionObject_setValueNoDelete(eo: &tmpIdentity, |
| 104904 | p: &anonToken, |
| 104905 | type: &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]); |
| 104906 | userIdentityToken = &tmpIdentity; |
| 104907 | } |
| 104908 | |
| 104909 | /* Could the token be decoded? */ |
| 104910 | if(userIdentityToken->encoding < UA_EXTENSIONOBJECT_DECODED) |
| 104911 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 104912 | |
| 104913 | const UA_DataType *tokenType = userIdentityToken->content.decoded.type; |
| 104914 | if(tokenType == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) { |
| 104915 | /* Anonymous login */ |
| 104916 | if(!context->allowAnonymous) |
| 104917 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 104918 | |
| 104919 | const UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*) |
| 104920 | userIdentityToken->content.decoded.data; |
| 104921 | |
| 104922 | /* Match the beginnig of the PolicyId. |
| 104923 | * Compatibility notice: Siemens OPC Scout v10 provides an empty |
| 104924 | * policyId. This is not compliant. For compatibility, assume that empty |
| 104925 | * policyId == ANONYMOUS_POLICY */ |
| 104926 | if(token->policyId.data && |
| 104927 | (token->policyId.length < anonymous_policy.length || |
| 104928 | strncmp(s1: (const char*)token->policyId.data, |
| 104929 | s2: (const char*)anonymous_policy.data, |
| 104930 | n: anonymous_policy.length) != 0)) { |
| 104931 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 104932 | } |
| 104933 | } else if(tokenType == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) { |
| 104934 | /* Username and password */ |
| 104935 | const UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken*) |
| 104936 | userIdentityToken->content.decoded.data; |
| 104937 | |
| 104938 | /* Match the beginnig of the PolicyId */ |
| 104939 | if(userToken->policyId.length < username_policy.length || |
| 104940 | strncmp(s1: (const char*)userToken->policyId.data, |
| 104941 | s2: (const char*)username_policy.data, |
| 104942 | n: username_policy.length) != 0) { |
| 104943 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 104944 | } |
| 104945 | |
| 104946 | /* The userToken has been decrypted by the server before forwarding |
| 104947 | * it to the plugin. This information can be used here. */ |
| 104948 | /* if(userToken->encryptionAlgorithm.length > 0) {} */ |
| 104949 | |
| 104950 | /* Empty username and password */ |
| 104951 | if(userToken->userName.length == 0 && userToken->password.length == 0) |
| 104952 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 104953 | |
| 104954 | /* Try to match username/pw */ |
| 104955 | UA_Boolean match = false; |
| 104956 | if(context->loginCallback) { |
| 104957 | if(context->loginCallback(&userToken->userName, &userToken->password, |
| 104958 | context->usernamePasswordLoginSize, context->usernamePasswordLogin, |
| 104959 | sessionContext, context->loginContext) == UA_STATUSCODE_GOOD) |
| 104960 | match = true; |
| 104961 | } else { |
| 104962 | for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) { |
| 104963 | if(UA_String_equal(p1: &userToken->userName, p2: &context->usernamePasswordLogin[i].username) && |
| 104964 | UA_String_equal(p1: &userToken->password, p2: &context->usernamePasswordLogin[i].password)) { |
| 104965 | match = true; |
| 104966 | break; |
| 104967 | } |
| 104968 | } |
| 104969 | } |
| 104970 | if(!match) |
| 104971 | return UA_STATUSCODE_BADUSERACCESSDENIED; |
| 104972 | } else if(tokenType == &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) { |
| 104973 | /* x509 certificate */ |
| 104974 | const UA_X509IdentityToken *userToken = (UA_X509IdentityToken*) |
| 104975 | userIdentityToken->content.decoded.data; |
| 104976 | |
| 104977 | /* Match the beginnig of the PolicyId */ |
| 104978 | if(userToken->policyId.length < certificate_policy.length || |
| 104979 | strncmp(s1: (const char*)userToken->policyId.data, |
| 104980 | s2: (const char*)certificate_policy.data, |
| 104981 | n: certificate_policy.length) != 0) { |
| 104982 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 104983 | } |
| 104984 | |
| 104985 | if(!config->sessionPKI.verifyCertificate) |
| 104986 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 104987 | |
| 104988 | UA_StatusCode res = config->sessionPKI. |
| 104989 | verifyCertificate(&config->sessionPKI, &userToken->certificateData); |
| 104990 | if(res != UA_STATUSCODE_GOOD) |
| 104991 | return UA_STATUSCODE_BADIDENTITYTOKENREJECTED; |
| 104992 | } else { |
| 104993 | /* Unsupported token type */ |
| 104994 | return UA_STATUSCODE_BADIDENTITYTOKENINVALID; |
| 104995 | } |
| 104996 | |
| 104997 | return UA_STATUSCODE_GOOD; |
| 104998 | } |
| 104999 | |
| 105000 | static void |
| 105001 | closeSession_default(UA_Server *server, UA_AccessControl *ac, |
| 105002 | const UA_NodeId *sessionId, void *sessionContext) { |
| 105003 | } |
| 105004 | |
| 105005 | static UA_UInt32 |
| 105006 | getUserRightsMask_default(UA_Server *server, UA_AccessControl *ac, |
| 105007 | const UA_NodeId *sessionId, void *sessionContext, |
| 105008 | const UA_NodeId *nodeId, void *nodeContext) { |
| 105009 | return 0xFFFFFFFF; |
| 105010 | } |
| 105011 | |
| 105012 | static UA_Byte |
| 105013 | getUserAccessLevel_default(UA_Server *server, UA_AccessControl *ac, |
| 105014 | const UA_NodeId *sessionId, void *sessionContext, |
| 105015 | const UA_NodeId *nodeId, void *nodeContext) { |
| 105016 | return 0xFF; |
| 105017 | } |
| 105018 | |
| 105019 | static UA_Boolean |
| 105020 | getUserExecutable_default(UA_Server *server, UA_AccessControl *ac, |
| 105021 | const UA_NodeId *sessionId, void *sessionContext, |
| 105022 | const UA_NodeId *methodId, void *methodContext) { |
| 105023 | return true; |
| 105024 | } |
| 105025 | |
| 105026 | static UA_Boolean |
| 105027 | getUserExecutableOnObject_default(UA_Server *server, UA_AccessControl *ac, |
| 105028 | const UA_NodeId *sessionId, void *sessionContext, |
| 105029 | const UA_NodeId *methodId, void *methodContext, |
| 105030 | const UA_NodeId *objectId, void *objectContext) { |
| 105031 | return true; |
| 105032 | } |
| 105033 | |
| 105034 | static UA_Boolean |
| 105035 | allowAddNode_default(UA_Server *server, UA_AccessControl *ac, |
| 105036 | const UA_NodeId *sessionId, void *sessionContext, |
| 105037 | const UA_AddNodesItem *item) { |
| 105038 | return true; |
| 105039 | } |
| 105040 | |
| 105041 | static UA_Boolean |
| 105042 | allowAddReference_default(UA_Server *server, UA_AccessControl *ac, |
| 105043 | const UA_NodeId *sessionId, void *sessionContext, |
| 105044 | const UA_AddReferencesItem *item) { |
| 105045 | return true; |
| 105046 | } |
| 105047 | |
| 105048 | static UA_Boolean |
| 105049 | allowDeleteNode_default(UA_Server *server, UA_AccessControl *ac, |
| 105050 | const UA_NodeId *sessionId, void *sessionContext, |
| 105051 | const UA_DeleteNodesItem *item) { |
| 105052 | return true; |
| 105053 | } |
| 105054 | |
| 105055 | static UA_Boolean |
| 105056 | allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac, |
| 105057 | const UA_NodeId *sessionId, void *sessionContext, |
| 105058 | const UA_DeleteReferencesItem *item) { |
| 105059 | return true; |
| 105060 | } |
| 105061 | |
| 105062 | static UA_Boolean |
| 105063 | allowBrowseNode_default(UA_Server *server, UA_AccessControl *ac, |
| 105064 | const UA_NodeId *sessionId, void *sessionContext, |
| 105065 | const UA_NodeId *nodeId, void *nodeContext) { |
| 105066 | return true; |
| 105067 | } |
| 105068 | |
| 105069 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 105070 | static UA_Boolean |
| 105071 | allowTransferSubscription_default(UA_Server *server, UA_AccessControl *ac, |
| 105072 | const UA_NodeId *oldSessionId, void *oldSessionContext, |
| 105073 | const UA_NodeId *newSessionId, void *newSessionContext) { |
| 105074 | if(!oldSessionId) |
| 105075 | return true; |
| 105076 | /* Allow the transfer if the same user-id was used to activate both sessions */ |
| 105077 | UA_Variant session1UserId; |
| 105078 | UA_Variant_init(p: &session1UserId); |
| 105079 | UA_Server_getSessionAttribute(server, sessionId: oldSessionId, |
| 105080 | key: UA_QUALIFIEDNAME(nsIndex: 0, chars: "clientUserId"), |
| 105081 | outValue: &session1UserId); |
| 105082 | UA_Variant session2UserId; |
| 105083 | UA_Variant_init(p: &session2UserId); |
| 105084 | UA_Server_getSessionAttribute(server, sessionId: newSessionId, |
| 105085 | key: UA_QUALIFIEDNAME(nsIndex: 0, chars: "clientUserId"), |
| 105086 | outValue: &session2UserId); |
| 105087 | |
| 105088 | return (UA_order(p1: &session1UserId, p2: &session2UserId, |
| 105089 | type: &UA_TYPES[UA_TYPES_VARIANT]) == UA_ORDER_EQ); |
| 105090 | } |
| 105091 | #endif |
| 105092 | |
| 105093 | #ifdef UA_ENABLE_HISTORIZING |
| 105094 | static UA_Boolean |
| 105095 | allowHistoryUpdateUpdateData_default(UA_Server *server, UA_AccessControl *ac, |
| 105096 | const UA_NodeId *sessionId, void *sessionContext, |
| 105097 | const UA_NodeId *nodeId, |
| 105098 | UA_PerformUpdateType performInsertReplace, |
| 105099 | const UA_DataValue *value) { |
| 105100 | return true; |
| 105101 | } |
| 105102 | |
| 105103 | static UA_Boolean |
| 105104 | allowHistoryUpdateDeleteRawModified_default(UA_Server *server, UA_AccessControl *ac, |
| 105105 | const UA_NodeId *sessionId, void *sessionContext, |
| 105106 | const UA_NodeId *nodeId, |
| 105107 | UA_DateTime startTimestamp, |
| 105108 | UA_DateTime endTimestamp, |
| 105109 | bool isDeleteModified) { |
| 105110 | return true; |
| 105111 | } |
| 105112 | #endif |
| 105113 | |
| 105114 | /***************************************/ |
| 105115 | /* Create Delete Access Control Plugin */ |
| 105116 | /***************************************/ |
| 105117 | |
| 105118 | static void clear_default(UA_AccessControl *ac) { |
| 105119 | UA_Array_delete(p: (void*)(uintptr_t)ac->userTokenPolicies, |
| 105120 | size: ac->userTokenPoliciesSize, |
| 105121 | type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY]); |
| 105122 | ac->userTokenPolicies = NULL; |
| 105123 | ac->userTokenPoliciesSize = 0; |
| 105124 | |
| 105125 | AccessControlContext *context = (AccessControlContext*)ac->context; |
| 105126 | |
| 105127 | if (context) { |
| 105128 | for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) { |
| 105129 | UA_String_clear(p: &context->usernamePasswordLogin[i].username); |
| 105130 | UA_String_clear(p: &context->usernamePasswordLogin[i].password); |
| 105131 | } |
| 105132 | if(context->usernamePasswordLoginSize > 0) |
| 105133 | UA_free(ptr: context->usernamePasswordLogin); |
| 105134 | |
| 105135 | UA_free(ptr: ac->context); |
| 105136 | ac->context = NULL; |
| 105137 | } |
| 105138 | } |
| 105139 | |
| 105140 | UA_StatusCode |
| 105141 | UA_AccessControl_default(UA_ServerConfig *config, |
| 105142 | UA_Boolean allowAnonymous, |
| 105143 | const UA_ByteString *userTokenPolicyUri, |
| 105144 | size_t usernamePasswordLoginSize, |
| 105145 | const UA_UsernamePasswordLogin *usernamePasswordLogin) { |
| 105146 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 105147 | msg: "AccessControl: Unconfigured AccessControl. Users have all permissions."); |
| 105148 | UA_AccessControl *ac = &config->accessControl; |
| 105149 | |
| 105150 | if(ac->clear) |
| 105151 | ac->clear(ac); |
| 105152 | |
| 105153 | ac->clear = clear_default; |
| 105154 | ac->activateSession = activateSession_default; |
| 105155 | ac->closeSession = closeSession_default; |
| 105156 | ac->getUserRightsMask = getUserRightsMask_default; |
| 105157 | ac->getUserAccessLevel = getUserAccessLevel_default; |
| 105158 | ac->getUserExecutable = getUserExecutable_default; |
| 105159 | ac->getUserExecutableOnObject = getUserExecutableOnObject_default; |
| 105160 | ac->allowAddNode = allowAddNode_default; |
| 105161 | ac->allowAddReference = allowAddReference_default; |
| 105162 | ac->allowBrowseNode = allowBrowseNode_default; |
| 105163 | |
| 105164 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 105165 | ac->allowTransferSubscription = allowTransferSubscription_default; |
| 105166 | #endif |
| 105167 | |
| 105168 | #ifdef UA_ENABLE_HISTORIZING |
| 105169 | ac->allowHistoryUpdateUpdateData = allowHistoryUpdateUpdateData_default; |
| 105170 | ac->allowHistoryUpdateDeleteRawModified = allowHistoryUpdateDeleteRawModified_default; |
| 105171 | #endif |
| 105172 | |
| 105173 | ac->allowDeleteNode = allowDeleteNode_default; |
| 105174 | ac->allowDeleteReference = allowDeleteReference_default; |
| 105175 | |
| 105176 | AccessControlContext *context = (AccessControlContext*) |
| 105177 | UA_malloc(size: sizeof(AccessControlContext)); |
| 105178 | if(!context) |
| 105179 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 105180 | memset(s: context, c: 0, n: sizeof(AccessControlContext)); |
| 105181 | ac->context = context; |
| 105182 | |
| 105183 | /* Allow anonymous? */ |
| 105184 | context->allowAnonymous = allowAnonymous; |
| 105185 | if(allowAnonymous) { |
| 105186 | UA_LOG_INFO(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 105187 | msg: "AccessControl: Anonymous login is enabled"); |
| 105188 | } |
| 105189 | |
| 105190 | /* Copy username/password to the access control plugin */ |
| 105191 | if(usernamePasswordLoginSize > 0) { |
| 105192 | context->usernamePasswordLogin = (UA_UsernamePasswordLogin*) |
| 105193 | UA_malloc(size: usernamePasswordLoginSize * sizeof(UA_UsernamePasswordLogin)); |
| 105194 | if(!context->usernamePasswordLogin) |
| 105195 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 105196 | context->usernamePasswordLoginSize = usernamePasswordLoginSize; |
| 105197 | for(size_t i = 0; i < usernamePasswordLoginSize; i++) { |
| 105198 | UA_String_copy(src: &usernamePasswordLogin[i].username, |
| 105199 | dst: &context->usernamePasswordLogin[i].username); |
| 105200 | UA_String_copy(src: &usernamePasswordLogin[i].password, |
| 105201 | dst: &context->usernamePasswordLogin[i].password); |
| 105202 | } |
| 105203 | } |
| 105204 | |
| 105205 | size_t numOfPolcies = 1; |
| 105206 | if(!userTokenPolicyUri) { |
| 105207 | if(config->securityPoliciesSize > 0) |
| 105208 | numOfPolcies = config->securityPoliciesSize; |
| 105209 | else { |
| 105210 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 105211 | msg: "No security policies defined for the secure channel."); |
| 105212 | return UA_STATUSCODE_BADINTERNALERROR; |
| 105213 | } |
| 105214 | } |
| 105215 | |
| 105216 | /* Set the allowed policies */ |
| 105217 | size_t policies = 0; |
| 105218 | if(allowAnonymous) |
| 105219 | policies++; |
| 105220 | if(usernamePasswordLoginSize > 0) |
| 105221 | policies++; |
| 105222 | if(config->sessionPKI.verifyCertificate) |
| 105223 | policies++; |
| 105224 | ac->userTokenPoliciesSize = 0; |
| 105225 | ac->userTokenPolicies = (UA_UserTokenPolicy *) |
| 105226 | UA_Array_new(size: policies * numOfPolcies, type: &UA_TYPES[UA_TYPES_USERTOKENPOLICY]); |
| 105227 | if(!ac->userTokenPolicies) |
| 105228 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 105229 | ac->userTokenPoliciesSize = policies * numOfPolcies; |
| 105230 | |
| 105231 | if(policies == 0) { |
| 105232 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 105233 | msg: "No allowed policies set."); |
| 105234 | return UA_STATUSCODE_GOOD; |
| 105235 | } |
| 105236 | |
| 105237 | const UA_ByteString *utpUri = NULL; |
| 105238 | policies = 0; |
| 105239 | for(size_t i = 0; i < numOfPolcies; i++) { |
| 105240 | if(userTokenPolicyUri) { |
| 105241 | utpUri = userTokenPolicyUri; |
| 105242 | } else { |
| 105243 | utpUri = &config->securityPolicies[i].policyUri; |
| 105244 | } |
| 105245 | if(allowAnonymous) { |
| 105246 | ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS; |
| 105247 | ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY); |
| 105248 | UA_ByteString_copy(src: utpUri, |
| 105249 | dst: &ac->userTokenPolicies[policies].securityPolicyUri); |
| 105250 | policies++; |
| 105251 | } |
| 105252 | |
| 105253 | if(config->sessionPKI.verifyCertificate) { |
| 105254 | ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_CERTIFICATE; |
| 105255 | ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(CERTIFICATE_POLICY); |
| 105256 | #if UA_LOGLEVEL <= 400 |
| 105257 | if(UA_ByteString_equal(p1: utpUri, p2: &UA_SECURITY_POLICY_NONE_URI)) { |
| 105258 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 105259 | msg: "x509 Certificate Authentication configured, " |
| 105260 | "but no encrypting SecurityPolicy. " |
| 105261 | "This can leak credentials on the network."); |
| 105262 | } |
| 105263 | #endif |
| 105264 | UA_ByteString_copy(src: utpUri, |
| 105265 | dst: &ac->userTokenPolicies[policies].securityPolicyUri); |
| 105266 | policies++; |
| 105267 | } |
| 105268 | |
| 105269 | if(usernamePasswordLoginSize > 0) { |
| 105270 | ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME; |
| 105271 | ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY); |
| 105272 | #if UA_LOGLEVEL <= 400 |
| 105273 | if(UA_ByteString_equal(p1: utpUri, p2: &UA_SECURITY_POLICY_NONE_URI)) { |
| 105274 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SERVER, |
| 105275 | msg: "Username/Password Authentication configured, " |
| 105276 | "but no encrypting SecurityPolicy. " |
| 105277 | "This can leak credentials on the network."); |
| 105278 | } |
| 105279 | #endif |
| 105280 | UA_ByteString_copy(src: utpUri, |
| 105281 | dst: &ac->userTokenPolicies[policies].securityPolicyUri); |
| 105282 | policies++; |
| 105283 | } |
| 105284 | } |
| 105285 | return UA_STATUSCODE_GOOD; |
| 105286 | } |
| 105287 | |
| 105288 | UA_StatusCode |
| 105289 | UA_AccessControl_defaultWithLoginCallback(UA_ServerConfig *config, |
| 105290 | UA_Boolean allowAnonymous, |
| 105291 | const UA_ByteString *userTokenPolicyUri, |
| 105292 | size_t usernamePasswordLoginSize, |
| 105293 | const UA_UsernamePasswordLogin *usernamePasswordLogin, |
| 105294 | UA_UsernamePasswordLoginCallback loginCallback, |
| 105295 | void *loginContext) { |
| 105296 | AccessControlContext *context; |
| 105297 | UA_StatusCode sc = |
| 105298 | UA_AccessControl_default(config, allowAnonymous, userTokenPolicyUri, |
| 105299 | usernamePasswordLoginSize, usernamePasswordLogin); |
| 105300 | if(sc != UA_STATUSCODE_GOOD) |
| 105301 | return sc; |
| 105302 | |
| 105303 | context = (AccessControlContext *)config->accessControl.context; |
| 105304 | context->loginCallback = loginCallback; |
| 105305 | context->loginContext = loginContext; |
| 105306 | |
| 105307 | return UA_STATUSCODE_GOOD; |
| 105308 | } |
| 105309 | |
| 105310 | |
| 105311 | /**** amalgamated original file "/plugins/ua_nodestore_ziptree.c" ****/ |
| 105312 | |
| 105313 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 105314 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 105315 | * |
| 105316 | * Copyright 2014-2018 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 105317 | * Copyright 2017 (c) Julian Grothoff |
| 105318 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 105319 | */ |
| 105320 | |
| 105321 | |
| 105322 | #ifndef container_of |
| 105323 | #define container_of(ptr, type, member) \ |
| 105324 | (type *)((uintptr_t)ptr - offsetof(type,member)) |
| 105325 | #endif |
| 105326 | |
| 105327 | struct NodeEntry; |
| 105328 | typedef struct NodeEntry NodeEntry; |
| 105329 | |
| 105330 | struct NodeEntry { |
| 105331 | ZIP_ENTRY(NodeEntry) zipfields; |
| 105332 | UA_UInt32 nodeIdHash; |
| 105333 | UA_UInt16 refCount; /* How many consumers have a reference to the node? */ |
| 105334 | UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */ |
| 105335 | NodeEntry *orig; /* If a copy is made to replace a node, track that we |
| 105336 | * replace only the node from which the copy was made. |
| 105337 | * Important for concurrent operations. */ |
| 105338 | UA_NodeId nodeId; /* This is actually a UA_Node that also starts with a NodeId */ |
| 105339 | }; |
| 105340 | |
| 105341 | /* Absolute ordering for NodeIds */ |
| 105342 | static enum ZIP_CMP |
| 105343 | cmpNodeId(const void *a, const void *b) { |
| 105344 | const NodeEntry *aa = (const NodeEntry*)a; |
| 105345 | const NodeEntry *bb = (const NodeEntry*)b; |
| 105346 | |
| 105347 | /* Compare hash */ |
| 105348 | if(aa->nodeIdHash < bb->nodeIdHash) |
| 105349 | return ZIP_CMP_LESS; |
| 105350 | if(aa->nodeIdHash > bb->nodeIdHash) |
| 105351 | return ZIP_CMP_MORE; |
| 105352 | |
| 105353 | /* Compore nodes in detail */ |
| 105354 | return (enum ZIP_CMP)UA_NodeId_order(n1: &aa->nodeId, n2: &bb->nodeId); |
| 105355 | } |
| 105356 | |
| 105357 | ZIP_HEAD(NodeTree, NodeEntry); |
| 105358 | typedef struct NodeTree NodeTree; |
| 105359 | |
| 105360 | typedef struct { |
| 105361 | NodeTree root; |
| 105362 | |
| 105363 | /* Maps ReferenceTypeIndex to the NodeId of the ReferenceType */ |
| 105364 | UA_NodeId referenceTypeIds[UA_REFERENCETYPESET_MAX]; |
| 105365 | UA_Byte referenceTypeCounter; |
| 105366 | } ZipContext; |
| 105367 | |
| 105368 | ZIP_FUNCTIONS(NodeTree, NodeEntry, zipfields, NodeEntry, zipfields, cmpNodeId) |
| 105369 | |
| 105370 | static NodeEntry * |
| 105371 | newEntry(UA_NodeClass nodeClass) { |
| 105372 | size_t size = sizeof(NodeEntry) - sizeof(UA_NodeId); |
| 105373 | switch(nodeClass) { |
| 105374 | case UA_NODECLASS_OBJECT: |
| 105375 | size += sizeof(UA_ObjectNode); |
| 105376 | break; |
| 105377 | case UA_NODECLASS_VARIABLE: |
| 105378 | size += sizeof(UA_VariableNode); |
| 105379 | break; |
| 105380 | case UA_NODECLASS_METHOD: |
| 105381 | size += sizeof(UA_MethodNode); |
| 105382 | break; |
| 105383 | case UA_NODECLASS_OBJECTTYPE: |
| 105384 | size += sizeof(UA_ObjectTypeNode); |
| 105385 | break; |
| 105386 | case UA_NODECLASS_VARIABLETYPE: |
| 105387 | size += sizeof(UA_VariableTypeNode); |
| 105388 | break; |
| 105389 | case UA_NODECLASS_REFERENCETYPE: |
| 105390 | size += sizeof(UA_ReferenceTypeNode); |
| 105391 | break; |
| 105392 | case UA_NODECLASS_DATATYPE: |
| 105393 | size += sizeof(UA_DataTypeNode); |
| 105394 | break; |
| 105395 | case UA_NODECLASS_VIEW: |
| 105396 | size += sizeof(UA_ViewNode); |
| 105397 | break; |
| 105398 | default: |
| 105399 | return NULL; |
| 105400 | } |
| 105401 | NodeEntry *entry = (NodeEntry*)UA_calloc(nmemb: 1, size: size); |
| 105402 | if(!entry) |
| 105403 | return NULL; |
| 105404 | UA_Node *node = (UA_Node*)&entry->nodeId; |
| 105405 | node->head.nodeClass = nodeClass; |
| 105406 | return entry; |
| 105407 | } |
| 105408 | |
| 105409 | static void |
| 105410 | deleteEntry(NodeEntry *entry) { |
| 105411 | UA_Node_clear(node: (UA_Node*)&entry->nodeId); |
| 105412 | UA_free(ptr: entry); |
| 105413 | } |
| 105414 | |
| 105415 | static void |
| 105416 | cleanupEntry(NodeEntry *entry) { |
| 105417 | if(entry->refCount > 0) |
| 105418 | return; |
| 105419 | if(entry->deleted) { |
| 105420 | deleteEntry(entry); |
| 105421 | return; |
| 105422 | } |
| 105423 | UA_NodeHead *head = (UA_NodeHead*)&entry->nodeId; |
| 105424 | for(size_t i = 0; i < head->referencesSize; i++) { |
| 105425 | UA_NodeReferenceKind *rk = &head->references[i]; |
| 105426 | if(rk->targetsSize > 16 && !rk->hasRefTree) |
| 105427 | UA_NodeReferenceKind_switch(rk); |
| 105428 | } |
| 105429 | } |
| 105430 | |
| 105431 | /***********************/ |
| 105432 | /* Interface functions */ |
| 105433 | /***********************/ |
| 105434 | |
| 105435 | /* Not yet inserted into the ZipContext */ |
| 105436 | static UA_Node * |
| 105437 | zipNsNewNode(void *nsCtx, UA_NodeClass nodeClass) { |
| 105438 | NodeEntry *entry = newEntry(nodeClass); |
| 105439 | if(!entry) |
| 105440 | return NULL; |
| 105441 | return (UA_Node*)&entry->nodeId; |
| 105442 | } |
| 105443 | |
| 105444 | /* Not yet inserted into the ZipContext */ |
| 105445 | static void |
| 105446 | zipNsDeleteNode(void *nsCtx, UA_Node *node) { |
| 105447 | deleteEntry(container_of(node, NodeEntry, nodeId)); |
| 105448 | } |
| 105449 | |
| 105450 | static const UA_Node * |
| 105451 | zipNsGetNode(void *nsCtx, const UA_NodeId *nodeId, |
| 105452 | UA_UInt32 attributeMask, |
| 105453 | UA_ReferenceTypeSet references, |
| 105454 | UA_BrowseDirection referenceDirections) { |
| 105455 | ZipContext *ns = (ZipContext*)nsCtx; |
| 105456 | NodeEntry dummy; |
| 105457 | dummy.nodeIdHash = UA_NodeId_hash(n: nodeId); |
| 105458 | dummy.nodeId = *nodeId; |
| 105459 | NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy); |
| 105460 | if(!entry) |
| 105461 | return NULL; |
| 105462 | ++entry->refCount; |
| 105463 | return (const UA_Node*)&entry->nodeId; |
| 105464 | } |
| 105465 | |
| 105466 | static const UA_Node * |
| 105467 | zipNsGetNodeFromPtr(void *nsCtx, UA_NodePointer ptr, |
| 105468 | UA_UInt32 attributeMask, |
| 105469 | UA_ReferenceTypeSet references, |
| 105470 | UA_BrowseDirection referenceDirections) { |
| 105471 | if(!UA_NodePointer_isLocal(np: ptr)) |
| 105472 | return NULL; |
| 105473 | UA_NodeId id = UA_NodePointer_toNodeId(np: ptr); |
| 105474 | return zipNsGetNode(nsCtx, nodeId: &id, attributeMask, |
| 105475 | references, referenceDirections); |
| 105476 | } |
| 105477 | |
| 105478 | static void |
| 105479 | zipNsReleaseNode(void *nsCtx, const UA_Node *node) { |
| 105480 | if(!node) |
| 105481 | return; |
| 105482 | NodeEntry *entry = container_of(node, NodeEntry, nodeId); |
| 105483 | UA_assert(entry->refCount > 0); |
| 105484 | --entry->refCount; |
| 105485 | cleanupEntry(entry); |
| 105486 | } |
| 105487 | |
| 105488 | static UA_StatusCode |
| 105489 | zipNsGetNodeCopy(void *nsCtx, const UA_NodeId *nodeId, |
| 105490 | UA_Node **outNode) { |
| 105491 | /* Get the node (with all attributes and references, the mask and refs are |
| 105492 | currently noy evaluated within the plugin.) */ |
| 105493 | const UA_Node *node = |
| 105494 | zipNsGetNode(nsCtx, nodeId, attributeMask: UA_NODEATTRIBUTESMASK_ALL, |
| 105495 | references: UA_REFERENCETYPESET_ALL, referenceDirections: UA_BROWSEDIRECTION_BOTH); |
| 105496 | if(!node) |
| 105497 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 105498 | |
| 105499 | /* Create the new entry */ |
| 105500 | NodeEntry *ne = newEntry(nodeClass: node->head.nodeClass); |
| 105501 | if(!ne) { |
| 105502 | zipNsReleaseNode(nsCtx, node); |
| 105503 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 105504 | } |
| 105505 | |
| 105506 | /* Copy the node content */ |
| 105507 | UA_Node *nnode = (UA_Node*)&ne->nodeId; |
| 105508 | UA_StatusCode retval = UA_Node_copy(src: node, dst: nnode); |
| 105509 | zipNsReleaseNode(nsCtx, node); |
| 105510 | if(retval != UA_STATUSCODE_GOOD) { |
| 105511 | deleteEntry(entry: ne); |
| 105512 | return retval; |
| 105513 | } |
| 105514 | |
| 105515 | ne->orig = container_of(node, NodeEntry, nodeId); |
| 105516 | *outNode = nnode; |
| 105517 | return UA_STATUSCODE_GOOD; |
| 105518 | } |
| 105519 | |
| 105520 | static UA_StatusCode |
| 105521 | zipNsInsertNode(void *nsCtx, UA_Node *node, UA_NodeId *addedNodeId) { |
| 105522 | NodeEntry *entry = container_of(node, NodeEntry, nodeId); |
| 105523 | ZipContext *ns = (ZipContext*)nsCtx; |
| 105524 | |
| 105525 | /* Ensure that the NodeId is unique */ |
| 105526 | NodeEntry dummy; |
| 105527 | memset(s: &dummy, c: 0, n: sizeof(NodeEntry)); |
| 105528 | dummy.nodeId = node->head.nodeId; |
| 105529 | if(node->head.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC && |
| 105530 | node->head.nodeId.identifier.numeric == 0) { |
| 105531 | do { /* Create a random nodeid until we find an unoccupied id */ |
| 105532 | UA_UInt32 numId = UA_UInt32_random(); |
| 105533 | #if SIZE_MAX <= UA_UINT32_MAX |
| 105534 | /* The compressed "immediate" representation of nodes does not |
| 105535 | * support the full range on 32bit systems. Generate smaller |
| 105536 | * identifiers as they can be stored more compactly. */ |
| 105537 | if(numId >= (0x01 << 24)) |
| 105538 | numId = numId % (0x01 << 24); |
| 105539 | #endif |
| 105540 | node->head.nodeId.identifier.numeric = numId; |
| 105541 | dummy.nodeId.identifier.numeric = numId; |
| 105542 | dummy.nodeIdHash = UA_NodeId_hash(n: &node->head.nodeId); |
| 105543 | } while(ZIP_FIND(NodeTree, &ns->root, &dummy)); |
| 105544 | } else { |
| 105545 | dummy.nodeIdHash = UA_NodeId_hash(n: &node->head.nodeId); |
| 105546 | if(ZIP_FIND(NodeTree, &ns->root, &dummy)) { /* The nodeid exists */ |
| 105547 | deleteEntry(entry); |
| 105548 | return UA_STATUSCODE_BADNODEIDEXISTS; |
| 105549 | } |
| 105550 | } |
| 105551 | |
| 105552 | /* Copy the NodeId */ |
| 105553 | if(addedNodeId) { |
| 105554 | UA_StatusCode retval = UA_NodeId_copy(src: &node->head.nodeId, dst: addedNodeId); |
| 105555 | if(retval != UA_STATUSCODE_GOOD) { |
| 105556 | deleteEntry(entry); |
| 105557 | return retval; |
| 105558 | } |
| 105559 | } |
| 105560 | |
| 105561 | /* For new ReferencetypeNodes add to the index map */ |
| 105562 | if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) { |
| 105563 | UA_ReferenceTypeNode *refNode = &node->referenceTypeNode; |
| 105564 | if(ns->referenceTypeCounter >= UA_REFERENCETYPESET_MAX) { |
| 105565 | deleteEntry(entry); |
| 105566 | return UA_STATUSCODE_BADINTERNALERROR; |
| 105567 | } |
| 105568 | |
| 105569 | UA_StatusCode retval = |
| 105570 | UA_NodeId_copy(src: &node->head.nodeId, dst: &ns->referenceTypeIds[ns->referenceTypeCounter]); |
| 105571 | if(retval != UA_STATUSCODE_GOOD) { |
| 105572 | deleteEntry(entry); |
| 105573 | return UA_STATUSCODE_BADINTERNALERROR; |
| 105574 | } |
| 105575 | |
| 105576 | /* Assign the ReferenceTypeIndex to the new ReferenceTypeNode */ |
| 105577 | refNode->referenceTypeIndex = ns->referenceTypeCounter; |
| 105578 | refNode->subTypes = UA_REFTYPESET(index: ns->referenceTypeCounter); |
| 105579 | |
| 105580 | ns->referenceTypeCounter++; |
| 105581 | } |
| 105582 | |
| 105583 | /* Insert the node */ |
| 105584 | entry->nodeIdHash = dummy.nodeIdHash; |
| 105585 | ZIP_INSERT(NodeTree, &ns->root, entry); |
| 105586 | return UA_STATUSCODE_GOOD; |
| 105587 | } |
| 105588 | |
| 105589 | static UA_StatusCode |
| 105590 | zipNsReplaceNode(void *nsCtx, UA_Node *node) { |
| 105591 | /* Find the node (the mask and refs are not evaluated yet by the plugin)*/ |
| 105592 | const UA_Node *oldNode = |
| 105593 | zipNsGetNode(nsCtx, nodeId: &node->head.nodeId, attributeMask: UA_NODEATTRIBUTESMASK_ALL, |
| 105594 | references: UA_REFERENCETYPESET_ALL, referenceDirections: UA_BROWSEDIRECTION_BOTH); |
| 105595 | if(!oldNode) { |
| 105596 | deleteEntry(container_of(node, NodeEntry, nodeId)); |
| 105597 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 105598 | } |
| 105599 | |
| 105600 | /* Test if the copy is current */ |
| 105601 | NodeEntry *entry = container_of(node, NodeEntry, nodeId); |
| 105602 | NodeEntry *oldEntry = container_of(oldNode, NodeEntry, nodeId); |
| 105603 | if(oldEntry != entry->orig) { |
| 105604 | /* The node was already updated since the copy was made */ |
| 105605 | deleteEntry(entry); |
| 105606 | zipNsReleaseNode(nsCtx, node: oldNode); |
| 105607 | return UA_STATUSCODE_BADINTERNALERROR; |
| 105608 | } |
| 105609 | |
| 105610 | /* Replace */ |
| 105611 | ZipContext *ns = (ZipContext*)nsCtx; |
| 105612 | ZIP_REMOVE(NodeTree, &ns->root, oldEntry); |
| 105613 | entry->nodeIdHash = oldEntry->nodeIdHash; |
| 105614 | ZIP_INSERT(NodeTree, &ns->root, entry); |
| 105615 | oldEntry->deleted = true; |
| 105616 | |
| 105617 | zipNsReleaseNode(nsCtx, node: oldNode); |
| 105618 | return UA_STATUSCODE_GOOD; |
| 105619 | } |
| 105620 | |
| 105621 | static UA_StatusCode |
| 105622 | zipNsRemoveNode(void *nsCtx, const UA_NodeId *nodeId) { |
| 105623 | ZipContext *ns = (ZipContext*)nsCtx; |
| 105624 | NodeEntry dummy; |
| 105625 | dummy.nodeIdHash = UA_NodeId_hash(n: nodeId); |
| 105626 | dummy.nodeId = *nodeId; |
| 105627 | NodeEntry *entry = ZIP_FIND(NodeTree, &ns->root, &dummy); |
| 105628 | if(!entry) |
| 105629 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 105630 | ZIP_REMOVE(NodeTree, &ns->root, entry); |
| 105631 | entry->deleted = true; |
| 105632 | cleanupEntry(entry); |
| 105633 | return UA_STATUSCODE_GOOD; |
| 105634 | } |
| 105635 | |
| 105636 | static const UA_NodeId * |
| 105637 | zipNsGetReferenceTypeId(void *nsCtx, UA_Byte refTypeIndex) { |
| 105638 | ZipContext *ns = (ZipContext*)nsCtx; |
| 105639 | if(refTypeIndex >= ns->referenceTypeCounter) |
| 105640 | return NULL; |
| 105641 | return &ns->referenceTypeIds[refTypeIndex]; |
| 105642 | } |
| 105643 | |
| 105644 | struct VisitorData { |
| 105645 | UA_NodestoreVisitor visitor; |
| 105646 | void *visitorContext; |
| 105647 | }; |
| 105648 | |
| 105649 | static void * |
| 105650 | nodeVisitor(void *data, NodeEntry *entry) { |
| 105651 | struct VisitorData *d = (struct VisitorData*)data; |
| 105652 | d->visitor(d->visitorContext, (UA_Node*)&entry->nodeId); |
| 105653 | return NULL; |
| 105654 | } |
| 105655 | |
| 105656 | static void |
| 105657 | zipNsIterate(void *nsCtx, UA_NodestoreVisitor visitor, |
| 105658 | void *visitorCtx) { |
| 105659 | struct VisitorData d; |
| 105660 | d.visitor = visitor; |
| 105661 | d.visitorContext = visitorCtx; |
| 105662 | ZipContext *ns = (ZipContext*)nsCtx; |
| 105663 | ZIP_ITER(NodeTree, &ns->root, nodeVisitor, &d); |
| 105664 | } |
| 105665 | |
| 105666 | static void * |
| 105667 | deleteNodeVisitor(void *data, NodeEntry *entry) { |
| 105668 | deleteEntry(entry); |
| 105669 | return NULL; |
| 105670 | } |
| 105671 | |
| 105672 | /***********************/ |
| 105673 | /* Nodestore Lifecycle */ |
| 105674 | /***********************/ |
| 105675 | |
| 105676 | static void |
| 105677 | zipNsClear(void *nsCtx) { |
| 105678 | if (!nsCtx) |
| 105679 | return; |
| 105680 | ZipContext *ns = (ZipContext*)nsCtx; |
| 105681 | ZIP_ITER(NodeTree, &ns->root, deleteNodeVisitor, NULL); |
| 105682 | |
| 105683 | /* Clean up the ReferenceTypes index array */ |
| 105684 | for(size_t i = 0; i < ns->referenceTypeCounter; i++) |
| 105685 | UA_NodeId_clear(p: &ns->referenceTypeIds[i]); |
| 105686 | |
| 105687 | UA_free(ptr: ns); |
| 105688 | } |
| 105689 | |
| 105690 | UA_StatusCode |
| 105691 | UA_Nodestore_ZipTree(UA_Nodestore *ns) { |
| 105692 | /* Allocate and initialize the context */ |
| 105693 | ZipContext *ctx = (ZipContext*)UA_malloc(size: sizeof(ZipContext)); |
| 105694 | if(!ctx) |
| 105695 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 105696 | |
| 105697 | ZIP_INIT(&ctx->root); |
| 105698 | ctx->referenceTypeCounter = 0; |
| 105699 | |
| 105700 | /* Populate the nodestore */ |
| 105701 | ns->context = (void*)ctx; |
| 105702 | ns->clear = zipNsClear; |
| 105703 | ns->newNode = zipNsNewNode; |
| 105704 | ns->deleteNode = zipNsDeleteNode; |
| 105705 | ns->getNode = zipNsGetNode; |
| 105706 | ns->getNodeFromPtr = zipNsGetNodeFromPtr; |
| 105707 | ns->releaseNode = zipNsReleaseNode; |
| 105708 | ns->getNodeCopy = zipNsGetNodeCopy; |
| 105709 | ns->insertNode = zipNsInsertNode; |
| 105710 | ns->replaceNode = zipNsReplaceNode; |
| 105711 | ns->removeNode = zipNsRemoveNode; |
| 105712 | ns->getReferenceTypeId = zipNsGetReferenceTypeId; |
| 105713 | ns->iterate = zipNsIterate; |
| 105714 | |
| 105715 | return UA_STATUSCODE_GOOD; |
| 105716 | } |
| 105717 | |
| 105718 | /**** amalgamated original file "/plugins/ua_nodestore_hashmap.c" ****/ |
| 105719 | |
| 105720 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 105721 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 105722 | * |
| 105723 | * Copyright 2014-2019 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 105724 | * Copyright 2017 (c) Julian Grothoff |
| 105725 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 105726 | */ |
| 105727 | |
| 105728 | |
| 105729 | #ifndef container_of |
| 105730 | #define container_of(ptr, type, member) \ |
| 105731 | (type *)((uintptr_t)ptr - offsetof(type,member)) |
| 105732 | #endif |
| 105733 | |
| 105734 | /* The default Nodestore is simply a hash-map from NodeIds to Nodes. To find an |
| 105735 | * entry, iterate over candidate positions according to the NodeId hash. |
| 105736 | * |
| 105737 | * - Tombstone or non-matching NodeId: continue searching |
| 105738 | * - Matching NodeId: Return the entry |
| 105739 | * - NULL: Abort the search */ |
| 105740 | |
| 105741 | typedef struct UA_NodeMapEntry { |
| 105742 | struct UA_NodeMapEntry *orig; /* the version this is a copy from (or NULL) */ |
| 105743 | UA_UInt16 refCount; /* How many consumers have a reference to the node? */ |
| 105744 | UA_Boolean deleted; /* Node was marked as deleted and can be deleted when refCount == 0 */ |
| 105745 | UA_Node node; |
| 105746 | } UA_NodeMapEntry; |
| 105747 | |
| 105748 | #define UA_NODEMAP_MINSIZE 64 |
| 105749 | #define UA_NODEMAP_TOMBSTONE ((UA_NodeMapEntry*)0x01) |
| 105750 | |
| 105751 | typedef struct { |
| 105752 | UA_NodeMapEntry *entry; |
| 105753 | UA_UInt32 nodeIdHash; |
| 105754 | } UA_NodeMapSlot; |
| 105755 | |
| 105756 | typedef struct { |
| 105757 | UA_NodeMapSlot *slots; |
| 105758 | UA_UInt32 size; |
| 105759 | UA_UInt32 count; |
| 105760 | UA_UInt32 sizePrimeIndex; |
| 105761 | |
| 105762 | /* Maps ReferenceTypeIndex to the NodeId of the ReferenceType */ |
| 105763 | UA_NodeId referenceTypeIds[UA_REFERENCETYPESET_MAX]; |
| 105764 | UA_Byte referenceTypeCounter; |
| 105765 | } UA_NodeMap; |
| 105766 | |
| 105767 | /*********************/ |
| 105768 | /* HashMap Utilities */ |
| 105769 | /*********************/ |
| 105770 | |
| 105771 | /* The size of the hash-map is always a prime number. They are chosen to be |
| 105772 | * close to the next power of 2. So the size ca. doubles with each prime. */ |
| 105773 | static UA_UInt32 const primes[] = { |
| 105774 | 7, 13, 31, 61, 127, 251, |
| 105775 | 509, 1021, 2039, 4093, 8191, 16381, |
| 105776 | 32749, 65521, 131071, 262139, 524287, 1048573, |
| 105777 | 2097143, 4194301, 8388593, 16777213, 33554393, 67108859, |
| 105778 | 134217689, 268435399, 536870909, 1073741789, 2147483647, 4294967291 |
| 105779 | }; |
| 105780 | |
| 105781 | static UA_UInt32 mod(UA_UInt32 h, UA_UInt32 size) { return h % size; } |
| 105782 | static UA_UInt32 mod2(UA_UInt32 h, UA_UInt32 size) { return 1 + (h % (size - 2)); } |
| 105783 | |
| 105784 | static UA_UInt16 |
| 105785 | higher_prime_index(UA_UInt32 n) { |
| 105786 | UA_UInt16 low = 0; |
| 105787 | UA_UInt16 high = (UA_UInt16)(sizeof(primes) / sizeof(UA_UInt32)); |
| 105788 | while(low != high) { |
| 105789 | UA_UInt16 mid = (UA_UInt16)(low + ((high - low) / 2)); |
| 105790 | if(n > primes[mid]) |
| 105791 | low = (UA_UInt16)(mid + 1); |
| 105792 | else |
| 105793 | high = mid; |
| 105794 | } |
| 105795 | return low; |
| 105796 | } |
| 105797 | |
| 105798 | /* Returns an empty slot or null if the nodeid exists or if no empty slot is found. */ |
| 105799 | static UA_NodeMapSlot * |
| 105800 | findFreeSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) { |
| 105801 | UA_UInt32 h = UA_NodeId_hash(n: nodeid); |
| 105802 | UA_UInt32 size = ns->size; |
| 105803 | UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */ |
| 105804 | UA_UInt32 startIdx = (UA_UInt32)idx; |
| 105805 | UA_UInt32 hash2 = mod2(h, size); |
| 105806 | |
| 105807 | UA_NodeMapSlot *candidate = NULL; |
| 105808 | do { |
| 105809 | UA_NodeMapSlot *slot = &ns->slots[(UA_UInt32)idx]; |
| 105810 | |
| 105811 | if(slot->entry > UA_NODEMAP_TOMBSTONE) { |
| 105812 | /* A Node with the NodeId does already exist */ |
| 105813 | if(slot->nodeIdHash == h && |
| 105814 | UA_NodeId_equal(p1: &slot->entry->node.head.nodeId, p2: nodeid)) |
| 105815 | return NULL; |
| 105816 | } else { |
| 105817 | /* Found a candidate node */ |
| 105818 | if(!candidate) |
| 105819 | candidate = slot; |
| 105820 | /* No matching node can come afterwards */ |
| 105821 | if(slot->entry == NULL) |
| 105822 | return candidate; |
| 105823 | } |
| 105824 | |
| 105825 | idx += hash2; |
| 105826 | if(idx >= size) |
| 105827 | idx -= size; |
| 105828 | } while((UA_UInt32)idx != startIdx); |
| 105829 | |
| 105830 | return candidate; |
| 105831 | } |
| 105832 | |
| 105833 | /* The occupancy of the table after the call will be about 50% */ |
| 105834 | static UA_StatusCode |
| 105835 | expand(UA_NodeMap *ns) { |
| 105836 | UA_UInt32 osize = ns->size; |
| 105837 | UA_UInt32 count = ns->count; |
| 105838 | /* Resize only when table after removal of unused elements is either too |
| 105839 | full or too empty */ |
| 105840 | if(count * 2 < osize && (count * 8 > osize || osize <= UA_NODEMAP_MINSIZE)) |
| 105841 | return UA_STATUSCODE_GOOD; |
| 105842 | |
| 105843 | UA_NodeMapSlot *oslots = ns->slots; |
| 105844 | UA_UInt32 nindex = higher_prime_index(n: count * 2); |
| 105845 | UA_UInt32 nsize = primes[nindex]; |
| 105846 | UA_NodeMapSlot *nslots= (UA_NodeMapSlot*)UA_calloc(nmemb: nsize, size: sizeof(UA_NodeMapSlot)); |
| 105847 | if(!nslots) |
| 105848 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 105849 | |
| 105850 | ns->slots = nslots; |
| 105851 | ns->size = nsize; |
| 105852 | ns->sizePrimeIndex = nindex; |
| 105853 | |
| 105854 | /* recompute the position of every entry and insert the pointer */ |
| 105855 | for(size_t i = 0, j = 0; i < osize && j < count; ++i) { |
| 105856 | if(oslots[i].entry <= UA_NODEMAP_TOMBSTONE) |
| 105857 | continue; |
| 105858 | UA_NodeMapSlot *s = findFreeSlot(ns, nodeid: &oslots[i].entry->node.head.nodeId); |
| 105859 | UA_assert(s); |
| 105860 | *s = oslots[i]; |
| 105861 | ++j; |
| 105862 | } |
| 105863 | |
| 105864 | UA_free(ptr: oslots); |
| 105865 | return UA_STATUSCODE_GOOD; |
| 105866 | } |
| 105867 | |
| 105868 | static UA_NodeMapEntry * |
| 105869 | createEntry(UA_NodeClass nodeClass) { |
| 105870 | size_t size = sizeof(UA_NodeMapEntry) - sizeof(UA_Node); |
| 105871 | switch(nodeClass) { |
| 105872 | case UA_NODECLASS_OBJECT: |
| 105873 | size += sizeof(UA_ObjectNode); |
| 105874 | break; |
| 105875 | case UA_NODECLASS_VARIABLE: |
| 105876 | size += sizeof(UA_VariableNode); |
| 105877 | break; |
| 105878 | case UA_NODECLASS_METHOD: |
| 105879 | size += sizeof(UA_MethodNode); |
| 105880 | break; |
| 105881 | case UA_NODECLASS_OBJECTTYPE: |
| 105882 | size += sizeof(UA_ObjectTypeNode); |
| 105883 | break; |
| 105884 | case UA_NODECLASS_VARIABLETYPE: |
| 105885 | size += sizeof(UA_VariableTypeNode); |
| 105886 | break; |
| 105887 | case UA_NODECLASS_REFERENCETYPE: |
| 105888 | size += sizeof(UA_ReferenceTypeNode); |
| 105889 | break; |
| 105890 | case UA_NODECLASS_DATATYPE: |
| 105891 | size += sizeof(UA_DataTypeNode); |
| 105892 | break; |
| 105893 | case UA_NODECLASS_VIEW: |
| 105894 | size += sizeof(UA_ViewNode); |
| 105895 | break; |
| 105896 | default: |
| 105897 | return NULL; |
| 105898 | } |
| 105899 | UA_NodeMapEntry *entry = (UA_NodeMapEntry*)UA_calloc(nmemb: 1, size: size); |
| 105900 | if(!entry) |
| 105901 | return NULL; |
| 105902 | entry->node.head.nodeClass = nodeClass; |
| 105903 | return entry; |
| 105904 | } |
| 105905 | |
| 105906 | static void |
| 105907 | deleteNodeMapEntry(UA_NodeMapEntry *entry) { |
| 105908 | UA_Node_clear(node: &entry->node); |
| 105909 | UA_free(ptr: entry); |
| 105910 | } |
| 105911 | |
| 105912 | static void |
| 105913 | cleanupNodeMapEntry(UA_NodeMapEntry *entry) { |
| 105914 | if(entry->refCount > 0) |
| 105915 | return; |
| 105916 | if(entry->deleted) { |
| 105917 | deleteNodeMapEntry(entry); |
| 105918 | return; |
| 105919 | } |
| 105920 | for(size_t i = 0; i < entry->node.head.referencesSize; i++) { |
| 105921 | UA_NodeReferenceKind *rk = &entry->node.head.references[i]; |
| 105922 | if(rk->targetsSize > 16 && !rk->hasRefTree) |
| 105923 | UA_NodeReferenceKind_switch(rk); |
| 105924 | } |
| 105925 | } |
| 105926 | |
| 105927 | static UA_NodeMapSlot * |
| 105928 | findOccupiedSlot(const UA_NodeMap *ns, const UA_NodeId *nodeid) { |
| 105929 | UA_UInt32 h = UA_NodeId_hash(n: nodeid); |
| 105930 | UA_UInt32 size = ns->size; |
| 105931 | UA_UInt64 idx = mod(h, size); /* Use 64bit container to avoid overflow */ |
| 105932 | UA_UInt32 hash2 = mod2(h, size); |
| 105933 | UA_UInt32 startIdx = (UA_UInt32)idx; |
| 105934 | |
| 105935 | do { |
| 105936 | UA_NodeMapSlot *slot= &ns->slots[(UA_UInt32)idx]; |
| 105937 | if(slot->entry > UA_NODEMAP_TOMBSTONE) { |
| 105938 | if(slot->nodeIdHash == h && |
| 105939 | UA_NodeId_equal(p1: &slot->entry->node.head.nodeId, p2: nodeid)) |
| 105940 | return slot; |
| 105941 | } else { |
| 105942 | if(slot->entry == NULL) |
| 105943 | return NULL; /* No further entry possible */ |
| 105944 | } |
| 105945 | |
| 105946 | idx += hash2; |
| 105947 | if(idx >= size) |
| 105948 | idx -= size; |
| 105949 | } while((UA_UInt32)idx != startIdx); |
| 105950 | |
| 105951 | return NULL; |
| 105952 | } |
| 105953 | |
| 105954 | /***********************/ |
| 105955 | /* Interface functions */ |
| 105956 | /***********************/ |
| 105957 | |
| 105958 | static UA_Node * |
| 105959 | UA_NodeMap_newNode(void *context, UA_NodeClass nodeClass) { |
| 105960 | UA_NodeMapEntry *entry = createEntry(nodeClass); |
| 105961 | if(!entry) |
| 105962 | return NULL; |
| 105963 | return &entry->node; |
| 105964 | } |
| 105965 | |
| 105966 | static void |
| 105967 | UA_NodeMap_deleteNode(void *context, UA_Node *node) { |
| 105968 | UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node); |
| 105969 | UA_assert(&entry->node == node); |
| 105970 | deleteNodeMapEntry(entry); |
| 105971 | } |
| 105972 | |
| 105973 | static const UA_Node * |
| 105974 | UA_NodeMap_getNode(void *context, const UA_NodeId *nodeid, |
| 105975 | UA_UInt32 attributeMask, |
| 105976 | UA_ReferenceTypeSet references, |
| 105977 | UA_BrowseDirection referenceDirections) { |
| 105978 | UA_NodeMap *ns = (UA_NodeMap*)context; |
| 105979 | UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid); |
| 105980 | if(!slot) |
| 105981 | return NULL; |
| 105982 | ++slot->entry->refCount; |
| 105983 | return &slot->entry->node; |
| 105984 | } |
| 105985 | |
| 105986 | static const UA_Node * |
| 105987 | UA_NodeMap_getNodeFromPtr(void *context, UA_NodePointer ptr, |
| 105988 | UA_UInt32 attributeMask, |
| 105989 | UA_ReferenceTypeSet references, |
| 105990 | UA_BrowseDirection referenceDirections) { |
| 105991 | if(!UA_NodePointer_isLocal(np: ptr)) |
| 105992 | return NULL; |
| 105993 | UA_NodeId id = UA_NodePointer_toNodeId(np: ptr); |
| 105994 | return UA_NodeMap_getNode(context, nodeid: &id, attributeMask, references, referenceDirections); |
| 105995 | } |
| 105996 | |
| 105997 | static void |
| 105998 | UA_NodeMap_releaseNode(void *context, const UA_Node *node) { |
| 105999 | if (!node) |
| 106000 | return; |
| 106001 | UA_NodeMapEntry *entry = container_of(node, UA_NodeMapEntry, node); |
| 106002 | UA_assert(&entry->node == node); |
| 106003 | UA_assert(entry->refCount > 0); |
| 106004 | --entry->refCount; |
| 106005 | cleanupNodeMapEntry(entry); |
| 106006 | } |
| 106007 | |
| 106008 | static UA_StatusCode |
| 106009 | UA_NodeMap_getNodeCopy(void *context, const UA_NodeId *nodeid, |
| 106010 | UA_Node **outNode) { |
| 106011 | UA_NodeMap *ns = (UA_NodeMap*)context; |
| 106012 | UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid); |
| 106013 | if(!slot) |
| 106014 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 106015 | UA_NodeMapEntry *entry = slot->entry; |
| 106016 | UA_NodeMapEntry *newItem = createEntry(nodeClass: entry->node.head.nodeClass); |
| 106017 | if(!newItem) |
| 106018 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 106019 | UA_StatusCode retval = UA_Node_copy(src: &entry->node, dst: &newItem->node); |
| 106020 | if(retval == UA_STATUSCODE_GOOD) { |
| 106021 | newItem->orig = entry; /* Store the pointer to the original */ |
| 106022 | *outNode = &newItem->node; |
| 106023 | } else { |
| 106024 | deleteNodeMapEntry(entry: newItem); |
| 106025 | } |
| 106026 | return retval; |
| 106027 | } |
| 106028 | |
| 106029 | static UA_StatusCode |
| 106030 | UA_NodeMap_removeNode(void *context, const UA_NodeId *nodeid) { |
| 106031 | UA_NodeMap *ns = (UA_NodeMap*)context; |
| 106032 | UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid); |
| 106033 | if(!slot) |
| 106034 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 106035 | |
| 106036 | UA_NodeMapEntry *entry = slot->entry; |
| 106037 | slot->entry = UA_NODEMAP_TOMBSTONE; |
| 106038 | entry->deleted = true; |
| 106039 | cleanupNodeMapEntry(entry); |
| 106040 | --ns->count; |
| 106041 | /* Downsize the hashmap if it is very empty */ |
| 106042 | if(ns->count * 8 < ns->size && ns->size > UA_NODEMAP_MINSIZE) |
| 106043 | expand(ns); /* Can fail. Just continue with the bigger hashmap. */ |
| 106044 | return UA_STATUSCODE_GOOD; |
| 106045 | } |
| 106046 | |
| 106047 | /* |
| 106048 | * If this function fails in any way, the node parameter is deleted here, |
| 106049 | * so the caller function does not need to take care of it anymore |
| 106050 | */ |
| 106051 | static UA_StatusCode |
| 106052 | UA_NodeMap_insertNode(void *context, UA_Node *node, |
| 106053 | UA_NodeId *addedNodeId) { |
| 106054 | UA_NodeMap *ns = (UA_NodeMap*)context; |
| 106055 | if(ns->size * 3 <= ns->count * 4) { |
| 106056 | if(expand(ns) != UA_STATUSCODE_GOOD){ |
| 106057 | deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node)); |
| 106058 | return UA_STATUSCODE_BADINTERNALERROR; |
| 106059 | } |
| 106060 | } |
| 106061 | |
| 106062 | UA_NodeMapSlot *slot; |
| 106063 | if(node->head.nodeId.identifierType == UA_NODEIDTYPE_NUMERIC && |
| 106064 | node->head.nodeId.identifier.numeric == 0) { |
| 106065 | /* Create a random nodeid: Start at least with 50,000 to make sure we |
| 106066 | * don not conflict with nodes from the spec. If we find a conflict, we |
| 106067 | * just try another identifier until we have tried all possible |
| 106068 | * identifiers. Since the size is prime and we don't change the increase |
| 106069 | * val, we will reach the starting id again. E.g. adding a nodeset will |
| 106070 | * create children while there are still other nodes which need to be |
| 106071 | * created. Thus the node ids may collide. */ |
| 106072 | UA_UInt32 size = ns->size; |
| 106073 | UA_UInt64 identifier = mod(h: 50000 + size+1, UA_UINT32_MAX); /* Use 64bit to |
| 106074 | * avoid overflow */ |
| 106075 | UA_UInt32 increase = mod2(h: ns->count+1, size); |
| 106076 | UA_UInt32 startId = (UA_UInt32)identifier; /* mod ensures us that the id |
| 106077 | * is a valid 32 bit integer */ |
| 106078 | |
| 106079 | do { |
| 106080 | node->head.nodeId.identifier.numeric = (UA_UInt32)identifier; |
| 106081 | slot = findFreeSlot(ns, nodeid: &node->head.nodeId); |
| 106082 | if(slot) |
| 106083 | break; |
| 106084 | identifier += increase; |
| 106085 | if(identifier >= size) |
| 106086 | identifier -= size; |
| 106087 | #if SIZE_MAX <= UA_UINT32_MAX |
| 106088 | /* The compressed "immediate" representation of nodes does not |
| 106089 | * support the full range on 32bit systems. Generate smaller |
| 106090 | * identifiers as they can be stored more compactly. */ |
| 106091 | if(identifier >= (0x01 << 24)) |
| 106092 | identifier = identifier % (0x01 << 24); |
| 106093 | #endif |
| 106094 | } while((UA_UInt32)identifier != startId); |
| 106095 | } else { |
| 106096 | slot = findFreeSlot(ns, nodeid: &node->head.nodeId); |
| 106097 | } |
| 106098 | |
| 106099 | if(!slot) { |
| 106100 | deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node)); |
| 106101 | return UA_STATUSCODE_BADNODEIDEXISTS; |
| 106102 | } |
| 106103 | |
| 106104 | /* Copy the NodeId */ |
| 106105 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 106106 | if(addedNodeId) { |
| 106107 | retval = UA_NodeId_copy(src: &node->head.nodeId, dst: addedNodeId); |
| 106108 | if(retval != UA_STATUSCODE_GOOD) { |
| 106109 | deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node)); |
| 106110 | return retval; |
| 106111 | } |
| 106112 | } |
| 106113 | |
| 106114 | /* For new ReferencetypeNodes add to the index map */ |
| 106115 | if(node->head.nodeClass == UA_NODECLASS_REFERENCETYPE) { |
| 106116 | UA_ReferenceTypeNode *refNode = &node->referenceTypeNode; |
| 106117 | if(ns->referenceTypeCounter >= UA_REFERENCETYPESET_MAX) { |
| 106118 | deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node)); |
| 106119 | return UA_STATUSCODE_BADINTERNALERROR; |
| 106120 | } |
| 106121 | |
| 106122 | retval = UA_NodeId_copy(src: &node->head.nodeId, dst: &ns->referenceTypeIds[ns->referenceTypeCounter]); |
| 106123 | if(retval != UA_STATUSCODE_GOOD) { |
| 106124 | deleteNodeMapEntry(container_of(node, UA_NodeMapEntry, node)); |
| 106125 | return UA_STATUSCODE_BADINTERNALERROR; |
| 106126 | } |
| 106127 | |
| 106128 | /* Assign the ReferenceTypeIndex to the new ReferenceTypeNode */ |
| 106129 | refNode->referenceTypeIndex = ns->referenceTypeCounter; |
| 106130 | refNode->subTypes = UA_REFTYPESET(index: ns->referenceTypeCounter); |
| 106131 | |
| 106132 | ns->referenceTypeCounter++; |
| 106133 | } |
| 106134 | |
| 106135 | /* Insert the node */ |
| 106136 | UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node); |
| 106137 | slot->nodeIdHash = UA_NodeId_hash(n: &node->head.nodeId); |
| 106138 | slot->entry = newEntry; |
| 106139 | ++ns->count; |
| 106140 | return retval; |
| 106141 | } |
| 106142 | |
| 106143 | static UA_StatusCode |
| 106144 | UA_NodeMap_replaceNode(void *context, UA_Node *node) { |
| 106145 | UA_NodeMap *ns = (UA_NodeMap*)context; |
| 106146 | UA_NodeMapEntry *newEntry = container_of(node, UA_NodeMapEntry, node); |
| 106147 | |
| 106148 | /* Find the node */ |
| 106149 | UA_NodeMapSlot *slot = findOccupiedSlot(ns, nodeid: &node->head.nodeId); |
| 106150 | if(!slot) { |
| 106151 | deleteNodeMapEntry(entry: newEntry); |
| 106152 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 106153 | } |
| 106154 | |
| 106155 | /* The node was already updated since the copy was made? */ |
| 106156 | UA_NodeMapEntry *oldEntry = slot->entry; |
| 106157 | if(oldEntry != newEntry->orig) { |
| 106158 | deleteNodeMapEntry(entry: newEntry); |
| 106159 | return UA_STATUSCODE_BADINTERNALERROR; |
| 106160 | } |
| 106161 | |
| 106162 | /* Replace the entry */ |
| 106163 | slot->entry = newEntry; |
| 106164 | oldEntry->deleted = true; |
| 106165 | cleanupNodeMapEntry(entry: oldEntry); |
| 106166 | return UA_STATUSCODE_GOOD; |
| 106167 | } |
| 106168 | |
| 106169 | static const UA_NodeId * |
| 106170 | UA_NodeMap_getReferenceTypeId(void *nsCtx, UA_Byte refTypeIndex) { |
| 106171 | UA_NodeMap *ns = (UA_NodeMap*)nsCtx; |
| 106172 | if(refTypeIndex >= ns->referenceTypeCounter) |
| 106173 | return NULL; |
| 106174 | return &ns->referenceTypeIds[refTypeIndex]; |
| 106175 | } |
| 106176 | |
| 106177 | static void |
| 106178 | UA_NodeMap_iterate(void *context, UA_NodestoreVisitor visitor, |
| 106179 | void *visitorContext) { |
| 106180 | UA_NodeMap *ns = (UA_NodeMap*)context; |
| 106181 | for(UA_UInt32 i = 0; i < ns->size; ++i) { |
| 106182 | UA_NodeMapSlot *slot = &ns->slots[i]; |
| 106183 | if(slot->entry > UA_NODEMAP_TOMBSTONE) { |
| 106184 | /* The visitor can delete the node. So refcount here. */ |
| 106185 | slot->entry->refCount++; |
| 106186 | visitor(visitorContext, &slot->entry->node); |
| 106187 | slot->entry->refCount--; |
| 106188 | cleanupNodeMapEntry(entry: slot->entry); |
| 106189 | } |
| 106190 | } |
| 106191 | } |
| 106192 | |
| 106193 | static void |
| 106194 | UA_NodeMap_delete(void *context) { |
| 106195 | /* Already cleaned up? */ |
| 106196 | if(!context) |
| 106197 | return; |
| 106198 | |
| 106199 | UA_NodeMap *ns = (UA_NodeMap*)context; |
| 106200 | UA_UInt32 size = ns->size; |
| 106201 | UA_NodeMapSlot *slots = ns->slots; |
| 106202 | for(UA_UInt32 i = 0; i < size; ++i) { |
| 106203 | if(slots[i].entry > UA_NODEMAP_TOMBSTONE) { |
| 106204 | /* On debugging builds, check that all nodes were release */ |
| 106205 | UA_assert(slots[i].entry->refCount == 0); |
| 106206 | /* Delete the node */ |
| 106207 | deleteNodeMapEntry(entry: slots[i].entry); |
| 106208 | } |
| 106209 | } |
| 106210 | UA_free(ptr: ns->slots); |
| 106211 | |
| 106212 | /* Clean up the ReferenceTypes index array */ |
| 106213 | for(size_t i = 0; i < ns->referenceTypeCounter; i++) |
| 106214 | UA_NodeId_clear(p: &ns->referenceTypeIds[i]); |
| 106215 | |
| 106216 | UA_free(ptr: ns); |
| 106217 | } |
| 106218 | |
| 106219 | UA_StatusCode |
| 106220 | UA_Nodestore_HashMap(UA_Nodestore *ns) { |
| 106221 | /* Allocate and initialize the nodemap */ |
| 106222 | UA_NodeMap *nodemap = (UA_NodeMap*)UA_malloc(size: sizeof(UA_NodeMap)); |
| 106223 | if(!nodemap) |
| 106224 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 106225 | nodemap->sizePrimeIndex = higher_prime_index(UA_NODEMAP_MINSIZE); |
| 106226 | nodemap->size = primes[nodemap->sizePrimeIndex]; |
| 106227 | nodemap->count = 0; |
| 106228 | nodemap->slots = (UA_NodeMapSlot*) |
| 106229 | UA_calloc(nmemb: nodemap->size, size: sizeof(UA_NodeMapSlot)); |
| 106230 | if(!nodemap->slots) { |
| 106231 | UA_free(ptr: nodemap); |
| 106232 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 106233 | } |
| 106234 | |
| 106235 | nodemap->referenceTypeCounter = 0; |
| 106236 | |
| 106237 | /* Populate the nodestore */ |
| 106238 | ns->context = nodemap; |
| 106239 | ns->clear = UA_NodeMap_delete; |
| 106240 | ns->newNode = UA_NodeMap_newNode; |
| 106241 | ns->deleteNode = UA_NodeMap_deleteNode; |
| 106242 | ns->getNode = UA_NodeMap_getNode; |
| 106243 | ns->getNodeFromPtr = UA_NodeMap_getNodeFromPtr; |
| 106244 | ns->releaseNode = UA_NodeMap_releaseNode; |
| 106245 | ns->getNodeCopy = UA_NodeMap_getNodeCopy; |
| 106246 | ns->insertNode = UA_NodeMap_insertNode; |
| 106247 | ns->replaceNode = UA_NodeMap_replaceNode; |
| 106248 | ns->removeNode = UA_NodeMap_removeNode; |
| 106249 | ns->getReferenceTypeId = UA_NodeMap_getReferenceTypeId; |
| 106250 | ns->iterate = UA_NodeMap_iterate; |
| 106251 | return UA_STATUSCODE_GOOD; |
| 106252 | } |
| 106253 | |
| 106254 | /**** amalgamated original file "/plugins/ua_config_default.c" ****/ |
| 106255 | |
| 106256 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 106257 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 106258 | * |
| 106259 | * Copyright 2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 106260 | * Copyright 2017 (c) Julian Grothoff |
| 106261 | * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB |
| 106262 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 106263 | * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA |
| 106264 | * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG |
| 106265 | * Copyright 2018 (c) Fabian Arndt, Root-Core |
| 106266 | * Copyright 2019 (c) Kalycito Infotech Private Limited |
| 106267 | * Copyright 2017-2020 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 106268 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 106269 | */ |
| 106270 | |
| 106271 | |
| 106272 | |
| 106273 | #include <stdio.h> |
| 106274 | #ifdef UA_ARCHITECTURE_WIN32 |
| 106275 | # include <winsock2.h> |
| 106276 | #else |
| 106277 | # include <unistd.h> |
| 106278 | #endif |
| 106279 | |
| 106280 | /* Struct initialization works across ANSI C/C99/C++ if it is done when the |
| 106281 | * variable is first declared. Assigning values to existing structs is |
| 106282 | * heterogeneous across the three. */ |
| 106283 | static UA_INLINE UA_UInt32Range |
| 106284 | UA_UINT32RANGE(UA_UInt32 min, UA_UInt32 max) { |
| 106285 | UA_UInt32Range range = {min, max}; |
| 106286 | return range; |
| 106287 | } |
| 106288 | |
| 106289 | static UA_INLINE UA_DurationRange |
| 106290 | UA_DURATIONRANGE(UA_Duration min, UA_Duration max) { |
| 106291 | UA_DurationRange range = {min, max}; |
| 106292 | return range; |
| 106293 | } |
| 106294 | |
| 106295 | /* Request the private key password from stdin if no callback is defined */ |
| 106296 | #ifdef UA_ENABLE_ENCRYPTION |
| 106297 | static UA_StatusCode |
| 106298 | readPrivateKeyPassword(UA_ByteString *password) { |
| 106299 | /* Read from stdin */ |
| 106300 | char buf[256]; |
| 106301 | fputs(s: "Private key requires a password. Enter and press return: ", stdout); |
| 106302 | char *s = fgets(s: buf, n: 256, stdin); |
| 106303 | if(!s) |
| 106304 | return UA_STATUSCODE_BADINTERNALERROR; |
| 106305 | |
| 106306 | /* Get rid of any trailing \n */ |
| 106307 | size_t len = strlen(s: buf); |
| 106308 | if(len == 0) |
| 106309 | return UA_STATUSCODE_BADINTERNALERROR; |
| 106310 | if(buf[len-1] == '\n') |
| 106311 | buf[len-1] = 0; |
| 106312 | |
| 106313 | *password = UA_BYTESTRING_ALLOC(buf); |
| 106314 | return UA_STATUSCODE_GOOD; |
| 106315 | } |
| 106316 | #endif |
| 106317 | |
| 106318 | UA_Server * |
| 106319 | UA_Server_new(void) { |
| 106320 | UA_ServerConfig config; |
| 106321 | memset(s: &config, c: 0, n: sizeof(UA_ServerConfig)); |
| 106322 | UA_StatusCode res = UA_ServerConfig_setDefault(config: &config); |
| 106323 | if(res != UA_STATUSCODE_GOOD) |
| 106324 | return NULL; |
| 106325 | return UA_Server_newWithConfig(config: &config); |
| 106326 | } |
| 106327 | |
| 106328 | #if defined(UA_ARCHITECTURE_POSIX) || defined(UA_ARCHITECTURE_WIN32) |
| 106329 | |
| 106330 | /* Required for the definition of SIGINT */ |
| 106331 | #include <signal.h> |
| 106332 | |
| 106333 | struct InterruptContext { |
| 106334 | UA_Server *server; |
| 106335 | UA_Boolean running; |
| 106336 | }; |
| 106337 | |
| 106338 | static void |
| 106339 | shutdownServer(UA_Server *server, void *context) { |
| 106340 | struct InterruptContext *ic = (struct InterruptContext*)context; |
| 106341 | UA_ServerConfig *config = UA_Server_getConfig(server: ic->server); |
| 106342 | UA_LOG_INFO(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 106343 | msg: "Stopping the server"); |
| 106344 | ic->running = false; |
| 106345 | } |
| 106346 | |
| 106347 | static void |
| 106348 | interruptServer(UA_InterruptManager *im, uintptr_t interruptHandle, |
| 106349 | void *context, const UA_KeyValueMap *parameters) { |
| 106350 | struct InterruptContext *ic = (struct InterruptContext*)context; |
| 106351 | UA_ServerConfig *config = UA_Server_getConfig(server: ic->server); |
| 106352 | |
| 106353 | if(config->shutdownDelay <= 0.0) { |
| 106354 | UA_LOG_INFO(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 106355 | msg: "Received SIGINT interrupt. Stopping the server."); |
| 106356 | ic->running = false; |
| 106357 | return; |
| 106358 | } |
| 106359 | |
| 106360 | UA_LOG_INFO(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 106361 | msg: "Received SIGINT interrupt. Stopping the server in %.2fs.", |
| 106362 | config->shutdownDelay / 1000.0); |
| 106363 | |
| 106364 | UA_UInt32 secondsTillShutdown = (UA_UInt32)(config->shutdownDelay / 1000.0); |
| 106365 | UA_Variant val; |
| 106366 | UA_Variant_setScalar(v: &val, p: &secondsTillShutdown, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 106367 | UA_Server_writeValue(server: ic->server, |
| 106368 | nodeId: UA_NODEID_NUMERIC(nsIndex: 0, UA_NS0ID_SERVER_SERVERSTATUS_SECONDSTILLSHUTDOWN), value: val); |
| 106369 | UA_Server_addTimedCallback(server: ic->server, callback: shutdownServer, data: ic, date: UA_DateTime_nowMonotonic() + |
| 106370 | (UA_DateTime)(config->shutdownDelay * UA_DATETIME_MSEC), |
| 106371 | NULL); |
| 106372 | |
| 106373 | /* Notify the application that the server is stopping */ |
| 106374 | if(config->notifyLifecycleState) |
| 106375 | config->notifyLifecycleState(ic->server, UA_LIFECYCLESTATE_STOPPING); |
| 106376 | } |
| 106377 | |
| 106378 | UA_StatusCode |
| 106379 | UA_Server_runUntilInterrupt(UA_Server *server) { |
| 106380 | if(!server) |
| 106381 | return UA_STATUSCODE_BADINTERNALERROR; |
| 106382 | UA_ServerConfig *config = UA_Server_getConfig(server); |
| 106383 | UA_EventLoop *el = config->eventLoop; |
| 106384 | if(!el) |
| 106385 | return UA_STATUSCODE_BADINTERNALERROR; |
| 106386 | |
| 106387 | /* Get the interrupt manager */ |
| 106388 | UA_EventSource *es = el->eventSources; |
| 106389 | while(es) { |
| 106390 | if(es->eventSourceType == UA_EVENTSOURCETYPE_INTERRUPTMANAGER) |
| 106391 | break; |
| 106392 | es = es->next; |
| 106393 | } |
| 106394 | if(!es) { |
| 106395 | UA_LOG_ERROR(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 106396 | msg: "No Interrupt EventSource configured"); |
| 106397 | return UA_STATUSCODE_BADINTERNALERROR; |
| 106398 | } |
| 106399 | UA_InterruptManager *im = (UA_InterruptManager*)es; |
| 106400 | |
| 106401 | /* Register the interrupt */ |
| 106402 | struct InterruptContext ic; |
| 106403 | ic.server = server; |
| 106404 | ic.running = true; |
| 106405 | UA_StatusCode retval = |
| 106406 | im->registerInterrupt(im, SIGINT, &UA_KEYVALUEMAP_NULL, |
| 106407 | interruptServer, &ic); |
| 106408 | if(retval != UA_STATUSCODE_GOOD) { |
| 106409 | UA_LOG_ERROR(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 106410 | msg: "Could not register the interrupt with status code %s", |
| 106411 | UA_StatusCode_name(code: retval)); |
| 106412 | return retval; |
| 106413 | } |
| 106414 | |
| 106415 | /* Run the server */ |
| 106416 | retval = UA_Server_run_startup(server); |
| 106417 | if(retval != UA_STATUSCODE_GOOD) |
| 106418 | goto deregister_interrupt; |
| 106419 | while(ic.running) { |
| 106420 | UA_Server_run_iterate(server, true); |
| 106421 | } |
| 106422 | |
| 106423 | /* Shut down the server */ |
| 106424 | retval = UA_Server_run_shutdown(server); |
| 106425 | |
| 106426 | /* Deregister the interrupt */ |
| 106427 | deregister_interrupt: |
| 106428 | im->deregisterInterrupt(im, SIGINT); |
| 106429 | return retval; |
| 106430 | } |
| 106431 | |
| 106432 | #endif /* defined(UA_ARCHITECTURE_POSIX) || defined(UA_ARCHITECTURE_WIN32) */ |
| 106433 | |
| 106434 | /*******************************/ |
| 106435 | /* Default Connection Settings */ |
| 106436 | /*******************************/ |
| 106437 | |
| 106438 | const UA_ConnectionConfig UA_ConnectionConfig_default = { |
| 106439 | 0, /* .protocolVersion */ |
| 106440 | 1 << 16, /* .sendBufferSize, 64k per chunk */ |
| 106441 | 1 << 16, /* .recvBufferSize, 64k per chunk */ |
| 106442 | 1 << 29, /* .localMaxMessageSize, 512 MB */ |
| 106443 | 1 << 29, /* .remoteMaxMessageSize, 512 MB */ |
| 106444 | 1 << 14, /* .localMaxChunkCount, 16k */ |
| 106445 | 1 << 14 /* .remoteMaxChunkCount, 16k */ |
| 106446 | }; |
| 106447 | |
| 106448 | /***************************/ |
| 106449 | /* Default Server Settings */ |
| 106450 | /***************************/ |
| 106451 | |
| 106452 | #define MANUFACTURER_NAME "open62541" |
| 106453 | #define PRODUCT_NAME "open62541 OPC UA Server" |
| 106454 | #define PRODUCT_URI "http://open62541.org" |
| 106455 | #define APPLICATION_NAME "open62541-based OPC UA Application" |
| 106456 | #define APPLICATION_URI "urn:unconfigured:application" |
| 106457 | #define APPLICATION_URI_SERVER "urn:open62541.server.application" |
| 106458 | |
| 106459 | #ifdef UA_INCLUDE_INSECURE_POLICIES |
| 106460 | # define SECURITY_POLICY_SIZE 5 |
| 106461 | #else |
| 106462 | # define SECURITY_POLICY_SIZE 3 |
| 106463 | #endif |
| 106464 | |
| 106465 | #define STRINGIFY(arg) #arg |
| 106466 | #define VERSION(MAJOR, MINOR, PATCH, LABEL) \ |
| 106467 | STRINGIFY(MAJOR) "." STRINGIFY(MINOR) "." STRINGIFY(PATCH) LABEL |
| 106468 | |
| 106469 | static UA_StatusCode |
| 106470 | addEndpoint(UA_ServerConfig *conf, |
| 106471 | const UA_SecurityPolicy *securityPolicy, |
| 106472 | UA_MessageSecurityMode securityMode) { |
| 106473 | /* Test if the endpoint already exists */ |
| 106474 | for(size_t i = 0; i < conf->endpointsSize; i++) { |
| 106475 | UA_EndpointDescription *ep = &conf->endpoints[i]; |
| 106476 | if(!UA_String_equal(p1: &securityPolicy->policyUri, p2: &ep->securityPolicyUri)) |
| 106477 | continue; |
| 106478 | if(ep->securityMode != securityMode) |
| 106479 | continue; |
| 106480 | return UA_STATUSCODE_GOOD; |
| 106481 | } |
| 106482 | |
| 106483 | /* Reallocate the array size */ |
| 106484 | UA_EndpointDescription *tmp = (UA_EndpointDescription *) |
| 106485 | UA_realloc(ptr: conf->endpoints, |
| 106486 | size: sizeof(UA_EndpointDescription) * (1 + conf->endpointsSize)); |
| 106487 | if(!tmp) |
| 106488 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 106489 | conf->endpoints = tmp; |
| 106490 | |
| 106491 | /* The following fields are overwritten internally with up-to-date |
| 106492 | * information from the server config: |
| 106493 | * |
| 106494 | * UserTokenPolicies |
| 106495 | * ApplicationDescription (server) |
| 106496 | * ServerCertificate |
| 106497 | * EndpointURL */ |
| 106498 | UA_EndpointDescription *endpoint = &conf->endpoints[conf->endpointsSize]; |
| 106499 | UA_EndpointDescription_init(p: endpoint); |
| 106500 | endpoint->transportProfileUri = |
| 106501 | UA_STRING_ALLOC("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary"); |
| 106502 | endpoint->securityMode = securityMode; |
| 106503 | |
| 106504 | /* A numeric value that indicates how secure the EndpointDescription is compared to other EndpointDescriptions |
| 106505 | * for the same Server. A value of 0 indicates that the EndpointDescription is not recommended and is only |
| 106506 | * supported for backward compatibility. A higher value indicates better security. */ |
| 106507 | UA_String noneuri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None"); |
| 106508 | UA_String basic128uri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15"); |
| 106509 | UA_String basic256uri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic256"); |
| 106510 | if(UA_String_equal(p1: &securityPolicy->policyUri, p2: &noneuri) || |
| 106511 | UA_String_equal(p1: &securityPolicy->policyUri, p2: &basic128uri) || |
| 106512 | UA_String_equal(p1: &securityPolicy->policyUri, p2: &basic256uri)) { |
| 106513 | endpoint->securityLevel = 0; |
| 106514 | } else { |
| 106515 | endpoint->securityLevel = 1; |
| 106516 | } |
| 106517 | |
| 106518 | UA_StatusCode retval = UA_String_copy(src: &securityPolicy->policyUri, |
| 106519 | dst: &endpoint->securityPolicyUri); |
| 106520 | |
| 106521 | if(retval == UA_STATUSCODE_GOOD) { |
| 106522 | conf->endpointsSize++; |
| 106523 | } else { |
| 106524 | UA_EndpointDescription_clear(p: endpoint); |
| 106525 | if(conf->endpointsSize == 0) { |
| 106526 | UA_free(ptr: conf->endpoints); |
| 106527 | conf->endpoints = NULL; |
| 106528 | } |
| 106529 | } |
| 106530 | |
| 106531 | return retval; |
| 106532 | } |
| 106533 | |
| 106534 | static UA_StatusCode |
| 106535 | setDefaultConfig(UA_ServerConfig *conf, UA_UInt16 portNumber) { |
| 106536 | if(!conf) |
| 106537 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 106538 | |
| 106539 | /* NodeStore */ |
| 106540 | if(conf->nodestore.context == NULL) |
| 106541 | UA_Nodestore_HashMap(ns: &conf->nodestore); |
| 106542 | |
| 106543 | /* Logging */ |
| 106544 | if(conf->logging == NULL) |
| 106545 | conf->logging = UA_Log_Stdout_new(minlevel: UA_LOGLEVEL_INFO); |
| 106546 | |
| 106547 | /* EventLoop */ |
| 106548 | if(conf->eventLoop == NULL) { |
| 106549 | conf->eventLoop = UA_EventLoop_new_POSIX(logger: conf->logging); |
| 106550 | if(conf->eventLoop == NULL) |
| 106551 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 106552 | |
| 106553 | conf->externalEventLoop = false; |
| 106554 | |
| 106555 | /* Add the TCP connection manager */ |
| 106556 | UA_ConnectionManager *tcpCM = |
| 106557 | UA_ConnectionManager_new_POSIX_TCP(eventSourceName: UA_STRING(chars: "tcp connection manager")); |
| 106558 | if(tcpCM) |
| 106559 | conf->eventLoop->registerEventSource(conf->eventLoop, (UA_EventSource *)tcpCM); |
| 106560 | |
| 106561 | /* Add the UDP connection manager */ |
| 106562 | UA_ConnectionManager *udpCM = |
| 106563 | UA_ConnectionManager_new_POSIX_UDP(eventSourceName: UA_STRING(chars: "udp connection manager")); |
| 106564 | if(udpCM) |
| 106565 | conf->eventLoop->registerEventSource(conf->eventLoop, (UA_EventSource *)udpCM); |
| 106566 | |
| 106567 | /* Add the Ethernet connection manager */ |
| 106568 | #if defined(UA_ARCHITECTURE_POSIX) && (defined(__linux__)) |
| 106569 | UA_ConnectionManager *ethCM = |
| 106570 | UA_ConnectionManager_new_POSIX_Ethernet(eventSourceName: UA_STRING(chars: "eth connection manager")); |
| 106571 | if(ethCM) |
| 106572 | conf->eventLoop->registerEventSource(conf->eventLoop, (UA_EventSource *)ethCM); |
| 106573 | #endif |
| 106574 | |
| 106575 | /* Add the interrupt manager */ |
| 106576 | UA_InterruptManager *im = UA_InterruptManager_new_POSIX(eventSourceName: UA_STRING(chars: "interrupt manager")); |
| 106577 | if(im) { |
| 106578 | conf->eventLoop->registerEventSource(conf->eventLoop, &im->eventSource); |
| 106579 | } else { |
| 106580 | UA_LOG_WARNING(logger: conf->logging, category: UA_LOGCATEGORY_USERLAND, |
| 106581 | msg: "Cannot create the Interrupt Manager (only relevant if used)"); |
| 106582 | } |
| 106583 | #ifdef UA_ENABLE_MQTT |
| 106584 | /* Add the MQTT connection manager */ |
| 106585 | UA_ConnectionManager *mqttCM = |
| 106586 | UA_ConnectionManager_new_MQTT(UA_STRING("mqtt connection manager")); |
| 106587 | if(mqttCM) |
| 106588 | conf->eventLoop->registerEventSource(conf->eventLoop, (UA_EventSource *)mqttCM); |
| 106589 | #endif |
| 106590 | } |
| 106591 | if(conf->eventLoop != NULL) { |
| 106592 | if(conf->eventLoop->state != UA_EVENTLOOPSTATE_STARTED) { |
| 106593 | UA_StatusCode statusCode = conf->eventLoop->start(conf->eventLoop); |
| 106594 | if(statusCode != UA_STATUSCODE_GOOD) { |
| 106595 | return statusCode; |
| 106596 | } |
| 106597 | } |
| 106598 | } |
| 106599 | |
| 106600 | /* If a second server is started later it can "steal" the port. |
| 106601 | * Having port reuse enabled is important for development. |
| 106602 | * Otherwise a long TCP TIME_WAIT is required before the port can be used again. */ |
| 106603 | conf->tcpReuseAddr = true; |
| 106604 | |
| 106605 | /* --> Start setting the default static config <-- */ |
| 106606 | |
| 106607 | conf->shutdownDelay = 0.0; |
| 106608 | |
| 106609 | /* Server Description */ |
| 106610 | UA_BuildInfo_clear(p: &conf->buildInfo); |
| 106611 | conf->buildInfo.productUri = UA_STRING_ALLOC(PRODUCT_URI); |
| 106612 | conf->buildInfo.manufacturerName = UA_STRING_ALLOC(MANUFACTURER_NAME); |
| 106613 | conf->buildInfo.productName = UA_STRING_ALLOC(PRODUCT_NAME); |
| 106614 | conf->buildInfo.softwareVersion = |
| 106615 | UA_STRING_ALLOC(VERSION(UA_OPEN62541_VER_MAJOR, UA_OPEN62541_VER_MINOR, |
| 106616 | UA_OPEN62541_VER_PATCH, UA_OPEN62541_VER_LABEL)); |
| 106617 | conf->buildInfo.buildNumber = UA_STRING_ALLOC(__DATE__ " "__TIME__); |
| 106618 | conf->buildInfo.buildDate = UA_DateTime_now(); |
| 106619 | |
| 106620 | UA_ApplicationDescription_clear(p: &conf->applicationDescription); |
| 106621 | conf->applicationDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI_SERVER); |
| 106622 | conf->applicationDescription.productUri = UA_STRING_ALLOC(PRODUCT_URI); |
| 106623 | conf->applicationDescription.applicationName = |
| 106624 | UA_LOCALIZEDTEXT_ALLOC(locale: "en", APPLICATION_NAME); |
| 106625 | conf->applicationDescription.applicationType = UA_APPLICATIONTYPE_SERVER; |
| 106626 | /* conf->applicationDescription.gatewayServerUri = UA_STRING_NULL; */ |
| 106627 | /* conf->applicationDescription.discoveryProfileUri = UA_STRING_NULL; */ |
| 106628 | /* conf->applicationDescription.discoveryUrlsSize = 0; */ |
| 106629 | /* conf->applicationDescription.discoveryUrls = NULL; */ |
| 106630 | |
| 106631 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 106632 | UA_MdnsDiscoveryConfiguration_clear(&conf->mdnsConfig); |
| 106633 | conf->mdnsInterfaceIP = UA_STRING_NULL; |
| 106634 | # if !defined(UA_HAS_GETIFADDR) |
| 106635 | conf->mdnsIpAddressList = NULL; |
| 106636 | conf->mdnsIpAddressListSize = 0; |
| 106637 | # endif |
| 106638 | #endif |
| 106639 | |
| 106640 | /* Custom DataTypes */ |
| 106641 | /* conf->customDataTypesSize = 0; */ |
| 106642 | /* conf->customDataTypes = NULL; */ |
| 106643 | |
| 106644 | /* Networking */ |
| 106645 | /* Set up the local ServerUrls. They are used during startup to initialize |
| 106646 | * the server sockets. */ |
| 106647 | UA_String serverUrls[1]; |
| 106648 | size_t serverUrlsSize = 0; |
| 106649 | char serverUrlBuffer[1][512]; |
| 106650 | |
| 106651 | if(portNumber == 0) { |
| 106652 | UA_LOG_WARNING(logger: conf->logging, category: UA_LOGCATEGORY_USERLAND, |
| 106653 | msg: "Dynamic port assignment will be used."); |
| 106654 | } |
| 106655 | |
| 106656 | if(conf->serverUrlsSize > 0) { |
| 106657 | UA_LOG_WARNING(logger: conf->logging, category: UA_LOGCATEGORY_USERLAND, |
| 106658 | msg: "ServerUrls already set. Overriding."); |
| 106659 | UA_Array_delete(p: conf->serverUrls, size: conf->serverUrlsSize, |
| 106660 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 106661 | conf->serverUrls = NULL; |
| 106662 | conf->serverUrlsSize = 0; |
| 106663 | } |
| 106664 | |
| 106665 | /* Listen on all interfaces (also external). This must be the first |
| 106666 | * entry if this is desired. Otherwise some interfaces may be blocked |
| 106667 | * (already in use) with a hostname that is only locally reachable.*/ |
| 106668 | mp_snprintf(s: serverUrlBuffer[0], n: sizeof(serverUrlBuffer[0]), |
| 106669 | format: "opc.tcp://:%u", portNumber); |
| 106670 | serverUrls[serverUrlsSize] = UA_STRING(chars: serverUrlBuffer[0]); |
| 106671 | serverUrlsSize++; |
| 106672 | |
| 106673 | /* Add to the config */ |
| 106674 | UA_StatusCode retval = |
| 106675 | UA_Array_copy(src: serverUrls, size: serverUrlsSize, |
| 106676 | dst: (void**)&conf->serverUrls, type: &UA_TYPES[UA_TYPES_STRING]); |
| 106677 | if(retval != UA_STATUSCODE_GOOD) |
| 106678 | return retval; |
| 106679 | conf->serverUrlsSize = serverUrlsSize; |
| 106680 | |
| 106681 | /* Endpoints */ |
| 106682 | /* conf->endpoints = {0, NULL}; */ |
| 106683 | |
| 106684 | /* Set Logger for Certificate Verification */ |
| 106685 | if(!conf->secureChannelPKI.logging) |
| 106686 | conf->secureChannelPKI.logging = conf->logging; |
| 106687 | if(!conf->sessionPKI.logging) |
| 106688 | conf->sessionPKI.logging = conf->logging; |
| 106689 | |
| 106690 | /* Certificate Verification that accepts every certificate. Can be |
| 106691 | * overwritten when the policy is specialized. */ |
| 106692 | UA_CertificateVerification_AcceptAll(cv: &conf->secureChannelPKI); |
| 106693 | |
| 106694 | UA_CertificateVerification_AcceptAll(cv: &conf->sessionPKI); |
| 106695 | |
| 106696 | /* * Global Node Lifecycle * */ |
| 106697 | /* conf->nodeLifecycle.constructor = NULL; */ |
| 106698 | /* conf->nodeLifecycle.destructor = NULL; */ |
| 106699 | /* conf->nodeLifecycle.createOptionalChild = NULL; */ |
| 106700 | /* conf->nodeLifecycle.generateChildNodeId = NULL; */ |
| 106701 | conf->modellingRulesOnInstances = true; |
| 106702 | |
| 106703 | /* Limits for SecureChannels */ |
| 106704 | conf->maxSecureChannels = 100; |
| 106705 | conf->maxSecurityTokenLifetime = 10 * 60 * 1000; /* 10 minutes */ |
| 106706 | |
| 106707 | /* Limits for Sessions */ |
| 106708 | conf->maxSessions = 100; |
| 106709 | conf->maxSessionTimeout = 60.0 * 60.0 * 1000.0; /* 1h */ |
| 106710 | |
| 106711 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 106712 | /* Limits for Subscriptions */ |
| 106713 | conf->publishingIntervalLimits = UA_DURATIONRANGE(min: 100.0, max: 3600.0 * 1000.0); |
| 106714 | conf->lifeTimeCountLimits = UA_UINT32RANGE(min: 3, max: 15000); |
| 106715 | conf->keepAliveCountLimits = UA_UINT32RANGE(min: 1, max: 100); |
| 106716 | conf->maxNotificationsPerPublish = 1000; |
| 106717 | conf->enableRetransmissionQueue = true; |
| 106718 | conf->maxRetransmissionQueueSize = 0; /* unlimited */ |
| 106719 | # ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 106720 | conf->maxEventsPerNode = 0; /* unlimited */ |
| 106721 | # endif |
| 106722 | |
| 106723 | /* Limits for MonitoredItems */ |
| 106724 | conf->samplingIntervalLimits = UA_DURATIONRANGE(min: 50.0, max: 24.0 * 3600.0 * 1000.0); |
| 106725 | conf->queueSizeLimits = UA_UINT32RANGE(min: 1, max: 100); |
| 106726 | #endif |
| 106727 | |
| 106728 | #ifdef UA_ENABLE_DISCOVERY |
| 106729 | conf->discoveryCleanupTimeout = 60 * 60; |
| 106730 | #endif |
| 106731 | |
| 106732 | #ifdef UA_ENABLE_HISTORIZING |
| 106733 | /* conf->accessHistoryDataCapability = false; */ |
| 106734 | /* conf->maxReturnDataValues = 0; */ |
| 106735 | |
| 106736 | /* conf->accessHistoryEventsCapability = false; */ |
| 106737 | /* conf->maxReturnEventValues = 0; */ |
| 106738 | |
| 106739 | /* conf->insertDataCapability = false; */ |
| 106740 | /* conf->insertEventCapability = false; */ |
| 106741 | /* conf->insertAnnotationsCapability = false; */ |
| 106742 | |
| 106743 | /* conf->replaceDataCapability = false; */ |
| 106744 | /* conf->replaceEventCapability = false; */ |
| 106745 | |
| 106746 | /* conf->updateDataCapability = false; */ |
| 106747 | /* conf->updateEventCapability = false; */ |
| 106748 | |
| 106749 | /* conf->deleteRawCapability = false; */ |
| 106750 | /* conf->deleteEventCapability = false; */ |
| 106751 | /* conf->deleteAtTimeDataCapability = false; */ |
| 106752 | #endif |
| 106753 | |
| 106754 | #if UA_MULTITHREADING >= 100 |
| 106755 | conf->maxAsyncOperationQueueSize = 0; |
| 106756 | conf->asyncOperationTimeout = 120000; /* Async Operation Timeout in ms (2 minutes) */ |
| 106757 | #endif |
| 106758 | |
| 106759 | #ifdef UA_ENABLE_PUBSUB |
| 106760 | conf->pubSubConfig.enableDeltaFrames = true; |
| 106761 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 106762 | conf->pubSubConfig.enableInformationModelMethods = true; |
| 106763 | #endif |
| 106764 | #endif |
| 106765 | |
| 106766 | /* --> Finish setting the default static config <-- */ |
| 106767 | |
| 106768 | return UA_STATUSCODE_GOOD; |
| 106769 | } |
| 106770 | |
| 106771 | UA_EXPORT UA_StatusCode |
| 106772 | UA_ServerConfig_setBasics(UA_ServerConfig* conf) { |
| 106773 | return UA_ServerConfig_setBasics_withPort(conf, portNumber: 4840); |
| 106774 | } |
| 106775 | |
| 106776 | UA_EXPORT UA_StatusCode |
| 106777 | UA_ServerConfig_setBasics_withPort(UA_ServerConfig* conf, UA_UInt16 portNumber) { |
| 106778 | return setDefaultConfig(conf, portNumber); |
| 106779 | } |
| 106780 | |
| 106781 | UA_EXPORT UA_StatusCode |
| 106782 | UA_ServerConfig_addSecurityPolicyNone(UA_ServerConfig *config, |
| 106783 | const UA_ByteString *certificate) { |
| 106784 | /* Allocate the SecurityPolicies */ |
| 106785 | UA_SecurityPolicy *tmp = (UA_SecurityPolicy *) |
| 106786 | UA_realloc(ptr: config->securityPolicies, |
| 106787 | size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize)); |
| 106788 | if(!tmp) |
| 106789 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 106790 | config->securityPolicies = tmp; |
| 106791 | |
| 106792 | /* Populate the SecurityPolicies */ |
| 106793 | UA_ByteString localCertificate = UA_BYTESTRING_NULL; |
| 106794 | if(certificate) |
| 106795 | localCertificate = *certificate; |
| 106796 | UA_StatusCode retval = |
| 106797 | UA_SecurityPolicy_None(policy: &config->securityPolicies[config->securityPoliciesSize], |
| 106798 | localCertificate, logger: config->logging); |
| 106799 | if(retval != UA_STATUSCODE_GOOD) { |
| 106800 | if(config->securityPoliciesSize == 0) { |
| 106801 | UA_free(ptr: config->securityPolicies); |
| 106802 | config->securityPolicies = NULL; |
| 106803 | } |
| 106804 | return retval; |
| 106805 | } |
| 106806 | |
| 106807 | config->securityPoliciesSize++; |
| 106808 | return UA_STATUSCODE_GOOD; |
| 106809 | } |
| 106810 | |
| 106811 | UA_EXPORT UA_StatusCode |
| 106812 | UA_ServerConfig_addEndpoint(UA_ServerConfig *config, const UA_String securityPolicyUri, |
| 106813 | UA_MessageSecurityMode securityMode) { |
| 106814 | /* Lookup the security policy */ |
| 106815 | const UA_SecurityPolicy *policy = NULL; |
| 106816 | for (size_t i = 0; i < config->securityPoliciesSize; ++i) { |
| 106817 | if (UA_String_equal(p1: &securityPolicyUri, p2: &config->securityPolicies[i].policyUri)) { |
| 106818 | policy = &config->securityPolicies[i]; |
| 106819 | break; |
| 106820 | } |
| 106821 | } |
| 106822 | if(!policy) |
| 106823 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 106824 | |
| 106825 | /* Populate the endpoint */ |
| 106826 | return addEndpoint(conf: config, securityPolicy: policy, securityMode); |
| 106827 | } |
| 106828 | |
| 106829 | UA_EXPORT UA_StatusCode |
| 106830 | UA_ServerConfig_addAllEndpoints(UA_ServerConfig *config) { |
| 106831 | /* Populate the endpoints */ |
| 106832 | for(size_t i = 0; i < config->securityPoliciesSize; ++i) { |
| 106833 | if(UA_String_equal(p1: &UA_SECURITY_POLICY_NONE_URI, p2: &config->securityPolicies[i].policyUri)) { |
| 106834 | UA_StatusCode retval = |
| 106835 | addEndpoint(conf: config, securityPolicy: &config->securityPolicies[i], securityMode: UA_MESSAGESECURITYMODE_NONE); |
| 106836 | if(retval != UA_STATUSCODE_GOOD) |
| 106837 | return retval; |
| 106838 | } else { |
| 106839 | UA_StatusCode retval = |
| 106840 | addEndpoint(conf: config, securityPolicy: &config->securityPolicies[i], securityMode: UA_MESSAGESECURITYMODE_SIGN); |
| 106841 | if(retval != UA_STATUSCODE_GOOD) |
| 106842 | return retval; |
| 106843 | retval = addEndpoint(conf: config, securityPolicy: &config->securityPolicies[i], |
| 106844 | securityMode: UA_MESSAGESECURITYMODE_SIGNANDENCRYPT); |
| 106845 | if(retval != UA_STATUSCODE_GOOD) |
| 106846 | return retval; |
| 106847 | } |
| 106848 | } |
| 106849 | |
| 106850 | return UA_STATUSCODE_GOOD; |
| 106851 | } |
| 106852 | |
| 106853 | UA_EXPORT UA_StatusCode |
| 106854 | UA_ServerConfig_addAllSecureEndpoints(UA_ServerConfig *config) { |
| 106855 | UA_String noneuri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None"); |
| 106856 | UA_String basic128uri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15"); |
| 106857 | UA_String basic256uri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic256"); |
| 106858 | |
| 106859 | /* Delete all predefined endpoints. */ |
| 106860 | if(config->endpointsSize > 0) { |
| 106861 | for(size_t i = 0; i < config->endpointsSize; ++i) |
| 106862 | UA_EndpointDescription_clear(p: &config->endpoints[i]); |
| 106863 | |
| 106864 | UA_free(ptr: config->endpoints); |
| 106865 | config->endpoints = NULL; |
| 106866 | config->endpointsSize = 0; |
| 106867 | } |
| 106868 | |
| 106869 | /* Populate the endpoints */ |
| 106870 | for(size_t i = 0; i < config->securityPoliciesSize; ++i) { |
| 106871 | /* Skip the None and all deprecated policies */ |
| 106872 | if(UA_String_equal(p1: &config->securityPolicies[i].policyUri, p2: &noneuri) || |
| 106873 | UA_String_equal(p1: &config->securityPolicies[i].policyUri, p2: &basic128uri) || |
| 106874 | UA_String_equal(p1: &config->securityPolicies[i].policyUri, p2: &basic256uri)) { |
| 106875 | continue; |
| 106876 | } |
| 106877 | UA_StatusCode retval = |
| 106878 | addEndpoint(conf: config, securityPolicy: &config->securityPolicies[i], securityMode: UA_MESSAGESECURITYMODE_SIGN); |
| 106879 | if(retval != UA_STATUSCODE_GOOD) |
| 106880 | return retval; |
| 106881 | retval = addEndpoint(conf: config, securityPolicy: &config->securityPolicies[i], |
| 106882 | securityMode: UA_MESSAGESECURITYMODE_SIGNANDENCRYPT); |
| 106883 | if(retval != UA_STATUSCODE_GOOD) |
| 106884 | return retval; |
| 106885 | } |
| 106886 | |
| 106887 | return UA_STATUSCODE_GOOD; |
| 106888 | } |
| 106889 | |
| 106890 | UA_EXPORT UA_StatusCode |
| 106891 | UA_ServerConfig_setMinimalCustomBuffer(UA_ServerConfig *config, UA_UInt16 portNumber, |
| 106892 | const UA_ByteString *certificate, |
| 106893 | UA_UInt32 sendBufferSize, |
| 106894 | UA_UInt32 recvBufferSize) { |
| 106895 | if(!config) |
| 106896 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 106897 | |
| 106898 | UA_StatusCode retval = setDefaultConfig(conf: config, portNumber); |
| 106899 | if(retval != UA_STATUSCODE_GOOD) { |
| 106900 | UA_ServerConfig_clean(config); |
| 106901 | return retval; |
| 106902 | } |
| 106903 | |
| 106904 | /* Set the TCP settings */ |
| 106905 | config->tcpBufSize = recvBufferSize; |
| 106906 | |
| 106907 | /* Allocate the SecurityPolicies */ |
| 106908 | retval = UA_ServerConfig_addSecurityPolicyNone(config, certificate); |
| 106909 | if(retval != UA_STATUSCODE_GOOD) { |
| 106910 | UA_ServerConfig_clean(config); |
| 106911 | return retval; |
| 106912 | } |
| 106913 | |
| 106914 | /* Initialize the Access Control plugin */ |
| 106915 | retval = UA_AccessControl_default(config, true, NULL, usernamePasswordLoginSize: 0, NULL); |
| 106916 | if(retval != UA_STATUSCODE_GOOD) { |
| 106917 | UA_ServerConfig_clean(config); |
| 106918 | return retval; |
| 106919 | } |
| 106920 | |
| 106921 | /* Allocate the endpoint */ |
| 106922 | retval = UA_ServerConfig_addEndpoint(config, securityPolicyUri: UA_SECURITY_POLICY_NONE_URI, |
| 106923 | securityMode: UA_MESSAGESECURITYMODE_NONE); |
| 106924 | if(retval != UA_STATUSCODE_GOOD) { |
| 106925 | UA_ServerConfig_clean(config); |
| 106926 | return retval; |
| 106927 | } |
| 106928 | |
| 106929 | return UA_STATUSCODE_GOOD; |
| 106930 | } |
| 106931 | |
| 106932 | #ifdef UA_ENABLE_ENCRYPTION |
| 106933 | |
| 106934 | UA_EXPORT UA_StatusCode |
| 106935 | UA_ServerConfig_addSecurityPolicyBasic128Rsa15(UA_ServerConfig *config, |
| 106936 | const UA_ByteString *certificate, |
| 106937 | const UA_ByteString *privateKey) { |
| 106938 | /* Allocate the SecurityPolicies */ |
| 106939 | UA_SecurityPolicy *tmp = (UA_SecurityPolicy *) |
| 106940 | UA_realloc(ptr: config->securityPolicies, |
| 106941 | size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize)); |
| 106942 | if(!tmp) |
| 106943 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 106944 | config->securityPolicies = tmp; |
| 106945 | |
| 106946 | /* Populate the SecurityPolicies */ |
| 106947 | UA_ByteString localCertificate = UA_BYTESTRING_NULL; |
| 106948 | UA_ByteString localPrivateKey = UA_BYTESTRING_NULL; |
| 106949 | if(certificate) |
| 106950 | localCertificate = *certificate; |
| 106951 | if(privateKey) |
| 106952 | localPrivateKey = *privateKey; |
| 106953 | UA_StatusCode retval = |
| 106954 | UA_SecurityPolicy_Basic128Rsa15(policy: &config->securityPolicies[config->securityPoliciesSize], |
| 106955 | localCertificate, localPrivateKey, logger: config->logging); |
| 106956 | if(retval != UA_STATUSCODE_GOOD) { |
| 106957 | if(config->securityPoliciesSize == 0) { |
| 106958 | UA_free(ptr: config->securityPolicies); |
| 106959 | config->securityPolicies = NULL; |
| 106960 | } |
| 106961 | return retval; |
| 106962 | } |
| 106963 | |
| 106964 | config->securityPoliciesSize++; |
| 106965 | return UA_STATUSCODE_GOOD; |
| 106966 | } |
| 106967 | |
| 106968 | UA_EXPORT UA_StatusCode |
| 106969 | UA_ServerConfig_addSecurityPolicyBasic256(UA_ServerConfig *config, |
| 106970 | const UA_ByteString *certificate, |
| 106971 | const UA_ByteString *privateKey) { |
| 106972 | /* Allocate the SecurityPolicies */ |
| 106973 | UA_SecurityPolicy *tmp = (UA_SecurityPolicy *) |
| 106974 | UA_realloc(ptr: config->securityPolicies, |
| 106975 | size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize)); |
| 106976 | if(!tmp) |
| 106977 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 106978 | config->securityPolicies = tmp; |
| 106979 | |
| 106980 | /* Populate the SecurityPolicies */ |
| 106981 | UA_ByteString localCertificate = UA_BYTESTRING_NULL; |
| 106982 | UA_ByteString localPrivateKey = UA_BYTESTRING_NULL; |
| 106983 | if(certificate) |
| 106984 | localCertificate = *certificate; |
| 106985 | if(privateKey) |
| 106986 | localPrivateKey = *privateKey; |
| 106987 | UA_StatusCode retval = |
| 106988 | UA_SecurityPolicy_Basic256(policy: &config->securityPolicies[config->securityPoliciesSize], |
| 106989 | localCertificate, localPrivateKey, logger: config->logging); |
| 106990 | if(retval != UA_STATUSCODE_GOOD) { |
| 106991 | if(config->securityPoliciesSize == 0) { |
| 106992 | UA_free(ptr: config->securityPolicies); |
| 106993 | config->securityPolicies = NULL; |
| 106994 | } |
| 106995 | return retval; |
| 106996 | } |
| 106997 | |
| 106998 | config->securityPoliciesSize++; |
| 106999 | return UA_STATUSCODE_GOOD; |
| 107000 | } |
| 107001 | |
| 107002 | UA_EXPORT UA_StatusCode |
| 107003 | UA_ServerConfig_addSecurityPolicyBasic256Sha256(UA_ServerConfig *config, |
| 107004 | const UA_ByteString *certificate, |
| 107005 | const UA_ByteString *privateKey) { |
| 107006 | /* Allocate the SecurityPolicies */ |
| 107007 | UA_SecurityPolicy *tmp = (UA_SecurityPolicy *) |
| 107008 | UA_realloc(ptr: config->securityPolicies, |
| 107009 | size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize)); |
| 107010 | if(!tmp) |
| 107011 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 107012 | config->securityPolicies = tmp; |
| 107013 | |
| 107014 | /* Populate the SecurityPolicies */ |
| 107015 | UA_ByteString localCertificate = UA_BYTESTRING_NULL; |
| 107016 | UA_ByteString localPrivateKey = UA_BYTESTRING_NULL; |
| 107017 | if(certificate) |
| 107018 | localCertificate = *certificate; |
| 107019 | if(privateKey) |
| 107020 | localPrivateKey = *privateKey; |
| 107021 | UA_StatusCode retval = |
| 107022 | UA_SecurityPolicy_Basic256Sha256(policy: &config->securityPolicies[config->securityPoliciesSize], |
| 107023 | localCertificate, localPrivateKey, logger: config->logging); |
| 107024 | if(retval != UA_STATUSCODE_GOOD) { |
| 107025 | if(config->securityPoliciesSize == 0) { |
| 107026 | UA_free(ptr: config->securityPolicies); |
| 107027 | config->securityPolicies = NULL; |
| 107028 | } |
| 107029 | return retval; |
| 107030 | } |
| 107031 | |
| 107032 | config->securityPoliciesSize++; |
| 107033 | return UA_STATUSCODE_GOOD; |
| 107034 | } |
| 107035 | |
| 107036 | UA_EXPORT UA_StatusCode |
| 107037 | UA_ServerConfig_addSecurityPolicyAes128Sha256RsaOaep(UA_ServerConfig *config, |
| 107038 | const UA_ByteString *certificate, |
| 107039 | const UA_ByteString *privateKey) { |
| 107040 | /* Allocate the SecurityPolicies */ |
| 107041 | UA_SecurityPolicy *tmp = (UA_SecurityPolicy *) |
| 107042 | UA_realloc(ptr: config->securityPolicies, |
| 107043 | size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize)); |
| 107044 | if(!tmp) |
| 107045 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 107046 | config->securityPolicies = tmp; |
| 107047 | |
| 107048 | /* Populate the SecurityPolicies */ |
| 107049 | UA_ByteString localCertificate = UA_BYTESTRING_NULL; |
| 107050 | UA_ByteString localPrivateKey = UA_BYTESTRING_NULL; |
| 107051 | if(certificate) |
| 107052 | localCertificate = *certificate; |
| 107053 | if(privateKey) |
| 107054 | localPrivateKey = *privateKey; |
| 107055 | UA_StatusCode retval = |
| 107056 | UA_SecurityPolicy_Aes128Sha256RsaOaep(policy: &config->securityPolicies[config->securityPoliciesSize], |
| 107057 | localCertificate, localPrivateKey, logger: config->logging); |
| 107058 | if(retval != UA_STATUSCODE_GOOD) { |
| 107059 | if(config->securityPoliciesSize == 0) { |
| 107060 | UA_free(ptr: config->securityPolicies); |
| 107061 | config->securityPolicies = NULL; |
| 107062 | } |
| 107063 | return retval; |
| 107064 | } |
| 107065 | |
| 107066 | config->securityPoliciesSize++; |
| 107067 | return UA_STATUSCODE_GOOD; |
| 107068 | } |
| 107069 | |
| 107070 | UA_EXPORT UA_StatusCode |
| 107071 | UA_ServerConfig_addSecurityPolicyAes256Sha256RsaPss(UA_ServerConfig *config, |
| 107072 | const UA_ByteString *certificate, |
| 107073 | const UA_ByteString *privateKey) { |
| 107074 | /* Allocate the SecurityPolicies */ |
| 107075 | UA_SecurityPolicy *tmp = (UA_SecurityPolicy *) |
| 107076 | UA_realloc(ptr: config->securityPolicies, |
| 107077 | size: sizeof(UA_SecurityPolicy) * (1 + config->securityPoliciesSize)); |
| 107078 | if(!tmp) |
| 107079 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 107080 | config->securityPolicies = tmp; |
| 107081 | |
| 107082 | /* Populate the SecurityPolicies */ |
| 107083 | UA_ByteString localCertificate = UA_BYTESTRING_NULL; |
| 107084 | UA_ByteString localPrivateKey = UA_BYTESTRING_NULL; |
| 107085 | if(certificate) |
| 107086 | localCertificate = *certificate; |
| 107087 | if(privateKey) |
| 107088 | localPrivateKey = *privateKey; |
| 107089 | UA_StatusCode retval = |
| 107090 | UA_SecurityPolicy_Aes256Sha256RsaPss(policy: &config->securityPolicies[config->securityPoliciesSize], |
| 107091 | localCertificate, localPrivateKey, logger: config->logging); |
| 107092 | if(retval != UA_STATUSCODE_GOOD) { |
| 107093 | if(config->securityPoliciesSize == 0) { |
| 107094 | UA_free(ptr: config->securityPolicies); |
| 107095 | config->securityPolicies = NULL; |
| 107096 | } |
| 107097 | return retval; |
| 107098 | } |
| 107099 | |
| 107100 | config->securityPoliciesSize++; |
| 107101 | return UA_STATUSCODE_GOOD; |
| 107102 | } |
| 107103 | |
| 107104 | /* Always returns UA_STATUSCODE_GOOD. Logs a warning if policies could not be added. */ |
| 107105 | static UA_StatusCode |
| 107106 | addAllSecurityPolicies(UA_ServerConfig *config, const UA_ByteString *certificate, |
| 107107 | const UA_ByteString *privateKey, UA_Boolean onlySecure) { |
| 107108 | /* Populate the SecurityPolicies */ |
| 107109 | UA_ByteString localCertificate = UA_BYTESTRING_NULL; |
| 107110 | UA_ByteString localPrivateKey = UA_BYTESTRING_NULL; |
| 107111 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 107112 | if(certificate) |
| 107113 | localCertificate = *certificate; |
| 107114 | if(privateKey) |
| 107115 | localPrivateKey = *privateKey; |
| 107116 | |
| 107117 | /* Load the private key and convert to the DER format. Use an empty password |
| 107118 | * on the first try -- maybe the key does not require a password. */ |
| 107119 | UA_ByteString decryptedPrivateKey = UA_BYTESTRING_NULL; |
| 107120 | UA_ByteString keyPassword = UA_BYTESTRING_NULL; |
| 107121 | UA_StatusCode keySuccess = UA_STATUSCODE_GOOD; |
| 107122 | |
| 107123 | if (privateKey && privateKey->length > 0) |
| 107124 | keySuccess = UA_PKI_decryptPrivateKey(privateKey: localPrivateKey, password: keyPassword, |
| 107125 | outDerKey: &decryptedPrivateKey); |
| 107126 | |
| 107127 | /* Get the password and decrypt. An application might want to loop / retry |
| 107128 | * here to allow users to correct their entry. */ |
| 107129 | if(keySuccess != UA_STATUSCODE_GOOD) { |
| 107130 | if(config->privateKeyPasswordCallback) |
| 107131 | keySuccess = config->privateKeyPasswordCallback(config, &keyPassword); |
| 107132 | else |
| 107133 | keySuccess = readPrivateKeyPassword(password: &keyPassword); |
| 107134 | if(keySuccess != UA_STATUSCODE_GOOD) |
| 107135 | return keySuccess; |
| 107136 | keySuccess = UA_PKI_decryptPrivateKey(privateKey: localPrivateKey, password: keyPassword, |
| 107137 | outDerKey: &decryptedPrivateKey); |
| 107138 | UA_ByteString_memZero(bs: &keyPassword); |
| 107139 | UA_ByteString_clear(p: &keyPassword); |
| 107140 | } |
| 107141 | if(keySuccess != UA_STATUSCODE_GOOD) |
| 107142 | return keySuccess; |
| 107143 | |
| 107144 | /* Basic256Sha256 */ |
| 107145 | retval = UA_ServerConfig_addSecurityPolicyBasic256Sha256(config, certificate: &localCertificate, |
| 107146 | privateKey: &decryptedPrivateKey); |
| 107147 | if(retval != UA_STATUSCODE_GOOD) { |
| 107148 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 107149 | msg: "Could not add SecurityPolicy#Basic256Sha256 with error code %s", |
| 107150 | UA_StatusCode_name(code: retval)); |
| 107151 | } |
| 107152 | |
| 107153 | /* Aes256Sha256RsaPss */ |
| 107154 | retval = UA_ServerConfig_addSecurityPolicyAes256Sha256RsaPss(config, certificate: &localCertificate, |
| 107155 | privateKey: &decryptedPrivateKey); |
| 107156 | if(retval != UA_STATUSCODE_GOOD) { |
| 107157 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 107158 | msg: "Could not add SecurityPolicy#Aes256Sha256RsaPss with error code %s", |
| 107159 | UA_StatusCode_name(code: retval)); |
| 107160 | } |
| 107161 | |
| 107162 | /* Aes128Sha256RsaOaep */ |
| 107163 | retval = UA_ServerConfig_addSecurityPolicyAes128Sha256RsaOaep(config, certificate: &localCertificate, |
| 107164 | privateKey: &decryptedPrivateKey); |
| 107165 | if(retval != UA_STATUSCODE_GOOD) { |
| 107166 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 107167 | msg: "Could not add SecurityPolicy#Aes128Sha256RsaOaep with error code %s", |
| 107168 | UA_StatusCode_name(code: retval)); |
| 107169 | } |
| 107170 | |
| 107171 | if(onlySecure) { |
| 107172 | UA_ByteString_memZero(bs: &decryptedPrivateKey); |
| 107173 | UA_ByteString_clear(p: &decryptedPrivateKey); |
| 107174 | return UA_STATUSCODE_GOOD; |
| 107175 | } |
| 107176 | |
| 107177 | /* None */ |
| 107178 | retval = UA_ServerConfig_addSecurityPolicyNone(config, certificate: &localCertificate); |
| 107179 | if(retval != UA_STATUSCODE_GOOD) { |
| 107180 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 107181 | msg: "Could not add SecurityPolicy#None with error code %s", |
| 107182 | UA_StatusCode_name(code: retval)); |
| 107183 | } |
| 107184 | |
| 107185 | #ifdef UA_INCLUDE_INSECURE_POLICIES |
| 107186 | /* Basic128Rsa15 should no longer be used */ |
| 107187 | retval = UA_ServerConfig_addSecurityPolicyBasic128Rsa15(config, &localCertificate, |
| 107188 | &decryptedPrivateKey); |
| 107189 | if(retval != UA_STATUSCODE_GOOD) { |
| 107190 | UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_USERLAND, |
| 107191 | "Could not add SecurityPolicy#Basic128Rsa15 with error code %s", |
| 107192 | UA_StatusCode_name(retval)); |
| 107193 | } |
| 107194 | |
| 107195 | /* Basic256 should no longer be used */ |
| 107196 | retval = UA_ServerConfig_addSecurityPolicyBasic256(config, &localCertificate, |
| 107197 | &decryptedPrivateKey); |
| 107198 | if(retval != UA_STATUSCODE_GOOD) { |
| 107199 | UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_USERLAND, |
| 107200 | "Could not add SecurityPolicy#Basic256 with error code %s", |
| 107201 | UA_StatusCode_name(retval)); |
| 107202 | } |
| 107203 | #endif |
| 107204 | |
| 107205 | UA_ByteString_memZero(bs: &decryptedPrivateKey); |
| 107206 | UA_ByteString_clear(p: &decryptedPrivateKey); |
| 107207 | return UA_STATUSCODE_GOOD; |
| 107208 | } |
| 107209 | |
| 107210 | UA_StatusCode |
| 107211 | UA_ServerConfig_addAllSecurityPolicies(UA_ServerConfig *config, |
| 107212 | const UA_ByteString *certificate, |
| 107213 | const UA_ByteString *privateKey) { |
| 107214 | return addAllSecurityPolicies(config, certificate, privateKey, false); |
| 107215 | } |
| 107216 | |
| 107217 | /* Always returns UA_STATUSCODE_GOOD. Logs a warning if policies could not be added. */ |
| 107218 | UA_StatusCode |
| 107219 | UA_ServerConfig_addAllSecureSecurityPolicies(UA_ServerConfig *config, |
| 107220 | const UA_ByteString *certificate, |
| 107221 | const UA_ByteString *privateKey) { |
| 107222 | return addAllSecurityPolicies(config, certificate, privateKey, true); |
| 107223 | |
| 107224 | } |
| 107225 | |
| 107226 | UA_EXPORT UA_StatusCode |
| 107227 | UA_ServerConfig_setDefaultWithSecurityPolicies(UA_ServerConfig *conf, |
| 107228 | UA_UInt16 portNumber, |
| 107229 | const UA_ByteString *certificate, |
| 107230 | const UA_ByteString *privateKey, |
| 107231 | const UA_ByteString *trustList, |
| 107232 | size_t trustListSize, |
| 107233 | const UA_ByteString *issuerList, |
| 107234 | size_t issuerListSize, |
| 107235 | const UA_ByteString *revocationList, |
| 107236 | size_t revocationListSize) { |
| 107237 | UA_StatusCode retval = setDefaultConfig(conf, portNumber); |
| 107238 | if(retval != UA_STATUSCODE_GOOD) { |
| 107239 | UA_ServerConfig_clean(config: conf); |
| 107240 | return retval; |
| 107241 | } |
| 107242 | |
| 107243 | retval = UA_CertificateVerification_Trustlist(cv: &conf->sessionPKI, |
| 107244 | certificateTrustList: trustList, certificateTrustListSize: trustListSize, |
| 107245 | certificateIssuerList: issuerList, certificateIssuerListSize: issuerListSize, |
| 107246 | certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize); |
| 107247 | if(retval != UA_STATUSCODE_GOOD) |
| 107248 | return retval; |
| 107249 | |
| 107250 | retval = UA_CertificateVerification_Trustlist(cv: &conf->secureChannelPKI, |
| 107251 | certificateTrustList: trustList, certificateTrustListSize: trustListSize, |
| 107252 | certificateIssuerList: issuerList, certificateIssuerListSize: issuerListSize, |
| 107253 | certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize); |
| 107254 | if(retval != UA_STATUSCODE_GOOD) |
| 107255 | return retval; |
| 107256 | |
| 107257 | retval = UA_ServerConfig_addAllSecurityPolicies(config: conf, certificate, privateKey); |
| 107258 | |
| 107259 | if(retval == UA_STATUSCODE_GOOD) { |
| 107260 | retval = UA_AccessControl_default(config: conf, true, NULL, usernamePasswordLoginSize: 0, NULL); |
| 107261 | } |
| 107262 | if(retval != UA_STATUSCODE_GOOD) { |
| 107263 | UA_ServerConfig_clean(config: conf); |
| 107264 | return retval; |
| 107265 | } |
| 107266 | |
| 107267 | retval = UA_ServerConfig_addAllEndpoints(config: conf); |
| 107268 | if(retval != UA_STATUSCODE_GOOD) { |
| 107269 | UA_ServerConfig_clean(config: conf); |
| 107270 | return retval; |
| 107271 | } |
| 107272 | |
| 107273 | return UA_STATUSCODE_GOOD; |
| 107274 | } |
| 107275 | |
| 107276 | UA_EXPORT UA_StatusCode |
| 107277 | UA_ServerConfig_setDefaultWithSecureSecurityPolicies(UA_ServerConfig *conf, |
| 107278 | UA_UInt16 portNumber, |
| 107279 | const UA_ByteString *certificate, |
| 107280 | const UA_ByteString *privateKey, |
| 107281 | const UA_ByteString *trustList, |
| 107282 | size_t trustListSize, |
| 107283 | const UA_ByteString *issuerList, |
| 107284 | size_t issuerListSize, |
| 107285 | const UA_ByteString *revocationList, |
| 107286 | size_t revocationListSize) { |
| 107287 | UA_StatusCode retval = setDefaultConfig(conf, portNumber); |
| 107288 | if(retval != UA_STATUSCODE_GOOD) { |
| 107289 | UA_ServerConfig_clean(config: conf); |
| 107290 | return retval; |
| 107291 | } |
| 107292 | |
| 107293 | retval = UA_CertificateVerification_Trustlist(cv: &conf->sessionPKI, |
| 107294 | certificateTrustList: trustList, certificateTrustListSize: trustListSize, |
| 107295 | certificateIssuerList: issuerList, certificateIssuerListSize: issuerListSize, |
| 107296 | certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize); |
| 107297 | if(retval != UA_STATUSCODE_GOOD) |
| 107298 | return retval; |
| 107299 | |
| 107300 | retval = UA_CertificateVerification_Trustlist(cv: &conf->secureChannelPKI, |
| 107301 | certificateTrustList: trustList, certificateTrustListSize: trustListSize, |
| 107302 | certificateIssuerList: issuerList, certificateIssuerListSize: issuerListSize, |
| 107303 | certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize); |
| 107304 | if(retval != UA_STATUSCODE_GOOD) |
| 107305 | return retval; |
| 107306 | |
| 107307 | retval = UA_ServerConfig_addAllSecureSecurityPolicies(config: conf, certificate, privateKey); |
| 107308 | |
| 107309 | if(retval == UA_STATUSCODE_GOOD) { |
| 107310 | retval = UA_AccessControl_default(config: conf, false, NULL, usernamePasswordLoginSize: 0, NULL); |
| 107311 | } |
| 107312 | if(retval != UA_STATUSCODE_GOOD) { |
| 107313 | UA_ServerConfig_clean(config: conf); |
| 107314 | return retval; |
| 107315 | } |
| 107316 | |
| 107317 | retval = UA_ServerConfig_addAllSecureEndpoints(config: conf); |
| 107318 | if(retval != UA_STATUSCODE_GOOD) { |
| 107319 | UA_ServerConfig_clean(config: conf); |
| 107320 | return retval; |
| 107321 | } |
| 107322 | conf->securityPolicyNoneDiscoveryOnly = true; |
| 107323 | |
| 107324 | return UA_STATUSCODE_GOOD; |
| 107325 | } |
| 107326 | |
| 107327 | #endif |
| 107328 | |
| 107329 | /***************************/ |
| 107330 | /* Default Client Settings */ |
| 107331 | /***************************/ |
| 107332 | |
| 107333 | UA_Client * UA_Client_new(void) { |
| 107334 | UA_ClientConfig config; |
| 107335 | memset(s: &config, c: 0, n: sizeof(UA_ClientConfig)); |
| 107336 | /* Set up basic usable config including logger and event loop */ |
| 107337 | UA_StatusCode res = UA_ClientConfig_setDefault(config: &config); |
| 107338 | if(res != UA_STATUSCODE_GOOD) |
| 107339 | return NULL; |
| 107340 | return UA_Client_newWithConfig(config: &config); |
| 107341 | } |
| 107342 | |
| 107343 | UA_StatusCode |
| 107344 | UA_ClientConfig_setDefault(UA_ClientConfig *config) { |
| 107345 | /* The following fields are untouched and OK to leave as NULL or 0: |
| 107346 | * clientContext |
| 107347 | * userIdentityToken |
| 107348 | * securityMode |
| 107349 | * securityPolicyUri |
| 107350 | * endpoint |
| 107351 | * userTokenPolicy |
| 107352 | * customDataTypes |
| 107353 | * connectivityCheckInterval |
| 107354 | * stateCallback |
| 107355 | * inactivityCallback |
| 107356 | * outStandingPublishRequests |
| 107357 | * subscriptionInactivityCallback |
| 107358 | * sessionLocaleIds |
| 107359 | * sessionLocaleIdsSize */ |
| 107360 | |
| 107361 | if(config->timeout == 0) |
| 107362 | config->timeout = 5 * 1000; /* 5 seconds */ |
| 107363 | if(config->secureChannelLifeTime == 0) |
| 107364 | config->secureChannelLifeTime = 10 * 60 * 1000; /* 10 minutes */ |
| 107365 | |
| 107366 | if(config->logging == NULL) |
| 107367 | config->logging = UA_Log_Stdout_new(minlevel: UA_LOGLEVEL_INFO); |
| 107368 | |
| 107369 | /* EventLoop */ |
| 107370 | if(config->eventLoop == NULL) { |
| 107371 | config->eventLoop = UA_EventLoop_new_POSIX(logger: config->logging); |
| 107372 | config->externalEventLoop = false; |
| 107373 | |
| 107374 | /* Add the TCP connection manager */ |
| 107375 | UA_ConnectionManager *tcpCM = |
| 107376 | UA_ConnectionManager_new_POSIX_TCP(eventSourceName: UA_STRING(chars: "tcp connection manager")); |
| 107377 | config->eventLoop->registerEventSource(config->eventLoop, (UA_EventSource *)tcpCM); |
| 107378 | |
| 107379 | /* Add the UDP connection manager */ |
| 107380 | UA_ConnectionManager *udpCM = |
| 107381 | UA_ConnectionManager_new_POSIX_UDP(eventSourceName: UA_STRING(chars: "udp connection manager")); |
| 107382 | config->eventLoop->registerEventSource(config->eventLoop, (UA_EventSource *)udpCM); |
| 107383 | } |
| 107384 | |
| 107385 | if(config->localConnectionConfig.recvBufferSize == 0) |
| 107386 | config->localConnectionConfig = UA_ConnectionConfig_default; |
| 107387 | |
| 107388 | if(!config->certificateVerification.logging) { |
| 107389 | config->certificateVerification.logging = config->logging; |
| 107390 | } |
| 107391 | |
| 107392 | if(!config->certificateVerification.verifyCertificate) { |
| 107393 | /* Certificate Verification that accepts every certificate. Can be |
| 107394 | * overwritten when the policy is specialized. */ |
| 107395 | UA_CertificateVerification_AcceptAll(cv: &config->certificateVerification); |
| 107396 | } |
| 107397 | |
| 107398 | /* With encryption enabled, the applicationUri needs to match the URI from |
| 107399 | * the certificate */ |
| 107400 | if(!config->clientDescription.applicationUri.data) |
| 107401 | config->clientDescription.applicationUri = UA_STRING_ALLOC(APPLICATION_URI); |
| 107402 | if(config->clientDescription.applicationType == 0) |
| 107403 | config->clientDescription.applicationType = UA_APPLICATIONTYPE_CLIENT; |
| 107404 | |
| 107405 | if(config->securityPoliciesSize == 0) { |
| 107406 | config->securityPolicies = (UA_SecurityPolicy*)UA_malloc(size: sizeof(UA_SecurityPolicy)); |
| 107407 | if(!config->securityPolicies) |
| 107408 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 107409 | UA_StatusCode retval = UA_SecurityPolicy_None(policy: config->securityPolicies, |
| 107410 | localCertificate: UA_BYTESTRING_NULL, logger: config->logging); |
| 107411 | if(retval != UA_STATUSCODE_GOOD) { |
| 107412 | UA_free(ptr: config->securityPolicies); |
| 107413 | config->securityPolicies = NULL; |
| 107414 | return retval; |
| 107415 | } |
| 107416 | config->securityPoliciesSize = 1; |
| 107417 | } |
| 107418 | |
| 107419 | if(config->requestedSessionTimeout == 0) |
| 107420 | config->requestedSessionTimeout = 1200000; |
| 107421 | |
| 107422 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 107423 | if(config->outStandingPublishRequests == 0) |
| 107424 | config->outStandingPublishRequests = 10; |
| 107425 | #endif |
| 107426 | |
| 107427 | return UA_STATUSCODE_GOOD; |
| 107428 | } |
| 107429 | |
| 107430 | #ifdef UA_ENABLE_ENCRYPTION |
| 107431 | |
| 107432 | static UA_StatusCode |
| 107433 | securityPolicies_addAll(UA_SecurityPolicy *sp, size_t *length, |
| 107434 | UA_ByteString certificate, UA_ByteString privateKey, UA_Logger *logging) { |
| 107435 | UA_StatusCode retval; |
| 107436 | size_t size = *length; |
| 107437 | |
| 107438 | #ifdef UA_INCLUDE_INSECURE_POLICIES |
| 107439 | /* Basic128Rsa15 is unsecure and should not be used */ |
| 107440 | retval = UA_SecurityPolicy_Basic128Rsa15(&sp[size], certificate, privateKey, logging); |
| 107441 | if(retval == UA_STATUSCODE_GOOD) { |
| 107442 | size++; |
| 107443 | } else { |
| 107444 | UA_LOG_WARNING(logging, UA_LOGCATEGORY_USERLAND, |
| 107445 | "Could not add SecurityPolicy#Basic128Rsa15 with error code %s", |
| 107446 | UA_StatusCode_name(retval)); |
| 107447 | } |
| 107448 | |
| 107449 | /* Basic256 is unsecure and should not be used */ |
| 107450 | retval = UA_SecurityPolicy_Basic256(&sp[size], certificate, privateKey, logging); |
| 107451 | if(retval == UA_STATUSCODE_GOOD) { |
| 107452 | size++; |
| 107453 | } else { |
| 107454 | UA_LOG_WARNING(logging, UA_LOGCATEGORY_USERLAND, |
| 107455 | "Could not add SecurityPolicy#Basic256 with error code %s", |
| 107456 | UA_StatusCode_name(retval)); |
| 107457 | } |
| 107458 | #endif |
| 107459 | retval = UA_SecurityPolicy_Aes256Sha256RsaPss(policy: &sp[size], localCertificate: certificate, localPrivateKey: privateKey, logger: logging); |
| 107460 | if(retval == UA_STATUSCODE_GOOD) { |
| 107461 | size++; |
| 107462 | } else { |
| 107463 | UA_LOG_WARNING(logger: logging, category: UA_LOGCATEGORY_USERLAND, |
| 107464 | msg: "Could not add SecurityPolicy#Aes256Sha256RsaPss with error code %s", |
| 107465 | UA_StatusCode_name(code: retval)); |
| 107466 | } |
| 107467 | |
| 107468 | retval = UA_SecurityPolicy_Basic256Sha256(policy: &sp[size], localCertificate: certificate, localPrivateKey: privateKey, logger: logging); |
| 107469 | if(retval == UA_STATUSCODE_GOOD) { |
| 107470 | size++; |
| 107471 | } else { |
| 107472 | UA_LOG_WARNING(logger: logging, category: UA_LOGCATEGORY_USERLAND, |
| 107473 | msg: "Could not add SecurityPolicy#Basic256Sha256 with error code %s", |
| 107474 | UA_StatusCode_name(code: retval)); |
| 107475 | } |
| 107476 | |
| 107477 | retval = UA_SecurityPolicy_Aes128Sha256RsaOaep(policy: &sp[size], localCertificate: certificate, localPrivateKey: privateKey, logger: logging); |
| 107478 | if(retval == UA_STATUSCODE_GOOD) { |
| 107479 | size++; |
| 107480 | } else { |
| 107481 | UA_LOG_WARNING(logger: logging, category: UA_LOGCATEGORY_USERLAND, |
| 107482 | msg: "Could not add SecurityPolicy#Aes128Sha256RsaOaep with error code %s", |
| 107483 | UA_StatusCode_name(code: retval)); |
| 107484 | } |
| 107485 | *length = size; |
| 107486 | return retval; |
| 107487 | } |
| 107488 | |
| 107489 | static UA_StatusCode |
| 107490 | clientConfig_setAuthenticationSecurityPolicies(UA_ClientConfig *config, |
| 107491 | UA_ByteString certificateAuth, |
| 107492 | UA_ByteString privateKeyAuth) { |
| 107493 | UA_SecurityPolicy *sp = (UA_SecurityPolicy*) |
| 107494 | UA_realloc(ptr: config->authSecurityPolicies, size: sizeof(UA_SecurityPolicy) * SECURITY_POLICY_SIZE); |
| 107495 | if(!sp) |
| 107496 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 107497 | config->authSecurityPolicies = sp; |
| 107498 | |
| 107499 | /* Clean up old SecurityPolicies */ |
| 107500 | for(size_t i = 0; i < config->authSecurityPoliciesSize; i++) { |
| 107501 | config->authSecurityPolicies[i].clear(&config->authSecurityPolicies[i]); |
| 107502 | } |
| 107503 | config->authSecurityPoliciesSize = 0; |
| 107504 | |
| 107505 | UA_StatusCode retval = securityPolicies_addAll(sp, length: &config->authSecurityPoliciesSize, |
| 107506 | certificate: certificateAuth, privateKey: privateKeyAuth, logging: config->logging); |
| 107507 | |
| 107508 | if(config->authSecurityPoliciesSize == 0) { |
| 107509 | UA_free(ptr: config->authSecurityPolicies); |
| 107510 | config->authSecurityPolicies = NULL; |
| 107511 | } |
| 107512 | |
| 107513 | return retval; |
| 107514 | } |
| 107515 | |
| 107516 | UA_StatusCode |
| 107517 | UA_ClientConfig_setDefaultEncryption(UA_ClientConfig *config, |
| 107518 | UA_ByteString localCertificate, UA_ByteString privateKey, |
| 107519 | const UA_ByteString *trustList, size_t trustListSize, |
| 107520 | const UA_ByteString *revocationList, size_t revocationListSize) { |
| 107521 | UA_StatusCode retval = UA_ClientConfig_setDefault(config); |
| 107522 | if(retval != UA_STATUSCODE_GOOD) |
| 107523 | return retval; |
| 107524 | |
| 107525 | if(trustListSize || revocationListSize) { |
| 107526 | retval = UA_CertificateVerification_Trustlist(cv: &config->certificateVerification, |
| 107527 | certificateTrustList: trustList, certificateTrustListSize: trustListSize, |
| 107528 | NULL, certificateIssuerListSize: 0, |
| 107529 | certificateRevocationList: revocationList, certificateRevocationListSize: revocationListSize); |
| 107530 | if(retval != UA_STATUSCODE_GOOD) |
| 107531 | return retval; |
| 107532 | } else { |
| 107533 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 107534 | msg: "Empty trustlist and revocationlist passed, leaving the previously configured certificate verification in place"); |
| 107535 | } |
| 107536 | |
| 107537 | /* Populate SecurityPolicies, append to pre existing and don't overwrite */ |
| 107538 | UA_SecurityPolicy *sp = (UA_SecurityPolicy*) |
| 107539 | UA_realloc(ptr: config->securityPolicies, size: sizeof(UA_SecurityPolicy) * (config->securityPoliciesSize + SECURITY_POLICY_SIZE)); |
| 107540 | if(!sp) |
| 107541 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 107542 | config->securityPolicies = sp; |
| 107543 | |
| 107544 | /* Load the private key and convert to the DER format. Use an empty password |
| 107545 | * on the first try -- maybe the key does not require a password. */ |
| 107546 | UA_ByteString decryptedPrivateKey = UA_BYTESTRING_NULL; |
| 107547 | UA_ByteString keyPassword = UA_BYTESTRING_NULL; |
| 107548 | UA_StatusCode keySuccess = UA_STATUSCODE_GOOD; |
| 107549 | |
| 107550 | if (privateKey.length > 0) |
| 107551 | keySuccess = UA_PKI_decryptPrivateKey(privateKey, password: keyPassword, |
| 107552 | outDerKey: &decryptedPrivateKey); |
| 107553 | |
| 107554 | /* Get the password and decrypt. An application might want to loop / retry |
| 107555 | * here to allow users to correct their entry. */ |
| 107556 | if(keySuccess != UA_STATUSCODE_GOOD) { |
| 107557 | if(config->privateKeyPasswordCallback) |
| 107558 | keySuccess = config->privateKeyPasswordCallback(config, &keyPassword); |
| 107559 | else |
| 107560 | keySuccess = readPrivateKeyPassword(password: &keyPassword); |
| 107561 | if(keySuccess != UA_STATUSCODE_GOOD) |
| 107562 | return keySuccess; |
| 107563 | keySuccess = UA_PKI_decryptPrivateKey(privateKey, password: keyPassword, outDerKey: &decryptedPrivateKey); |
| 107564 | UA_ByteString_memZero(bs: &keyPassword); |
| 107565 | UA_ByteString_clear(p: &keyPassword); |
| 107566 | } |
| 107567 | if(keySuccess != UA_STATUSCODE_GOOD) |
| 107568 | return keySuccess; |
| 107569 | |
| 107570 | securityPolicies_addAll(sp, length: &config->securityPoliciesSize, |
| 107571 | certificate: localCertificate, privateKey: decryptedPrivateKey, logging: config->logging); |
| 107572 | |
| 107573 | /* Set the same certificate also for authentication. |
| 107574 | * Can be overridden with a different certificate. */ |
| 107575 | if(config->authSecurityPoliciesSize == 0) |
| 107576 | clientConfig_setAuthenticationSecurityPolicies(config, certificateAuth: localCertificate, |
| 107577 | privateKeyAuth: decryptedPrivateKey); |
| 107578 | |
| 107579 | UA_ByteString_memZero(bs: &decryptedPrivateKey); |
| 107580 | UA_ByteString_clear(p: &decryptedPrivateKey); |
| 107581 | |
| 107582 | if(config->securityPoliciesSize == 0) { |
| 107583 | UA_free(ptr: config->securityPolicies); |
| 107584 | config->securityPolicies = NULL; |
| 107585 | } |
| 107586 | |
| 107587 | return UA_STATUSCODE_GOOD; |
| 107588 | } |
| 107589 | #endif |
| 107590 | |
| 107591 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_MBEDTLS) |
| 107592 | UA_StatusCode |
| 107593 | UA_ClientConfig_setAuthenticationCert(UA_ClientConfig *config, |
| 107594 | UA_ByteString certificateAuth, |
| 107595 | UA_ByteString privateKeyAuth) { |
| 107596 | #ifdef UA_ENABLE_ENCRYPTION_LIBRESSL |
| 107597 | UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_USERLAND, |
| 107598 | "Certificate authentication with LibreSSL as crypto backend is not supported."); |
| 107599 | return UA_STATUSCODE_BADNOTIMPLEMENTED; |
| 107600 | #endif |
| 107601 | |
| 107602 | /* Create UserIdentityToken */ |
| 107603 | UA_X509IdentityToken* identityToken = UA_X509IdentityToken_new(); |
| 107604 | if(!identityToken) |
| 107605 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 107606 | /* Don't set identityToken->policyId. This is taken from the appropriate |
| 107607 | * endpoint at runtime. */ |
| 107608 | UA_StatusCode retval = UA_ByteString_copy(src: &certificateAuth, dst: &identityToken->certificateData); |
| 107609 | if(retval != UA_STATUSCODE_GOOD) |
| 107610 | return retval; |
| 107611 | UA_ExtensionObject_clear(p: &config->userIdentityToken); |
| 107612 | config->userIdentityToken.encoding = UA_EXTENSIONOBJECT_DECODED; |
| 107613 | config->userIdentityToken.content.decoded.type = &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]; |
| 107614 | config->userIdentityToken.content.decoded.data = identityToken; |
| 107615 | |
| 107616 | /* Populate SecurityPolicies */ |
| 107617 | return clientConfig_setAuthenticationSecurityPolicies(config, certificateAuth, privateKeyAuth); |
| 107618 | } |
| 107619 | #endif |
| 107620 | |
| 107621 | /**** amalgamated original file "/plugins/ua_config_json.c" ****/ |
| 107622 | |
| 107623 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 107624 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 107625 | * |
| 107626 | * Copyright 2023 (c) Fraunhofer IOSB (Author: Noel Graf) |
| 107627 | */ |
| 107628 | |
| 107629 | #ifdef UA_ENABLE_ENCRYPTION |
| 107630 | #endif |
| 107631 | |
| 107632 | #define MAX_TOKENS 256 |
| 107633 | |
| 107634 | typedef struct { |
| 107635 | const char *json; |
| 107636 | const cj5_token *tokens; |
| 107637 | cj5_result result; |
| 107638 | unsigned int tokensSize; |
| 107639 | size_t index; |
| 107640 | UA_Byte depth; |
| 107641 | } ParsingCtx; |
| 107642 | |
| 107643 | static UA_ByteString |
| 107644 | getJsonPart(cj5_token tok, const char *json) { |
| 107645 | UA_ByteString bs; |
| 107646 | UA_ByteString_init(p: &bs); |
| 107647 | if(tok.type == CJ5_TOKEN_STRING) { |
| 107648 | bs.data = (UA_Byte*)(uintptr_t)(json + tok.start - 1); |
| 107649 | bs.length = (tok.end - tok.start) + 3; |
| 107650 | return bs; |
| 107651 | } else { |
| 107652 | bs.data = (UA_Byte*)(uintptr_t)(json + tok.start); |
| 107653 | bs.length = (tok.end - tok.start) + 1; |
| 107654 | return bs; |
| 107655 | } |
| 107656 | } |
| 107657 | |
| 107658 | /* Forward declarations*/ |
| 107659 | #define PARSE_JSON(TYPE) static UA_StatusCode \ |
| 107660 | TYPE##_parseJson(ParsingCtx *ctx, void *configField, size_t *configFieldSize) |
| 107661 | |
| 107662 | typedef UA_StatusCode |
| 107663 | (*parseJsonSignature)(ParsingCtx *ctx, void *configField, size_t *configFieldSize); |
| 107664 | |
| 107665 | #ifdef UA_ENABLE_ENCRYPTION |
| 107666 | static UA_ByteString |
| 107667 | loadCertificateFile(const char *const path); |
| 107668 | #endif |
| 107669 | |
| 107670 | /* The DataType "kind" is an internal type classification. It is used to |
| 107671 | * dispatch handling to the correct routines. */ |
| 107672 | #define UA_SERVERCONFIGFIELDKINDS 25 |
| 107673 | typedef enum { |
| 107674 | /* Basic Types */ |
| 107675 | UA_SERVERCONFIGFIELD_INT64 = 0, |
| 107676 | UA_SERVERCONFIGFIELD_UINT16, |
| 107677 | UA_SERVERCONFIGFIELD_UINT32, |
| 107678 | UA_SERVERCONFIGFIELD_UINT64, |
| 107679 | UA_SERVERCONFIGFIELD_STRING, |
| 107680 | UA_SERVERCONFIGFIELD_LOCALIZEDTEXT, |
| 107681 | UA_SERVERCONFIGFIELD_DOUBLE, |
| 107682 | UA_SERVERCONFIGFIELD_BOOLEAN, |
| 107683 | UA_SERVERCONFIGFIELD_DURATION, |
| 107684 | UA_SERVERCONFIGFIELD_DURATIONRANGE, |
| 107685 | UA_SERVERCONFIGFIELD_UINT32RANGE, |
| 107686 | |
| 107687 | /* Advanced Types */ |
| 107688 | UA_SERVERCONFIGFIELD_BUILDINFO, |
| 107689 | UA_SERVERCONFIGFIELD_APPLICATIONDESCRIPTION, |
| 107690 | UA_SERVERCONFIGFIELD_STRINGARRAY, |
| 107691 | UA_SERVERCONFIGFIELD_UINT32ARRAY, |
| 107692 | UA_SERVERCONFIGFIELD_DATETIME, |
| 107693 | UA_SERVERCONFIGFIELD_SUBSCRIPTIONCONFIGURATION, |
| 107694 | UA_SERVERCONFIGFIELD_TCPCONFIGURATION, |
| 107695 | UA_SERVERCONFIGFIELD_PUBSUBCONFIGURATION, |
| 107696 | UA_SERVERCONFIGFIELD_HISTORIZINGCONFIGURATION, |
| 107697 | UA_SERVERCONFIGFIELD_MDNSCONFIGURATION, |
| 107698 | UA_SERVERCONFIGFIELD_SECURITYPOLICIES, |
| 107699 | UA_SERVERCONFIGFIELD_SECURITYPKI, |
| 107700 | |
| 107701 | /* Enumerations */ |
| 107702 | UA_SERVERCONFIGFIELD_APPLICATIONTYPE, |
| 107703 | UA_SERVERCONFIGFIELD_RULEHANDLING |
| 107704 | } UA_ServerConfigFieldKind; |
| 107705 | |
| 107706 | extern const parseJsonSignature parseJsonJumpTable[UA_SERVERCONFIGFIELDKINDS]; |
| 107707 | |
| 107708 | /*----------------------Basic Types------------------------*/ |
| 107709 | PARSE_JSON(Int64Field) { |
| 107710 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107711 | UA_ByteString buf = getJsonPart(tok, json: ctx->json); |
| 107712 | UA_Int64 out; |
| 107713 | UA_StatusCode retval = UA_decodeJson(src: &buf, dst: &out, type: &UA_TYPES[UA_TYPES_INT64], NULL); |
| 107714 | if(retval != UA_STATUSCODE_GOOD) |
| 107715 | return retval; |
| 107716 | UA_Int64 *field = (UA_Int64*)configField; |
| 107717 | *field = out; |
| 107718 | return retval; |
| 107719 | } |
| 107720 | PARSE_JSON(UInt16Field) { |
| 107721 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107722 | UA_ByteString buf = getJsonPart(tok, json: ctx->json); |
| 107723 | UA_UInt16 out; |
| 107724 | UA_StatusCode retval = UA_decodeJson(src: &buf, dst: &out, type: &UA_TYPES[UA_TYPES_UINT16], NULL); |
| 107725 | if(retval != UA_STATUSCODE_GOOD) |
| 107726 | return retval; |
| 107727 | UA_UInt16 *field = (UA_UInt16*)configField; |
| 107728 | *field = out; |
| 107729 | return retval; |
| 107730 | } |
| 107731 | PARSE_JSON(UInt32Field) { |
| 107732 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107733 | UA_ByteString buf = getJsonPart(tok, json: ctx->json); |
| 107734 | UA_UInt32 out; |
| 107735 | UA_StatusCode retval = UA_decodeJson(src: &buf, dst: &out, type: &UA_TYPES[UA_TYPES_UINT32], NULL); |
| 107736 | if(retval != UA_STATUSCODE_GOOD) |
| 107737 | return retval; |
| 107738 | UA_UInt32 *field = (UA_UInt32*)configField; |
| 107739 | *field = out; |
| 107740 | return retval; |
| 107741 | } |
| 107742 | PARSE_JSON(UInt64Field) { |
| 107743 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107744 | UA_ByteString buf = getJsonPart(tok, json: ctx->json); |
| 107745 | UA_UInt64 out; |
| 107746 | UA_StatusCode retval = UA_decodeJson(src: &buf, dst: &out, type: &UA_TYPES[UA_TYPES_UINT64], NULL); |
| 107747 | if(retval != UA_STATUSCODE_GOOD) |
| 107748 | return retval; |
| 107749 | UA_UInt64 *field = (UA_UInt64*)configField; |
| 107750 | *field = out; |
| 107751 | return retval; |
| 107752 | } |
| 107753 | PARSE_JSON(StringField) { |
| 107754 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107755 | UA_ByteString buf = getJsonPart(tok, json: ctx->json); |
| 107756 | UA_String out; |
| 107757 | UA_StatusCode retval = UA_decodeJson(src: &buf, dst: &out, type: &UA_TYPES[UA_TYPES_STRING], NULL); |
| 107758 | if(retval != UA_STATUSCODE_GOOD) |
| 107759 | return retval; |
| 107760 | UA_String *field = (UA_String*)configField; |
| 107761 | if(field != NULL) { |
| 107762 | UA_String_clear(p: field); |
| 107763 | *field = out; |
| 107764 | } |
| 107765 | return retval; |
| 107766 | } |
| 107767 | PARSE_JSON(LocalizedTextField) { |
| 107768 | /* |
| 107769 | applicationName: { |
| 107770 | locale: "de-DE", |
| 107771 | text: "Test text" |
| 107772 | } |
| 107773 | */ |
| 107774 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107775 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 107776 | UA_String locale; |
| 107777 | UA_String text; |
| 107778 | for(size_t j = tok.size/2; j > 0; j--) { |
| 107779 | tok = ctx->tokens[++ctx->index]; |
| 107780 | switch (tok.type) { |
| 107781 | case CJ5_TOKEN_STRING: { |
| 107782 | char *field = (char*)UA_malloc(size: tok.size + 1); |
| 107783 | unsigned int str_len = 0; |
| 107784 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field, buflen: &str_len); |
| 107785 | |
| 107786 | tok = ctx->tokens[++ctx->index]; |
| 107787 | UA_ByteString buf = getJsonPart(tok, json: ctx->json); |
| 107788 | if(strcmp(s1: field, s2: "locale") == 0) |
| 107789 | retval |= UA_decodeJson(src: &buf, dst: &locale, type: &UA_TYPES[UA_TYPES_STRING], NULL); |
| 107790 | else if(strcmp(s1: field, s2: "text") == 0) |
| 107791 | retval |= UA_decodeJson(src: &buf, dst: &text, type: &UA_TYPES[UA_TYPES_STRING], NULL); |
| 107792 | else { |
| 107793 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 107794 | } |
| 107795 | UA_free(ptr: field); |
| 107796 | break; |
| 107797 | } |
| 107798 | default: |
| 107799 | break; |
| 107800 | } |
| 107801 | } |
| 107802 | UA_LocalizedText out; |
| 107803 | out.locale = locale; |
| 107804 | out.text = text; |
| 107805 | if(retval != UA_STATUSCODE_GOOD) |
| 107806 | return retval; |
| 107807 | UA_LocalizedText *field = (UA_LocalizedText*)configField; |
| 107808 | if(field != NULL) { |
| 107809 | UA_LocalizedText_clear(p: field); |
| 107810 | *field = out; |
| 107811 | } |
| 107812 | return retval; |
| 107813 | } |
| 107814 | PARSE_JSON(DoubleField) { |
| 107815 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107816 | UA_ByteString buf = getJsonPart(tok, json: ctx->json); |
| 107817 | UA_Double out; |
| 107818 | UA_StatusCode retval = UA_decodeJson(src: &buf, dst: &out, type: &UA_TYPES[UA_TYPES_DOUBLE], NULL); |
| 107819 | if(retval != UA_STATUSCODE_GOOD) |
| 107820 | return retval; |
| 107821 | UA_Double *field = (UA_Double *)configField; |
| 107822 | *field = out; |
| 107823 | return retval; |
| 107824 | } |
| 107825 | PARSE_JSON(BooleanField) { |
| 107826 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107827 | UA_ByteString buf = getJsonPart(tok, json: ctx->json); |
| 107828 | UA_Boolean out; |
| 107829 | if(tok.type != CJ5_TOKEN_BOOL) { |
| 107830 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Value of type bool expected."); |
| 107831 | return UA_STATUSCODE_BADTYPEMISMATCH; |
| 107832 | } |
| 107833 | UA_String val = UA_STRING(chars: "true"); |
| 107834 | if(UA_String_equal(p1: &val, p2: &buf)) { |
| 107835 | out = true; |
| 107836 | }else { |
| 107837 | out = false; |
| 107838 | } |
| 107839 | /* set server config field */ |
| 107840 | UA_Boolean *field = (UA_Boolean *)configField; |
| 107841 | *field = out; |
| 107842 | return UA_STATUSCODE_GOOD; |
| 107843 | } |
| 107844 | PARSE_JSON(DurationField) { |
| 107845 | UA_Double double_value; |
| 107846 | UA_StatusCode retval = DoubleField_parseJson(ctx, configField: &double_value, NULL); |
| 107847 | if(retval != UA_STATUSCODE_GOOD) |
| 107848 | return retval; |
| 107849 | UA_Duration *field = (UA_Duration*)configField; |
| 107850 | *field = (UA_Duration)double_value; |
| 107851 | return retval; |
| 107852 | } |
| 107853 | PARSE_JSON(DurationRangeField) { |
| 107854 | UA_DurationRange *field = (UA_DurationRange*)configField; |
| 107855 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107856 | for(size_t j = tok.size/2; j > 0; j--) { |
| 107857 | tok = ctx->tokens[++ctx->index]; |
| 107858 | switch (tok.type) { |
| 107859 | case CJ5_TOKEN_STRING: { |
| 107860 | char *field_str = (char*)UA_malloc(size: tok.size + 1); |
| 107861 | unsigned int str_len = 0; |
| 107862 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field_str, buflen: &str_len); |
| 107863 | if(strcmp(s1: field_str, s2: "min") == 0) |
| 107864 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_DURATION](ctx, &field->min, NULL); |
| 107865 | else if(strcmp(s1: field_str, s2: "max") == 0) |
| 107866 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_DURATION](ctx, &field->max, NULL); |
| 107867 | else { |
| 107868 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 107869 | } |
| 107870 | UA_free(ptr: field_str); |
| 107871 | break; |
| 107872 | } |
| 107873 | default: |
| 107874 | break; |
| 107875 | } |
| 107876 | } |
| 107877 | return UA_STATUSCODE_GOOD; |
| 107878 | } |
| 107879 | PARSE_JSON(UInt32RangeField) { |
| 107880 | UA_UInt32Range *field = (UA_UInt32Range*)configField; |
| 107881 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107882 | for(size_t j = tok.size/2; j > 0; j--) { |
| 107883 | tok = ctx->tokens[++ctx->index]; |
| 107884 | switch (tok.type) { |
| 107885 | case CJ5_TOKEN_STRING: { |
| 107886 | char *field_str = (char*)UA_malloc(size: tok.size + 1); |
| 107887 | unsigned int str_len = 0; |
| 107888 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field_str, buflen: &str_len); |
| 107889 | if(strcmp(s1: field_str, s2: "min") == 0) |
| 107890 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &field->min, NULL); |
| 107891 | else if(strcmp(s1: field_str, s2: "max") == 0) |
| 107892 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &field->max, NULL); |
| 107893 | else { |
| 107894 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 107895 | } |
| 107896 | UA_free(ptr: field_str); |
| 107897 | break; |
| 107898 | } |
| 107899 | default: |
| 107900 | break; |
| 107901 | } |
| 107902 | } |
| 107903 | return UA_STATUSCODE_GOOD; |
| 107904 | } |
| 107905 | |
| 107906 | /*----------------------Advanced Types------------------------*/ |
| 107907 | PARSE_JSON(BuildInfo) { |
| 107908 | UA_BuildInfo *field = (UA_BuildInfo*)configField; |
| 107909 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107910 | for(size_t j = tok.size/2; j > 0; j--) { |
| 107911 | tok = ctx->tokens[++ctx->index]; |
| 107912 | switch (tok.type) { |
| 107913 | case CJ5_TOKEN_STRING: { |
| 107914 | char *field_str = (char*)UA_malloc(size: tok.size + 1); |
| 107915 | unsigned int str_len = 0; |
| 107916 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field_str, buflen: &str_len); |
| 107917 | if(strcmp(s1: field_str, s2: "productUri") == 0) |
| 107918 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &field->productUri, NULL); |
| 107919 | else if(strcmp(s1: field_str, s2: "manufacturerName") == 0) |
| 107920 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &field->manufacturerName, NULL); |
| 107921 | else if(strcmp(s1: field_str, s2: "productName") == 0) |
| 107922 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &field->productName, NULL); |
| 107923 | else if(strcmp(s1: field_str, s2: "softwareVersion") == 0) |
| 107924 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &field->softwareVersion, NULL); |
| 107925 | else if(strcmp(s1: field_str, s2: "buildNumber") == 0) |
| 107926 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &field->buildNumber, NULL); |
| 107927 | else if(strcmp(s1: field_str, s2: "buildDate") == 0) |
| 107928 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_DATETIME](ctx, &field->buildDate, NULL); |
| 107929 | else { |
| 107930 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 107931 | } |
| 107932 | UA_free(ptr: field_str); |
| 107933 | break; |
| 107934 | } |
| 107935 | default: |
| 107936 | break; |
| 107937 | } |
| 107938 | } |
| 107939 | return UA_STATUSCODE_GOOD; |
| 107940 | } |
| 107941 | PARSE_JSON(ApplicationDescriptionField) { |
| 107942 | UA_ApplicationDescription *field = (UA_ApplicationDescription*)configField; |
| 107943 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107944 | for(size_t j = tok.size/2; j > 0; j--) { |
| 107945 | tok = ctx->tokens[++ctx->index]; |
| 107946 | switch (tok.type) { |
| 107947 | case CJ5_TOKEN_STRING: { |
| 107948 | char *field_str = (char*)UA_malloc(size: tok.size + 1); |
| 107949 | unsigned int str_len = 0; |
| 107950 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field_str, buflen: &str_len); |
| 107951 | if(strcmp(s1: field_str, s2: "applicationUri") == 0) |
| 107952 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &field->applicationUri, NULL); |
| 107953 | else if(strcmp(s1: field_str, s2: "productUri") == 0) |
| 107954 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &field->productUri, NULL); |
| 107955 | else if(strcmp(s1: field_str, s2: "applicationName") == 0) |
| 107956 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_LOCALIZEDTEXT](ctx, &field->applicationName, NULL); |
| 107957 | else if(strcmp(s1: field_str, s2: "applicationType") == 0) |
| 107958 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_APPLICATIONTYPE](ctx, &field->applicationType, NULL); |
| 107959 | else if(strcmp(s1: field_str, s2: "gatewayServerUri") == 0) |
| 107960 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &field->gatewayServerUri, NULL); |
| 107961 | else if(strcmp(s1: field_str, s2: "discoveryProfileUri") == 0) |
| 107962 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &field->discoveryProfileUri, NULL); |
| 107963 | else if(strcmp(s1: field_str, s2: "discoveryUrls") == 0) |
| 107964 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRINGARRAY](ctx, &field->discoveryUrls, &field->discoveryUrlsSize); |
| 107965 | else { |
| 107966 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 107967 | } |
| 107968 | UA_free(ptr: field_str); |
| 107969 | break; |
| 107970 | } |
| 107971 | default: |
| 107972 | break; |
| 107973 | } |
| 107974 | } |
| 107975 | return UA_STATUSCODE_GOOD; |
| 107976 | } |
| 107977 | PARSE_JSON(StringArrayField) { |
| 107978 | if(configFieldSize == NULL) { |
| 107979 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Pointer to the array size is not set."); |
| 107980 | return UA_STATUSCODE_BADARGUMENTSMISSING; |
| 107981 | } |
| 107982 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 107983 | UA_String *stringArray = (UA_String*)UA_malloc(size: sizeof(UA_String) * tok.size); |
| 107984 | size_t stringArraySize = 0; |
| 107985 | for(size_t j = tok.size; j > 0; j--) { |
| 107986 | UA_String out = {.length = 0, .data = NULL};; |
| 107987 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &out, NULL); |
| 107988 | UA_String_copy(src: &out, dst: &stringArray[stringArraySize++]); |
| 107989 | UA_String_clear(p: &out); |
| 107990 | } |
| 107991 | /* Add to the config */ |
| 107992 | UA_String **field = (UA_String**)configField; |
| 107993 | if(*configFieldSize > 0) { |
| 107994 | UA_Array_delete(p: *field, size: *configFieldSize, |
| 107995 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 107996 | *field = NULL; |
| 107997 | *configFieldSize = 0; |
| 107998 | } |
| 107999 | UA_StatusCode retval = |
| 108000 | UA_Array_copy(src: stringArray, size: stringArraySize, |
| 108001 | dst: (void**)field, type: &UA_TYPES[UA_TYPES_STRING]); |
| 108002 | *configFieldSize = stringArraySize; |
| 108003 | |
| 108004 | /* Clean up */ |
| 108005 | UA_Array_delete(p: stringArray, size: stringArraySize, type: &UA_TYPES[UA_TYPES_STRING]); |
| 108006 | return retval; |
| 108007 | } |
| 108008 | PARSE_JSON(UInt32ArrayField) { |
| 108009 | if(configFieldSize == NULL) { |
| 108010 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Pointer to the array size is not set."); |
| 108011 | return UA_STATUSCODE_BADARGUMENTSMISSING; |
| 108012 | } |
| 108013 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 108014 | UA_UInt32 *numberArray = (UA_UInt32*)UA_malloc(size: sizeof(UA_UInt32) * tok.size);; |
| 108015 | size_t numberArraySize = 0; |
| 108016 | for(size_t j = tok.size; j > 0; j--) { |
| 108017 | UA_UInt32 value; |
| 108018 | UA_StatusCode retval = UInt32Field_parseJson(ctx, configField: &value, NULL); |
| 108019 | if(retval != UA_STATUSCODE_GOOD) |
| 108020 | continue; |
| 108021 | numberArray[numberArraySize++] = value; |
| 108022 | } |
| 108023 | /* Add to the config */ |
| 108024 | UA_UInt32 **field = (UA_UInt32**)configField; |
| 108025 | if(*configFieldSize > 0) { |
| 108026 | UA_Array_delete(p: *field, size: *configFieldSize, |
| 108027 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 108028 | *field = NULL; |
| 108029 | *configFieldSize = 0; |
| 108030 | } |
| 108031 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 108032 | if(numberArraySize > 0) { |
| 108033 | retval = UA_Array_copy(src: numberArray, size: numberArraySize, |
| 108034 | dst: (void **)field, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 108035 | *configFieldSize = numberArraySize; |
| 108036 | } |
| 108037 | /* Clean up */ |
| 108038 | UA_Array_delete(p: numberArray, size: numberArraySize, type: &UA_TYPES[UA_TYPES_UINT32]); |
| 108039 | return retval; |
| 108040 | } |
| 108041 | PARSE_JSON(DateTimeField) { |
| 108042 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 108043 | UA_ByteString buf = getJsonPart(tok, json: ctx->json); |
| 108044 | UA_DateTime out; |
| 108045 | UA_DateTime_init(p: &out); |
| 108046 | UA_StatusCode retval = UA_decodeJson(src: &buf, dst: &out, type: &UA_TYPES[UA_TYPES_DATETIME], NULL); |
| 108047 | if(retval != UA_STATUSCODE_GOOD) |
| 108048 | return retval; |
| 108049 | UA_DateTime *field = (UA_DateTime*)configField; |
| 108050 | *field = out; |
| 108051 | return retval; |
| 108052 | } |
| 108053 | |
| 108054 | PARSE_JSON(MdnsConfigurationField) { |
| 108055 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 108056 | UA_ServerConfig *config = (UA_ServerConfig*)configField; |
| 108057 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 108058 | for(size_t j = tok.size/2; j > 0; j--) { |
| 108059 | tok = ctx->tokens[++ctx->index]; |
| 108060 | switch (tok.type) { |
| 108061 | case CJ5_TOKEN_STRING: { |
| 108062 | char *field_str = (char*)UA_malloc(tok.size + 1); |
| 108063 | unsigned int str_len = 0; |
| 108064 | cj5_get_str(&ctx->result, (unsigned int)ctx->index, field_str, &str_len); |
| 108065 | if(strcmp(field_str, "mdnsServerName") == 0) |
| 108066 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &config->mdnsConfig.mdnsServerName, NULL); |
| 108067 | else if(strcmp(field_str, "serverCapabilities") == 0) |
| 108068 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRINGARRAY](ctx, &config->mdnsConfig.serverCapabilities, &config->mdnsConfig.serverCapabilitiesSize); |
| 108069 | else if(strcmp(field_str, "mdnsInterfaceIP") == 0) |
| 108070 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &config->mdnsInterfaceIP, NULL); |
| 108071 | /* mdnsIpAddressList and mdnsIpAddressListSize are only available if UA_HAS_GETIFADDR is not defined: */ |
| 108072 | # if !defined(UA_HAS_GETIFADDR) |
| 108073 | else if(strcmp(field_str, "mdnsIpAddressList") == 0) |
| 108074 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32ARRAY](ctx, &config->mdnsIpAddressList, &config->mdnsIpAddressListSize); |
| 108075 | # endif |
| 108076 | else { |
| 108077 | UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "Unknown field name."); |
| 108078 | } |
| 108079 | UA_free(field_str); |
| 108080 | break; |
| 108081 | } |
| 108082 | default: |
| 108083 | break; |
| 108084 | } |
| 108085 | } |
| 108086 | #endif |
| 108087 | return UA_STATUSCODE_GOOD; |
| 108088 | } |
| 108089 | |
| 108090 | PARSE_JSON(SubscriptionConfigurationField) { |
| 108091 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 108092 | UA_ServerConfig *config = (UA_ServerConfig*)configField; |
| 108093 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 108094 | for(size_t j = tok.size/2; j > 0; j--) { |
| 108095 | tok = ctx->tokens[++ctx->index]; |
| 108096 | switch (tok.type) { |
| 108097 | case CJ5_TOKEN_STRING: { |
| 108098 | char *field_str = (char*)UA_malloc(size: tok.size + 1); |
| 108099 | unsigned int str_len = 0; |
| 108100 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field_str, buflen: &str_len); |
| 108101 | if(strcmp(s1: field_str, s2: "maxSubscriptions") == 0) |
| 108102 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->maxSubscriptions, NULL); |
| 108103 | else if(strcmp(s1: field_str, s2: "maxSubscriptionsPerSession") == 0) |
| 108104 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->maxSubscriptionsPerSession, NULL); |
| 108105 | else if(strcmp(s1: field_str, s2: "publishingIntervalLimits") == 0) |
| 108106 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_DURATIONRANGE](ctx, &config->publishingIntervalLimits, NULL); |
| 108107 | else if(strcmp(s1: field_str, s2: "lifeTimeCountLimits") == 0) |
| 108108 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32RANGE](ctx, &config->lifeTimeCountLimits, NULL); |
| 108109 | else if(strcmp(s1: field_str, s2: "keepAliveCountLimits") == 0) |
| 108110 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32RANGE](ctx, &config->keepAliveCountLimits, NULL); |
| 108111 | else if(strcmp(s1: field_str, s2: "maxNotificationsPerPublish") == 0) |
| 108112 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->maxNotificationsPerPublish, NULL); |
| 108113 | else if(strcmp(s1: field_str, s2: "enableRetransmissionQueue") == 0) |
| 108114 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->enableRetransmissionQueue, NULL); |
| 108115 | else if(strcmp(s1: field_str, s2: "maxRetransmissionQueueSize") == 0) |
| 108116 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->maxRetransmissionQueueSize, NULL); |
| 108117 | # ifdef UA_ENABLE_SUBSCRIPTIONS_EVENTS |
| 108118 | else if(strcmp(s1: field_str, s2: "maxEventsPerNode") == 0) |
| 108119 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->maxEventsPerNode, NULL); |
| 108120 | # endif |
| 108121 | else if(strcmp(s1: field_str, s2: "maxMonitoredItems") == 0) |
| 108122 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->maxMonitoredItems, NULL); |
| 108123 | else if(strcmp(s1: field_str, s2: "maxMonitoredItemsPerSubscription") == 0) |
| 108124 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->maxMonitoredItemsPerSubscription, NULL); |
| 108125 | else if(strcmp(s1: field_str, s2: "samplingIntervalLimits") == 0) |
| 108126 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_DURATIONRANGE](ctx, &config->samplingIntervalLimits, NULL); |
| 108127 | else if(strcmp(s1: field_str, s2: "queueSizeLimits") == 0) |
| 108128 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32RANGE](ctx, &config->queueSizeLimits, NULL); |
| 108129 | else if(strcmp(s1: field_str, s2: "maxPublishReqPerSession") == 0) |
| 108130 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->maxPublishReqPerSession, NULL); |
| 108131 | else { |
| 108132 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 108133 | } |
| 108134 | UA_free(ptr: field_str); |
| 108135 | break; |
| 108136 | } |
| 108137 | default: |
| 108138 | break; |
| 108139 | } |
| 108140 | } |
| 108141 | #endif |
| 108142 | return UA_STATUSCODE_GOOD; |
| 108143 | } |
| 108144 | |
| 108145 | PARSE_JSON(TcpConfigurationField) { |
| 108146 | UA_ServerConfig *config = (UA_ServerConfig*)configField; |
| 108147 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 108148 | for(size_t j = tok.size/2; j > 0; j--) { |
| 108149 | tok = ctx->tokens[++ctx->index]; |
| 108150 | switch (tok.type) { |
| 108151 | case CJ5_TOKEN_STRING: { |
| 108152 | char *field_str = (char*)UA_malloc(size: tok.size + 1); |
| 108153 | unsigned int str_len = 0; |
| 108154 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field_str, buflen: &str_len); |
| 108155 | if(strcmp(s1: field_str, s2: "tcpBufSize") == 0) |
| 108156 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->tcpBufSize, NULL); |
| 108157 | else if(strcmp(s1: field_str, s2: "tcpMaxMsgSize") == 0) |
| 108158 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->tcpMaxMsgSize, NULL); |
| 108159 | else if(strcmp(s1: field_str, s2: "tcpMaxChunks") == 0) |
| 108160 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->tcpMaxChunks, NULL); |
| 108161 | else { |
| 108162 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 108163 | } |
| 108164 | UA_free(ptr: field_str); |
| 108165 | break; |
| 108166 | } |
| 108167 | default: |
| 108168 | break; |
| 108169 | } |
| 108170 | } |
| 108171 | return UA_STATUSCODE_GOOD; |
| 108172 | } |
| 108173 | |
| 108174 | PARSE_JSON(PubsubConfigurationField) { |
| 108175 | #ifdef UA_ENABLE_PUBSUB |
| 108176 | UA_PubSubConfiguration *field = (UA_PubSubConfiguration*)configField; |
| 108177 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 108178 | for(size_t j = tok.size/2; j > 0; j--) { |
| 108179 | tok = ctx->tokens[++ctx->index]; |
| 108180 | switch (tok.type) { |
| 108181 | case CJ5_TOKEN_STRING: { |
| 108182 | char *field_str = (char*)UA_malloc(size: tok.size + 1); |
| 108183 | unsigned int str_len = 0; |
| 108184 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field_str, buflen: &str_len); |
| 108185 | if(strcmp(s1: field_str, s2: "enableDeltaFrames") == 0) |
| 108186 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &field->enableDeltaFrames, NULL); |
| 108187 | #ifdef UA_ENABLE_PUBSUB_INFORMATIONMODEL |
| 108188 | else if(strcmp(s1: field_str, s2: "enableInformationModelMethods") == 0) |
| 108189 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &field->enableInformationModelMethods, NULL); |
| 108190 | #endif |
| 108191 | else { |
| 108192 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 108193 | } |
| 108194 | UA_free(ptr: field_str); |
| 108195 | break; |
| 108196 | } |
| 108197 | default: |
| 108198 | break; |
| 108199 | } |
| 108200 | } |
| 108201 | #endif |
| 108202 | return UA_STATUSCODE_GOOD; |
| 108203 | } |
| 108204 | |
| 108205 | PARSE_JSON(HistorizingConfigurationField) { |
| 108206 | #ifdef UA_ENABLE_HISTORIZING |
| 108207 | UA_ServerConfig *config = (UA_ServerConfig*)configField; |
| 108208 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 108209 | for(size_t j = tok.size/2; j > 0; j--) { |
| 108210 | tok = ctx->tokens[++ctx->index]; |
| 108211 | switch (tok.type) { |
| 108212 | case CJ5_TOKEN_STRING: { |
| 108213 | char *field_str = (char*)UA_malloc(size: tok.size + 1); |
| 108214 | unsigned int str_len = 0; |
| 108215 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field_str, buflen: &str_len); |
| 108216 | if(strcmp(s1: field_str, s2: "accessHistoryDataCapability") == 0) |
| 108217 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->accessHistoryDataCapability, NULL); |
| 108218 | else if(strcmp(s1: field_str, s2: "maxReturnDataValues") == 0) |
| 108219 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->maxReturnDataValues, NULL); |
| 108220 | else if(strcmp(s1: field_str, s2: "accessHistoryEventsCapability") == 0) |
| 108221 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->accessHistoryEventsCapability, NULL); |
| 108222 | else if(strcmp(s1: field_str, s2: "maxReturnEventValues") == 0) |
| 108223 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](ctx, &config->maxReturnEventValues, NULL); |
| 108224 | else if(strcmp(s1: field_str, s2: "insertDataCapability") == 0) |
| 108225 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->insertDataCapability, NULL); |
| 108226 | else if(strcmp(s1: field_str, s2: "insertEventCapability") == 0) |
| 108227 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->insertEventCapability, NULL); |
| 108228 | else if(strcmp(s1: field_str, s2: "insertAnnotationsCapability") == 0) |
| 108229 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->insertAnnotationsCapability, NULL); |
| 108230 | else if(strcmp(s1: field_str, s2: "replaceDataCapability") == 0) |
| 108231 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->replaceDataCapability, NULL); |
| 108232 | else if(strcmp(s1: field_str, s2: "replaceEventCapability") == 0) |
| 108233 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->replaceEventCapability, NULL); |
| 108234 | else if(strcmp(s1: field_str, s2: "updateDataCapability") == 0) |
| 108235 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->updateDataCapability, NULL); |
| 108236 | else if(strcmp(s1: field_str, s2: "updateEventCapability") == 0) |
| 108237 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->updateEventCapability, NULL); |
| 108238 | else if(strcmp(s1: field_str, s2: "deleteRawCapability") == 0) |
| 108239 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->deleteRawCapability, NULL); |
| 108240 | else if(strcmp(s1: field_str, s2: "deleteEventCapability") == 0) |
| 108241 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->deleteEventCapability, NULL); |
| 108242 | else if(strcmp(s1: field_str, s2: "deleteAtTimeDataCapability") == 0) |
| 108243 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](ctx, &config->deleteAtTimeDataCapability, NULL); |
| 108244 | else { |
| 108245 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 108246 | } |
| 108247 | UA_free(ptr: field_str); |
| 108248 | break; |
| 108249 | } |
| 108250 | default: |
| 108251 | break; |
| 108252 | } |
| 108253 | } |
| 108254 | #endif |
| 108255 | return UA_STATUSCODE_GOOD; |
| 108256 | } |
| 108257 | |
| 108258 | PARSE_JSON(SecurityPolciesField) { |
| 108259 | #ifdef UA_ENABLE_ENCRYPTION |
| 108260 | UA_ServerConfig *config = (UA_ServerConfig*)configField; |
| 108261 | |
| 108262 | UA_String noneuri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None"); |
| 108263 | UA_String basic128Rsa15uri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15"); |
| 108264 | UA_String basic256uri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic256"); |
| 108265 | UA_String basic256Sha256uri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"); |
| 108266 | UA_String aes128sha256rsaoaepuri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep"); |
| 108267 | UA_String aes256sha256rsapssuri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss"); |
| 108268 | |
| 108269 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 108270 | for(size_t j = tok.size; j > 0; j--) { |
| 108271 | |
| 108272 | UA_String policy = {.length = 0, .data = NULL}; |
| 108273 | UA_ByteString certificate = {.length = 0, .data = NULL}; |
| 108274 | UA_ByteString privateKey = {.length = 0, .data = NULL}; |
| 108275 | |
| 108276 | tok = ctx->tokens[++ctx->index]; |
| 108277 | for(size_t i = tok.size / 2; i > 0; i--) { |
| 108278 | tok = ctx->tokens[++ctx->index]; |
| 108279 | switch(tok.type) { |
| 108280 | case CJ5_TOKEN_STRING: { |
| 108281 | char *field_str = (char *)UA_malloc(size: tok.size + 1); |
| 108282 | unsigned int str_len = 0; |
| 108283 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field_str, buflen: &str_len); |
| 108284 | if(strcmp(s1: field_str, s2: "certificate") == 0) { |
| 108285 | UA_String out = {.length = 0, .data = NULL}; |
| 108286 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &out, NULL); |
| 108287 | |
| 108288 | if(out.length > 0) { |
| 108289 | char *certfile = (char *)UA_malloc(size: out.length + 1); |
| 108290 | memcpy(dest: certfile, src: out.data, n: out.length); |
| 108291 | certfile[out.length] = '\0'; |
| 108292 | certificate = loadCertificateFile(path: certfile); |
| 108293 | UA_String_clear(p: &out); |
| 108294 | UA_free(ptr: certfile); |
| 108295 | } |
| 108296 | } else if(strcmp(s1: field_str, s2: "privateKey") == 0) { |
| 108297 | UA_String out = {.length = 0, .data = NULL}; |
| 108298 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &out, NULL); |
| 108299 | |
| 108300 | if(out.length > 0) { |
| 108301 | char *keyfile = (char *)UA_malloc(size: out.length + 1); |
| 108302 | memcpy(dest: keyfile, src: out.data, n: out.length); |
| 108303 | keyfile[out.length] = '\0'; |
| 108304 | privateKey = loadCertificateFile(path: keyfile); |
| 108305 | UA_String_clear(p: &out); |
| 108306 | UA_free(ptr: keyfile); |
| 108307 | } |
| 108308 | } else if(strcmp(s1: field_str, s2: "policy") == 0) { |
| 108309 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &policy, NULL); |
| 108310 | } else { |
| 108311 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 108312 | } |
| 108313 | UA_free(ptr: field_str); |
| 108314 | break; |
| 108315 | } |
| 108316 | default: |
| 108317 | break; |
| 108318 | } |
| 108319 | } |
| 108320 | |
| 108321 | if(certificate.length == 0 || privateKey.length == 0) { |
| 108322 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 108323 | msg: "Certificate and PrivateKey must be set for every policy."); |
| 108324 | if(policy.length > 0) |
| 108325 | UA_String_clear(p: &policy); |
| 108326 | if(certificate.length > 0) |
| 108327 | UA_ByteString_clear(p: &certificate); |
| 108328 | if(privateKey.length > 0) |
| 108329 | UA_ByteString_clear(p: &privateKey); |
| 108330 | return UA_STATUSCODE_BADINTERNALERROR; |
| 108331 | } |
| 108332 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 108333 | if(UA_String_equal(p1: &policy, p2: &noneuri)) { |
| 108334 | /* Nothing to do! */ |
| 108335 | } else if(UA_String_equal(p1: &policy, p2: &basic128Rsa15uri)) { |
| 108336 | retval = UA_ServerConfig_addSecurityPolicyBasic128Rsa15(config, certificate: &certificate, privateKey: &privateKey); |
| 108337 | if(retval != UA_STATUSCODE_GOOD) { |
| 108338 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 108339 | msg: "Could not add SecurityPolicy#Basic128Rsa15 with error code %s", |
| 108340 | UA_StatusCode_name(code: retval)); |
| 108341 | } |
| 108342 | } else if(UA_String_equal(p1: &policy, p2: &basic256uri)) { |
| 108343 | retval = UA_ServerConfig_addSecurityPolicyBasic256(config, certificate: &certificate, privateKey: &privateKey); |
| 108344 | if(retval != UA_STATUSCODE_GOOD) { |
| 108345 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 108346 | msg: "Could not add SecurityPolicy#Basic256 with error code %s", |
| 108347 | UA_StatusCode_name(code: retval)); |
| 108348 | } |
| 108349 | } else if(UA_String_equal(p1: &policy, p2: &basic256Sha256uri)) { |
| 108350 | retval = UA_ServerConfig_addSecurityPolicyBasic256Sha256(config, certificate: &certificate, privateKey: &privateKey); |
| 108351 | if(retval != UA_STATUSCODE_GOOD) { |
| 108352 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 108353 | msg: "Could not add SecurityPolicy#Basic256Sha256 with error code %s", |
| 108354 | UA_StatusCode_name(code: retval)); |
| 108355 | } |
| 108356 | } else if(UA_String_equal(p1: &policy, p2: &aes128sha256rsaoaepuri)) { |
| 108357 | retval = UA_ServerConfig_addSecurityPolicyAes128Sha256RsaOaep(config, certificate: &certificate, privateKey: &privateKey); |
| 108358 | if(retval != UA_STATUSCODE_GOOD) { |
| 108359 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 108360 | msg: "Could not add SecurityPolicy#Aes128Sha256RsaOaep with error code %s", |
| 108361 | UA_StatusCode_name(code: retval)); |
| 108362 | } |
| 108363 | } else if(UA_String_equal(p1: &policy, p2: &aes256sha256rsapssuri)) { |
| 108364 | retval = UA_ServerConfig_addSecurityPolicyAes256Sha256RsaPss(config, certificate: &certificate, privateKey: &privateKey); |
| 108365 | if(retval != UA_STATUSCODE_GOOD) { |
| 108366 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, |
| 108367 | msg: "Could not add SecurityPolicy#Aes256Sha256RsaPss with error code %s", |
| 108368 | UA_StatusCode_name(code: retval)); |
| 108369 | } |
| 108370 | } else { |
| 108371 | UA_LOG_WARNING(logger: config->logging, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown Security Policy."); |
| 108372 | } |
| 108373 | |
| 108374 | /* Add all Endpoints */ |
| 108375 | UA_ServerConfig_addAllEndpoints(config); |
| 108376 | |
| 108377 | if(policy.length > 0) |
| 108378 | UA_String_clear(p: &policy); |
| 108379 | if(certificate.length > 0) |
| 108380 | UA_ByteString_clear(p: &certificate); |
| 108381 | if(privateKey.length > 0) |
| 108382 | UA_ByteString_clear(p: &privateKey); |
| 108383 | } |
| 108384 | #endif |
| 108385 | return UA_STATUSCODE_GOOD; |
| 108386 | } |
| 108387 | |
| 108388 | PARSE_JSON(SecurityPkiField) { |
| 108389 | #ifdef UA_ENABLE_ENCRYPTION |
| 108390 | UA_CertificateVerification *field = (UA_CertificateVerification*)configField; |
| 108391 | UA_String trustListFolder = {.length = 0, .data = NULL}; |
| 108392 | UA_String issuerListFolder = {.length = 0, .data = NULL}; |
| 108393 | UA_String revocationListFolder = {.length = 0, .data = NULL}; |
| 108394 | |
| 108395 | cj5_token tok = ctx->tokens[++ctx->index]; |
| 108396 | for(size_t i = tok.size/2; i > 0; i--) { |
| 108397 | tok = ctx->tokens[++ctx->index]; |
| 108398 | switch(tok.type) { |
| 108399 | case CJ5_TOKEN_STRING: { |
| 108400 | char *field_str = (char*)UA_malloc(size: tok.size + 1); |
| 108401 | unsigned int str_len = 0; |
| 108402 | cj5_get_str(r: &ctx->result, tok_index: (unsigned int)ctx->index, buf: field_str, buflen: &str_len); |
| 108403 | if(strcmp(s1: field_str, s2: "trustListFolder") == 0) { |
| 108404 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &trustListFolder, NULL); |
| 108405 | } else if(strcmp(s1: field_str, s2: "issuerListFolder") == 0) { |
| 108406 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &issuerListFolder, NULL); |
| 108407 | } else if(strcmp(s1: field_str, s2: "revocationListFolder") == 0) { |
| 108408 | parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRING](ctx, &revocationListFolder, NULL); |
| 108409 | } else { |
| 108410 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Unknown field name."); |
| 108411 | } |
| 108412 | UA_free(ptr: field_str); |
| 108413 | break; |
| 108414 | } |
| 108415 | default: |
| 108416 | break; |
| 108417 | } |
| 108418 | } |
| 108419 | #ifndef __linux__ |
| 108420 | /* Currently not supported! */ |
| 108421 | (void)field; |
| 108422 | return UA_STATUSCODE_GOOD; |
| 108423 | #else |
| 108424 | /* set server config field */ |
| 108425 | char *sTrustListFolder = NULL; |
| 108426 | char *sIssuerListFolder = NULL; |
| 108427 | char *sRevocationListFolder = NULL; |
| 108428 | if(trustListFolder.length > 0) { |
| 108429 | sTrustListFolder = (char*)UA_malloc(size: trustListFolder.length+1); |
| 108430 | memcpy(dest: sTrustListFolder, src: trustListFolder.data, n: trustListFolder.length); |
| 108431 | sTrustListFolder[trustListFolder.length] = '\0'; |
| 108432 | } |
| 108433 | if(issuerListFolder.length > 0) { |
| 108434 | sIssuerListFolder = (char*)UA_malloc(size: issuerListFolder.length+1); |
| 108435 | memcpy(dest: sIssuerListFolder, src: issuerListFolder.data, n: issuerListFolder.length); |
| 108436 | sIssuerListFolder[issuerListFolder.length] = '\0'; |
| 108437 | } |
| 108438 | if(revocationListFolder.length > 0) { |
| 108439 | sRevocationListFolder = (char*)UA_malloc(size: revocationListFolder.length+1); |
| 108440 | memcpy(dest: sRevocationListFolder, src: revocationListFolder.data, n: revocationListFolder.length); |
| 108441 | sRevocationListFolder[revocationListFolder.length] = '\0'; |
| 108442 | } |
| 108443 | if(field && field->clear) |
| 108444 | field->clear(field); |
| 108445 | #ifdef UA_ENABLE_CERT_REJECTED_DIR |
| 108446 | UA_StatusCode retval = UA_CertificateVerification_CertFolders(field, sTrustListFolder, |
| 108447 | sIssuerListFolder, sRevocationListFolder, NULL); |
| 108448 | #else |
| 108449 | UA_StatusCode retval = UA_CertificateVerification_CertFolders(cv: field, trustListFolder: sTrustListFolder, |
| 108450 | issuerListFolder: sIssuerListFolder, revocationListFolder: sRevocationListFolder); |
| 108451 | #endif |
| 108452 | /* Clean up */ |
| 108453 | if(sTrustListFolder) |
| 108454 | UA_free(ptr: sTrustListFolder); |
| 108455 | if(sIssuerListFolder) |
| 108456 | UA_free(ptr: sIssuerListFolder); |
| 108457 | if(sRevocationListFolder) |
| 108458 | UA_free(ptr: sRevocationListFolder); |
| 108459 | UA_String_clear(p: &trustListFolder); |
| 108460 | UA_String_clear(p: &issuerListFolder); |
| 108461 | UA_String_clear(p: &revocationListFolder); |
| 108462 | |
| 108463 | return retval; |
| 108464 | #endif |
| 108465 | #endif |
| 108466 | return UA_STATUSCODE_GOOD; |
| 108467 | } |
| 108468 | |
| 108469 | /*----------------------Enumerations------------------------*/ |
| 108470 | PARSE_JSON(ApplicationTypeField) { |
| 108471 | UA_UInt32 enum_value; |
| 108472 | UA_StatusCode retval = UInt32Field_parseJson(ctx, configField: &enum_value, NULL); |
| 108473 | if(retval != UA_STATUSCODE_GOOD) |
| 108474 | return retval; |
| 108475 | UA_ApplicationType *field = (UA_ApplicationType*)configField; |
| 108476 | *field = (UA_ApplicationType)enum_value; |
| 108477 | return retval; |
| 108478 | } |
| 108479 | PARSE_JSON(RuleHandlingField) { |
| 108480 | UA_UInt32 enum_value; |
| 108481 | UA_StatusCode retval = UInt32Field_parseJson(ctx, configField: &enum_value, NULL); |
| 108482 | if(retval != UA_STATUSCODE_GOOD) |
| 108483 | return retval; |
| 108484 | UA_RuleHandling *field = (UA_RuleHandling*)configField; |
| 108485 | *field = (UA_RuleHandling)enum_value; |
| 108486 | return retval; |
| 108487 | } |
| 108488 | |
| 108489 | const parseJsonSignature parseJsonJumpTable[UA_SERVERCONFIGFIELDKINDS] = { |
| 108490 | /* Basic Types */ |
| 108491 | (parseJsonSignature)Int64Field_parseJson, |
| 108492 | (parseJsonSignature)UInt16Field_parseJson, |
| 108493 | (parseJsonSignature)UInt32Field_parseJson, |
| 108494 | (parseJsonSignature)UInt64Field_parseJson, |
| 108495 | (parseJsonSignature)StringField_parseJson, |
| 108496 | (parseJsonSignature)LocalizedTextField_parseJson, |
| 108497 | (parseJsonSignature)DoubleField_parseJson, |
| 108498 | (parseJsonSignature)BooleanField_parseJson, |
| 108499 | (parseJsonSignature)DurationField_parseJson, |
| 108500 | (parseJsonSignature)DurationRangeField_parseJson, |
| 108501 | (parseJsonSignature)UInt32RangeField_parseJson, |
| 108502 | |
| 108503 | /* Advanced Types */ |
| 108504 | (parseJsonSignature)BuildInfo_parseJson, |
| 108505 | (parseJsonSignature)ApplicationDescriptionField_parseJson, |
| 108506 | (parseJsonSignature)StringArrayField_parseJson, |
| 108507 | (parseJsonSignature)UInt32ArrayField_parseJson, |
| 108508 | (parseJsonSignature)DateTimeField_parseJson, |
| 108509 | (parseJsonSignature)SubscriptionConfigurationField_parseJson, |
| 108510 | (parseJsonSignature)TcpConfigurationField_parseJson, |
| 108511 | (parseJsonSignature)PubsubConfigurationField_parseJson, |
| 108512 | (parseJsonSignature)HistorizingConfigurationField_parseJson, |
| 108513 | (parseJsonSignature)MdnsConfigurationField_parseJson, |
| 108514 | (parseJsonSignature)SecurityPolciesField_parseJson, |
| 108515 | (parseJsonSignature)SecurityPkiField_parseJson, |
| 108516 | |
| 108517 | /* Enumerations */ |
| 108518 | (parseJsonSignature)ApplicationTypeField_parseJson, |
| 108519 | (parseJsonSignature)RuleHandlingField_parseJson, |
| 108520 | }; |
| 108521 | |
| 108522 | static UA_StatusCode |
| 108523 | parseJSONConfig(UA_ServerConfig *config, UA_ByteString json_config) { |
| 108524 | // Parsing json config |
| 108525 | const char *json = (const char*)json_config.data; |
| 108526 | cj5_token tokens[MAX_TOKENS]; |
| 108527 | cj5_result r = cj5_parse(json5: json, len: (unsigned int)json_config.length, tokens, MAX_TOKENS, NULL); |
| 108528 | |
| 108529 | ParsingCtx ctx; |
| 108530 | ctx.json = json; |
| 108531 | ctx.result = r; |
| 108532 | ctx.tokens = r.tokens; |
| 108533 | ctx.tokensSize = r.num_tokens; |
| 108534 | ctx.index = 1; // The first token is ignored because it is known and not needed. |
| 108535 | |
| 108536 | size_t serverConfigSize = 0; |
| 108537 | if(ctx.tokens) |
| 108538 | serverConfigSize = (ctx.tokens[ctx.index-1].size/2); |
| 108539 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 108540 | for (size_t j = serverConfigSize; j > 0; j--) { |
| 108541 | cj5_token tok = ctx.tokens[ctx.index]; |
| 108542 | switch (tok.type) { |
| 108543 | case CJ5_TOKEN_STRING: { |
| 108544 | char *field = (char*)UA_malloc(size: tok.size + 1); |
| 108545 | unsigned int str_len = 0; |
| 108546 | cj5_get_str(r: &ctx.result, tok_index: (unsigned int)ctx.index, buf: field, buflen: &str_len); |
| 108547 | if(strcmp(s1: field, s2: "buildInfo") == 0) |
| 108548 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_BUILDINFO](&ctx, &config->buildInfo, NULL); |
| 108549 | else if(strcmp(s1: field, s2: "applicationDescription") == 0) |
| 108550 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_APPLICATIONDESCRIPTION](&ctx, &config->applicationDescription, NULL); |
| 108551 | else if(strcmp(s1: field, s2: "shutdownDelay") == 0) |
| 108552 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_DOUBLE](&ctx, &config->shutdownDelay, NULL); |
| 108553 | else if(strcmp(s1: field, s2: "verifyRequestTimestamp") == 0) |
| 108554 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_RULEHANDLING](&ctx, &config->verifyRequestTimestamp, NULL); |
| 108555 | else if(strcmp(s1: field, s2: "allowEmptyVariables") == 0) |
| 108556 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_RULEHANDLING](&ctx, &config->allowEmptyVariables, NULL); |
| 108557 | else if(strcmp(s1: field, s2: "serverUrls") == 0) |
| 108558 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_STRINGARRAY](&ctx, &config->serverUrls, &config->serverUrlsSize); |
| 108559 | else if(strcmp(s1: field, s2: "tcpEnabled") == 0) |
| 108560 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](&ctx, &config->tcpEnabled, NULL); |
| 108561 | else if(strcmp(s1: field, s2: "tcp") == 0) |
| 108562 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_TCPCONFIGURATION](&ctx, config, NULL); |
| 108563 | else if(strcmp(s1: field, s2: "securityPolicyNoneDiscoveryOnly") == 0) |
| 108564 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](&ctx, &config->securityPolicyNoneDiscoveryOnly, NULL); |
| 108565 | else if(strcmp(s1: field, s2: "modellingRulesOnInstances") == 0) |
| 108566 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](&ctx, &config->modellingRulesOnInstances, NULL); |
| 108567 | else if(strcmp(s1: field, s2: "maxSecureChannels") == 0) |
| 108568 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT16](&ctx, &config->maxSecureChannels, NULL); |
| 108569 | else if(strcmp(s1: field, s2: "maxSecurityTokenLifetime") == 0) |
| 108570 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->maxSecurityTokenLifetime, NULL); |
| 108571 | else if(strcmp(s1: field, s2: "maxSessions") == 0) |
| 108572 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT16](&ctx, &config->maxSessions, NULL); |
| 108573 | else if(strcmp(s1: field, s2: "maxSessionTimeout") == 0) |
| 108574 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_DOUBLE](&ctx, &config->maxSessionTimeout, NULL); |
| 108575 | else if(strcmp(s1: field, s2: "maxNodesPerRead") == 0) |
| 108576 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->maxNodesPerRead, NULL); |
| 108577 | else if(strcmp(s1: field, s2: "maxNodesPerWrite") == 0) |
| 108578 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->maxNodesPerWrite, NULL); |
| 108579 | else if(strcmp(s1: field, s2: "maxNodesPerMethodCall") == 0) |
| 108580 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->maxNodesPerMethodCall, NULL); |
| 108581 | else if(strcmp(s1: field, s2: "maxNodesPerBrowse") == 0) |
| 108582 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->maxNodesPerBrowse, NULL); |
| 108583 | else if(strcmp(s1: field, s2: "maxNodesPerRegisterNodes") == 0) |
| 108584 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->maxNodesPerRegisterNodes, NULL); |
| 108585 | else if(strcmp(s1: field, s2: "maxNodesPerTranslateBrowsePathsToNodeIds") == 0) |
| 108586 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->maxNodesPerTranslateBrowsePathsToNodeIds, NULL); |
| 108587 | else if(strcmp(s1: field, s2: "maxNodesPerNodeManagement") == 0) |
| 108588 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->maxNodesPerNodeManagement, NULL); |
| 108589 | else if(strcmp(s1: field, s2: "maxMonitoredItemsPerCall") == 0) |
| 108590 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->maxMonitoredItemsPerCall, NULL); |
| 108591 | else if(strcmp(s1: field, s2: "maxReferencesPerNode") == 0) |
| 108592 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->maxReferencesPerNode, NULL); |
| 108593 | else if(strcmp(s1: field, s2: "reverseReconnectInterval") == 0) |
| 108594 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->reverseReconnectInterval, NULL); |
| 108595 | |
| 108596 | #if UA_MULTITHREADING >= 100 |
| 108597 | else if(strcmp(field, "asyncOperationTimeout") == 0) |
| 108598 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_DOUBLE](&ctx, &config->asyncOperationTimeout, NULL); |
| 108599 | else if(strcmp(field, "maxAsyncOperationQueueSize") == 0) |
| 108600 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT64](&ctx, &config->maxAsyncOperationQueueSize, NULL); |
| 108601 | #endif |
| 108602 | |
| 108603 | #ifdef UA_ENABLE_DISCOVERY |
| 108604 | else if(strcmp(s1: field, s2: "discoveryCleanupTimeout") == 0) |
| 108605 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32](&ctx, &config->discoveryCleanupTimeout, NULL); |
| 108606 | #ifdef UA_ENABLE_DISCOVERY_MULTICAST |
| 108607 | else if(strcmp(field, "mdnsEnabled") == 0) |
| 108608 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](&ctx, &config->mdnsEnabled, NULL); |
| 108609 | else if(strcmp(field, "mdns") == 0) |
| 108610 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_MDNSCONFIGURATION](&ctx, config, NULL); |
| 108611 | #if !defined(UA_HAS_GETIFADDR) |
| 108612 | else if(strcmp(field, "mdnsIpAddressList") == 0) |
| 108613 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_UINT32ARRAY](&ctx, &config->mdnsIpAddressList, &config->mdnsIpAddressListSize); |
| 108614 | #endif |
| 108615 | #endif |
| 108616 | #endif |
| 108617 | |
| 108618 | #ifdef UA_ENABLE_SUBSCRIPTIONS |
| 108619 | else if(strcmp(s1: field, s2: "subscriptionsEnabled") == 0) |
| 108620 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](&ctx, &config->subscriptionsEnabled, NULL); |
| 108621 | else if(strcmp(s1: field, s2: "subscriptions") == 0) |
| 108622 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_SUBSCRIPTIONCONFIGURATION](&ctx, config, NULL); |
| 108623 | # endif |
| 108624 | |
| 108625 | #ifdef UA_ENABLE_HISTORIZING |
| 108626 | else if(strcmp(s1: field, s2: "historizingEnabled") == 0) |
| 108627 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](&ctx, &config->historizingEnabled, NULL); |
| 108628 | else if(strcmp(s1: field, s2: "historizing") == 0) |
| 108629 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_HISTORIZINGCONFIGURATION](&ctx, config, NULL); |
| 108630 | #endif |
| 108631 | |
| 108632 | #ifdef UA_ENABLE_PUBSUB |
| 108633 | else if(strcmp(s1: field, s2: "pubsubEnabled") == 0) |
| 108634 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_BOOLEAN](&ctx, &config->pubsubEnabled, NULL); |
| 108635 | else if(strcmp(s1: field, s2: "pubsub") == 0) |
| 108636 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_PUBSUBCONFIGURATION](&ctx, config, NULL); |
| 108637 | #endif |
| 108638 | #ifdef UA_ENABLE_ENCRYPTION |
| 108639 | else if(strcmp(s1: field, s2: "securityPolicies") == 0) |
| 108640 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_SECURITYPOLICIES](&ctx, config, NULL); |
| 108641 | else if(strcmp(s1: field, s2: "secureChannelPKI") == 0) |
| 108642 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_SECURITYPKI](&ctx, &config->secureChannelPKI, NULL); |
| 108643 | else if(strcmp(s1: field, s2: "sessionPKI") == 0) |
| 108644 | retval = parseJsonJumpTable[UA_SERVERCONFIGFIELD_SECURITYPKI](&ctx, &config->sessionPKI, NULL); |
| 108645 | #endif |
| 108646 | else { |
| 108647 | UA_LOG_WARNING(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "Field name '%s' unknown or misspelled. Maybe the feature is not enabled either.", field); |
| 108648 | } |
| 108649 | UA_free(ptr: field); |
| 108650 | if(retval != UA_STATUSCODE_GOOD) { |
| 108651 | UA_LOG_ERROR(logger: UA_Log_Stdout, category: UA_LOGCATEGORY_USERLAND, msg: "An error occurred while parsing the configuration file."); |
| 108652 | return retval; |
| 108653 | } |
| 108654 | break; |
| 108655 | } |
| 108656 | default: |
| 108657 | break; |
| 108658 | } |
| 108659 | ctx.index += 1; |
| 108660 | } |
| 108661 | return retval; |
| 108662 | } |
| 108663 | |
| 108664 | UA_Server * |
| 108665 | UA_Server_newFromFile(const UA_ByteString json_config) { |
| 108666 | UA_ServerConfig config; |
| 108667 | memset(s: &config, c: 0, n: sizeof(UA_ServerConfig)); |
| 108668 | UA_StatusCode res = UA_ServerConfig_setDefault(config: &config); |
| 108669 | res |= parseJSONConfig(config: &config, json_config); |
| 108670 | if(res != UA_STATUSCODE_GOOD) |
| 108671 | return NULL; |
| 108672 | return UA_Server_newWithConfig(config: &config); |
| 108673 | } |
| 108674 | |
| 108675 | UA_StatusCode |
| 108676 | UA_ServerConfig_updateFromFile(UA_ServerConfig *config, const UA_ByteString json_config) { |
| 108677 | UA_StatusCode res = parseJSONConfig(config, json_config); |
| 108678 | return res; |
| 108679 | } |
| 108680 | |
| 108681 | #ifdef UA_ENABLE_ENCRYPTION |
| 108682 | static UA_ByteString |
| 108683 | loadCertificateFile(const char *const path) { |
| 108684 | UA_ByteString fileContents = UA_STRING_NULL; |
| 108685 | |
| 108686 | /* Open the file */ |
| 108687 | FILE *fp = fopen(filename: path, modes: "rb"); |
| 108688 | if(!fp) { |
| 108689 | errno = 0; /* We read errno also from the tcp layer... */ |
| 108690 | return fileContents; |
| 108691 | } |
| 108692 | |
| 108693 | /* Get the file length, allocate the data and read */ |
| 108694 | fseek(stream: fp, off: 0, SEEK_END); |
| 108695 | fileContents.length = (size_t)ftell(stream: fp); |
| 108696 | fileContents.data = (UA_Byte *)UA_malloc(size: fileContents.length * sizeof(UA_Byte)); |
| 108697 | if(fileContents.data) { |
| 108698 | fseek(stream: fp, off: 0, SEEK_SET); |
| 108699 | size_t read = fread(ptr: fileContents.data, size: sizeof(UA_Byte), n: fileContents.length, stream: fp); |
| 108700 | if(read != fileContents.length) |
| 108701 | UA_ByteString_clear(p: &fileContents); |
| 108702 | } else { |
| 108703 | fileContents.length = 0; |
| 108704 | } |
| 108705 | fclose(stream: fp); |
| 108706 | |
| 108707 | return fileContents; |
| 108708 | } |
| 108709 | #endif |
| 108710 | |
| 108711 | /**** amalgamated original file "/plugins/historydata/ua_history_data_backend_memory.c" ****/ |
| 108712 | |
| 108713 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 108714 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 108715 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 108716 | * |
| 108717 | * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler) |
| 108718 | * Copyright 2021 (c) luibass92 <luibass92@live.it> (Author: Luigi Bassetta) |
| 108719 | */ |
| 108720 | |
| 108721 | |
| 108722 | #include <limits.h> |
| 108723 | #include <string.h> |
| 108724 | |
| 108725 | typedef struct { |
| 108726 | UA_DateTime timestamp; |
| 108727 | UA_DataValue value; |
| 108728 | } UA_DataValueMemoryStoreItem; |
| 108729 | |
| 108730 | static void |
| 108731 | UA_DataValueMemoryStoreItem_clear(UA_DataValueMemoryStoreItem* item) { |
| 108732 | UA_DateTime_clear(p: &item->timestamp); |
| 108733 | UA_DataValue_clear(p: &item->value); |
| 108734 | } |
| 108735 | |
| 108736 | typedef struct { |
| 108737 | UA_NodeId nodeId; |
| 108738 | UA_DataValueMemoryStoreItem **dataStore; |
| 108739 | size_t storeEnd; |
| 108740 | size_t storeSize; |
| 108741 | /* New field useful for circular buffer management */ |
| 108742 | size_t lastInserted; |
| 108743 | } UA_NodeIdStoreContextItem_backend_memory; |
| 108744 | |
| 108745 | static void |
| 108746 | UA_NodeIdStoreContextItem_clear(UA_NodeIdStoreContextItem_backend_memory* item) { |
| 108747 | UA_NodeId_clear(p: &item->nodeId); |
| 108748 | for (size_t i = 0; i < item->storeEnd; ++i) { |
| 108749 | UA_DataValueMemoryStoreItem_clear(item: item->dataStore[i]); |
| 108750 | UA_free(ptr: item->dataStore[i]); |
| 108751 | } |
| 108752 | UA_free(ptr: item->dataStore); |
| 108753 | } |
| 108754 | |
| 108755 | typedef struct { |
| 108756 | UA_NodeIdStoreContextItem_backend_memory *dataStore; |
| 108757 | size_t storeEnd; |
| 108758 | size_t storeSize; |
| 108759 | size_t initialStoreSize; |
| 108760 | } UA_MemoryStoreContext; |
| 108761 | |
| 108762 | static void |
| 108763 | UA_MemoryStoreContext_clear(UA_MemoryStoreContext* ctx) { |
| 108764 | for (size_t i = 0; i < ctx->storeEnd; ++i) { |
| 108765 | UA_NodeIdStoreContextItem_clear(item: &ctx->dataStore[i]); |
| 108766 | } |
| 108767 | UA_free(ptr: ctx->dataStore); |
| 108768 | memset(s: ctx, c: 0, n: sizeof(UA_MemoryStoreContext)); |
| 108769 | } |
| 108770 | |
| 108771 | static UA_NodeIdStoreContextItem_backend_memory * |
| 108772 | getNewNodeIdContext_backend_memory(UA_MemoryStoreContext* context, |
| 108773 | UA_Server *server, |
| 108774 | const UA_NodeId *nodeId) { |
| 108775 | UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext*)context; |
| 108776 | if (ctx->storeEnd >= ctx->storeSize) { |
| 108777 | size_t newStoreSize = ctx->storeSize * 2; |
| 108778 | if (newStoreSize == 0) |
| 108779 | return NULL; |
| 108780 | ctx->dataStore = (UA_NodeIdStoreContextItem_backend_memory*)UA_realloc(ptr: ctx->dataStore, size: (newStoreSize * sizeof(UA_NodeIdStoreContextItem_backend_memory))); |
| 108781 | if (!ctx->dataStore) { |
| 108782 | ctx->storeSize = 0; |
| 108783 | return NULL; |
| 108784 | } |
| 108785 | ctx->storeSize = newStoreSize; |
| 108786 | } |
| 108787 | UA_NodeIdStoreContextItem_backend_memory *item = &ctx->dataStore[ctx->storeEnd]; |
| 108788 | UA_NodeId_copy(src: nodeId, dst: &item->nodeId); |
| 108789 | UA_DataValueMemoryStoreItem ** store = (UA_DataValueMemoryStoreItem **)UA_calloc(nmemb: ctx->initialStoreSize, size: sizeof(UA_DataValueMemoryStoreItem*)); |
| 108790 | if (!store) { |
| 108791 | UA_NodeIdStoreContextItem_clear(item); |
| 108792 | return NULL; |
| 108793 | } |
| 108794 | item->dataStore = store; |
| 108795 | item->storeSize = ctx->initialStoreSize; |
| 108796 | item->storeEnd = 0; |
| 108797 | ++ctx->storeEnd; |
| 108798 | return item; |
| 108799 | } |
| 108800 | |
| 108801 | static UA_NodeIdStoreContextItem_backend_memory * |
| 108802 | getNodeIdStoreContextItem_backend_memory(UA_MemoryStoreContext* context, |
| 108803 | UA_Server *server, |
| 108804 | const UA_NodeId *nodeId) |
| 108805 | { |
| 108806 | for (size_t i = 0; i < context->storeEnd; ++i) { |
| 108807 | if (UA_NodeId_equal(p1: nodeId, p2: &context->dataStore[i].nodeId)) { |
| 108808 | return &context->dataStore[i]; |
| 108809 | } |
| 108810 | } |
| 108811 | return getNewNodeIdContext_backend_memory(context, server, nodeId); |
| 108812 | } |
| 108813 | |
| 108814 | static UA_Boolean |
| 108815 | binarySearch_backend_memory(const UA_NodeIdStoreContextItem_backend_memory* item, |
| 108816 | const UA_DateTime timestamp, |
| 108817 | size_t *index) { |
| 108818 | if (item->storeEnd == 0) { |
| 108819 | *index = item->storeEnd; |
| 108820 | return false; |
| 108821 | } |
| 108822 | size_t min = 0; |
| 108823 | size_t max = item->storeEnd - 1; |
| 108824 | while (min <= max) { |
| 108825 | *index = (min + max) / 2; |
| 108826 | if (item->dataStore[*index]->timestamp == timestamp) { |
| 108827 | return true; |
| 108828 | } else if (item->dataStore[*index]->timestamp < timestamp) { |
| 108829 | if (*index == item->storeEnd - 1) { |
| 108830 | *index = item->storeEnd; |
| 108831 | return false; |
| 108832 | } |
| 108833 | min = *index + 1; |
| 108834 | } else { |
| 108835 | if (*index == 0) |
| 108836 | return false; |
| 108837 | max = *index - 1; |
| 108838 | } |
| 108839 | } |
| 108840 | *index = min; |
| 108841 | return false; |
| 108842 | |
| 108843 | } |
| 108844 | |
| 108845 | static size_t |
| 108846 | resultSize_backend_memory(UA_Server *server, |
| 108847 | void *context, |
| 108848 | const UA_NodeId *sessionId, |
| 108849 | void *sessionContext, |
| 108850 | const UA_NodeId * nodeId, |
| 108851 | size_t startIndex, |
| 108852 | size_t endIndex) { |
| 108853 | const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId); |
| 108854 | if (item->storeEnd == 0 |
| 108855 | || startIndex == item->storeEnd |
| 108856 | || endIndex == item->storeEnd) |
| 108857 | return 0; |
| 108858 | return endIndex - startIndex + 1; |
| 108859 | } |
| 108860 | |
| 108861 | static size_t |
| 108862 | getDateTimeMatch_backend_memory(UA_Server *server, |
| 108863 | void *context, |
| 108864 | const UA_NodeId *sessionId, |
| 108865 | void *sessionContext, |
| 108866 | const UA_NodeId * nodeId, |
| 108867 | const UA_DateTime timestamp, |
| 108868 | const MatchStrategy strategy) { |
| 108869 | const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId); |
| 108870 | size_t current; |
| 108871 | UA_Boolean retval = binarySearch_backend_memory(item, timestamp, index: ¤t); |
| 108872 | |
| 108873 | if ((strategy == MATCH_EQUAL |
| 108874 | || strategy == MATCH_EQUAL_OR_AFTER |
| 108875 | || strategy == MATCH_EQUAL_OR_BEFORE) |
| 108876 | && retval) |
| 108877 | return current; |
| 108878 | switch (strategy) { |
| 108879 | case MATCH_AFTER: |
| 108880 | if (retval) |
| 108881 | return current+1; |
| 108882 | return current; |
| 108883 | case MATCH_EQUAL_OR_AFTER: |
| 108884 | return current; |
| 108885 | case MATCH_EQUAL_OR_BEFORE: |
| 108886 | // retval == true aka "equal" is handled before |
| 108887 | // Fall through if !retval |
| 108888 | case MATCH_BEFORE: |
| 108889 | if (current > 0) |
| 108890 | return current-1; |
| 108891 | else |
| 108892 | return item->storeEnd; |
| 108893 | default: |
| 108894 | break; |
| 108895 | } |
| 108896 | return item->storeEnd; |
| 108897 | } |
| 108898 | |
| 108899 | |
| 108900 | static UA_StatusCode |
| 108901 | serverSetHistoryData_backend_memory(UA_Server *server, |
| 108902 | void *context, |
| 108903 | const UA_NodeId *sessionId, |
| 108904 | void *sessionContext, |
| 108905 | const UA_NodeId * nodeId, |
| 108906 | UA_Boolean historizing, |
| 108907 | const UA_DataValue *value) |
| 108908 | { |
| 108909 | UA_NodeIdStoreContextItem_backend_memory *item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId); |
| 108910 | |
| 108911 | if (item->storeEnd >= item->storeSize) { |
| 108912 | size_t newStoreSize = item->storeSize == 0 ? INITIAL_MEMORY_STORE_SIZE : item->storeSize * 2; |
| 108913 | item->dataStore = (UA_DataValueMemoryStoreItem **)UA_realloc(ptr: item->dataStore, size: (newStoreSize * sizeof(UA_DataValueMemoryStoreItem*))); |
| 108914 | if (!item->dataStore) { |
| 108915 | item->storeSize = 0; |
| 108916 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 108917 | } |
| 108918 | item->storeSize = newStoreSize; |
| 108919 | } |
| 108920 | UA_DateTime timestamp = 0; |
| 108921 | if (value->hasSourceTimestamp) { |
| 108922 | timestamp = value->sourceTimestamp; |
| 108923 | } else if (value->hasServerTimestamp) { |
| 108924 | timestamp = value->serverTimestamp; |
| 108925 | } else { |
| 108926 | timestamp = UA_DateTime_now(); |
| 108927 | } |
| 108928 | UA_DataValueMemoryStoreItem *newItem = (UA_DataValueMemoryStoreItem *)UA_calloc(nmemb: 1, size: sizeof(UA_DataValueMemoryStoreItem)); |
| 108929 | newItem->timestamp = timestamp; |
| 108930 | UA_DataValue_copy(src: value, dst: &newItem->value); |
| 108931 | if(!newItem->value.hasServerTimestamp) { |
| 108932 | newItem->value.serverTimestamp = timestamp; |
| 108933 | newItem->value.hasServerTimestamp = true; |
| 108934 | } |
| 108935 | size_t index = getDateTimeMatch_backend_memory(server, |
| 108936 | context, |
| 108937 | NULL, |
| 108938 | NULL, |
| 108939 | nodeId, |
| 108940 | timestamp, |
| 108941 | strategy: MATCH_EQUAL_OR_AFTER); |
| 108942 | if (item->storeEnd > 0 && index < item->storeEnd) { |
| 108943 | memmove(dest: &item->dataStore[index+1], src: &item->dataStore[index], n: sizeof(UA_DataValueMemoryStoreItem*) * (item->storeEnd - index)); |
| 108944 | } |
| 108945 | item->dataStore[index] = newItem; |
| 108946 | ++item->storeEnd; |
| 108947 | return UA_STATUSCODE_GOOD; |
| 108948 | } |
| 108949 | |
| 108950 | static void |
| 108951 | UA_MemoryStoreContext_delete(UA_MemoryStoreContext* ctx) { |
| 108952 | UA_MemoryStoreContext_clear(ctx); |
| 108953 | UA_free(ptr: ctx); |
| 108954 | } |
| 108955 | |
| 108956 | static size_t |
| 108957 | getEnd_backend_memory(UA_Server *server, |
| 108958 | void *context, |
| 108959 | const UA_NodeId *sessionId, |
| 108960 | void *sessionContext, |
| 108961 | const UA_NodeId * nodeId) { |
| 108962 | const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId); |
| 108963 | return item->storeEnd; |
| 108964 | } |
| 108965 | |
| 108966 | static size_t |
| 108967 | lastIndex_backend_memory(UA_Server *server, |
| 108968 | void *context, |
| 108969 | const UA_NodeId *sessionId, |
| 108970 | void *sessionContext, |
| 108971 | const UA_NodeId * nodeId) { |
| 108972 | const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId); |
| 108973 | if (item->storeEnd == 0) |
| 108974 | return 0; |
| 108975 | return item->storeEnd - 1; |
| 108976 | } |
| 108977 | |
| 108978 | static size_t |
| 108979 | firstIndex_backend_memory(UA_Server *server, |
| 108980 | void *context, |
| 108981 | const UA_NodeId *sessionId, |
| 108982 | void *sessionContext, |
| 108983 | const UA_NodeId * nodeId) { |
| 108984 | return 0; |
| 108985 | } |
| 108986 | |
| 108987 | static UA_Boolean |
| 108988 | boundSupported_backend_memory(UA_Server *server, |
| 108989 | void *context, |
| 108990 | const UA_NodeId *sessionId, |
| 108991 | void *sessionContext, |
| 108992 | const UA_NodeId * nodeId) { |
| 108993 | return true; |
| 108994 | } |
| 108995 | |
| 108996 | static UA_Boolean |
| 108997 | timestampsToReturnSupported_backend_memory(UA_Server *server, |
| 108998 | void *context, |
| 108999 | const UA_NodeId *sessionId, |
| 109000 | void *sessionContext, |
| 109001 | const UA_NodeId *nodeId, |
| 109002 | const UA_TimestampsToReturn timestampsToReturn) { |
| 109003 | const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId); |
| 109004 | if (item->storeEnd == 0) { |
| 109005 | return true; |
| 109006 | } |
| 109007 | if (timestampsToReturn == UA_TIMESTAMPSTORETURN_NEITHER |
| 109008 | || timestampsToReturn == UA_TIMESTAMPSTORETURN_INVALID |
| 109009 | || (timestampsToReturn == UA_TIMESTAMPSTORETURN_SERVER |
| 109010 | && !item->dataStore[0]->value.hasServerTimestamp) |
| 109011 | || (timestampsToReturn == UA_TIMESTAMPSTORETURN_SOURCE |
| 109012 | && !item->dataStore[0]->value.hasSourceTimestamp) |
| 109013 | || (timestampsToReturn == UA_TIMESTAMPSTORETURN_BOTH |
| 109014 | && !(item->dataStore[0]->value.hasSourceTimestamp |
| 109015 | && item->dataStore[0]->value.hasServerTimestamp))) { |
| 109016 | return false; |
| 109017 | } |
| 109018 | return true; |
| 109019 | } |
| 109020 | |
| 109021 | static const UA_DataValue* |
| 109022 | getDataValue_backend_memory(UA_Server *server, |
| 109023 | void *context, |
| 109024 | const UA_NodeId *sessionId, |
| 109025 | void *sessionContext, |
| 109026 | const UA_NodeId * nodeId, size_t index) { |
| 109027 | const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId); |
| 109028 | return &item->dataStore[index]->value; |
| 109029 | } |
| 109030 | |
| 109031 | static UA_StatusCode |
| 109032 | UA_DataValue_backend_copyRange(const UA_DataValue *src, UA_DataValue *dst, |
| 109033 | const UA_NumericRange range) |
| 109034 | { |
| 109035 | memcpy(dest: dst, src: src, n: sizeof(UA_DataValue)); |
| 109036 | if (src->hasValue) |
| 109037 | return UA_Variant_copyRange(src: &src->value, dst: &dst->value, range); |
| 109038 | return UA_STATUSCODE_BADDATAUNAVAILABLE; |
| 109039 | } |
| 109040 | |
| 109041 | static UA_StatusCode |
| 109042 | copyDataValues_backend_memory(UA_Server *server, |
| 109043 | void *context, |
| 109044 | const UA_NodeId *sessionId, |
| 109045 | void *sessionContext, |
| 109046 | const UA_NodeId * nodeId, |
| 109047 | size_t startIndex, |
| 109048 | size_t endIndex, |
| 109049 | UA_Boolean reverse, |
| 109050 | size_t maxValues, |
| 109051 | UA_NumericRange range, |
| 109052 | UA_Boolean releaseContinuationPoints, |
| 109053 | const UA_ByteString *continuationPoint, |
| 109054 | UA_ByteString *outContinuationPoint, |
| 109055 | size_t * providedValues, |
| 109056 | UA_DataValue * values) |
| 109057 | { |
| 109058 | size_t skip = 0; |
| 109059 | if (continuationPoint->length > 0) { |
| 109060 | if (continuationPoint->length == sizeof(size_t)) { |
| 109061 | skip = *((size_t*)(continuationPoint->data)); |
| 109062 | } else { |
| 109063 | return UA_STATUSCODE_BADCONTINUATIONPOINTINVALID; |
| 109064 | } |
| 109065 | } |
| 109066 | const UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)context, server, nodeId); |
| 109067 | size_t index = startIndex; |
| 109068 | size_t counter = 0; |
| 109069 | size_t skipedValues = 0; |
| 109070 | if (reverse) { |
| 109071 | while (index >= endIndex && index < item->storeEnd && counter < maxValues) { |
| 109072 | if (skipedValues++ >= skip) { |
| 109073 | if (range.dimensionsSize > 0) { |
| 109074 | UA_DataValue_backend_copyRange(src: &item->dataStore[index]->value, dst: &values[counter], range); |
| 109075 | } else { |
| 109076 | UA_DataValue_copy(src: &item->dataStore[index]->value, dst: &values[counter]); |
| 109077 | } |
| 109078 | ++counter; |
| 109079 | } |
| 109080 | --index; |
| 109081 | } |
| 109082 | } else { |
| 109083 | while (index <= endIndex && counter < maxValues) { |
| 109084 | if (skipedValues++ >= skip) { |
| 109085 | if (range.dimensionsSize > 0) { |
| 109086 | UA_DataValue_backend_copyRange(src: &item->dataStore[index]->value, dst: &values[counter], range); |
| 109087 | } else { |
| 109088 | UA_DataValue_copy(src: &item->dataStore[index]->value, dst: &values[counter]); |
| 109089 | } |
| 109090 | ++counter; |
| 109091 | } |
| 109092 | ++index; |
| 109093 | } |
| 109094 | } |
| 109095 | |
| 109096 | if (providedValues) |
| 109097 | *providedValues = counter; |
| 109098 | |
| 109099 | if ((!reverse && (endIndex-startIndex-skip+1) > counter) || (reverse && (startIndex-endIndex-skip+1) > counter)) { |
| 109100 | outContinuationPoint->length = sizeof(size_t); |
| 109101 | size_t t = sizeof(size_t); |
| 109102 | outContinuationPoint->data = (UA_Byte*)UA_malloc(size: t); |
| 109103 | *((size_t*)(outContinuationPoint->data)) = skip + counter; |
| 109104 | } |
| 109105 | |
| 109106 | return UA_STATUSCODE_GOOD; |
| 109107 | } |
| 109108 | |
| 109109 | static UA_StatusCode |
| 109110 | insertDataValue_backend_memory(UA_Server *server, |
| 109111 | void *hdbContext, |
| 109112 | const UA_NodeId *sessionId, |
| 109113 | void *sessionContext, |
| 109114 | const UA_NodeId *nodeId, |
| 109115 | const UA_DataValue *value) |
| 109116 | { |
| 109117 | if (!value->hasSourceTimestamp && !value->hasServerTimestamp) |
| 109118 | return UA_STATUSCODE_BADINVALIDTIMESTAMP; |
| 109119 | const UA_DateTime timestamp = value->hasSourceTimestamp ? value->sourceTimestamp : value->serverTimestamp; |
| 109120 | UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)hdbContext, server, nodeId); |
| 109121 | |
| 109122 | size_t index = getDateTimeMatch_backend_memory(server, |
| 109123 | context: hdbContext, |
| 109124 | sessionId, |
| 109125 | sessionContext, |
| 109126 | nodeId, |
| 109127 | timestamp, |
| 109128 | strategy: MATCH_EQUAL_OR_AFTER); |
| 109129 | if (item->storeEnd != index && item->dataStore[index]->timestamp == timestamp) |
| 109130 | return UA_STATUSCODE_BADENTRYEXISTS; |
| 109131 | |
| 109132 | if (item->storeEnd >= item->storeSize) { |
| 109133 | size_t newStoreSize = item->storeSize == 0 ? INITIAL_MEMORY_STORE_SIZE : item->storeSize * 2; |
| 109134 | item->dataStore = (UA_DataValueMemoryStoreItem **)UA_realloc(ptr: item->dataStore, size: (newStoreSize * sizeof(UA_DataValueMemoryStoreItem*))); |
| 109135 | if (!item->dataStore) { |
| 109136 | item->storeSize = 0; |
| 109137 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 109138 | } |
| 109139 | item->storeSize = newStoreSize; |
| 109140 | } |
| 109141 | UA_DataValueMemoryStoreItem *newItem = (UA_DataValueMemoryStoreItem *)UA_calloc(nmemb: 1, size: sizeof(UA_DataValueMemoryStoreItem)); |
| 109142 | newItem->timestamp = timestamp; |
| 109143 | UA_DataValue_copy(src: value, dst: &newItem->value); |
| 109144 | if(!newItem->value.hasServerTimestamp) { |
| 109145 | newItem->value.serverTimestamp = timestamp; |
| 109146 | newItem->value.hasServerTimestamp = true; |
| 109147 | } |
| 109148 | |
| 109149 | if (item->storeEnd > 0 && index < item->storeEnd) { |
| 109150 | memmove(dest: &item->dataStore[index+1], src: &item->dataStore[index], n: sizeof(UA_DataValueMemoryStoreItem*) * (item->storeEnd - index)); |
| 109151 | } |
| 109152 | item->dataStore[index] = newItem; |
| 109153 | ++item->storeEnd; |
| 109154 | return UA_STATUSCODE_GOOD; |
| 109155 | } |
| 109156 | |
| 109157 | static UA_StatusCode |
| 109158 | replaceDataValue_backend_memory(UA_Server *server, |
| 109159 | void *hdbContext, |
| 109160 | const UA_NodeId *sessionId, |
| 109161 | void *sessionContext, |
| 109162 | const UA_NodeId *nodeId, |
| 109163 | const UA_DataValue *value) |
| 109164 | { |
| 109165 | if (!value->hasSourceTimestamp && !value->hasServerTimestamp) |
| 109166 | return UA_STATUSCODE_BADINVALIDTIMESTAMP; |
| 109167 | const UA_DateTime timestamp = value->hasSourceTimestamp ? value->sourceTimestamp : value->serverTimestamp; |
| 109168 | UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)hdbContext, server, nodeId); |
| 109169 | |
| 109170 | size_t index = getDateTimeMatch_backend_memory(server, |
| 109171 | context: hdbContext, |
| 109172 | sessionId, |
| 109173 | sessionContext, |
| 109174 | nodeId, |
| 109175 | timestamp, |
| 109176 | strategy: MATCH_EQUAL); |
| 109177 | if (index == item->storeEnd) |
| 109178 | return UA_STATUSCODE_BADNOENTRYEXISTS; |
| 109179 | UA_DataValue_clear(p: &item->dataStore[index]->value); |
| 109180 | UA_DataValue_copy(src: value, dst: &item->dataStore[index]->value); |
| 109181 | if(!item->dataStore[index]->value.hasServerTimestamp) { |
| 109182 | item->dataStore[index]->value.serverTimestamp = timestamp; |
| 109183 | item->dataStore[index]->value.hasServerTimestamp = true; |
| 109184 | } |
| 109185 | return UA_STATUSCODE_GOOD; |
| 109186 | } |
| 109187 | |
| 109188 | static UA_StatusCode |
| 109189 | updateDataValue_backend_memory(UA_Server *server, |
| 109190 | void *hdbContext, |
| 109191 | const UA_NodeId *sessionId, |
| 109192 | void *sessionContext, |
| 109193 | const UA_NodeId *nodeId, |
| 109194 | const UA_DataValue *value) |
| 109195 | { |
| 109196 | // we first try to replace, because it is cheap |
| 109197 | UA_StatusCode ret = replaceDataValue_backend_memory(server, |
| 109198 | hdbContext, |
| 109199 | sessionId, |
| 109200 | sessionContext, |
| 109201 | nodeId, |
| 109202 | value); |
| 109203 | if (ret == UA_STATUSCODE_GOOD) |
| 109204 | return UA_STATUSCODE_GOODENTRYREPLACED; |
| 109205 | |
| 109206 | ret = insertDataValue_backend_memory(server, |
| 109207 | hdbContext, |
| 109208 | sessionId, |
| 109209 | sessionContext, |
| 109210 | nodeId, |
| 109211 | value); |
| 109212 | if (ret == UA_STATUSCODE_GOOD) |
| 109213 | return UA_STATUSCODE_GOODENTRYINSERTED; |
| 109214 | |
| 109215 | return ret; |
| 109216 | } |
| 109217 | |
| 109218 | static UA_StatusCode |
| 109219 | removeDataValue_backend_memory(UA_Server *server, |
| 109220 | void *hdbContext, |
| 109221 | const UA_NodeId *sessionId, |
| 109222 | void *sessionContext, |
| 109223 | const UA_NodeId *nodeId, |
| 109224 | UA_DateTime startTimestamp, |
| 109225 | UA_DateTime endTimestamp) |
| 109226 | { |
| 109227 | UA_NodeIdStoreContextItem_backend_memory* item = getNodeIdStoreContextItem_backend_memory(context: (UA_MemoryStoreContext*)hdbContext, server, nodeId); |
| 109228 | size_t storeEnd = item->storeEnd; |
| 109229 | // The first index which will be deleted |
| 109230 | size_t index1; |
| 109231 | // the first index which is not deleted |
| 109232 | size_t index2; |
| 109233 | if (startTimestamp > endTimestamp) { |
| 109234 | return UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED; |
| 109235 | } |
| 109236 | if (startTimestamp == endTimestamp) { |
| 109237 | index1 = getDateTimeMatch_backend_memory(server, |
| 109238 | context: hdbContext, |
| 109239 | sessionId, |
| 109240 | sessionContext, |
| 109241 | nodeId, |
| 109242 | timestamp: startTimestamp, |
| 109243 | strategy: MATCH_EQUAL); |
| 109244 | if (index1 == storeEnd) |
| 109245 | return UA_STATUSCODE_BADNODATA; |
| 109246 | index2 = index1 + 1; |
| 109247 | } else { |
| 109248 | index1 = getDateTimeMatch_backend_memory(server, |
| 109249 | context: hdbContext, |
| 109250 | sessionId, |
| 109251 | sessionContext, |
| 109252 | nodeId, |
| 109253 | timestamp: startTimestamp, |
| 109254 | strategy: MATCH_EQUAL_OR_AFTER); |
| 109255 | index2 = getDateTimeMatch_backend_memory(server, |
| 109256 | context: hdbContext, |
| 109257 | sessionId, |
| 109258 | sessionContext, |
| 109259 | nodeId, |
| 109260 | timestamp: endTimestamp, |
| 109261 | strategy: MATCH_BEFORE); |
| 109262 | if (index2 == storeEnd || index1 == storeEnd || index1 > index2 ) |
| 109263 | return UA_STATUSCODE_BADNODATA; |
| 109264 | ++index2; |
| 109265 | } |
| 109266 | #ifndef __clang_analyzer__ |
| 109267 | for (size_t i = index1; i < index2; ++i) { |
| 109268 | UA_DataValueMemoryStoreItem_clear(item: item->dataStore[i]); |
| 109269 | UA_free(ptr: item->dataStore[i]); |
| 109270 | } |
| 109271 | memmove(dest: &item->dataStore[index1], src: &item->dataStore[index2], n: sizeof(UA_DataValueMemoryStoreItem*) * (item->storeEnd - index2)); |
| 109272 | item->storeEnd -= index2 - index1; |
| 109273 | #else |
| 109274 | (void)index1; |
| 109275 | (void)index2; |
| 109276 | #endif |
| 109277 | return UA_STATUSCODE_GOOD; |
| 109278 | } |
| 109279 | |
| 109280 | static void |
| 109281 | deleteMembers_backend_memory(UA_HistoryDataBackend *backend) |
| 109282 | { |
| 109283 | if (backend == NULL || backend->context == NULL) |
| 109284 | return; |
| 109285 | UA_MemoryStoreContext_clear(ctx: (UA_MemoryStoreContext*)backend->context); |
| 109286 | UA_free(ptr: backend->context); |
| 109287 | } |
| 109288 | |
| 109289 | |
| 109290 | |
| 109291 | UA_HistoryDataBackend |
| 109292 | UA_HistoryDataBackend_Memory(size_t initialNodeIdStoreSize, size_t initialDataStoreSize) { |
| 109293 | if (initialNodeIdStoreSize == 0) |
| 109294 | initialNodeIdStoreSize = 1; |
| 109295 | if (initialDataStoreSize == 0) |
| 109296 | initialDataStoreSize = 1; |
| 109297 | UA_HistoryDataBackend result; |
| 109298 | memset(s: &result, c: 0, n: sizeof(UA_HistoryDataBackend)); |
| 109299 | UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext *)UA_calloc(nmemb: 1, size: sizeof(UA_MemoryStoreContext)); |
| 109300 | if (!ctx) |
| 109301 | return result; |
| 109302 | ctx->dataStore = (UA_NodeIdStoreContextItem_backend_memory*)UA_calloc(nmemb: initialNodeIdStoreSize, size: sizeof(UA_NodeIdStoreContextItem_backend_memory)); |
| 109303 | ctx->initialStoreSize = initialDataStoreSize; |
| 109304 | ctx->storeSize = initialNodeIdStoreSize; |
| 109305 | ctx->storeEnd = 0; |
| 109306 | result.serverSetHistoryData = &serverSetHistoryData_backend_memory; |
| 109307 | result.resultSize = &resultSize_backend_memory; |
| 109308 | result.getEnd = &getEnd_backend_memory; |
| 109309 | result.lastIndex = &lastIndex_backend_memory; |
| 109310 | result.firstIndex = &firstIndex_backend_memory; |
| 109311 | result.getDateTimeMatch = &getDateTimeMatch_backend_memory; |
| 109312 | result.copyDataValues = ©DataValues_backend_memory; |
| 109313 | result.getDataValue = &getDataValue_backend_memory; |
| 109314 | result.boundSupported = &boundSupported_backend_memory; |
| 109315 | result.timestampsToReturnSupported = ×tampsToReturnSupported_backend_memory; |
| 109316 | result.insertDataValue = &insertDataValue_backend_memory; |
| 109317 | result.updateDataValue = &updateDataValue_backend_memory; |
| 109318 | result.replaceDataValue = &replaceDataValue_backend_memory; |
| 109319 | result.removeDataValue = &removeDataValue_backend_memory; |
| 109320 | result.deleteMembers = &deleteMembers_backend_memory; |
| 109321 | result.getHistoryData = NULL; |
| 109322 | result.context = ctx; |
| 109323 | return result; |
| 109324 | } |
| 109325 | |
| 109326 | void |
| 109327 | UA_HistoryDataBackend_Memory_clear(UA_HistoryDataBackend *backend) |
| 109328 | { |
| 109329 | UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext*)backend->context; |
| 109330 | UA_MemoryStoreContext_delete(ctx); |
| 109331 | memset(s: backend, c: 0, n: sizeof(UA_HistoryDataBackend)); |
| 109332 | } |
| 109333 | |
| 109334 | /* Circular buffer implementation */ |
| 109335 | |
| 109336 | static UA_NodeIdStoreContextItem_backend_memory * |
| 109337 | getNewNodeIdContext_backend_memory_Circular(UA_MemoryStoreContext *context, |
| 109338 | UA_Server *server, |
| 109339 | const UA_NodeId *nodeId) { |
| 109340 | UA_MemoryStoreContext *ctx = (UA_MemoryStoreContext *)context; |
| 109341 | if(ctx->storeEnd >= ctx->storeSize) { |
| 109342 | return NULL; |
| 109343 | } |
| 109344 | UA_NodeIdStoreContextItem_backend_memory *item = &ctx->dataStore[ctx->storeEnd]; |
| 109345 | UA_NodeId_copy(src: nodeId, dst: &item->nodeId); |
| 109346 | UA_DataValueMemoryStoreItem **store = (UA_DataValueMemoryStoreItem **)UA_calloc(nmemb: ctx->initialStoreSize, size: sizeof(UA_DataValueMemoryStoreItem *)); |
| 109347 | if(!store) { |
| 109348 | UA_NodeIdStoreContextItem_clear(item); |
| 109349 | return NULL; |
| 109350 | } |
| 109351 | item->dataStore = store; |
| 109352 | item->storeSize = ctx->initialStoreSize; |
| 109353 | item->storeEnd = 0; |
| 109354 | ++ctx->storeEnd; |
| 109355 | return item; |
| 109356 | } |
| 109357 | |
| 109358 | static UA_NodeIdStoreContextItem_backend_memory * |
| 109359 | getNodeIdStoreContextItem_backend_memory_Circular(UA_MemoryStoreContext *context, |
| 109360 | UA_Server *server, |
| 109361 | const UA_NodeId *nodeId) { |
| 109362 | for(size_t i = 0; i < context->storeEnd; ++i) { |
| 109363 | if(UA_NodeId_equal(p1: nodeId, p2: &context->dataStore[i].nodeId)) { |
| 109364 | return &context->dataStore[i]; |
| 109365 | } |
| 109366 | } |
| 109367 | return getNewNodeIdContext_backend_memory_Circular(context, server, nodeId); |
| 109368 | } |
| 109369 | |
| 109370 | static UA_StatusCode |
| 109371 | serverSetHistoryData_backend_memory_Circular(UA_Server *server, |
| 109372 | void *context, |
| 109373 | const UA_NodeId *sessionId, |
| 109374 | void *sessionContext, |
| 109375 | const UA_NodeId *nodeId, |
| 109376 | UA_Boolean historizing, |
| 109377 | const UA_DataValue *value) { |
| 109378 | UA_NodeIdStoreContextItem_backend_memory *item = getNodeIdStoreContextItem_backend_memory_Circular(context: (UA_MemoryStoreContext *)context, server, nodeId); |
| 109379 | if(item == NULL) { |
| 109380 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 109381 | } |
| 109382 | if(item->lastInserted >= item->storeSize) { |
| 109383 | /* If the buffer size is overcomed, push new elements from the start of the buffer */ |
| 109384 | item->lastInserted = 0; |
| 109385 | } |
| 109386 | UA_DateTime timestamp = 0; |
| 109387 | if(value->hasSourceTimestamp) { |
| 109388 | timestamp = value->sourceTimestamp; |
| 109389 | } else if(value->hasServerTimestamp) { |
| 109390 | timestamp = value->serverTimestamp; |
| 109391 | } else { |
| 109392 | timestamp = UA_DateTime_now(); |
| 109393 | } |
| 109394 | UA_DataValueMemoryStoreItem *newItem = (UA_DataValueMemoryStoreItem *)UA_calloc(nmemb: 1, size: sizeof(UA_DataValueMemoryStoreItem)); |
| 109395 | newItem->timestamp = timestamp; |
| 109396 | UA_DataValue_copy(src: value, dst: &newItem->value); |
| 109397 | if(!newItem->value.hasServerTimestamp) { |
| 109398 | newItem->value.serverTimestamp = timestamp; |
| 109399 | newItem->value.hasServerTimestamp = true; |
| 109400 | } |
| 109401 | |
| 109402 | |
| 109403 | /* This implementation does NOT sort values by timestamp */ |
| 109404 | |
| 109405 | if(item->dataStore[item->lastInserted] != NULL) { |
| 109406 | UA_DataValueMemoryStoreItem_clear(item: item->dataStore[item->lastInserted]); |
| 109407 | UA_free(ptr: item->dataStore[item->lastInserted]); |
| 109408 | } |
| 109409 | item->dataStore[item->lastInserted] = newItem; |
| 109410 | ++item->lastInserted; |
| 109411 | |
| 109412 | if(item->storeEnd < item->storeSize) { |
| 109413 | ++item->storeEnd; |
| 109414 | } |
| 109415 | |
| 109416 | return UA_STATUSCODE_GOOD; |
| 109417 | } |
| 109418 | |
| 109419 | static size_t |
| 109420 | getResultSize_service_Circular(const UA_HistoryDataBackend *backend, UA_Server *server, |
| 109421 | const UA_NodeId *sessionId, void *sessionContext, |
| 109422 | const UA_NodeId *nodeId, UA_DateTime start, |
| 109423 | UA_DateTime end, UA_UInt32 numValuesPerNode, |
| 109424 | UA_Boolean returnBounds, size_t *startIndex, |
| 109425 | size_t *endIndex, UA_Boolean *addFirst, |
| 109426 | UA_Boolean *addLast, UA_Boolean *reverse) { |
| 109427 | *startIndex = 0; |
| 109428 | *endIndex = backend->lastIndex(server, backend->context, sessionId, sessionContext, nodeId); |
| 109429 | *addFirst = false; |
| 109430 | *addLast = false; |
| 109431 | if(end == LLONG_MIN) { |
| 109432 | *reverse = false; |
| 109433 | } else if(start == LLONG_MIN) { |
| 109434 | *reverse = true; |
| 109435 | } else { |
| 109436 | *reverse = end < start; |
| 109437 | } |
| 109438 | |
| 109439 | size_t size = 0; |
| 109440 | const UA_NodeIdStoreContextItem_backend_memory *item = getNodeIdStoreContextItem_backend_memory_Circular(context: (UA_MemoryStoreContext *)backend->context, server, nodeId); |
| 109441 | if(item == NULL) { |
| 109442 | size = 0; |
| 109443 | } else { |
| 109444 | size = item->storeEnd; |
| 109445 | } |
| 109446 | return size; |
| 109447 | } |
| 109448 | |
| 109449 | static UA_StatusCode |
| 109450 | getHistoryData_service_Circular(UA_Server *server, |
| 109451 | const UA_NodeId *sessionId, |
| 109452 | void *sessionContext, |
| 109453 | const UA_HistoryDataBackend *backend, |
| 109454 | const UA_DateTime start, |
| 109455 | const UA_DateTime end, |
| 109456 | const UA_NodeId *nodeId, |
| 109457 | size_t maxSize, |
| 109458 | UA_UInt32 numValuesPerNode, |
| 109459 | UA_Boolean returnBounds, |
| 109460 | UA_TimestampsToReturn timestampsToReturn, |
| 109461 | UA_NumericRange range, |
| 109462 | UA_Boolean releaseContinuationPoints, |
| 109463 | const UA_ByteString *continuationPoint, |
| 109464 | UA_ByteString *outContinuationPoint, |
| 109465 | UA_HistoryData *historyData) { |
| 109466 | size_t *resultSize = &historyData->dataValuesSize; |
| 109467 | UA_DataValue **result = &historyData->dataValues; |
| 109468 | size_t skip = 0; |
| 109469 | UA_ByteString backendContinuationPoint; |
| 109470 | UA_ByteString_init(p: &backendContinuationPoint); |
| 109471 | if(continuationPoint->length > 0) { |
| 109472 | if(continuationPoint->length < sizeof(size_t)) |
| 109473 | return UA_STATUSCODE_BADCONTINUATIONPOINTINVALID; |
| 109474 | skip = *((size_t *)(continuationPoint->data)); |
| 109475 | backendContinuationPoint.length = continuationPoint->length - sizeof(size_t); |
| 109476 | backendContinuationPoint.data = continuationPoint->data + sizeof(size_t); |
| 109477 | } |
| 109478 | size_t storeEnd = backend->getEnd(server, backend->context, sessionId, sessionContext, nodeId); |
| 109479 | size_t startIndex; |
| 109480 | size_t endIndex; |
| 109481 | UA_Boolean addFirst; |
| 109482 | UA_Boolean addLast; |
| 109483 | UA_Boolean reverse; |
| 109484 | size_t _resultSize = getResultSize_service_Circular(backend, |
| 109485 | server, |
| 109486 | sessionId, |
| 109487 | sessionContext, |
| 109488 | nodeId, |
| 109489 | start, |
| 109490 | end, |
| 109491 | numValuesPerNode: numValuesPerNode == 0 ? 0 : numValuesPerNode + (UA_UInt32)skip, |
| 109492 | returnBounds, |
| 109493 | startIndex: &startIndex, |
| 109494 | endIndex: &endIndex, |
| 109495 | addFirst: &addFirst, |
| 109496 | addLast: &addLast, |
| 109497 | reverse: &reverse); |
| 109498 | *resultSize = _resultSize - skip; |
| 109499 | if(*resultSize > maxSize) { |
| 109500 | *resultSize = maxSize; |
| 109501 | } |
| 109502 | UA_DataValue *outResult = (UA_DataValue *)UA_Array_new(size: *resultSize, type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 109503 | if(!outResult) { |
| 109504 | *resultSize = 0; |
| 109505 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 109506 | } |
| 109507 | *result = outResult; |
| 109508 | size_t counter = 0; |
| 109509 | if(addFirst) { |
| 109510 | if(skip == 0) { |
| 109511 | outResult[counter].hasStatus = true; |
| 109512 | outResult[counter].status = UA_STATUSCODE_BADBOUNDNOTFOUND; |
| 109513 | outResult[counter].hasSourceTimestamp = true; |
| 109514 | if(start == LLONG_MIN) { |
| 109515 | outResult[counter].sourceTimestamp = end; |
| 109516 | } else { |
| 109517 | outResult[counter].sourceTimestamp = start; |
| 109518 | } |
| 109519 | ++counter; |
| 109520 | } |
| 109521 | } |
| 109522 | UA_ByteString backendOutContinuationPoint; |
| 109523 | UA_ByteString_init(p: &backendOutContinuationPoint); |
| 109524 | if(endIndex != storeEnd && startIndex != storeEnd) { |
| 109525 | size_t retval = 0; |
| 109526 | size_t valueSize = *resultSize - counter; |
| 109527 | if(valueSize + skip > _resultSize - addFirst - addLast) { |
| 109528 | if(skip == 0) { |
| 109529 | valueSize = _resultSize - addFirst - addLast; |
| 109530 | } else { |
| 109531 | valueSize = _resultSize - skip - addLast; |
| 109532 | } |
| 109533 | } |
| 109534 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 109535 | if(valueSize > 0) |
| 109536 | ret = backend->copyDataValues(server, |
| 109537 | backend->context, |
| 109538 | sessionId, |
| 109539 | sessionContext, |
| 109540 | nodeId, |
| 109541 | startIndex, |
| 109542 | endIndex, |
| 109543 | reverse, |
| 109544 | valueSize, |
| 109545 | range, |
| 109546 | releaseContinuationPoints, |
| 109547 | &backendContinuationPoint, |
| 109548 | &backendOutContinuationPoint, |
| 109549 | &retval, |
| 109550 | &outResult[counter]); |
| 109551 | if(ret != UA_STATUSCODE_GOOD) { |
| 109552 | UA_Array_delete(p: outResult, size: *resultSize, type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 109553 | *result = NULL; |
| 109554 | *resultSize = 0; |
| 109555 | return ret; |
| 109556 | } |
| 109557 | counter += retval; |
| 109558 | } |
| 109559 | if(addLast && counter < *resultSize) { |
| 109560 | outResult[counter].hasStatus = true; |
| 109561 | outResult[counter].status = UA_STATUSCODE_BADBOUNDNOTFOUND; |
| 109562 | outResult[counter].hasSourceTimestamp = true; |
| 109563 | if(start == LLONG_MIN && storeEnd != backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId)) { |
| 109564 | outResult[counter].sourceTimestamp = backend->getDataValue(server, backend->context, sessionId, sessionContext, nodeId, endIndex)->sourceTimestamp - UA_DATETIME_SEC; |
| 109565 | } else if(end == LLONG_MIN && storeEnd != backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId)) { |
| 109566 | outResult[counter].sourceTimestamp = backend->getDataValue(server, backend->context, sessionId, sessionContext, nodeId, endIndex)->sourceTimestamp + UA_DATETIME_SEC; |
| 109567 | } else { |
| 109568 | outResult[counter].sourceTimestamp = end; |
| 109569 | } |
| 109570 | } |
| 109571 | // there are more values |
| 109572 | if(skip + *resultSize < _resultSize |
| 109573 | // there are not more values for this request, but there are more values in |
| 109574 | // database |
| 109575 | || (backendOutContinuationPoint.length > 0 && numValuesPerNode != 0) |
| 109576 | // we deliver just one value which is a FIRST/LAST value |
| 109577 | || (skip == 0 && addFirst == true && *resultSize == 1)) { |
| 109578 | if(UA_ByteString_allocBuffer(bs: outContinuationPoint, length: backendOutContinuationPoint.length + sizeof(size_t)) != UA_STATUSCODE_GOOD) { |
| 109579 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 109580 | } |
| 109581 | *((size_t *)(outContinuationPoint->data)) = skip + *resultSize; |
| 109582 | if(backendOutContinuationPoint.length > 0) |
| 109583 | memcpy(dest: outContinuationPoint->data + sizeof(size_t), src: backendOutContinuationPoint.data, n: backendOutContinuationPoint.length); |
| 109584 | } |
| 109585 | UA_ByteString_clear(p: &backendOutContinuationPoint); |
| 109586 | return UA_STATUSCODE_GOOD; |
| 109587 | } |
| 109588 | |
| 109589 | UA_HistoryDataBackend |
| 109590 | UA_HistoryDataBackend_Memory_Circular(size_t initialNodeIdStoreSize, size_t initialDataStoreSize) { |
| 109591 | UA_HistoryDataBackend result = UA_HistoryDataBackend_Memory(initialNodeIdStoreSize, initialDataStoreSize); |
| 109592 | result.serverSetHistoryData = &serverSetHistoryData_backend_memory_Circular; |
| 109593 | result.getHistoryData = &getHistoryData_service_Circular; |
| 109594 | return result; |
| 109595 | } |
| 109596 | |
| 109597 | /**** amalgamated original file "/plugins/historydata/ua_history_data_gathering_default.c" ****/ |
| 109598 | |
| 109599 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 109600 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 109601 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 109602 | * |
| 109603 | * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler) |
| 109604 | * Copyright 2021 (c) luibass92 <luibass92@live.it> (Author: Luigi Bassetta) |
| 109605 | */ |
| 109606 | |
| 109607 | |
| 109608 | #include <string.h> |
| 109609 | |
| 109610 | typedef struct { |
| 109611 | UA_NodeId nodeId; |
| 109612 | UA_HistorizingNodeIdSettings setting; |
| 109613 | UA_MonitoredItemCreateResult monitoredResult; |
| 109614 | } UA_NodeIdStoreContextItem_gathering_default; |
| 109615 | |
| 109616 | typedef struct { |
| 109617 | UA_NodeIdStoreContextItem_gathering_default *dataStore; |
| 109618 | size_t storeEnd; |
| 109619 | size_t storeSize; |
| 109620 | } UA_NodeIdStoreContext; |
| 109621 | |
| 109622 | static void |
| 109623 | dataChangeCallback_gathering_default(UA_Server *server, |
| 109624 | UA_UInt32 monitoredItemId, |
| 109625 | void *monitoredItemContext, |
| 109626 | const UA_NodeId *nodeId, |
| 109627 | void *nodeContext, |
| 109628 | UA_UInt32 attributeId, |
| 109629 | const UA_DataValue *value) |
| 109630 | { |
| 109631 | UA_NodeIdStoreContextItem_gathering_default *context = (UA_NodeIdStoreContextItem_gathering_default*)monitoredItemContext; |
| 109632 | context->setting.historizingBackend.serverSetHistoryData(server, |
| 109633 | context->setting.historizingBackend.context, |
| 109634 | NULL, |
| 109635 | NULL, |
| 109636 | nodeId, |
| 109637 | UA_TRUE, |
| 109638 | value); |
| 109639 | } |
| 109640 | |
| 109641 | static UA_NodeIdStoreContextItem_gathering_default* |
| 109642 | getNodeIdStoreContextItem_gathering_default(UA_NodeIdStoreContext *context, |
| 109643 | const UA_NodeId *nodeId) |
| 109644 | { |
| 109645 | for (size_t i = 0; i < context->storeEnd; ++i) { |
| 109646 | if (UA_NodeId_equal(p1: &context->dataStore[i].nodeId, p2: nodeId)) { |
| 109647 | return &context->dataStore[i]; |
| 109648 | } |
| 109649 | } |
| 109650 | return NULL; |
| 109651 | } |
| 109652 | |
| 109653 | static UA_StatusCode |
| 109654 | startPoll(UA_Server *server, UA_NodeIdStoreContextItem_gathering_default *item) |
| 109655 | { |
| 109656 | UA_MonitoredItemCreateRequest monitorRequest = |
| 109657 | UA_MonitoredItemCreateRequest_default(nodeId: item->nodeId); |
| 109658 | monitorRequest.requestedParameters.samplingInterval = (double)item->setting.pollingInterval; |
| 109659 | monitorRequest.monitoringMode = UA_MONITORINGMODE_REPORTING; |
| 109660 | item->monitoredResult = |
| 109661 | UA_Server_createDataChangeMonitoredItem(server, |
| 109662 | timestampsToReturn: UA_TIMESTAMPSTORETURN_BOTH, |
| 109663 | item: monitorRequest, |
| 109664 | monitoredItemContext: item, |
| 109665 | callback: &dataChangeCallback_gathering_default); |
| 109666 | return item->monitoredResult.statusCode; |
| 109667 | } |
| 109668 | |
| 109669 | static UA_StatusCode |
| 109670 | stopPoll(UA_Server *server, UA_NodeIdStoreContextItem_gathering_default *item) |
| 109671 | { |
| 109672 | UA_StatusCode retval = UA_Server_deleteMonitoredItem(server, monitoredItemId: item->monitoredResult.monitoredItemId); |
| 109673 | UA_MonitoredItemCreateResult_init(p: &item->monitoredResult); |
| 109674 | return retval; |
| 109675 | } |
| 109676 | |
| 109677 | static UA_StatusCode |
| 109678 | stopPoll_gathering_default(UA_Server *server, |
| 109679 | void *context, |
| 109680 | const UA_NodeId *nodeId) |
| 109681 | { |
| 109682 | UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext *)context; |
| 109683 | UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId); |
| 109684 | if (!item) { |
| 109685 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 109686 | } |
| 109687 | if (item->setting.historizingUpdateStrategy != UA_HISTORIZINGUPDATESTRATEGY_POLL) |
| 109688 | return UA_STATUSCODE_BADNODEIDINVALID; |
| 109689 | if (item->monitoredResult.monitoredItemId == 0) |
| 109690 | return UA_STATUSCODE_BADMONITOREDITEMIDINVALID; |
| 109691 | return stopPoll(server, item); |
| 109692 | } |
| 109693 | |
| 109694 | static UA_StatusCode |
| 109695 | startPoll_gathering_default(UA_Server *server, |
| 109696 | void *context, |
| 109697 | const UA_NodeId *nodeId) |
| 109698 | { |
| 109699 | UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext *)context; |
| 109700 | UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId); |
| 109701 | if (!item) { |
| 109702 | return UA_STATUSCODE_BADNODEIDUNKNOWN; |
| 109703 | } |
| 109704 | if (item->setting.historizingUpdateStrategy != UA_HISTORIZINGUPDATESTRATEGY_POLL) |
| 109705 | return UA_STATUSCODE_BADNODEIDINVALID; |
| 109706 | if (item->monitoredResult.monitoredItemId > 0) |
| 109707 | return UA_STATUSCODE_BADMONITOREDITEMIDINVALID; |
| 109708 | return startPoll(server, item); |
| 109709 | } |
| 109710 | |
| 109711 | static UA_StatusCode |
| 109712 | registerNodeId_gathering_default(UA_Server *server, |
| 109713 | void *context, |
| 109714 | const UA_NodeId *nodeId, |
| 109715 | const UA_HistorizingNodeIdSettings setting) |
| 109716 | { |
| 109717 | UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context; |
| 109718 | if (getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId)) { |
| 109719 | return UA_STATUSCODE_BADNODEIDEXISTS; |
| 109720 | } |
| 109721 | if (ctx->storeEnd >= ctx->storeSize) { |
| 109722 | size_t newStoreSize = ctx->storeSize * 2; |
| 109723 | ctx->dataStore = (UA_NodeIdStoreContextItem_gathering_default*)UA_realloc(ptr: ctx->dataStore, size: (newStoreSize * sizeof(UA_NodeIdStoreContextItem_gathering_default))); |
| 109724 | if (!ctx->dataStore) { |
| 109725 | ctx->storeSize = 0; |
| 109726 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 109727 | } |
| 109728 | memset(s: &ctx->dataStore[ctx->storeSize], c: 0, n: (newStoreSize - ctx->storeSize) * sizeof(UA_NodeIdStoreContextItem_gathering_default)); |
| 109729 | ctx->storeSize = newStoreSize; |
| 109730 | } |
| 109731 | UA_NodeId_copy(src: nodeId, dst: &ctx->dataStore[ctx->storeEnd].nodeId); |
| 109732 | size_t current = ctx->storeEnd; |
| 109733 | ctx->dataStore[current].setting = setting; |
| 109734 | ++ctx->storeEnd; |
| 109735 | return UA_STATUSCODE_GOOD; |
| 109736 | } |
| 109737 | |
| 109738 | static const UA_HistorizingNodeIdSettings* |
| 109739 | getHistorizingSetting_gathering_default(UA_Server *server, |
| 109740 | void *context, |
| 109741 | const UA_NodeId *nodeId) |
| 109742 | { |
| 109743 | UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context; |
| 109744 | UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId); |
| 109745 | if (item) { |
| 109746 | return &item->setting; |
| 109747 | } |
| 109748 | return NULL; |
| 109749 | } |
| 109750 | |
| 109751 | static void |
| 109752 | deleteMembers_gathering_default(UA_HistoryDataGathering *gathering) |
| 109753 | { |
| 109754 | if (gathering == NULL || gathering->context == NULL) |
| 109755 | return; |
| 109756 | UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)gathering->context; |
| 109757 | for (size_t i = 0; i < ctx->storeEnd; ++i) { |
| 109758 | UA_NodeId_clear(p: &ctx->dataStore[i].nodeId); |
| 109759 | // There is still a monitored item present for this gathering |
| 109760 | // You need to remove it with UA_Server_deleteMonitoredItem |
| 109761 | UA_assert(ctx->dataStore[i].monitoredResult.monitoredItemId == 0); |
| 109762 | } |
| 109763 | UA_free(ptr: ctx->dataStore); |
| 109764 | UA_free(ptr: gathering->context); |
| 109765 | } |
| 109766 | |
| 109767 | static UA_Boolean |
| 109768 | updateNodeIdSetting_gathering_default(UA_Server *server, |
| 109769 | void *context, |
| 109770 | const UA_NodeId *nodeId, |
| 109771 | const UA_HistorizingNodeIdSettings setting) |
| 109772 | { |
| 109773 | UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context; |
| 109774 | UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId); |
| 109775 | if (!item) { |
| 109776 | return false; |
| 109777 | } |
| 109778 | stopPoll_gathering_default(server, context, nodeId); |
| 109779 | item->setting = setting; |
| 109780 | return true; |
| 109781 | } |
| 109782 | |
| 109783 | static void |
| 109784 | setValue_gathering_default(UA_Server *server, |
| 109785 | void *context, |
| 109786 | const UA_NodeId *sessionId, |
| 109787 | void *sessionContext, |
| 109788 | const UA_NodeId *nodeId, |
| 109789 | UA_Boolean historizing, |
| 109790 | const UA_DataValue *value) |
| 109791 | { |
| 109792 | UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext*)context; |
| 109793 | UA_NodeIdStoreContextItem_gathering_default *item = getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId); |
| 109794 | if (!item) { |
| 109795 | return; |
| 109796 | } |
| 109797 | if (item->setting.historizingUpdateStrategy == UA_HISTORIZINGUPDATESTRATEGY_VALUESET) { |
| 109798 | item->setting.historizingBackend.serverSetHistoryData(server, |
| 109799 | item->setting.historizingBackend.context, |
| 109800 | sessionId, |
| 109801 | sessionContext, |
| 109802 | nodeId, |
| 109803 | historizing, |
| 109804 | value); |
| 109805 | } |
| 109806 | } |
| 109807 | |
| 109808 | UA_HistoryDataGathering |
| 109809 | UA_HistoryDataGathering_Default(size_t initialNodeIdStoreSize) |
| 109810 | { |
| 109811 | UA_HistoryDataGathering gathering; |
| 109812 | memset(s: &gathering, c: 0, n: sizeof(UA_HistoryDataGathering)); |
| 109813 | gathering.setValue = &setValue_gathering_default; |
| 109814 | gathering.getHistorizingSetting = &getHistorizingSetting_gathering_default; |
| 109815 | gathering.registerNodeId = ®isterNodeId_gathering_default; |
| 109816 | gathering.startPoll = &startPoll_gathering_default; |
| 109817 | gathering.stopPoll = &stopPoll_gathering_default; |
| 109818 | gathering.deleteMembers = &deleteMembers_gathering_default; |
| 109819 | gathering.updateNodeIdSetting = &updateNodeIdSetting_gathering_default; |
| 109820 | UA_NodeIdStoreContext *context = (UA_NodeIdStoreContext*)UA_calloc(nmemb: 1, size: sizeof(UA_NodeIdStoreContext)); |
| 109821 | context->storeEnd = 0; |
| 109822 | context->storeSize = initialNodeIdStoreSize; |
| 109823 | context->dataStore = (UA_NodeIdStoreContextItem_gathering_default*)UA_calloc(nmemb: initialNodeIdStoreSize, size: sizeof(UA_NodeIdStoreContextItem_gathering_default)); |
| 109824 | gathering.context = context; |
| 109825 | return gathering; |
| 109826 | } |
| 109827 | |
| 109828 | /* Circular buffer implementation */ |
| 109829 | |
| 109830 | static UA_StatusCode |
| 109831 | registerNodeId_gathering_circular(UA_Server *server, void *context, |
| 109832 | const UA_NodeId *nodeId, |
| 109833 | const UA_HistorizingNodeIdSettings setting) { |
| 109834 | UA_NodeIdStoreContext *ctx = (UA_NodeIdStoreContext *)context; |
| 109835 | if(getNodeIdStoreContextItem_gathering_default(context: ctx, nodeId)) { |
| 109836 | return UA_STATUSCODE_BADNODEIDEXISTS; |
| 109837 | } |
| 109838 | if(ctx->storeEnd >= ctx->storeSize || !ctx->dataStore) { |
| 109839 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 109840 | } |
| 109841 | UA_NodeId_copy(src: nodeId, dst: &ctx->dataStore[ctx->storeEnd].nodeId); |
| 109842 | size_t current = ctx->storeEnd; |
| 109843 | ctx->dataStore[current].setting = setting; |
| 109844 | ++ctx->storeEnd; |
| 109845 | return UA_STATUSCODE_GOOD; |
| 109846 | } |
| 109847 | |
| 109848 | UA_HistoryDataGathering |
| 109849 | UA_HistoryDataGathering_Circular(size_t initialNodeIdStoreSize) { |
| 109850 | UA_HistoryDataGathering gathering = UA_HistoryDataGathering_Default(initialNodeIdStoreSize); |
| 109851 | gathering.registerNodeId = ®isterNodeId_gathering_circular; |
| 109852 | return gathering; |
| 109853 | } |
| 109854 | |
| 109855 | /**** amalgamated original file "/plugins/historydata/ua_history_database_default.c" ****/ |
| 109856 | |
| 109857 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 109858 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 109859 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 109860 | * |
| 109861 | * Copyright 2018 (c) basysKom GmbH <opensource@basyskom.com> (Author: Peter Rustler) |
| 109862 | */ |
| 109863 | |
| 109864 | |
| 109865 | #include <limits.h> |
| 109866 | |
| 109867 | typedef struct { |
| 109868 | UA_HistoryDataGathering gathering; |
| 109869 | } UA_HistoryDatabaseContext_default; |
| 109870 | |
| 109871 | static size_t |
| 109872 | getResultSize_service_default(const UA_HistoryDataBackend* backend, |
| 109873 | UA_Server *server, |
| 109874 | const UA_NodeId *sessionId, |
| 109875 | void* sessionContext, |
| 109876 | const UA_NodeId *nodeId, |
| 109877 | UA_DateTime start, |
| 109878 | UA_DateTime end, |
| 109879 | UA_UInt32 numValuesPerNode, |
| 109880 | UA_Boolean returnBounds, |
| 109881 | size_t *startIndex, |
| 109882 | size_t *endIndex, |
| 109883 | UA_Boolean *addFirst, |
| 109884 | UA_Boolean *addLast, |
| 109885 | UA_Boolean *reverse) |
| 109886 | { |
| 109887 | size_t storeEnd = backend->getEnd(server, backend->context, sessionId, sessionContext, nodeId); |
| 109888 | size_t firstIndex = backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId); |
| 109889 | size_t lastIndex = backend->lastIndex(server, backend->context, sessionId, sessionContext, nodeId); |
| 109890 | *startIndex = storeEnd; |
| 109891 | *endIndex = storeEnd; |
| 109892 | *addFirst = false; |
| 109893 | *addLast = false; |
| 109894 | if (end == LLONG_MIN) { |
| 109895 | *reverse = false; |
| 109896 | } else if (start == LLONG_MIN) { |
| 109897 | *reverse = true; |
| 109898 | } else { |
| 109899 | *reverse = end < start; |
| 109900 | } |
| 109901 | UA_Boolean equal = start == end; |
| 109902 | size_t size = 0; |
| 109903 | if (lastIndex != storeEnd) { |
| 109904 | if (equal) { |
| 109905 | if (returnBounds) { |
| 109906 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE); |
| 109907 | if (*startIndex == storeEnd) { |
| 109908 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER); |
| 109909 | *addFirst = true; |
| 109910 | } |
| 109911 | *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER); |
| 109912 | size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *startIndex, *endIndex); |
| 109913 | } else { |
| 109914 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL); |
| 109915 | *endIndex = *startIndex; |
| 109916 | if (*startIndex == storeEnd) |
| 109917 | size = 0; |
| 109918 | else |
| 109919 | size = 1; |
| 109920 | } |
| 109921 | } else if (start == LLONG_MIN) { |
| 109922 | *endIndex = firstIndex; |
| 109923 | if (returnBounds) { |
| 109924 | *addLast = true; |
| 109925 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_AFTER); |
| 109926 | if (*startIndex == storeEnd) { |
| 109927 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_BEFORE); |
| 109928 | *addFirst = true; |
| 109929 | } |
| 109930 | } else { |
| 109931 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_BEFORE); |
| 109932 | } |
| 109933 | size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *endIndex, *startIndex); |
| 109934 | } else if (end == LLONG_MIN) { |
| 109935 | *endIndex = lastIndex; |
| 109936 | if (returnBounds) { |
| 109937 | *addLast = true; |
| 109938 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE); |
| 109939 | if (*startIndex == storeEnd) { |
| 109940 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER); |
| 109941 | *addFirst = true; |
| 109942 | } |
| 109943 | } else { |
| 109944 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_AFTER); |
| 109945 | } |
| 109946 | size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *startIndex, *endIndex); |
| 109947 | } else if (*reverse) { |
| 109948 | if (returnBounds) { |
| 109949 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_AFTER); |
| 109950 | if (*startIndex == storeEnd) { |
| 109951 | *addFirst = true; |
| 109952 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_BEFORE); |
| 109953 | } |
| 109954 | *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_BEFORE); |
| 109955 | if (*endIndex == storeEnd) { |
| 109956 | *addLast = true; |
| 109957 | *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_AFTER); |
| 109958 | } |
| 109959 | } else { |
| 109960 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE); |
| 109961 | *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_AFTER); |
| 109962 | } |
| 109963 | size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *endIndex, *startIndex); |
| 109964 | } else { |
| 109965 | if (returnBounds) { |
| 109966 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_BEFORE); |
| 109967 | if (*startIndex == storeEnd) { |
| 109968 | *addFirst = true; |
| 109969 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_AFTER); |
| 109970 | } |
| 109971 | *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_EQUAL_OR_AFTER); |
| 109972 | if (*endIndex == storeEnd) { |
| 109973 | *addLast = true; |
| 109974 | *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_BEFORE); |
| 109975 | } |
| 109976 | } else { |
| 109977 | *startIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, start, MATCH_EQUAL_OR_AFTER); |
| 109978 | *endIndex = backend->getDateTimeMatch(server, backend->context, sessionId, sessionContext, nodeId, end, MATCH_BEFORE); |
| 109979 | } |
| 109980 | size = backend->resultSize(server, backend->context, sessionId, sessionContext, nodeId, *startIndex, *endIndex); |
| 109981 | } |
| 109982 | } else if (returnBounds) { |
| 109983 | *addLast = true; |
| 109984 | *addFirst = true; |
| 109985 | } |
| 109986 | |
| 109987 | if (*addLast) |
| 109988 | ++size; |
| 109989 | if (*addFirst) |
| 109990 | ++size; |
| 109991 | |
| 109992 | if (numValuesPerNode > 0 && size > numValuesPerNode) { |
| 109993 | size = numValuesPerNode; |
| 109994 | *addLast = false; |
| 109995 | } |
| 109996 | return size; |
| 109997 | } |
| 109998 | |
| 109999 | static UA_StatusCode |
| 110000 | getHistoryData_service_default(const UA_HistoryDataBackend* backend, |
| 110001 | const UA_DateTime start, |
| 110002 | const UA_DateTime end, |
| 110003 | UA_Server *server, |
| 110004 | const UA_NodeId *sessionId, |
| 110005 | void *sessionContext, |
| 110006 | const UA_NodeId* nodeId, |
| 110007 | size_t maxSize, |
| 110008 | UA_UInt32 numValuesPerNode, |
| 110009 | UA_Boolean returnBounds, |
| 110010 | UA_TimestampsToReturn timestampsToReturn, |
| 110011 | UA_NumericRange range, |
| 110012 | UA_Boolean releaseContinuationPoints, |
| 110013 | const UA_ByteString *continuationPoint, |
| 110014 | UA_ByteString *outContinuationPoint, |
| 110015 | size_t *resultSize, |
| 110016 | UA_DataValue ** result) |
| 110017 | { |
| 110018 | size_t skip = 0; |
| 110019 | UA_ByteString backendContinuationPoint; |
| 110020 | UA_ByteString_init(p: &backendContinuationPoint); |
| 110021 | if (continuationPoint->length > 0) { |
| 110022 | if (continuationPoint->length >= sizeof(size_t)) { |
| 110023 | skip = *((size_t*)(continuationPoint->data)); |
| 110024 | if (continuationPoint->length > 0) { |
| 110025 | backendContinuationPoint.length = continuationPoint->length - sizeof(size_t); |
| 110026 | backendContinuationPoint.data = continuationPoint->data + sizeof(size_t); |
| 110027 | } |
| 110028 | } else { |
| 110029 | return UA_STATUSCODE_BADCONTINUATIONPOINTINVALID; |
| 110030 | } |
| 110031 | } |
| 110032 | |
| 110033 | size_t storeEnd = backend->getEnd(server, backend->context, sessionId, sessionContext, nodeId); |
| 110034 | size_t startIndex; |
| 110035 | size_t endIndex; |
| 110036 | UA_Boolean addFirst; |
| 110037 | UA_Boolean addLast; |
| 110038 | UA_Boolean reverse; |
| 110039 | size_t _resultSize = getResultSize_service_default(backend, |
| 110040 | server, |
| 110041 | sessionId, |
| 110042 | sessionContext, |
| 110043 | nodeId, |
| 110044 | start, |
| 110045 | end, |
| 110046 | numValuesPerNode: numValuesPerNode == 0 ? 0 : numValuesPerNode + (UA_UInt32)skip, |
| 110047 | returnBounds, |
| 110048 | startIndex: &startIndex, |
| 110049 | endIndex: &endIndex, |
| 110050 | addFirst: &addFirst, |
| 110051 | addLast: &addLast, |
| 110052 | reverse: &reverse); |
| 110053 | *resultSize = _resultSize - skip; |
| 110054 | if (*resultSize > maxSize) { |
| 110055 | *resultSize = maxSize; |
| 110056 | } |
| 110057 | UA_DataValue *outResult= (UA_DataValue*)UA_Array_new(size: *resultSize, type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 110058 | if (!outResult) { |
| 110059 | *resultSize = 0; |
| 110060 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 110061 | } |
| 110062 | *result = outResult; |
| 110063 | |
| 110064 | size_t counter = 0; |
| 110065 | if (addFirst) { |
| 110066 | if (skip == 0) { |
| 110067 | outResult[counter].hasStatus = true; |
| 110068 | outResult[counter].status = UA_STATUSCODE_BADBOUNDNOTFOUND; |
| 110069 | outResult[counter].hasSourceTimestamp = true; |
| 110070 | if (start == LLONG_MIN) { |
| 110071 | outResult[counter].sourceTimestamp = end; |
| 110072 | } else { |
| 110073 | outResult[counter].sourceTimestamp = start; |
| 110074 | } |
| 110075 | ++counter; |
| 110076 | } |
| 110077 | } |
| 110078 | UA_ByteString backendOutContinuationPoint; |
| 110079 | UA_ByteString_init(p: &backendOutContinuationPoint); |
| 110080 | if (endIndex != storeEnd && startIndex != storeEnd) { |
| 110081 | size_t retval = 0; |
| 110082 | |
| 110083 | size_t valueSize = *resultSize - counter; |
| 110084 | if (valueSize + skip > _resultSize - addFirst - addLast) { |
| 110085 | if (skip == 0) { |
| 110086 | valueSize = _resultSize - addFirst - addLast; |
| 110087 | } else { |
| 110088 | valueSize = _resultSize - skip - addLast; |
| 110089 | } |
| 110090 | |
| 110091 | } |
| 110092 | |
| 110093 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 110094 | if (valueSize > 0) |
| 110095 | ret = backend->copyDataValues(server, |
| 110096 | backend->context, |
| 110097 | sessionId, |
| 110098 | sessionContext, |
| 110099 | nodeId, |
| 110100 | startIndex, |
| 110101 | endIndex, |
| 110102 | reverse, |
| 110103 | valueSize, |
| 110104 | range, |
| 110105 | releaseContinuationPoints, |
| 110106 | &backendContinuationPoint, |
| 110107 | &backendOutContinuationPoint, |
| 110108 | &retval, |
| 110109 | &outResult[counter]); |
| 110110 | if (ret != UA_STATUSCODE_GOOD) { |
| 110111 | UA_Array_delete(p: outResult, size: *resultSize, type: &UA_TYPES[UA_TYPES_DATAVALUE]); |
| 110112 | *result = NULL; |
| 110113 | *resultSize = 0; |
| 110114 | return ret; |
| 110115 | } |
| 110116 | counter += retval; |
| 110117 | } |
| 110118 | if (addLast && counter < *resultSize) { |
| 110119 | outResult[counter].hasStatus = true; |
| 110120 | outResult[counter].status = UA_STATUSCODE_BADBOUNDNOTFOUND; |
| 110121 | outResult[counter].hasSourceTimestamp = true; |
| 110122 | if (start == LLONG_MIN && storeEnd != backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId)) { |
| 110123 | outResult[counter].sourceTimestamp = backend->getDataValue(server, backend->context, sessionId, sessionContext, nodeId, endIndex)->sourceTimestamp - UA_DATETIME_SEC; |
| 110124 | } else if (end == LLONG_MIN && storeEnd != backend->firstIndex(server, backend->context, sessionId, sessionContext, nodeId)) { |
| 110125 | outResult[counter].sourceTimestamp = backend->getDataValue(server, backend->context, sessionId, sessionContext, nodeId, endIndex)->sourceTimestamp + UA_DATETIME_SEC; |
| 110126 | } else { |
| 110127 | outResult[counter].sourceTimestamp = end; |
| 110128 | } |
| 110129 | } |
| 110130 | // there are more values |
| 110131 | if (skip + *resultSize < _resultSize |
| 110132 | // there are not more values for this request, but there are more values in database |
| 110133 | || (backendOutContinuationPoint.length > 0 |
| 110134 | && numValuesPerNode != 0) |
| 110135 | // we deliver just one value which is a FIRST/LAST value |
| 110136 | || (skip == 0 |
| 110137 | && addFirst == true |
| 110138 | && *resultSize == 1)) { |
| 110139 | if(UA_ByteString_allocBuffer(bs: outContinuationPoint, length: backendOutContinuationPoint.length + sizeof(size_t)) |
| 110140 | != UA_STATUSCODE_GOOD) { |
| 110141 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 110142 | } |
| 110143 | *((size_t*)(outContinuationPoint->data)) = skip + *resultSize; |
| 110144 | if(backendOutContinuationPoint.length > 0) |
| 110145 | memcpy(dest: outContinuationPoint->data + sizeof(size_t), src: backendOutContinuationPoint.data, n: backendOutContinuationPoint.length); |
| 110146 | } |
| 110147 | UA_ByteString_clear(p: &backendOutContinuationPoint); |
| 110148 | return UA_STATUSCODE_GOOD; |
| 110149 | } |
| 110150 | |
| 110151 | static void |
| 110152 | updateData_service_default(UA_Server *server, |
| 110153 | void *hdbContext, |
| 110154 | const UA_NodeId *sessionId, |
| 110155 | void *sessionContext, |
| 110156 | const UA_RequestHeader *requestHeader, |
| 110157 | const UA_UpdateDataDetails *details, |
| 110158 | UA_HistoryUpdateResult *result) |
| 110159 | { |
| 110160 | UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)hdbContext; |
| 110161 | UA_Byte accessLevel = 0; |
| 110162 | UA_Server_readAccessLevel(server, |
| 110163 | nodeId: details->nodeId, |
| 110164 | outAccessLevel: &accessLevel); |
| 110165 | if (!(accessLevel & UA_ACCESSLEVELMASK_HISTORYWRITE)) { |
| 110166 | result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 110167 | return; |
| 110168 | } |
| 110169 | |
| 110170 | UA_Boolean historizing = false; |
| 110171 | UA_Server_readHistorizing(server, |
| 110172 | nodeId: details->nodeId, |
| 110173 | outHistorizing: &historizing); |
| 110174 | if (!historizing) { |
| 110175 | result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID; |
| 110176 | return; |
| 110177 | } |
| 110178 | const UA_HistorizingNodeIdSettings *setting = ctx->gathering.getHistorizingSetting( |
| 110179 | server, |
| 110180 | ctx->gathering.context, |
| 110181 | &details->nodeId); |
| 110182 | |
| 110183 | if (!setting) { |
| 110184 | result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID; |
| 110185 | return; |
| 110186 | } |
| 110187 | |
| 110188 | UA_ServerConfig *config = UA_Server_getConfig(server); |
| 110189 | result->operationResultsSize = details->updateValuesSize; |
| 110190 | result->operationResults = (UA_StatusCode*)UA_Array_new(size: result->operationResultsSize, type: &UA_TYPES[UA_TYPES_STATUSCODE]); |
| 110191 | for (size_t i = 0; i < details->updateValuesSize; ++i) { |
| 110192 | if (config->accessControl.allowHistoryUpdateUpdateData && |
| 110193 | !config->accessControl.allowHistoryUpdateUpdateData(server, &config->accessControl, sessionId, sessionContext, |
| 110194 | &details->nodeId, details->performInsertReplace, |
| 110195 | &details->updateValues[i])) { |
| 110196 | result->operationResults[i] = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 110197 | continue; |
| 110198 | } |
| 110199 | switch (details->performInsertReplace) { |
| 110200 | case UA_PERFORMUPDATETYPE_INSERT: |
| 110201 | if (!setting->historizingBackend.insertDataValue) { |
| 110202 | result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED; |
| 110203 | continue; |
| 110204 | } |
| 110205 | result->operationResults[i] |
| 110206 | = setting->historizingBackend.insertDataValue(server, |
| 110207 | setting->historizingBackend.context, |
| 110208 | sessionId, |
| 110209 | sessionContext, |
| 110210 | &details->nodeId, |
| 110211 | &details->updateValues[i]); |
| 110212 | continue; |
| 110213 | case UA_PERFORMUPDATETYPE_REPLACE: |
| 110214 | if (!setting->historizingBackend.replaceDataValue) { |
| 110215 | result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED; |
| 110216 | continue; |
| 110217 | } |
| 110218 | result->operationResults[i] |
| 110219 | = setting->historizingBackend.replaceDataValue(server, |
| 110220 | setting->historizingBackend.context, |
| 110221 | sessionId, |
| 110222 | sessionContext, |
| 110223 | &details->nodeId, |
| 110224 | &details->updateValues[i]); |
| 110225 | continue; |
| 110226 | case UA_PERFORMUPDATETYPE_UPDATE: |
| 110227 | if (!setting->historizingBackend.updateDataValue) { |
| 110228 | result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED; |
| 110229 | continue; |
| 110230 | } |
| 110231 | result->operationResults[i] |
| 110232 | = setting->historizingBackend.updateDataValue(server, |
| 110233 | setting->historizingBackend.context, |
| 110234 | sessionId, |
| 110235 | sessionContext, |
| 110236 | &details->nodeId, |
| 110237 | &details->updateValues[i]); |
| 110238 | continue; |
| 110239 | default: |
| 110240 | result->operationResults[i] = UA_STATUSCODE_BADHISTORYOPERATIONINVALID; |
| 110241 | continue; |
| 110242 | } |
| 110243 | } |
| 110244 | } |
| 110245 | |
| 110246 | |
| 110247 | static void |
| 110248 | deleteRawModified_service_default(UA_Server *server, |
| 110249 | void *hdbContext, |
| 110250 | const UA_NodeId *sessionId, |
| 110251 | void *sessionContext, |
| 110252 | const UA_RequestHeader *requestHeader, |
| 110253 | const UA_DeleteRawModifiedDetails *details, |
| 110254 | UA_HistoryUpdateResult *result) |
| 110255 | { |
| 110256 | if (details->isDeleteModified) { |
| 110257 | result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED; |
| 110258 | return; |
| 110259 | } |
| 110260 | UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)hdbContext; |
| 110261 | UA_Byte accessLevel = 0; |
| 110262 | UA_Server_readAccessLevel(server, |
| 110263 | nodeId: details->nodeId, |
| 110264 | outAccessLevel: &accessLevel); |
| 110265 | if (!(accessLevel & UA_ACCESSLEVELMASK_HISTORYWRITE)) { |
| 110266 | result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 110267 | return; |
| 110268 | } |
| 110269 | |
| 110270 | UA_Boolean historizing = false; |
| 110271 | UA_Server_readHistorizing(server, |
| 110272 | nodeId: details->nodeId, |
| 110273 | outHistorizing: &historizing); |
| 110274 | if (!historizing) { |
| 110275 | result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID; |
| 110276 | return; |
| 110277 | } |
| 110278 | const UA_HistorizingNodeIdSettings *setting = ctx->gathering.getHistorizingSetting( |
| 110279 | server, |
| 110280 | ctx->gathering.context, |
| 110281 | &details->nodeId); |
| 110282 | |
| 110283 | if (!setting) { |
| 110284 | result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID; |
| 110285 | return; |
| 110286 | } |
| 110287 | if (!setting->historizingBackend.removeDataValue) { |
| 110288 | result->statusCode = UA_STATUSCODE_BADHISTORYOPERATIONUNSUPPORTED; |
| 110289 | return; |
| 110290 | } |
| 110291 | |
| 110292 | UA_ServerConfig *config = UA_Server_getConfig(server); |
| 110293 | if (config->accessControl.allowHistoryUpdateDeleteRawModified && |
| 110294 | !config->accessControl.allowHistoryUpdateDeleteRawModified(server, |
| 110295 | &config->accessControl, sessionId, sessionContext, &details->nodeId, |
| 110296 | details->startTime, details->endTime, details->isDeleteModified)) { |
| 110297 | result->statusCode = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 110298 | return; |
| 110299 | } |
| 110300 | |
| 110301 | result->statusCode |
| 110302 | = setting->historizingBackend.removeDataValue(server, |
| 110303 | setting->historizingBackend.context, |
| 110304 | sessionId, |
| 110305 | sessionContext, |
| 110306 | &details->nodeId, |
| 110307 | details->startTime, |
| 110308 | details->endTime); |
| 110309 | } |
| 110310 | |
| 110311 | static void |
| 110312 | readRaw_service_default(UA_Server *server, |
| 110313 | void *context, |
| 110314 | const UA_NodeId *sessionId, |
| 110315 | void *sessionContext, |
| 110316 | const UA_RequestHeader *requestHeader, |
| 110317 | const UA_ReadRawModifiedDetails *historyReadDetails, |
| 110318 | UA_TimestampsToReturn timestampsToReturn, |
| 110319 | UA_Boolean releaseContinuationPoints, |
| 110320 | size_t nodesToReadSize, |
| 110321 | const UA_HistoryReadValueId *nodesToRead, |
| 110322 | UA_HistoryReadResponse *response, |
| 110323 | UA_HistoryData * const * const historyData) |
| 110324 | { |
| 110325 | UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)context; |
| 110326 | for (size_t i = 0; i < nodesToReadSize; ++i) { |
| 110327 | UA_Byte accessLevel = 0; |
| 110328 | UA_Server_readAccessLevel(server, |
| 110329 | nodeId: nodesToRead[i].nodeId, |
| 110330 | outAccessLevel: &accessLevel); |
| 110331 | if (!(accessLevel & UA_ACCESSLEVELMASK_HISTORYREAD)) { |
| 110332 | response->results[i].statusCode = UA_STATUSCODE_BADUSERACCESSDENIED; |
| 110333 | continue; |
| 110334 | } |
| 110335 | |
| 110336 | UA_Boolean historizing = false; |
| 110337 | UA_Server_readHistorizing(server, |
| 110338 | nodeId: nodesToRead[i].nodeId, |
| 110339 | outHistorizing: &historizing); |
| 110340 | if (!historizing) { |
| 110341 | response->results[i].statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID; |
| 110342 | continue; |
| 110343 | } |
| 110344 | |
| 110345 | const UA_HistorizingNodeIdSettings *setting = ctx->gathering.getHistorizingSetting( |
| 110346 | server, |
| 110347 | ctx->gathering.context, |
| 110348 | &nodesToRead[i].nodeId); |
| 110349 | |
| 110350 | if (!setting) { |
| 110351 | response->results[i].statusCode = UA_STATUSCODE_BADHISTORYOPERATIONINVALID; |
| 110352 | continue; |
| 110353 | } |
| 110354 | |
| 110355 | if (historyReadDetails->returnBounds && !setting->historizingBackend.boundSupported( |
| 110356 | server, |
| 110357 | setting->historizingBackend.context, |
| 110358 | sessionId, |
| 110359 | sessionContext, |
| 110360 | &nodesToRead[i].nodeId)) { |
| 110361 | response->results[i].statusCode = UA_STATUSCODE_BADBOUNDNOTSUPPORTED; |
| 110362 | continue; |
| 110363 | } |
| 110364 | |
| 110365 | if (!setting->historizingBackend.timestampsToReturnSupported( |
| 110366 | server, |
| 110367 | setting->historizingBackend.context, |
| 110368 | sessionId, |
| 110369 | sessionContext, |
| 110370 | &nodesToRead[i].nodeId, |
| 110371 | timestampsToReturn)) { |
| 110372 | response->results[i].statusCode = UA_STATUSCODE_BADTIMESTAMPNOTSUPPORTED; |
| 110373 | continue; |
| 110374 | } |
| 110375 | |
| 110376 | UA_NumericRange range; |
| 110377 | range.dimensionsSize = 0; |
| 110378 | range.dimensions = NULL; |
| 110379 | if (nodesToRead[i].indexRange.length > 0) { |
| 110380 | UA_StatusCode rangeParseResult = UA_NumericRange_parse(range: &range, str: nodesToRead[i].indexRange); |
| 110381 | if (rangeParseResult != UA_STATUSCODE_GOOD) { |
| 110382 | response->results[i].statusCode = rangeParseResult; |
| 110383 | continue; |
| 110384 | } |
| 110385 | } |
| 110386 | |
| 110387 | UA_StatusCode getHistoryDataStatusCode; |
| 110388 | if (setting->historizingBackend.getHistoryData) { |
| 110389 | getHistoryDataStatusCode = setting->historizingBackend.getHistoryData( |
| 110390 | server, |
| 110391 | sessionId, |
| 110392 | sessionContext, |
| 110393 | &setting->historizingBackend, |
| 110394 | historyReadDetails->startTime, |
| 110395 | historyReadDetails->endTime, |
| 110396 | &nodesToRead[i].nodeId, |
| 110397 | setting->maxHistoryDataResponseSize, |
| 110398 | historyReadDetails->numValuesPerNode, |
| 110399 | historyReadDetails->returnBounds, |
| 110400 | timestampsToReturn, |
| 110401 | range, |
| 110402 | releaseContinuationPoints, |
| 110403 | &nodesToRead[i].continuationPoint, |
| 110404 | &response->results[i].continuationPoint, |
| 110405 | historyData[i]); |
| 110406 | } else { |
| 110407 | getHistoryDataStatusCode = getHistoryData_service_default( |
| 110408 | backend: &setting->historizingBackend, |
| 110409 | start: historyReadDetails->startTime, |
| 110410 | end: historyReadDetails->endTime, |
| 110411 | server, |
| 110412 | sessionId, |
| 110413 | sessionContext, |
| 110414 | nodeId: &nodesToRead[i].nodeId, |
| 110415 | maxSize: setting->maxHistoryDataResponseSize, |
| 110416 | numValuesPerNode: historyReadDetails->numValuesPerNode, |
| 110417 | returnBounds: historyReadDetails->returnBounds, |
| 110418 | timestampsToReturn, |
| 110419 | range, |
| 110420 | releaseContinuationPoints, |
| 110421 | continuationPoint: &nodesToRead[i].continuationPoint, |
| 110422 | outContinuationPoint: &response->results[i].continuationPoint, |
| 110423 | resultSize: &historyData[i]->dataValuesSize, |
| 110424 | result: &historyData[i]->dataValues); |
| 110425 | } |
| 110426 | if (getHistoryDataStatusCode != UA_STATUSCODE_GOOD) { |
| 110427 | response->results[i].statusCode = getHistoryDataStatusCode; |
| 110428 | continue; |
| 110429 | } |
| 110430 | } |
| 110431 | response->responseHeader.serviceResult = UA_STATUSCODE_GOOD; |
| 110432 | return; |
| 110433 | } |
| 110434 | |
| 110435 | static void |
| 110436 | setValue_service_default(UA_Server *server, |
| 110437 | void *context, |
| 110438 | const UA_NodeId *sessionId, |
| 110439 | void *sessionContext, |
| 110440 | const UA_NodeId *nodeId, |
| 110441 | UA_Boolean historizing, |
| 110442 | const UA_DataValue *value) |
| 110443 | { |
| 110444 | UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)context; |
| 110445 | if (ctx->gathering.setValue) |
| 110446 | ctx->gathering.setValue(server, |
| 110447 | ctx->gathering.context, |
| 110448 | sessionId, |
| 110449 | sessionContext, |
| 110450 | nodeId, |
| 110451 | historizing, |
| 110452 | value); |
| 110453 | } |
| 110454 | |
| 110455 | static void |
| 110456 | clear_service_default(UA_HistoryDatabase *hdb) |
| 110457 | { |
| 110458 | if (hdb == NULL || hdb->context == NULL) |
| 110459 | return; |
| 110460 | UA_HistoryDatabaseContext_default *ctx = (UA_HistoryDatabaseContext_default*)hdb->context; |
| 110461 | ctx->gathering.deleteMembers(&ctx->gathering); |
| 110462 | UA_free(ptr: ctx); |
| 110463 | } |
| 110464 | |
| 110465 | UA_HistoryDatabase |
| 110466 | UA_HistoryDatabase_default(UA_HistoryDataGathering gathering) |
| 110467 | { |
| 110468 | UA_HistoryDatabase hdb; |
| 110469 | memset(s: &hdb, c: 0, n: sizeof(UA_HistoryDatabase)); |
| 110470 | UA_HistoryDatabaseContext_default *context = |
| 110471 | (UA_HistoryDatabaseContext_default*) |
| 110472 | UA_calloc(nmemb: 1, size: sizeof(UA_HistoryDatabaseContext_default)); |
| 110473 | context->gathering = gathering; |
| 110474 | hdb.context = context; |
| 110475 | hdb.readRaw = &readRaw_service_default; |
| 110476 | hdb.setValue = &setValue_service_default; |
| 110477 | hdb.updateData = &updateData_service_default; |
| 110478 | hdb.deleteRawModified = &deleteRawModified_service_default; |
| 110479 | hdb.clear = clear_service_default; |
| 110480 | return hdb; |
| 110481 | } |
| 110482 | |
| 110483 | /**** amalgamated original file "/plugins/ua_log_syslog.c" ****/ |
| 110484 | |
| 110485 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 110486 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 110487 | * |
| 110488 | * Copyright 2020 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 110489 | */ |
| 110490 | |
| 110491 | |
| 110492 | #if defined(__linux__) || defined(__unix__) |
| 110493 | |
| 110494 | #include <syslog.h> |
| 110495 | #include <stdio.h> |
| 110496 | |
| 110497 | const char *syslogLevelNames[6] = {"trace", "debug", "info", |
| 110498 | "warn", "error", "fatal"}; |
| 110499 | const char *syslogCategoryNames[UA_LOGCATEGORIES] = |
| 110500 | {"network", "channel", "session", "server", "client", |
| 110501 | "userland", "securitypolicy", "eventloop", "pubsub", "discovery"}; |
| 110502 | |
| 110503 | #ifdef __clang__ |
| 110504 | __attribute__((__format__(__printf__, 4 , 0))) |
| 110505 | #endif |
| 110506 | static void |
| 110507 | UA_Log_Syslog_log(void *context, UA_LogLevel level, UA_LogCategory category, |
| 110508 | const char *msg, va_list args) { |
| 110509 | /* Assume that context is casted to UA_LogLevel */ |
| 110510 | if(context != NULL && (UA_LogLevel)(uintptr_t)context > level) |
| 110511 | return; |
| 110512 | |
| 110513 | int priority = LOG_INFO; |
| 110514 | switch(level) { |
| 110515 | case UA_LOGLEVEL_DEBUG: |
| 110516 | priority = LOG_DEBUG; |
| 110517 | break; |
| 110518 | case UA_LOGLEVEL_INFO: |
| 110519 | priority = LOG_INFO; |
| 110520 | break; |
| 110521 | case UA_LOGLEVEL_WARNING: |
| 110522 | priority = LOG_WARNING; |
| 110523 | break; |
| 110524 | case UA_LOGLEVEL_ERROR: |
| 110525 | priority = LOG_ERR; |
| 110526 | break; |
| 110527 | case UA_LOGLEVEL_FATAL: |
| 110528 | priority = LOG_CRIT; |
| 110529 | break; |
| 110530 | case UA_LOGLEVEL_TRACE: |
| 110531 | default: |
| 110532 | return; |
| 110533 | } |
| 110534 | |
| 110535 | int logLevelSlot = ((int)level / 100) - 1; |
| 110536 | if(logLevelSlot < 0 || logLevelSlot > 5) |
| 110537 | logLevelSlot = 5; /* Set to fatal if the level is outside the range */ |
| 110538 | |
| 110539 | #define LOGBUFSIZE 512 |
| 110540 | char logbuf[LOGBUFSIZE]; |
| 110541 | int pos = snprintf(s: logbuf, LOGBUFSIZE, format: "[%s/%s] ", |
| 110542 | syslogLevelNames[logLevelSlot], |
| 110543 | syslogCategoryNames[category]); |
| 110544 | if(pos < 0) { |
| 110545 | syslog(LOG_WARNING, fmt: "Log message too long for syslog"); |
| 110546 | return; |
| 110547 | } |
| 110548 | pos = vsnprintf(s: &logbuf[pos], LOGBUFSIZE - (size_t)pos, format: msg, arg: args); |
| 110549 | if(pos < 0) { |
| 110550 | syslog(LOG_WARNING, fmt: "Log message too long for syslog"); |
| 110551 | return; |
| 110552 | } |
| 110553 | |
| 110554 | syslog(pri: priority, fmt: "%s", logbuf); |
| 110555 | } |
| 110556 | |
| 110557 | static void |
| 110558 | UA_Log_Syslog_clear(UA_Logger *logger) { |
| 110559 | /* closelog is optional. We don't use it as several loggers might be |
| 110560 | * instantiated in parallel. */ |
| 110561 | /* closelog(); */ |
| 110562 | UA_free(ptr: logger); |
| 110563 | } |
| 110564 | |
| 110565 | UA_Logger |
| 110566 | UA_Log_Syslog(void) { |
| 110567 | return UA_Log_Syslog_withLevel(minlevel: UA_LOGLEVEL_TRACE); |
| 110568 | } |
| 110569 | |
| 110570 | UA_Logger |
| 110571 | UA_Log_Syslog_withLevel(UA_LogLevel minlevel) { |
| 110572 | UA_Logger logger = {UA_Log_Syslog_log, (void*)(uintptr_t)minlevel, NULL}; |
| 110573 | return logger; |
| 110574 | } |
| 110575 | |
| 110576 | UA_Logger * |
| 110577 | UA_Log_Syslog_new(UA_LogLevel minlevel) { |
| 110578 | UA_Logger *logger = (UA_Logger*)UA_malloc(size: sizeof(UA_Logger)); |
| 110579 | if(!logger) |
| 110580 | return NULL; |
| 110581 | *logger = UA_Log_Syslog_withLevel(minlevel); |
| 110582 | logger->clear = UA_Log_Syslog_clear; |
| 110583 | return logger; |
| 110584 | } |
| 110585 | |
| 110586 | #endif |
| 110587 | |
| 110588 | /**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic128rsa15.c" ****/ |
| 110589 | |
| 110590 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 110591 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 110592 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 110593 | * |
| 110594 | * Copyright 2018-2019 (c) Mark Giraud, Fraunhofer IOSB |
| 110595 | * Copyright 2019 (c) Kalycito Infotech Private Limited |
| 110596 | * Copyright 2018 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 110597 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 110598 | * Copyright 2020 (c) basysKom GmbH |
| 110599 | * |
| 110600 | */ |
| 110601 | |
| 110602 | |
| 110603 | #ifdef UA_ENABLE_ENCRYPTION_MBEDTLS |
| 110604 | |
| 110605 | |
| 110606 | #include <mbedtls/aes.h> |
| 110607 | #include <mbedtls/ctr_drbg.h> |
| 110608 | #include <mbedtls/entropy.h> |
| 110609 | #include <mbedtls/error.h> |
| 110610 | #include <mbedtls/md.h> |
| 110611 | #include <mbedtls/sha1.h> |
| 110612 | #include <mbedtls/version.h> |
| 110613 | #include <mbedtls/x509_crt.h> |
| 110614 | |
| 110615 | /* Notes: |
| 110616 | * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to |
| 110617 | * allocate temp buffers. |
| 110618 | * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer |
| 110619 | */ |
| 110620 | |
| 110621 | #define UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN 11 |
| 110622 | #define UA_SECURITYPOLICY_BASIC128RSA15_SYM_KEY_LENGTH 16 |
| 110623 | #define UA_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH 16 |
| 110624 | #define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE 16 |
| 110625 | #define UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE 16 |
| 110626 | #define UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH 128 |
| 110627 | #define UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH 512 |
| 110628 | |
| 110629 | typedef struct { |
| 110630 | UA_ByteString localCertThumbprint; |
| 110631 | |
| 110632 | mbedtls_ctr_drbg_context drbgContext; |
| 110633 | mbedtls_entropy_context entropyContext; |
| 110634 | mbedtls_md_context_t sha1MdContext; |
| 110635 | mbedtls_pk_context localPrivateKey; |
| 110636 | } Basic128Rsa15_PolicyContext; |
| 110637 | |
| 110638 | typedef struct { |
| 110639 | Basic128Rsa15_PolicyContext *policyContext; |
| 110640 | |
| 110641 | UA_ByteString localSymSigningKey; |
| 110642 | UA_ByteString localSymEncryptingKey; |
| 110643 | UA_ByteString localSymIv; |
| 110644 | |
| 110645 | UA_ByteString remoteSymSigningKey; |
| 110646 | UA_ByteString remoteSymEncryptingKey; |
| 110647 | UA_ByteString remoteSymIv; |
| 110648 | |
| 110649 | mbedtls_x509_crt remoteCertificate; |
| 110650 | } Basic128Rsa15_ChannelContext; |
| 110651 | |
| 110652 | /********************/ |
| 110653 | /* AsymmetricModule */ |
| 110654 | /********************/ |
| 110655 | |
| 110656 | static UA_StatusCode |
| 110657 | asym_verify_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 110658 | const UA_ByteString *message, |
| 110659 | const UA_ByteString *signature) { |
| 110660 | if(message == NULL || signature == NULL || cc == NULL) |
| 110661 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110662 | |
| 110663 | return mbedtls_verifySig_sha1(&cc->remoteCertificate, message, signature); |
| 110664 | } |
| 110665 | |
| 110666 | static UA_StatusCode |
| 110667 | asym_sign_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 110668 | const UA_ByteString *message, |
| 110669 | UA_ByteString *signature) { |
| 110670 | if(message == NULL || signature == NULL || cc == NULL) |
| 110671 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110672 | |
| 110673 | Basic128Rsa15_PolicyContext *pc = cc->policyContext; |
| 110674 | return mbedtls_sign_sha1(&pc->localPrivateKey, &pc->drbgContext, |
| 110675 | message, signature); |
| 110676 | } |
| 110677 | |
| 110678 | static size_t |
| 110679 | asym_getLocalSignatureSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) { |
| 110680 | if(cc == NULL) |
| 110681 | return 0; |
| 110682 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 110683 | return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len; |
| 110684 | #else |
| 110685 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey)); |
| 110686 | #endif |
| 110687 | } |
| 110688 | |
| 110689 | static size_t |
| 110690 | asym_getRemoteSignatureSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) { |
| 110691 | if(cc == NULL) |
| 110692 | return 0; |
| 110693 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 110694 | return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len; |
| 110695 | #else |
| 110696 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 110697 | #endif |
| 110698 | } |
| 110699 | |
| 110700 | static UA_StatusCode |
| 110701 | asym_encrypt_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 110702 | UA_ByteString *data) { |
| 110703 | if(cc == NULL || data == NULL) |
| 110704 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110705 | |
| 110706 | mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 110707 | mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); |
| 110708 | |
| 110709 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 110710 | size_t keylen = remoteRsaContext->len; |
| 110711 | #else |
| 110712 | size_t keylen = mbedtls_rsa_get_len(remoteRsaContext); |
| 110713 | #endif |
| 110714 | size_t plainTextBlockSize = |
| 110715 | keylen - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN; |
| 110716 | if(data->length % plainTextBlockSize != 0) |
| 110717 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110718 | |
| 110719 | size_t blocks = data->length / plainTextBlockSize; |
| 110720 | UA_ByteString encrypted; |
| 110721 | UA_StatusCode retval = UA_ByteString_allocBuffer(&encrypted, blocks * keylen); |
| 110722 | if(retval != UA_STATUSCODE_GOOD) |
| 110723 | return retval; |
| 110724 | |
| 110725 | size_t lenDataToEncrypt = data->length; |
| 110726 | size_t inOffset = 0; |
| 110727 | size_t offset = 0; |
| 110728 | size_t outLength = 0; |
| 110729 | Basic128Rsa15_PolicyContext *pc = cc->policyContext; |
| 110730 | while(lenDataToEncrypt >= plainTextBlockSize) { |
| 110731 | int mbedErr = mbedtls_pk_encrypt(&cc->remoteCertificate.pk, |
| 110732 | data->data + inOffset, plainTextBlockSize, |
| 110733 | encrypted.data + offset, &outLength, |
| 110734 | encrypted.length - offset, |
| 110735 | mbedtls_ctr_drbg_random, |
| 110736 | &pc->drbgContext); |
| 110737 | if(mbedErr) { |
| 110738 | UA_ByteString_clear(&encrypted); |
| 110739 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110740 | } |
| 110741 | |
| 110742 | inOffset += plainTextBlockSize; |
| 110743 | offset += outLength; |
| 110744 | lenDataToEncrypt -= plainTextBlockSize; |
| 110745 | } |
| 110746 | |
| 110747 | memcpy(data->data, encrypted.data, offset); |
| 110748 | UA_ByteString_clear(&encrypted); |
| 110749 | |
| 110750 | return UA_STATUSCODE_GOOD; |
| 110751 | } |
| 110752 | |
| 110753 | static UA_StatusCode |
| 110754 | asym_decrypt_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 110755 | UA_ByteString *data) { |
| 110756 | if(cc == NULL || data == NULL) |
| 110757 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110758 | |
| 110759 | Basic128Rsa15_PolicyContext *pc = cc->policyContext; |
| 110760 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey); |
| 110761 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_NONE); |
| 110762 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 110763 | size_t keylen = rsaContext->len; |
| 110764 | #else |
| 110765 | size_t keylen = mbedtls_rsa_get_len(rsaContext); |
| 110766 | #endif |
| 110767 | if(data->length % keylen != 0) |
| 110768 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110769 | |
| 110770 | size_t inOffset = 0; |
| 110771 | size_t outOffset = 0; |
| 110772 | size_t outLength = 0; |
| 110773 | unsigned char buf[512]; |
| 110774 | |
| 110775 | while(inOffset < data->length) { |
| 110776 | int mbedErr = mbedtls_pk_decrypt(&pc->localPrivateKey, |
| 110777 | data->data + inOffset, keylen, |
| 110778 | buf, &outLength, 512, |
| 110779 | mbedtls_ctr_drbg_random, |
| 110780 | &pc->drbgContext); |
| 110781 | if(mbedErr) |
| 110782 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 110783 | |
| 110784 | memcpy(data->data + outOffset, buf, outLength); |
| 110785 | inOffset += keylen; |
| 110786 | outOffset += outLength; |
| 110787 | } |
| 110788 | |
| 110789 | data->length = outOffset; |
| 110790 | return UA_STATUSCODE_GOOD; |
| 110791 | } |
| 110792 | |
| 110793 | static size_t |
| 110794 | asym_getLocalEncryptionKeyLength_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) { |
| 110795 | if(cc == NULL) |
| 110796 | return 0; |
| 110797 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 110798 | mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 110799 | return rsaContext->len; |
| 110800 | #else |
| 110801 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 110802 | #endif |
| 110803 | } |
| 110804 | |
| 110805 | static size_t |
| 110806 | asym_getRemoteEncryptionKeyLength_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) { |
| 110807 | return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8; |
| 110808 | } |
| 110809 | |
| 110810 | static size_t |
| 110811 | asym_getRemoteBlockSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) { |
| 110812 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 110813 | mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 110814 | return rsaContext->len; |
| 110815 | #else |
| 110816 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 110817 | #endif |
| 110818 | } |
| 110819 | |
| 110820 | static size_t |
| 110821 | asym_getRemotePlainTextBlockSize_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc) { |
| 110822 | if(cc == NULL) |
| 110823 | return 0; |
| 110824 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 110825 | mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 110826 | return rsaContext->len - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN; |
| 110827 | #else |
| 110828 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) - |
| 110829 | UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN; |
| 110830 | #endif |
| 110831 | } |
| 110832 | |
| 110833 | static UA_StatusCode |
| 110834 | asym_makeThumbprint_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy, |
| 110835 | const UA_ByteString *certificate, |
| 110836 | UA_ByteString *thumbprint) { |
| 110837 | if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL) |
| 110838 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110839 | return mbedtls_thumbprint_sha1(certificate, thumbprint); |
| 110840 | } |
| 110841 | |
| 110842 | static UA_StatusCode |
| 110843 | asymmetricModule_compareCertificateThumbprint_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy, |
| 110844 | const UA_ByteString *certificateThumbprint) { |
| 110845 | if(securityPolicy == NULL || certificateThumbprint == NULL) |
| 110846 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110847 | |
| 110848 | Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext; |
| 110849 | if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint)) |
| 110850 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 110851 | |
| 110852 | return UA_STATUSCODE_GOOD; |
| 110853 | } |
| 110854 | |
| 110855 | /*******************/ |
| 110856 | /* SymmetricModule */ |
| 110857 | /*******************/ |
| 110858 | |
| 110859 | static UA_StatusCode |
| 110860 | sym_verify_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 110861 | const UA_ByteString *message, |
| 110862 | const UA_ByteString *signature) { |
| 110863 | if(cc == NULL || message == NULL || signature == NULL) |
| 110864 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110865 | |
| 110866 | /* Compute MAC */ |
| 110867 | if(signature->length != UA_SHA1_LENGTH) |
| 110868 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 110869 | |
| 110870 | Basic128Rsa15_PolicyContext *pc = cc->policyContext; |
| 110871 | |
| 110872 | unsigned char mac[UA_SHA1_LENGTH]; |
| 110873 | mbedtls_hmac(&pc->sha1MdContext, &cc->remoteSymSigningKey, message, mac); |
| 110874 | |
| 110875 | /* Compare with Signature */ |
| 110876 | if(!UA_constantTimeEqual(signature->data, mac, UA_SHA1_LENGTH)) |
| 110877 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 110878 | return UA_STATUSCODE_GOOD; |
| 110879 | } |
| 110880 | |
| 110881 | static UA_StatusCode |
| 110882 | sym_sign_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc, |
| 110883 | const UA_ByteString *message, |
| 110884 | UA_ByteString *signature) { |
| 110885 | if(signature->length != UA_SHA1_LENGTH) |
| 110886 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110887 | |
| 110888 | mbedtls_hmac(&cc->policyContext->sha1MdContext, &cc->localSymSigningKey, |
| 110889 | message, signature->data); |
| 110890 | return UA_STATUSCODE_GOOD; |
| 110891 | } |
| 110892 | |
| 110893 | static size_t |
| 110894 | sym_getSignatureSize_sp_basic128rsa15(const void *channelContext) { |
| 110895 | return UA_SHA1_LENGTH; |
| 110896 | } |
| 110897 | |
| 110898 | static size_t |
| 110899 | sym_getSigningKeyLength_sp_basic128rsa15(const void *const channelContext) { |
| 110900 | return UA_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH; |
| 110901 | } |
| 110902 | |
| 110903 | static size_t |
| 110904 | sym_getEncryptionKeyLength_sp_basic128rsa15(const void *channelContext) { |
| 110905 | return UA_SECURITYPOLICY_BASIC128RSA15_SYM_KEY_LENGTH; |
| 110906 | } |
| 110907 | |
| 110908 | static size_t |
| 110909 | sym_getEncryptionBlockSize_sp_basic128rsa15(const void *const channelContext) { |
| 110910 | return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE; |
| 110911 | } |
| 110912 | |
| 110913 | static size_t |
| 110914 | sym_getPlainTextBlockSize_sp_basic128rsa15(const void *const channelContext) { |
| 110915 | return UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE; |
| 110916 | } |
| 110917 | |
| 110918 | static UA_StatusCode |
| 110919 | sym_encrypt_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc, |
| 110920 | UA_ByteString *data) { |
| 110921 | if(cc == NULL || data == NULL) |
| 110922 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110923 | |
| 110924 | if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE) |
| 110925 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110926 | |
| 110927 | size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC128RSA15_SYM_PLAIN_TEXT_BLOCK_SIZE; |
| 110928 | if(data->length % plainTextBlockSize != 0) |
| 110929 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110930 | |
| 110931 | /* Keylength in bits */ |
| 110932 | unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8); |
| 110933 | mbedtls_aes_context aesContext; |
| 110934 | int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength); |
| 110935 | if(mbedErr) |
| 110936 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110937 | |
| 110938 | UA_ByteString ivCopy; |
| 110939 | UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy); |
| 110940 | if(retval != UA_STATUSCODE_GOOD) |
| 110941 | return retval; |
| 110942 | |
| 110943 | mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length, |
| 110944 | ivCopy.data, data->data, data->data); |
| 110945 | if(mbedErr) |
| 110946 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 110947 | UA_ByteString_clear(&ivCopy); |
| 110948 | return retval; |
| 110949 | } |
| 110950 | |
| 110951 | static UA_StatusCode |
| 110952 | sym_decrypt_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc, |
| 110953 | UA_ByteString *data) { |
| 110954 | if(cc == NULL || data == NULL) |
| 110955 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110956 | |
| 110957 | size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE; |
| 110958 | if(cc->remoteSymIv.length != encryptionBlockSize) |
| 110959 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110960 | |
| 110961 | if(data->length % encryptionBlockSize != 0) |
| 110962 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110963 | |
| 110964 | unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8); |
| 110965 | mbedtls_aes_context aesContext; |
| 110966 | int mbedErr = mbedtls_aes_setkey_dec(&aesContext, |
| 110967 | cc->remoteSymEncryptingKey.data, keylength); |
| 110968 | if(mbedErr) |
| 110969 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110970 | |
| 110971 | UA_ByteString ivCopy; |
| 110972 | UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy); |
| 110973 | if(retval != UA_STATUSCODE_GOOD) |
| 110974 | return retval; |
| 110975 | |
| 110976 | mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length, |
| 110977 | ivCopy.data, data->data, data->data); |
| 110978 | if(mbedErr) |
| 110979 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 110980 | UA_ByteString_clear(&ivCopy); |
| 110981 | return retval; |
| 110982 | } |
| 110983 | |
| 110984 | static UA_StatusCode |
| 110985 | sym_generateKey_sp_basic128rsa15(void *policyContext, const UA_ByteString *secret, |
| 110986 | const UA_ByteString *seed, UA_ByteString *out) { |
| 110987 | if(secret == NULL || seed == NULL || out == NULL) |
| 110988 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110989 | Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)policyContext; |
| 110990 | return mbedtls_generateKey(&pc->sha1MdContext, secret, seed, out); |
| 110991 | } |
| 110992 | |
| 110993 | static UA_StatusCode |
| 110994 | sym_generateNonce_sp_basic128rsa15(void *policyContext, UA_ByteString *out) { |
| 110995 | if(out == NULL) |
| 110996 | return UA_STATUSCODE_BADINTERNALERROR; |
| 110997 | Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)policyContext; |
| 110998 | int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length); |
| 110999 | if(mbedErr) |
| 111000 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 111001 | return UA_STATUSCODE_GOOD; |
| 111002 | } |
| 111003 | |
| 111004 | /*****************/ |
| 111005 | /* ChannelModule */ |
| 111006 | /*****************/ |
| 111007 | |
| 111008 | /* Assumes that the certificate has been verified externally */ |
| 111009 | static UA_StatusCode |
| 111010 | parseRemoteCertificate_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 111011 | const UA_ByteString *remoteCertificate) { |
| 111012 | if(remoteCertificate == NULL || cc == NULL) |
| 111013 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111014 | |
| 111015 | /* Parse the certificate */ |
| 111016 | int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data, |
| 111017 | remoteCertificate->length); |
| 111018 | if(mbedErr) |
| 111019 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111020 | |
| 111021 | /* Check the key length */ |
| 111022 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 111023 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 111024 | if(rsaContext->len < UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH || |
| 111025 | rsaContext->len > UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH) |
| 111026 | return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; |
| 111027 | #else |
| 111028 | size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 111029 | if(keylen < UA_SECURITYPOLICY_BASIC128RSA15_MINASYMKEYLENGTH || |
| 111030 | keylen > UA_SECURITYPOLICY_BASIC128RSA15_MAXASYMKEYLENGTH) |
| 111031 | return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; |
| 111032 | #endif |
| 111033 | return UA_STATUSCODE_GOOD; |
| 111034 | } |
| 111035 | |
| 111036 | static void |
| 111037 | channelContext_deleteContext_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc) { |
| 111038 | UA_ByteString_clear(&cc->localSymSigningKey); |
| 111039 | UA_ByteString_clear(&cc->localSymEncryptingKey); |
| 111040 | UA_ByteString_clear(&cc->localSymIv); |
| 111041 | UA_ByteString_clear(&cc->remoteSymSigningKey); |
| 111042 | UA_ByteString_clear(&cc->remoteSymEncryptingKey); |
| 111043 | UA_ByteString_clear(&cc->remoteSymIv); |
| 111044 | mbedtls_x509_crt_free(&cc->remoteCertificate); |
| 111045 | UA_free(cc); |
| 111046 | } |
| 111047 | |
| 111048 | static UA_StatusCode |
| 111049 | channelContext_newContext_sp_basic128rsa15(const UA_SecurityPolicy *securityPolicy, |
| 111050 | const UA_ByteString *remoteCertificate, |
| 111051 | void **pp_contextData) { |
| 111052 | if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL) |
| 111053 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111054 | |
| 111055 | /* Allocate the channel context */ |
| 111056 | *pp_contextData = UA_malloc(sizeof(Basic128Rsa15_ChannelContext)); |
| 111057 | if(*pp_contextData == NULL) |
| 111058 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 111059 | |
| 111060 | Basic128Rsa15_ChannelContext *cc = (Basic128Rsa15_ChannelContext *)*pp_contextData; |
| 111061 | |
| 111062 | /* Initialize the channel context */ |
| 111063 | cc->policyContext = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext; |
| 111064 | |
| 111065 | UA_ByteString_init(&cc->localSymSigningKey); |
| 111066 | UA_ByteString_init(&cc->localSymEncryptingKey); |
| 111067 | UA_ByteString_init(&cc->localSymIv); |
| 111068 | |
| 111069 | UA_ByteString_init(&cc->remoteSymSigningKey); |
| 111070 | UA_ByteString_init(&cc->remoteSymEncryptingKey); |
| 111071 | UA_ByteString_init(&cc->remoteSymIv); |
| 111072 | |
| 111073 | mbedtls_x509_crt_init(&cc->remoteCertificate); |
| 111074 | |
| 111075 | // TODO: this can be optimized so that we dont allocate memory before parsing the certificate |
| 111076 | UA_StatusCode retval = parseRemoteCertificate_sp_basic128rsa15(cc, remoteCertificate); |
| 111077 | if(retval != UA_STATUSCODE_GOOD) { |
| 111078 | channelContext_deleteContext_sp_basic128rsa15(cc); |
| 111079 | *pp_contextData = NULL; |
| 111080 | } |
| 111081 | return retval; |
| 111082 | } |
| 111083 | |
| 111084 | static UA_StatusCode |
| 111085 | channelContext_setLocalSymEncryptingKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 111086 | const UA_ByteString *key) { |
| 111087 | if(key == NULL || cc == NULL) |
| 111088 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111089 | |
| 111090 | UA_ByteString_clear(&cc->localSymEncryptingKey); |
| 111091 | return UA_ByteString_copy(key, &cc->localSymEncryptingKey); |
| 111092 | } |
| 111093 | |
| 111094 | static UA_StatusCode |
| 111095 | channelContext_setLocalSymSigningKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 111096 | const UA_ByteString *key) { |
| 111097 | if(key == NULL || cc == NULL) |
| 111098 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111099 | |
| 111100 | UA_ByteString_clear(&cc->localSymSigningKey); |
| 111101 | return UA_ByteString_copy(key, &cc->localSymSigningKey); |
| 111102 | } |
| 111103 | |
| 111104 | |
| 111105 | static UA_StatusCode |
| 111106 | channelContext_setLocalSymIv_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 111107 | const UA_ByteString *iv) { |
| 111108 | if(iv == NULL || cc == NULL) |
| 111109 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111110 | |
| 111111 | UA_ByteString_clear(&cc->localSymIv); |
| 111112 | return UA_ByteString_copy(iv, &cc->localSymIv); |
| 111113 | } |
| 111114 | |
| 111115 | static UA_StatusCode |
| 111116 | channelContext_setRemoteSymEncryptingKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 111117 | const UA_ByteString *key) { |
| 111118 | if(key == NULL || cc == NULL) |
| 111119 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111120 | |
| 111121 | UA_ByteString_clear(&cc->remoteSymEncryptingKey); |
| 111122 | return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey); |
| 111123 | } |
| 111124 | |
| 111125 | static UA_StatusCode |
| 111126 | channelContext_setRemoteSymSigningKey_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 111127 | const UA_ByteString *key) { |
| 111128 | if(key == NULL || cc == NULL) |
| 111129 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111130 | |
| 111131 | UA_ByteString_clear(&cc->remoteSymSigningKey); |
| 111132 | return UA_ByteString_copy(key, &cc->remoteSymSigningKey); |
| 111133 | } |
| 111134 | |
| 111135 | static UA_StatusCode |
| 111136 | channelContext_setRemoteSymIv_sp_basic128rsa15(Basic128Rsa15_ChannelContext *cc, |
| 111137 | const UA_ByteString *iv) { |
| 111138 | if(iv == NULL || cc == NULL) |
| 111139 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111140 | |
| 111141 | UA_ByteString_clear(&cc->remoteSymIv); |
| 111142 | return UA_ByteString_copy(iv, &cc->remoteSymIv); |
| 111143 | } |
| 111144 | |
| 111145 | static UA_StatusCode |
| 111146 | channelContext_compareCertificate_sp_basic128rsa15(const Basic128Rsa15_ChannelContext *cc, |
| 111147 | const UA_ByteString *certificate) { |
| 111148 | if(cc == NULL || certificate == NULL) |
| 111149 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111150 | |
| 111151 | mbedtls_x509_crt cert; |
| 111152 | mbedtls_x509_crt_init(&cert); |
| 111153 | int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length); |
| 111154 | if(mbedErr) |
| 111155 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111156 | |
| 111157 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 111158 | if(cert.raw.len != cc->remoteCertificate.raw.len || |
| 111159 | memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0) |
| 111160 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111161 | |
| 111162 | mbedtls_x509_crt_free(&cert); |
| 111163 | return retval; |
| 111164 | } |
| 111165 | |
| 111166 | static void |
| 111167 | clear_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy) { |
| 111168 | if(securityPolicy == NULL) |
| 111169 | return; |
| 111170 | |
| 111171 | UA_ByteString_clear(&securityPolicy->localCertificate); |
| 111172 | |
| 111173 | if(securityPolicy->policyContext == NULL) |
| 111174 | return; |
| 111175 | |
| 111176 | /* delete all allocated members in the context */ |
| 111177 | Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *) |
| 111178 | securityPolicy->policyContext; |
| 111179 | |
| 111180 | mbedtls_ctr_drbg_free(&pc->drbgContext); |
| 111181 | mbedtls_entropy_free(&pc->entropyContext); |
| 111182 | mbedtls_pk_free(&pc->localPrivateKey); |
| 111183 | mbedtls_md_free(&pc->sha1MdContext); |
| 111184 | UA_ByteString_clear(&pc->localCertThumbprint); |
| 111185 | |
| 111186 | UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 111187 | "Deleted members of EndpointContext for sp_basic128rsa15"); |
| 111188 | |
| 111189 | UA_free(pc); |
| 111190 | securityPolicy->policyContext = NULL; |
| 111191 | } |
| 111192 | |
| 111193 | static UA_StatusCode |
| 111194 | updateCertificateAndPrivateKey_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy, |
| 111195 | const UA_ByteString newCertificate, |
| 111196 | const UA_ByteString newPrivateKey) { |
| 111197 | if(securityPolicy == NULL) |
| 111198 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111199 | |
| 111200 | if(securityPolicy->policyContext == NULL) |
| 111201 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111202 | |
| 111203 | Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *)securityPolicy->policyContext; |
| 111204 | |
| 111205 | UA_ByteString_clear(&securityPolicy->localCertificate); |
| 111206 | |
| 111207 | UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate); |
| 111208 | |
| 111209 | if (retval != UA_STATUSCODE_GOOD) |
| 111210 | return retval; |
| 111211 | |
| 111212 | /* Set the new private key */ |
| 111213 | mbedtls_pk_free(&pc->localPrivateKey); |
| 111214 | mbedtls_pk_init(&pc->localPrivateKey); |
| 111215 | int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext); |
| 111216 | if(mbedErr) { |
| 111217 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111218 | goto error; |
| 111219 | } |
| 111220 | |
| 111221 | retval = asym_makeThumbprint_sp_basic128rsa15(securityPolicy, |
| 111222 | &securityPolicy->localCertificate, |
| 111223 | &pc->localCertThumbprint); |
| 111224 | if(retval != UA_STATUSCODE_GOOD) |
| 111225 | goto error; |
| 111226 | |
| 111227 | return retval; |
| 111228 | |
| 111229 | error: |
| 111230 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 111231 | "Could not update certificate and private key"); |
| 111232 | if(securityPolicy->policyContext != NULL) |
| 111233 | clear_sp_basic128rsa15(securityPolicy); |
| 111234 | return retval; |
| 111235 | } |
| 111236 | |
| 111237 | static UA_StatusCode |
| 111238 | policyContext_newContext_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy, |
| 111239 | const UA_ByteString localPrivateKey) { |
| 111240 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 111241 | if(securityPolicy == NULL) |
| 111242 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111243 | |
| 111244 | if (localPrivateKey.length == 0) { |
| 111245 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 111246 | "Can not initialize security policy. Private key is empty."); |
| 111247 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 111248 | } |
| 111249 | |
| 111250 | Basic128Rsa15_PolicyContext *pc = (Basic128Rsa15_PolicyContext *) |
| 111251 | UA_malloc(sizeof(Basic128Rsa15_PolicyContext)); |
| 111252 | securityPolicy->policyContext = (void *)pc; |
| 111253 | if(!pc) { |
| 111254 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 111255 | goto error; |
| 111256 | } |
| 111257 | |
| 111258 | /* Initialize the PolicyContext */ |
| 111259 | memset(pc, 0, sizeof(Basic128Rsa15_PolicyContext)); |
| 111260 | mbedtls_ctr_drbg_init(&pc->drbgContext); |
| 111261 | mbedtls_entropy_init(&pc->entropyContext); |
| 111262 | mbedtls_pk_init(&pc->localPrivateKey); |
| 111263 | mbedtls_md_init(&pc->sha1MdContext); |
| 111264 | |
| 111265 | /* Initialized the message digest */ |
| 111266 | const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); |
| 111267 | int mbedErr = mbedtls_md_setup(&pc->sha1MdContext, mdInfo, MBEDTLS_MD_SHA1); |
| 111268 | if(mbedErr) { |
| 111269 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 111270 | goto error; |
| 111271 | } |
| 111272 | |
| 111273 | mbedErr = mbedtls_entropy_self_test(0); |
| 111274 | |
| 111275 | if(mbedErr) { |
| 111276 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111277 | goto error; |
| 111278 | } |
| 111279 | |
| 111280 | /* Seed the RNG */ |
| 111281 | char *personalization = "open62541-drbg"; |
| 111282 | mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func, |
| 111283 | &pc->entropyContext, |
| 111284 | (const unsigned char *)personalization, 14); |
| 111285 | if(mbedErr) { |
| 111286 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111287 | goto error; |
| 111288 | } |
| 111289 | |
| 111290 | /* Set the private key */ |
| 111291 | mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext); |
| 111292 | |
| 111293 | if(mbedErr) { |
| 111294 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111295 | goto error; |
| 111296 | } |
| 111297 | |
| 111298 | /* Set the local certificate thumbprint */ |
| 111299 | retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH); |
| 111300 | if(retval != UA_STATUSCODE_GOOD) |
| 111301 | goto error; |
| 111302 | retval = asym_makeThumbprint_sp_basic128rsa15(securityPolicy, |
| 111303 | &securityPolicy->localCertificate, |
| 111304 | &pc->localCertThumbprint); |
| 111305 | if(retval != UA_STATUSCODE_GOOD) |
| 111306 | goto error; |
| 111307 | |
| 111308 | return UA_STATUSCODE_GOOD; |
| 111309 | |
| 111310 | error: |
| 111311 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 111312 | "Could not create securityContext: %s", UA_StatusCode_name(retval)); |
| 111313 | if(securityPolicy->policyContext != NULL) |
| 111314 | clear_sp_basic128rsa15(securityPolicy); |
| 111315 | return retval; |
| 111316 | } |
| 111317 | |
| 111318 | UA_StatusCode |
| 111319 | UA_SecurityPolicy_Basic128Rsa15(UA_SecurityPolicy *policy, const UA_ByteString localCertificate, |
| 111320 | const UA_ByteString localPrivateKey, const UA_Logger *logger) { |
| 111321 | memset(policy, 0, sizeof(UA_SecurityPolicy)); |
| 111322 | policy->logger = logger; |
| 111323 | |
| 111324 | UA_LOG_WARNING(logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 111325 | "!! WARNING !! The Basic128Rsa15 SecurityPolicy is unsecure. " |
| 111326 | "There are known attacks that break the encryption."); |
| 111327 | |
| 111328 | policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15\0"); |
| 111329 | |
| 111330 | UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule; |
| 111331 | UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule; |
| 111332 | UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule; |
| 111333 | |
| 111334 | UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate); |
| 111335 | |
| 111336 | if (retval != UA_STATUSCODE_GOOD) |
| 111337 | return retval; |
| 111338 | |
| 111339 | /* AsymmetricModule */ |
| 111340 | UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm = |
| 111341 | &asymmetricModule->cryptoModule.signatureAlgorithm; |
| 111342 | asym_signatureAlgorithm->uri = |
| 111343 | UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0"); |
| 111344 | asym_signatureAlgorithm->verify = |
| 111345 | (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic128rsa15; |
| 111346 | asym_signatureAlgorithm->sign = |
| 111347 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic128rsa15; |
| 111348 | asym_signatureAlgorithm->getLocalSignatureSize = |
| 111349 | (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic128rsa15; |
| 111350 | asym_signatureAlgorithm->getRemoteSignatureSize = |
| 111351 | (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic128rsa15; |
| 111352 | asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function |
| 111353 | asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function |
| 111354 | |
| 111355 | UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm = |
| 111356 | &asymmetricModule->cryptoModule.encryptionAlgorithm; |
| 111357 | asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-1_5"); |
| 111358 | asym_encryptionAlgorithm->encrypt = |
| 111359 | (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic128rsa15; |
| 111360 | asym_encryptionAlgorithm->decrypt = |
| 111361 | (UA_StatusCode(*)(void *, UA_ByteString *)) asym_decrypt_sp_basic128rsa15; |
| 111362 | asym_encryptionAlgorithm->getLocalKeyLength = |
| 111363 | (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic128rsa15; |
| 111364 | asym_encryptionAlgorithm->getRemoteKeyLength = |
| 111365 | (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic128rsa15; |
| 111366 | asym_encryptionAlgorithm->getRemoteBlockSize = |
| 111367 | (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic128rsa15; |
| 111368 | asym_encryptionAlgorithm->getRemotePlainTextBlockSize = |
| 111369 | (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic128rsa15; |
| 111370 | |
| 111371 | asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic128rsa15; |
| 111372 | asymmetricModule->compareCertificateThumbprint = |
| 111373 | asymmetricModule_compareCertificateThumbprint_sp_basic128rsa15; |
| 111374 | |
| 111375 | /* SymmetricModule */ |
| 111376 | symmetricModule->generateKey = sym_generateKey_sp_basic128rsa15; |
| 111377 | symmetricModule->generateNonce = sym_generateNonce_sp_basic128rsa15; |
| 111378 | |
| 111379 | UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm = |
| 111380 | &symmetricModule->cryptoModule.signatureAlgorithm; |
| 111381 | sym_signatureAlgorithm->uri = |
| 111382 | UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0"); |
| 111383 | sym_signatureAlgorithm->verify = |
| 111384 | (UA_StatusCode (*)(void *, const UA_ByteString *, |
| 111385 | const UA_ByteString *))sym_verify_sp_basic128rsa15; |
| 111386 | sym_signatureAlgorithm->sign = |
| 111387 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic128rsa15; |
| 111388 | sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic128rsa15; |
| 111389 | sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic128rsa15; |
| 111390 | sym_signatureAlgorithm->getLocalKeyLength = |
| 111391 | (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic128rsa15; |
| 111392 | sym_signatureAlgorithm->getRemoteKeyLength = |
| 111393 | (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic128rsa15; |
| 111394 | |
| 111395 | UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm = |
| 111396 | &symmetricModule->cryptoModule.encryptionAlgorithm; |
| 111397 | sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc"); |
| 111398 | sym_encryptionAlgorithm->encrypt = |
| 111399 | (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic128rsa15; |
| 111400 | sym_encryptionAlgorithm->decrypt = |
| 111401 | (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic128rsa15; |
| 111402 | sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic128rsa15; |
| 111403 | sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic128rsa15; |
| 111404 | sym_encryptionAlgorithm->getRemoteBlockSize = |
| 111405 | (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic128rsa15; |
| 111406 | sym_encryptionAlgorithm->getRemotePlainTextBlockSize = |
| 111407 | (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic128rsa15; |
| 111408 | symmetricModule->secureChannelNonceLength = 16; |
| 111409 | |
| 111410 | // Use the same signature algorithm as the asymmetric component for certificate signing (see standard) |
| 111411 | policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 111412 | |
| 111413 | /* ChannelModule */ |
| 111414 | channelModule->newContext = channelContext_newContext_sp_basic128rsa15; |
| 111415 | channelModule->deleteContext = (void (*)(void *)) |
| 111416 | channelContext_deleteContext_sp_basic128rsa15; |
| 111417 | |
| 111418 | channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 111419 | channelContext_setLocalSymEncryptingKey_sp_basic128rsa15; |
| 111420 | channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 111421 | channelContext_setLocalSymSigningKey_sp_basic128rsa15; |
| 111422 | channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 111423 | channelContext_setLocalSymIv_sp_basic128rsa15; |
| 111424 | |
| 111425 | channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 111426 | channelContext_setRemoteSymEncryptingKey_sp_basic128rsa15; |
| 111427 | channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 111428 | channelContext_setRemoteSymSigningKey_sp_basic128rsa15; |
| 111429 | channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 111430 | channelContext_setRemoteSymIv_sp_basic128rsa15; |
| 111431 | |
| 111432 | channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *)) |
| 111433 | channelContext_compareCertificate_sp_basic128rsa15; |
| 111434 | |
| 111435 | policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic128rsa15; |
| 111436 | policy->clear = clear_sp_basic128rsa15; |
| 111437 | |
| 111438 | UA_StatusCode res = policyContext_newContext_sp_basic128rsa15(policy, localPrivateKey); |
| 111439 | if(res != UA_STATUSCODE_GOOD) |
| 111440 | clear_sp_basic128rsa15(policy); |
| 111441 | |
| 111442 | return res; |
| 111443 | } |
| 111444 | |
| 111445 | #endif |
| 111446 | |
| 111447 | /**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic256.c" ****/ |
| 111448 | |
| 111449 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 111450 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 111451 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 111452 | * |
| 111453 | * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB |
| 111454 | * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG |
| 111455 | * Copyright 2019 (c) Kalycito Infotech Private Limited |
| 111456 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 111457 | * Copyright 2020 (c) basysKom GmbH |
| 111458 | * |
| 111459 | */ |
| 111460 | |
| 111461 | |
| 111462 | #ifdef UA_ENABLE_ENCRYPTION_MBEDTLS |
| 111463 | |
| 111464 | |
| 111465 | #include <mbedtls/aes.h> |
| 111466 | #include <mbedtls/entropy.h> |
| 111467 | #include <mbedtls/error.h> |
| 111468 | #include <mbedtls/sha1.h> |
| 111469 | #include <mbedtls/version.h> |
| 111470 | |
| 111471 | /* Notes: |
| 111472 | * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to |
| 111473 | * allocate temp buffers. |
| 111474 | * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer |
| 111475 | */ |
| 111476 | |
| 111477 | #define UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN 42 |
| 111478 | #define UA_SHA1_LENGTH 20 |
| 111479 | #define UA_BASIC256_SYM_SIGNING_KEY_LENGTH 24 |
| 111480 | #define UA_SECURITYPOLICY_BASIC256_SYM_KEY_LENGTH 32 |
| 111481 | #define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE 16 |
| 111482 | #define UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE 16 |
| 111483 | #define UA_SECURITYPOLICY_BASIC256_MINASYMKEYLENGTH 128 |
| 111484 | #define UA_SECURITYPOLICY_BASIC256_MAXASYMKEYLENGTH 512 |
| 111485 | |
| 111486 | typedef struct { |
| 111487 | UA_ByteString localCertThumbprint; |
| 111488 | |
| 111489 | mbedtls_ctr_drbg_context drbgContext; |
| 111490 | mbedtls_entropy_context entropyContext; |
| 111491 | mbedtls_md_context_t sha1MdContext; |
| 111492 | mbedtls_pk_context localPrivateKey; |
| 111493 | } Basic256_PolicyContext; |
| 111494 | |
| 111495 | typedef struct { |
| 111496 | Basic256_PolicyContext *policyContext; |
| 111497 | |
| 111498 | UA_ByteString localSymSigningKey; |
| 111499 | UA_ByteString localSymEncryptingKey; |
| 111500 | UA_ByteString localSymIv; |
| 111501 | |
| 111502 | UA_ByteString remoteSymSigningKey; |
| 111503 | UA_ByteString remoteSymEncryptingKey; |
| 111504 | UA_ByteString remoteSymIv; |
| 111505 | |
| 111506 | mbedtls_x509_crt remoteCertificate; |
| 111507 | } Basic256_ChannelContext; |
| 111508 | |
| 111509 | /********************/ |
| 111510 | /* AsymmetricModule */ |
| 111511 | /********************/ |
| 111512 | |
| 111513 | /* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */ |
| 111514 | static UA_StatusCode |
| 111515 | asym_verify_sp_basic256(Basic256_ChannelContext *cc, |
| 111516 | const UA_ByteString *message, |
| 111517 | const UA_ByteString *signature) { |
| 111518 | if(message == NULL || signature == NULL || cc == NULL) |
| 111519 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111520 | |
| 111521 | return mbedtls_verifySig_sha1(&cc->remoteCertificate, message, signature); |
| 111522 | } |
| 111523 | |
| 111524 | /* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */ |
| 111525 | static UA_StatusCode |
| 111526 | asym_sign_sp_basic256(Basic256_ChannelContext *cc, |
| 111527 | const UA_ByteString *message, |
| 111528 | UA_ByteString *signature) { |
| 111529 | if(message == NULL || signature == NULL || cc == NULL) |
| 111530 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111531 | |
| 111532 | Basic256_PolicyContext *pc = cc->policyContext; |
| 111533 | return mbedtls_sign_sha1(&pc->localPrivateKey, &pc->drbgContext, |
| 111534 | message, signature); |
| 111535 | } |
| 111536 | |
| 111537 | static size_t |
| 111538 | asym_getLocalSignatureSize_sp_basic256(const Basic256_ChannelContext *cc) { |
| 111539 | if(cc == NULL) |
| 111540 | return 0; |
| 111541 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 111542 | return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len; |
| 111543 | #else |
| 111544 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey)); |
| 111545 | #endif |
| 111546 | } |
| 111547 | |
| 111548 | static size_t |
| 111549 | asym_getRemoteSignatureSize_sp_basic256(const Basic256_ChannelContext *cc) { |
| 111550 | if(cc == NULL) |
| 111551 | return 0; |
| 111552 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 111553 | return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len; |
| 111554 | #else |
| 111555 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 111556 | #endif |
| 111557 | } |
| 111558 | |
| 111559 | static size_t |
| 111560 | asym_getRemotePlainTextBlockSize_sp_basic256(const Basic256_ChannelContext *cc) { |
| 111561 | if(cc == NULL) |
| 111562 | return 0; |
| 111563 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 111564 | mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 111565 | return rsaContext->len - UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN; |
| 111566 | #else |
| 111567 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) - |
| 111568 | UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN; |
| 111569 | #endif |
| 111570 | } |
| 111571 | |
| 111572 | /* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */ |
| 111573 | static UA_StatusCode |
| 111574 | asym_encrypt_sp_basic256(Basic256_ChannelContext *cc, |
| 111575 | UA_ByteString *data) { |
| 111576 | if(cc == NULL || data == NULL) |
| 111577 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111578 | |
| 111579 | const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_basic256(cc); |
| 111580 | |
| 111581 | mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 111582 | mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1); |
| 111583 | |
| 111584 | return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext, |
| 111585 | data, plainTextBlockSize); |
| 111586 | } |
| 111587 | |
| 111588 | /* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */ |
| 111589 | static UA_StatusCode |
| 111590 | asym_decrypt_sp_basic256(Basic256_ChannelContext *cc, |
| 111591 | UA_ByteString *data) { |
| 111592 | if(cc == NULL || data == NULL) |
| 111593 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111594 | return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey, |
| 111595 | &cc->policyContext->drbgContext, data, MBEDTLS_MD_SHA1); |
| 111596 | } |
| 111597 | |
| 111598 | static size_t |
| 111599 | asym_getLocalEncryptionKeyLength_sp_basic256(const Basic256_ChannelContext *cc) { |
| 111600 | return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8; |
| 111601 | } |
| 111602 | |
| 111603 | static size_t |
| 111604 | asym_getRemoteEncryptionKeyLength_sp_basic256(const Basic256_ChannelContext *cc) { |
| 111605 | return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8; |
| 111606 | } |
| 111607 | |
| 111608 | static size_t |
| 111609 | asym_getRemoteBlockSize_sp_basic256(const Basic256_ChannelContext *cc) { |
| 111610 | if(cc == NULL) |
| 111611 | return 0; |
| 111612 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 111613 | mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 111614 | return rsaContext->len; |
| 111615 | #else |
| 111616 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 111617 | #endif |
| 111618 | } |
| 111619 | |
| 111620 | static UA_StatusCode |
| 111621 | asym_makeThumbprint_sp_basic256(const UA_SecurityPolicy *securityPolicy, |
| 111622 | const UA_ByteString *certificate, |
| 111623 | UA_ByteString *thumbprint) { |
| 111624 | if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL) |
| 111625 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111626 | return mbedtls_thumbprint_sha1(certificate, thumbprint); |
| 111627 | } |
| 111628 | |
| 111629 | static UA_StatusCode |
| 111630 | asymmetricModule_compareCertificateThumbprint_sp_basic256(const UA_SecurityPolicy *securityPolicy, |
| 111631 | const UA_ByteString *certificateThumbprint) { |
| 111632 | if(securityPolicy == NULL || certificateThumbprint == NULL) |
| 111633 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111634 | |
| 111635 | Basic256_PolicyContext *pc = (Basic256_PolicyContext *)securityPolicy->policyContext; |
| 111636 | if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint)) |
| 111637 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 111638 | |
| 111639 | return UA_STATUSCODE_GOOD; |
| 111640 | } |
| 111641 | |
| 111642 | /*******************/ |
| 111643 | /* SymmetricModule */ |
| 111644 | /*******************/ |
| 111645 | |
| 111646 | static UA_StatusCode |
| 111647 | sym_verify_sp_basic256(Basic256_ChannelContext *cc, |
| 111648 | const UA_ByteString *message, |
| 111649 | const UA_ByteString *signature) { |
| 111650 | if(cc == NULL || message == NULL || signature == NULL) |
| 111651 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111652 | |
| 111653 | /* Compute MAC */ |
| 111654 | if(signature->length != UA_SHA1_LENGTH) |
| 111655 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111656 | |
| 111657 | Basic256_PolicyContext *pc = cc->policyContext; |
| 111658 | |
| 111659 | unsigned char mac[UA_SHA1_LENGTH]; |
| 111660 | mbedtls_hmac(&pc->sha1MdContext, &cc->remoteSymSigningKey, message, mac); |
| 111661 | |
| 111662 | /* Compare with Signature */ |
| 111663 | if(!UA_constantTimeEqual(signature->data, mac, UA_SHA1_LENGTH)) |
| 111664 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111665 | return UA_STATUSCODE_GOOD; |
| 111666 | } |
| 111667 | |
| 111668 | static UA_StatusCode |
| 111669 | sym_sign_sp_basic256(const Basic256_ChannelContext *cc, |
| 111670 | const UA_ByteString *message, UA_ByteString *signature) { |
| 111671 | if(signature->length != UA_SHA1_LENGTH) |
| 111672 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111673 | |
| 111674 | mbedtls_hmac(&cc->policyContext->sha1MdContext, &cc->localSymSigningKey, |
| 111675 | message, signature->data); |
| 111676 | return UA_STATUSCODE_GOOD; |
| 111677 | } |
| 111678 | |
| 111679 | static size_t |
| 111680 | sym_getSignatureSize_sp_basic256(const void *channelContext) { |
| 111681 | return UA_SHA1_LENGTH; |
| 111682 | } |
| 111683 | |
| 111684 | static size_t |
| 111685 | sym_getSigningKeyLength_sp_basic256(const void *const channelContext) { |
| 111686 | return UA_BASIC256_SYM_SIGNING_KEY_LENGTH; |
| 111687 | } |
| 111688 | |
| 111689 | static size_t |
| 111690 | sym_getEncryptionKeyLength_sp_basic256(const void *channelContext) { |
| 111691 | return UA_SECURITYPOLICY_BASIC256_SYM_KEY_LENGTH; |
| 111692 | } |
| 111693 | |
| 111694 | static size_t |
| 111695 | sym_getEncryptionBlockSize_sp_basic256(const void *const channelContext) { |
| 111696 | return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE; |
| 111697 | } |
| 111698 | |
| 111699 | static size_t |
| 111700 | sym_getPlainTextBlockSize_sp_basic256(const void *const channelContext) { |
| 111701 | return UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE; |
| 111702 | } |
| 111703 | |
| 111704 | static UA_StatusCode |
| 111705 | sym_encrypt_sp_basic256(const Basic256_ChannelContext *cc, |
| 111706 | UA_ByteString *data) { |
| 111707 | if(cc == NULL || data == NULL) |
| 111708 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111709 | |
| 111710 | if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE) |
| 111711 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111712 | |
| 111713 | size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC256_SYM_PLAIN_TEXT_BLOCK_SIZE; |
| 111714 | if(data->length % plainTextBlockSize != 0) |
| 111715 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111716 | |
| 111717 | /* Keylength in bits */ |
| 111718 | unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8); |
| 111719 | mbedtls_aes_context aesContext; |
| 111720 | int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength); |
| 111721 | if(mbedErr) |
| 111722 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111723 | |
| 111724 | UA_ByteString ivCopy; |
| 111725 | UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy); |
| 111726 | if(retval != UA_STATUSCODE_GOOD) |
| 111727 | return retval; |
| 111728 | |
| 111729 | mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length, |
| 111730 | ivCopy.data, data->data, data->data); |
| 111731 | if(mbedErr) |
| 111732 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 111733 | UA_ByteString_clear(&ivCopy); |
| 111734 | return retval; |
| 111735 | } |
| 111736 | |
| 111737 | static UA_StatusCode |
| 111738 | sym_decrypt_sp_basic256(const Basic256_ChannelContext *cc, |
| 111739 | UA_ByteString *data) { |
| 111740 | if(cc == NULL || data == NULL) |
| 111741 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111742 | |
| 111743 | size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE; |
| 111744 | if(cc->remoteSymIv.length != encryptionBlockSize) |
| 111745 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111746 | |
| 111747 | if(data->length % encryptionBlockSize != 0) |
| 111748 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111749 | |
| 111750 | unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8); |
| 111751 | mbedtls_aes_context aesContext; |
| 111752 | int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength); |
| 111753 | if(mbedErr) |
| 111754 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111755 | |
| 111756 | UA_ByteString ivCopy; |
| 111757 | UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy); |
| 111758 | if(retval != UA_STATUSCODE_GOOD) |
| 111759 | return retval; |
| 111760 | |
| 111761 | mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length, |
| 111762 | ivCopy.data, data->data, data->data); |
| 111763 | if(mbedErr) |
| 111764 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 111765 | UA_ByteString_clear(&ivCopy); |
| 111766 | return retval; |
| 111767 | } |
| 111768 | |
| 111769 | static UA_StatusCode |
| 111770 | sym_generateKey_sp_basic256(void *policyContext, const UA_ByteString *secret, |
| 111771 | const UA_ByteString *seed, UA_ByteString *out) { |
| 111772 | if(secret == NULL || seed == NULL || out == NULL) |
| 111773 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111774 | Basic256_PolicyContext *pc = (Basic256_PolicyContext *)policyContext; |
| 111775 | return mbedtls_generateKey(&pc->sha1MdContext, secret, seed, out); |
| 111776 | } |
| 111777 | |
| 111778 | static UA_StatusCode |
| 111779 | sym_generateNonce_sp_basic256(void *policyContext, UA_ByteString *out) { |
| 111780 | if(out == NULL) |
| 111781 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111782 | Basic256_PolicyContext *pc = (Basic256_PolicyContext *)policyContext; |
| 111783 | int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length); |
| 111784 | if(mbedErr) |
| 111785 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 111786 | return UA_STATUSCODE_GOOD; |
| 111787 | } |
| 111788 | |
| 111789 | /*****************/ |
| 111790 | /* ChannelModule */ |
| 111791 | /*****************/ |
| 111792 | |
| 111793 | /* Assumes that the certificate has been verified externally */ |
| 111794 | static UA_StatusCode |
| 111795 | parseRemoteCertificate_sp_basic256(Basic256_ChannelContext *cc, |
| 111796 | const UA_ByteString *remoteCertificate) { |
| 111797 | if(remoteCertificate == NULL || cc == NULL) |
| 111798 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111799 | |
| 111800 | /* Parse the certificate */ |
| 111801 | int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data, |
| 111802 | remoteCertificate->length); |
| 111803 | if(mbedErr) |
| 111804 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111805 | |
| 111806 | /* Check the key length */ |
| 111807 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 111808 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 111809 | size_t keylen = rsaContext->len; |
| 111810 | #else |
| 111811 | size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 111812 | #endif |
| 111813 | if(keylen < UA_SECURITYPOLICY_BASIC256_MINASYMKEYLENGTH || |
| 111814 | keylen > UA_SECURITYPOLICY_BASIC256_MAXASYMKEYLENGTH) |
| 111815 | return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; |
| 111816 | |
| 111817 | return UA_STATUSCODE_GOOD; |
| 111818 | } |
| 111819 | |
| 111820 | static void |
| 111821 | channelContext_deleteContext_sp_basic256(Basic256_ChannelContext *cc) { |
| 111822 | UA_ByteString_clear(&cc->localSymSigningKey); |
| 111823 | UA_ByteString_clear(&cc->localSymEncryptingKey); |
| 111824 | UA_ByteString_clear(&cc->localSymIv); |
| 111825 | |
| 111826 | UA_ByteString_clear(&cc->remoteSymSigningKey); |
| 111827 | UA_ByteString_clear(&cc->remoteSymEncryptingKey); |
| 111828 | UA_ByteString_clear(&cc->remoteSymIv); |
| 111829 | |
| 111830 | mbedtls_x509_crt_free(&cc->remoteCertificate); |
| 111831 | |
| 111832 | UA_free(cc); |
| 111833 | } |
| 111834 | |
| 111835 | static UA_StatusCode |
| 111836 | channelContext_newContext_sp_basic256(const UA_SecurityPolicy *securityPolicy, |
| 111837 | const UA_ByteString *remoteCertificate, |
| 111838 | void **pp_contextData) { |
| 111839 | if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL) |
| 111840 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111841 | |
| 111842 | /* Allocate the channel context */ |
| 111843 | *pp_contextData = UA_malloc(sizeof(Basic256_ChannelContext)); |
| 111844 | if(*pp_contextData == NULL) |
| 111845 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 111846 | |
| 111847 | Basic256_ChannelContext *cc = (Basic256_ChannelContext *)*pp_contextData; |
| 111848 | |
| 111849 | /* Initialize the channel context */ |
| 111850 | cc->policyContext = (Basic256_PolicyContext *)securityPolicy->policyContext; |
| 111851 | |
| 111852 | UA_ByteString_init(&cc->localSymSigningKey); |
| 111853 | UA_ByteString_init(&cc->localSymEncryptingKey); |
| 111854 | UA_ByteString_init(&cc->localSymIv); |
| 111855 | |
| 111856 | UA_ByteString_init(&cc->remoteSymSigningKey); |
| 111857 | UA_ByteString_init(&cc->remoteSymEncryptingKey); |
| 111858 | UA_ByteString_init(&cc->remoteSymIv); |
| 111859 | |
| 111860 | mbedtls_x509_crt_init(&cc->remoteCertificate); |
| 111861 | |
| 111862 | // TODO: this can be optimized so that we dont allocate memory before parsing the certificate |
| 111863 | UA_StatusCode retval = parseRemoteCertificate_sp_basic256(cc, remoteCertificate); |
| 111864 | if(retval != UA_STATUSCODE_GOOD) { |
| 111865 | channelContext_deleteContext_sp_basic256(cc); |
| 111866 | *pp_contextData = NULL; |
| 111867 | } |
| 111868 | return retval; |
| 111869 | } |
| 111870 | |
| 111871 | static UA_StatusCode |
| 111872 | channelContext_setLocalSymEncryptingKey_sp_basic256(Basic256_ChannelContext *cc, |
| 111873 | const UA_ByteString *key) { |
| 111874 | if(key == NULL || cc == NULL) |
| 111875 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111876 | |
| 111877 | UA_ByteString_clear(&cc->localSymEncryptingKey); |
| 111878 | return UA_ByteString_copy(key, &cc->localSymEncryptingKey); |
| 111879 | } |
| 111880 | |
| 111881 | static UA_StatusCode |
| 111882 | channelContext_setLocalSymSigningKey_sp_basic256(Basic256_ChannelContext *cc, |
| 111883 | const UA_ByteString *key) { |
| 111884 | if(key == NULL || cc == NULL) |
| 111885 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111886 | |
| 111887 | UA_ByteString_clear(&cc->localSymSigningKey); |
| 111888 | return UA_ByteString_copy(key, &cc->localSymSigningKey); |
| 111889 | } |
| 111890 | |
| 111891 | |
| 111892 | static UA_StatusCode |
| 111893 | channelContext_setLocalSymIv_sp_basic256(Basic256_ChannelContext *cc, |
| 111894 | const UA_ByteString *iv) { |
| 111895 | if(iv == NULL || cc == NULL) |
| 111896 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111897 | |
| 111898 | UA_ByteString_clear(&cc->localSymIv); |
| 111899 | return UA_ByteString_copy(iv, &cc->localSymIv); |
| 111900 | } |
| 111901 | |
| 111902 | static UA_StatusCode |
| 111903 | channelContext_setRemoteSymEncryptingKey_sp_basic256(Basic256_ChannelContext *cc, |
| 111904 | const UA_ByteString *key) { |
| 111905 | if(key == NULL || cc == NULL) |
| 111906 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111907 | |
| 111908 | UA_ByteString_clear(&cc->remoteSymEncryptingKey); |
| 111909 | return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey); |
| 111910 | } |
| 111911 | |
| 111912 | static UA_StatusCode |
| 111913 | channelContext_setRemoteSymSigningKey_sp_basic256(Basic256_ChannelContext *cc, |
| 111914 | const UA_ByteString *key) { |
| 111915 | if(key == NULL || cc == NULL) |
| 111916 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111917 | |
| 111918 | UA_ByteString_clear(&cc->remoteSymSigningKey); |
| 111919 | return UA_ByteString_copy(key, &cc->remoteSymSigningKey); |
| 111920 | } |
| 111921 | |
| 111922 | static UA_StatusCode |
| 111923 | channelContext_setRemoteSymIv_sp_basic256(Basic256_ChannelContext *cc, |
| 111924 | const UA_ByteString *iv) { |
| 111925 | if(iv == NULL || cc == NULL) |
| 111926 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111927 | |
| 111928 | UA_ByteString_clear(&cc->remoteSymIv); |
| 111929 | return UA_ByteString_copy(iv, &cc->remoteSymIv); |
| 111930 | } |
| 111931 | |
| 111932 | static UA_StatusCode |
| 111933 | channelContext_compareCertificate_sp_basic256(const Basic256_ChannelContext *cc, |
| 111934 | const UA_ByteString *certificate) { |
| 111935 | if(cc == NULL || certificate == NULL) |
| 111936 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111937 | |
| 111938 | mbedtls_x509_crt cert; |
| 111939 | mbedtls_x509_crt_init(&cert); |
| 111940 | int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length); |
| 111941 | if(mbedErr) |
| 111942 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111943 | |
| 111944 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 111945 | if(cert.raw.len != cc->remoteCertificate.raw.len || |
| 111946 | memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0) |
| 111947 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 111948 | |
| 111949 | mbedtls_x509_crt_free(&cert); |
| 111950 | return retval; |
| 111951 | } |
| 111952 | |
| 111953 | static void |
| 111954 | clear_sp_basic256(UA_SecurityPolicy *securityPolicy) { |
| 111955 | if(securityPolicy == NULL) |
| 111956 | return; |
| 111957 | |
| 111958 | UA_ByteString_clear(&securityPolicy->localCertificate); |
| 111959 | |
| 111960 | if(securityPolicy->policyContext == NULL) |
| 111961 | return; |
| 111962 | |
| 111963 | /* delete all allocated members in the context */ |
| 111964 | Basic256_PolicyContext *pc = (Basic256_PolicyContext *) |
| 111965 | securityPolicy->policyContext; |
| 111966 | |
| 111967 | mbedtls_ctr_drbg_free(&pc->drbgContext); |
| 111968 | mbedtls_entropy_free(&pc->entropyContext); |
| 111969 | mbedtls_pk_free(&pc->localPrivateKey); |
| 111970 | mbedtls_md_free(&pc->sha1MdContext); |
| 111971 | UA_ByteString_clear(&pc->localCertThumbprint); |
| 111972 | |
| 111973 | UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 111974 | "Deleted members of EndpointContext for sp_basic256"); |
| 111975 | |
| 111976 | UA_free(pc); |
| 111977 | securityPolicy->policyContext = NULL; |
| 111978 | } |
| 111979 | |
| 111980 | static UA_StatusCode |
| 111981 | updateCertificateAndPrivateKey_sp_basic256(UA_SecurityPolicy *securityPolicy, |
| 111982 | const UA_ByteString newCertificate, |
| 111983 | const UA_ByteString newPrivateKey) { |
| 111984 | if(securityPolicy == NULL) |
| 111985 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111986 | |
| 111987 | if(securityPolicy->policyContext == NULL) |
| 111988 | return UA_STATUSCODE_BADINTERNALERROR; |
| 111989 | |
| 111990 | Basic256_PolicyContext *pc = (Basic256_PolicyContext *) |
| 111991 | securityPolicy->policyContext; |
| 111992 | |
| 111993 | UA_ByteString_clear(&securityPolicy->localCertificate); |
| 111994 | |
| 111995 | UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate); |
| 111996 | |
| 111997 | if (retval != UA_STATUSCODE_GOOD) |
| 111998 | return retval; |
| 111999 | |
| 112000 | /* Set the new private key */ |
| 112001 | mbedtls_pk_free(&pc->localPrivateKey); |
| 112002 | mbedtls_pk_init(&pc->localPrivateKey); |
| 112003 | |
| 112004 | int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext); |
| 112005 | |
| 112006 | if(mbedErr) { |
| 112007 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112008 | goto error; |
| 112009 | } |
| 112010 | |
| 112011 | retval = asym_makeThumbprint_sp_basic256(securityPolicy, |
| 112012 | &securityPolicy->localCertificate, |
| 112013 | &pc->localCertThumbprint); |
| 112014 | if(retval != UA_STATUSCODE_GOOD) |
| 112015 | goto error; |
| 112016 | |
| 112017 | return retval; |
| 112018 | |
| 112019 | error: |
| 112020 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 112021 | "Could not update certificate and private key"); |
| 112022 | if(securityPolicy->policyContext != NULL) |
| 112023 | clear_sp_basic256(securityPolicy); |
| 112024 | return retval; |
| 112025 | } |
| 112026 | |
| 112027 | static UA_StatusCode |
| 112028 | policyContext_newContext_sp_basic256(UA_SecurityPolicy *securityPolicy, |
| 112029 | const UA_ByteString localPrivateKey) { |
| 112030 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 112031 | if(securityPolicy == NULL) |
| 112032 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112033 | |
| 112034 | if (localPrivateKey.length == 0) { |
| 112035 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 112036 | "Can not initialize security policy. Private key is empty."); |
| 112037 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 112038 | } |
| 112039 | |
| 112040 | Basic256_PolicyContext *pc = (Basic256_PolicyContext *) |
| 112041 | UA_malloc(sizeof(Basic256_PolicyContext)); |
| 112042 | securityPolicy->policyContext = (void *)pc; |
| 112043 | if(!pc) { |
| 112044 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 112045 | goto error; |
| 112046 | } |
| 112047 | |
| 112048 | /* Initialize the PolicyContext */ |
| 112049 | memset(pc, 0, sizeof(Basic256_PolicyContext)); |
| 112050 | mbedtls_ctr_drbg_init(&pc->drbgContext); |
| 112051 | mbedtls_entropy_init(&pc->entropyContext); |
| 112052 | mbedtls_pk_init(&pc->localPrivateKey); |
| 112053 | mbedtls_md_init(&pc->sha1MdContext); |
| 112054 | |
| 112055 | /* Initialized the message digest */ |
| 112056 | const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); |
| 112057 | int mbedErr = mbedtls_md_setup(&pc->sha1MdContext, mdInfo, MBEDTLS_MD_SHA1); |
| 112058 | if(mbedErr) { |
| 112059 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 112060 | goto error; |
| 112061 | } |
| 112062 | |
| 112063 | mbedErr = mbedtls_entropy_self_test(0); |
| 112064 | |
| 112065 | if(mbedErr) { |
| 112066 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112067 | goto error; |
| 112068 | } |
| 112069 | |
| 112070 | /* Seed the RNG */ |
| 112071 | char *personalization = "open62541-drbg"; |
| 112072 | mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func, |
| 112073 | &pc->entropyContext, |
| 112074 | (const unsigned char *)personalization, 14); |
| 112075 | if(mbedErr) { |
| 112076 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112077 | goto error; |
| 112078 | } |
| 112079 | |
| 112080 | /* Set the private key */ |
| 112081 | mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext); |
| 112082 | if(mbedErr) { |
| 112083 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112084 | goto error; |
| 112085 | } |
| 112086 | |
| 112087 | /* Set the local certificate thumbprint */ |
| 112088 | retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH); |
| 112089 | if(retval != UA_STATUSCODE_GOOD) |
| 112090 | goto error; |
| 112091 | retval = asym_makeThumbprint_sp_basic256(securityPolicy, |
| 112092 | &securityPolicy->localCertificate, |
| 112093 | &pc->localCertThumbprint); |
| 112094 | if(retval != UA_STATUSCODE_GOOD) |
| 112095 | goto error; |
| 112096 | |
| 112097 | return UA_STATUSCODE_GOOD; |
| 112098 | |
| 112099 | error: |
| 112100 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 112101 | "Could not create securityContext: %s", UA_StatusCode_name(retval)); |
| 112102 | if(securityPolicy->policyContext != NULL) |
| 112103 | clear_sp_basic256(securityPolicy); |
| 112104 | return retval; |
| 112105 | } |
| 112106 | |
| 112107 | UA_StatusCode |
| 112108 | UA_SecurityPolicy_Basic256(UA_SecurityPolicy *policy, const UA_ByteString localCertificate, |
| 112109 | const UA_ByteString localPrivateKey, const UA_Logger *logger) { |
| 112110 | |
| 112111 | UA_LOG_WARNING(logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 112112 | "!! WARNING !! The Basic256 SecurityPolicy is unsecure. " |
| 112113 | "There are known attacks that break the encryption."); |
| 112114 | |
| 112115 | memset(policy, 0, sizeof(UA_SecurityPolicy)); |
| 112116 | policy->logger = logger; |
| 112117 | |
| 112118 | policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256\0"); |
| 112119 | |
| 112120 | UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule; |
| 112121 | UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule; |
| 112122 | UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule; |
| 112123 | |
| 112124 | UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate); |
| 112125 | |
| 112126 | if (retval != UA_STATUSCODE_GOOD) |
| 112127 | return retval; |
| 112128 | |
| 112129 | /* AsymmetricModule */ |
| 112130 | UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm = |
| 112131 | &asymmetricModule->cryptoModule.signatureAlgorithm; |
| 112132 | asym_signatureAlgorithm->uri = |
| 112133 | UA_STRING("http://www.w3.org/2000/09/xmldsig#rsa-sha1\0"); |
| 112134 | asym_signatureAlgorithm->verify = |
| 112135 | (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic256; |
| 112136 | asym_signatureAlgorithm->sign = |
| 112137 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic256; |
| 112138 | asym_signatureAlgorithm->getLocalSignatureSize = |
| 112139 | (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic256; |
| 112140 | asym_signatureAlgorithm->getRemoteSignatureSize = |
| 112141 | (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic256; |
| 112142 | asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function |
| 112143 | asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function |
| 112144 | |
| 112145 | UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm = |
| 112146 | &asymmetricModule->cryptoModule.encryptionAlgorithm; |
| 112147 | asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0"); |
| 112148 | asym_encryptionAlgorithm->encrypt = |
| 112149 | (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic256; |
| 112150 | asym_encryptionAlgorithm->decrypt = |
| 112151 | (UA_StatusCode(*)(void *, UA_ByteString *))asym_decrypt_sp_basic256; |
| 112152 | asym_encryptionAlgorithm->getLocalKeyLength = |
| 112153 | (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic256; |
| 112154 | asym_encryptionAlgorithm->getRemoteKeyLength = |
| 112155 | (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic256; |
| 112156 | asym_encryptionAlgorithm->getRemoteBlockSize = |
| 112157 | (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic256; |
| 112158 | asym_encryptionAlgorithm->getRemotePlainTextBlockSize = |
| 112159 | (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic256; |
| 112160 | |
| 112161 | asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic256; |
| 112162 | asymmetricModule->compareCertificateThumbprint = |
| 112163 | asymmetricModule_compareCertificateThumbprint_sp_basic256; |
| 112164 | |
| 112165 | /* SymmetricModule */ |
| 112166 | symmetricModule->generateKey = sym_generateKey_sp_basic256; |
| 112167 | symmetricModule->generateNonce = sym_generateNonce_sp_basic256; |
| 112168 | |
| 112169 | UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm = |
| 112170 | &symmetricModule->cryptoModule.signatureAlgorithm; |
| 112171 | sym_signatureAlgorithm->uri = |
| 112172 | UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0"); |
| 112173 | sym_signatureAlgorithm->verify = |
| 112174 | (UA_StatusCode (*)(void *, const UA_ByteString *, |
| 112175 | const UA_ByteString *))sym_verify_sp_basic256; |
| 112176 | sym_signatureAlgorithm->sign = |
| 112177 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic256; |
| 112178 | sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic256; |
| 112179 | sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic256; |
| 112180 | sym_signatureAlgorithm->getLocalKeyLength = |
| 112181 | (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256; |
| 112182 | sym_signatureAlgorithm->getRemoteKeyLength = |
| 112183 | (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256; |
| 112184 | |
| 112185 | UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm = |
| 112186 | &symmetricModule->cryptoModule.encryptionAlgorithm; |
| 112187 | sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc\0"); |
| 112188 | sym_encryptionAlgorithm->encrypt = |
| 112189 | (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic256; |
| 112190 | sym_encryptionAlgorithm->decrypt = |
| 112191 | (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic256; |
| 112192 | sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic256; |
| 112193 | sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic256; |
| 112194 | sym_encryptionAlgorithm->getRemoteBlockSize = |
| 112195 | (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic256; |
| 112196 | sym_encryptionAlgorithm->getRemotePlainTextBlockSize = |
| 112197 | (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic256; |
| 112198 | symmetricModule->secureChannelNonceLength = 32; |
| 112199 | |
| 112200 | // Use the same signature algorithm as the asymmetric component for certificate signing (see standard) |
| 112201 | policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 112202 | |
| 112203 | /* ChannelModule */ |
| 112204 | channelModule->newContext = channelContext_newContext_sp_basic256; |
| 112205 | channelModule->deleteContext = (void (*)(void *)) |
| 112206 | channelContext_deleteContext_sp_basic256; |
| 112207 | |
| 112208 | channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 112209 | channelContext_setLocalSymEncryptingKey_sp_basic256; |
| 112210 | channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 112211 | channelContext_setLocalSymSigningKey_sp_basic256; |
| 112212 | channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 112213 | channelContext_setLocalSymIv_sp_basic256; |
| 112214 | |
| 112215 | channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 112216 | channelContext_setRemoteSymEncryptingKey_sp_basic256; |
| 112217 | channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 112218 | channelContext_setRemoteSymSigningKey_sp_basic256; |
| 112219 | channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 112220 | channelContext_setRemoteSymIv_sp_basic256; |
| 112221 | |
| 112222 | channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *)) |
| 112223 | channelContext_compareCertificate_sp_basic256; |
| 112224 | |
| 112225 | policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic256; |
| 112226 | policy->clear = clear_sp_basic256; |
| 112227 | |
| 112228 | UA_StatusCode res = policyContext_newContext_sp_basic256(policy, localPrivateKey); |
| 112229 | if(res != UA_STATUSCODE_GOOD) |
| 112230 | clear_sp_basic256(policy); |
| 112231 | |
| 112232 | return res; |
| 112233 | } |
| 112234 | |
| 112235 | #endif |
| 112236 | |
| 112237 | /**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_basic256sha256.c" ****/ |
| 112238 | |
| 112239 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 112240 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 112241 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 112242 | * |
| 112243 | * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB |
| 112244 | * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG |
| 112245 | * Copyright 2018 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 112246 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 112247 | * Copyright 2020 (c) basysKom GmbH |
| 112248 | */ |
| 112249 | |
| 112250 | |
| 112251 | #ifdef UA_ENABLE_ENCRYPTION_MBEDTLS |
| 112252 | |
| 112253 | |
| 112254 | #include <mbedtls/aes.h> |
| 112255 | #include <mbedtls/ctr_drbg.h> |
| 112256 | #include <mbedtls/entropy.h> |
| 112257 | #include <mbedtls/error.h> |
| 112258 | #include <mbedtls/md.h> |
| 112259 | #include <mbedtls/sha1.h> |
| 112260 | #include <mbedtls/sha256.h> |
| 112261 | #include <mbedtls/version.h> |
| 112262 | #include <mbedtls/x509_crt.h> |
| 112263 | |
| 112264 | /* Notes: |
| 112265 | * mbedTLS' AES allows in-place encryption and decryption. Sow we don't have to |
| 112266 | * allocate temp buffers. |
| 112267 | * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer |
| 112268 | */ |
| 112269 | |
| 112270 | #define UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN 42 |
| 112271 | #define UA_SHA1_LENGTH 20 |
| 112272 | #define UA_SHA256_LENGTH 32 |
| 112273 | #define UA_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH 32 |
| 112274 | #define UA_SECURITYPOLICY_BASIC256SHA256_SYM_KEY_LENGTH 32 |
| 112275 | #define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE 16 |
| 112276 | #define UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE 16 |
| 112277 | #define UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH 256 |
| 112278 | #define UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH 512 |
| 112279 | |
| 112280 | typedef struct { |
| 112281 | UA_ByteString localCertThumbprint; |
| 112282 | |
| 112283 | mbedtls_ctr_drbg_context drbgContext; |
| 112284 | mbedtls_entropy_context entropyContext; |
| 112285 | mbedtls_md_context_t sha256MdContext; |
| 112286 | mbedtls_pk_context localPrivateKey; |
| 112287 | } Basic256Sha256_PolicyContext; |
| 112288 | |
| 112289 | typedef struct { |
| 112290 | Basic256Sha256_PolicyContext *policyContext; |
| 112291 | |
| 112292 | UA_ByteString localSymSigningKey; |
| 112293 | UA_ByteString localSymEncryptingKey; |
| 112294 | UA_ByteString localSymIv; |
| 112295 | |
| 112296 | UA_ByteString remoteSymSigningKey; |
| 112297 | UA_ByteString remoteSymEncryptingKey; |
| 112298 | UA_ByteString remoteSymIv; |
| 112299 | |
| 112300 | mbedtls_x509_crt remoteCertificate; |
| 112301 | } Basic256Sha256_ChannelContext; |
| 112302 | |
| 112303 | /********************/ |
| 112304 | /* AsymmetricModule */ |
| 112305 | /********************/ |
| 112306 | |
| 112307 | /* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */ |
| 112308 | static UA_StatusCode |
| 112309 | asym_verify_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112310 | const UA_ByteString *message, |
| 112311 | const UA_ByteString *signature) { |
| 112312 | if(message == NULL || signature == NULL || cc == NULL) |
| 112313 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112314 | |
| 112315 | unsigned char hash[UA_SHA256_LENGTH]; |
| 112316 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 112317 | // TODO check return status |
| 112318 | mbedtls_sha256_ret(message->data, message->length, hash, 0); |
| 112319 | #else |
| 112320 | mbedtls_sha256(message->data, message->length, hash, 0); |
| 112321 | #endif |
| 112322 | |
| 112323 | /* Set the RSA settings */ |
| 112324 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 112325 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256); |
| 112326 | |
| 112327 | /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_verify() */ |
| 112328 | /* Alternatively, use more specific function mbedtls_rsa_rsassa_pkcs1_v15_verify(), i.e. */ |
| 112329 | /* int mbedErr = mbedtls_rsa_rsassa_pkcs1_v15_verify(rsaContext, NULL, NULL, |
| 112330 | MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, |
| 112331 | UA_SHA256_LENGTH, hash, |
| 112332 | signature->data); */ |
| 112333 | int mbedErr = mbedtls_pk_verify(&cc->remoteCertificate.pk, |
| 112334 | MBEDTLS_MD_SHA256, hash, UA_SHA256_LENGTH, |
| 112335 | signature->data, signature->length); |
| 112336 | |
| 112337 | if(mbedErr) |
| 112338 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112339 | return UA_STATUSCODE_GOOD; |
| 112340 | } |
| 112341 | |
| 112342 | /* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */ |
| 112343 | static UA_StatusCode |
| 112344 | asym_sign_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112345 | const UA_ByteString *message, |
| 112346 | UA_ByteString *signature) { |
| 112347 | if(message == NULL || signature == NULL || cc == NULL) |
| 112348 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112349 | |
| 112350 | unsigned char hash[UA_SHA256_LENGTH]; |
| 112351 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 112352 | // TODO check return status |
| 112353 | mbedtls_sha256_ret(message->data, message->length, hash, 0); |
| 112354 | #else |
| 112355 | mbedtls_sha256(message->data, message->length, hash, 0); |
| 112356 | #endif |
| 112357 | |
| 112358 | Basic256Sha256_PolicyContext *pc = cc->policyContext; |
| 112359 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey); |
| 112360 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256); |
| 112361 | |
| 112362 | size_t sigLen = 0; |
| 112363 | |
| 112364 | /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_sign */ |
| 112365 | /* Alternatively use more specific function mbedtls_rsa_rsassa_pkcs1_v15_sign() */ |
| 112366 | int mbedErr = mbedtls_pk_sign(&pc->localPrivateKey, |
| 112367 | MBEDTLS_MD_SHA256, hash, |
| 112368 | UA_SHA256_LENGTH, signature->data, |
| 112369 | #if MBEDTLS_VERSION_NUMBER >= 0x03000000 |
| 112370 | signature->length, |
| 112371 | #endif |
| 112372 | &sigLen, mbedtls_ctr_drbg_random, |
| 112373 | &pc->drbgContext); |
| 112374 | if(mbedErr) |
| 112375 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112376 | return UA_STATUSCODE_GOOD; |
| 112377 | } |
| 112378 | |
| 112379 | static size_t |
| 112380 | asym_getLocalSignatureSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) { |
| 112381 | if(cc == NULL) |
| 112382 | return 0; |
| 112383 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 112384 | return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len; |
| 112385 | #else |
| 112386 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey)); |
| 112387 | #endif |
| 112388 | } |
| 112389 | |
| 112390 | static size_t |
| 112391 | asym_getRemoteSignatureSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) { |
| 112392 | if(cc == NULL) |
| 112393 | return 0; |
| 112394 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 112395 | return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len; |
| 112396 | #else |
| 112397 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 112398 | #endif |
| 112399 | } |
| 112400 | |
| 112401 | static size_t |
| 112402 | asym_getRemoteBlockSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) { |
| 112403 | if(cc == NULL) |
| 112404 | return 0; |
| 112405 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 112406 | mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 112407 | return rsaContext->len; |
| 112408 | #else |
| 112409 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 112410 | #endif |
| 112411 | } |
| 112412 | |
| 112413 | static size_t |
| 112414 | asym_getRemotePlainTextBlockSize_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) { |
| 112415 | if(cc == NULL) |
| 112416 | return 0; |
| 112417 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 112418 | mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 112419 | return rsaContext->len - UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN; |
| 112420 | #else |
| 112421 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) - |
| 112422 | UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN; |
| 112423 | #endif |
| 112424 | } |
| 112425 | |
| 112426 | |
| 112427 | /* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */ |
| 112428 | static UA_StatusCode |
| 112429 | asym_encrypt_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112430 | UA_ByteString *data) { |
| 112431 | if(cc == NULL || data == NULL) |
| 112432 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112433 | |
| 112434 | const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_basic256sha256(cc); |
| 112435 | |
| 112436 | mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 112437 | mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1); |
| 112438 | |
| 112439 | return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext, |
| 112440 | data, plainTextBlockSize); |
| 112441 | } |
| 112442 | |
| 112443 | /* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */ |
| 112444 | static UA_StatusCode |
| 112445 | asym_decrypt_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112446 | UA_ByteString *data) { |
| 112447 | if(cc == NULL || data == NULL) |
| 112448 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112449 | return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey, |
| 112450 | &cc->policyContext->drbgContext, data, MBEDTLS_MD_SHA1); |
| 112451 | } |
| 112452 | |
| 112453 | static size_t |
| 112454 | asym_getLocalEncryptionKeyLength_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) { |
| 112455 | return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8; |
| 112456 | } |
| 112457 | |
| 112458 | static size_t |
| 112459 | asym_getRemoteEncryptionKeyLength_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc) { |
| 112460 | return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8; |
| 112461 | } |
| 112462 | |
| 112463 | static UA_StatusCode |
| 112464 | asym_makeThumbprint_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy, |
| 112465 | const UA_ByteString *certificate, |
| 112466 | UA_ByteString *thumbprint) { |
| 112467 | if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL) |
| 112468 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112469 | return mbedtls_thumbprint_sha1(certificate, thumbprint); |
| 112470 | } |
| 112471 | |
| 112472 | static UA_StatusCode |
| 112473 | asymmetricModule_compareCertificateThumbprint_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy, |
| 112474 | const UA_ByteString *certificateThumbprint) { |
| 112475 | if(securityPolicy == NULL || certificateThumbprint == NULL) |
| 112476 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112477 | |
| 112478 | Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)securityPolicy->policyContext; |
| 112479 | if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint)) |
| 112480 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 112481 | |
| 112482 | return UA_STATUSCODE_GOOD; |
| 112483 | } |
| 112484 | |
| 112485 | /*******************/ |
| 112486 | /* SymmetricModule */ |
| 112487 | /*******************/ |
| 112488 | |
| 112489 | static UA_StatusCode |
| 112490 | sym_verify_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112491 | const UA_ByteString *message, |
| 112492 | const UA_ByteString *signature) { |
| 112493 | if(cc == NULL || message == NULL || signature == NULL) |
| 112494 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112495 | |
| 112496 | /* Compute MAC */ |
| 112497 | if(signature->length != UA_SHA256_LENGTH) |
| 112498 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112499 | |
| 112500 | Basic256Sha256_PolicyContext *pc = cc->policyContext; |
| 112501 | unsigned char mac[UA_SHA256_LENGTH]; |
| 112502 | mbedtls_hmac(&pc->sha256MdContext, &cc->remoteSymSigningKey, message, mac); |
| 112503 | |
| 112504 | /* Compare with Signature */ |
| 112505 | if(!UA_constantTimeEqual(signature->data, mac, UA_SHA256_LENGTH)) |
| 112506 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112507 | return UA_STATUSCODE_GOOD; |
| 112508 | } |
| 112509 | |
| 112510 | static UA_StatusCode |
| 112511 | sym_sign_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc, |
| 112512 | const UA_ByteString *message, |
| 112513 | UA_ByteString *signature) { |
| 112514 | if(signature->length != UA_SHA256_LENGTH) |
| 112515 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112516 | |
| 112517 | mbedtls_hmac(&cc->policyContext->sha256MdContext, &cc->localSymSigningKey, |
| 112518 | message, signature->data); |
| 112519 | return UA_STATUSCODE_GOOD; |
| 112520 | } |
| 112521 | |
| 112522 | static size_t |
| 112523 | sym_getSignatureSize_sp_basic256sha256(const void *channelContext) { |
| 112524 | return UA_SHA256_LENGTH; |
| 112525 | } |
| 112526 | |
| 112527 | static size_t |
| 112528 | sym_getSigningKeyLength_sp_basic256sha256(const void *channelContext) { |
| 112529 | return UA_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH; |
| 112530 | } |
| 112531 | |
| 112532 | static size_t |
| 112533 | sym_getEncryptionKeyLength_sp_basic256sha256(const void *channelContext) { |
| 112534 | return UA_SECURITYPOLICY_BASIC256SHA256_SYM_KEY_LENGTH; |
| 112535 | } |
| 112536 | |
| 112537 | static size_t |
| 112538 | sym_getEncryptionBlockSize_sp_basic256sha256(const void *channelContext) { |
| 112539 | return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE; |
| 112540 | } |
| 112541 | |
| 112542 | static size_t |
| 112543 | sym_getPlainTextBlockSize_sp_basic256sha256(const void *channelContext) { |
| 112544 | return UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE; |
| 112545 | } |
| 112546 | |
| 112547 | static UA_StatusCode |
| 112548 | sym_encrypt_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc, |
| 112549 | UA_ByteString *data) { |
| 112550 | if(cc == NULL || data == NULL) |
| 112551 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112552 | |
| 112553 | if(cc->localSymIv.length != UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE) |
| 112554 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112555 | |
| 112556 | size_t plainTextBlockSize = UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE; |
| 112557 | |
| 112558 | if(data->length % plainTextBlockSize != 0) |
| 112559 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112560 | |
| 112561 | /* Keylength in bits */ |
| 112562 | unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8); |
| 112563 | mbedtls_aes_context aesContext; |
| 112564 | int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength); |
| 112565 | if(mbedErr) |
| 112566 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112567 | |
| 112568 | UA_ByteString ivCopy; |
| 112569 | UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy); |
| 112570 | if(retval != UA_STATUSCODE_GOOD) |
| 112571 | return retval; |
| 112572 | |
| 112573 | mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length, |
| 112574 | ivCopy.data, data->data, data->data); |
| 112575 | if(mbedErr) |
| 112576 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 112577 | UA_ByteString_clear(&ivCopy); |
| 112578 | return retval; |
| 112579 | } |
| 112580 | |
| 112581 | static UA_StatusCode |
| 112582 | sym_decrypt_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc, |
| 112583 | UA_ByteString *data) { |
| 112584 | if(cc == NULL || data == NULL) |
| 112585 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112586 | |
| 112587 | size_t encryptionBlockSize = UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE; |
| 112588 | if(cc->remoteSymIv.length != encryptionBlockSize) |
| 112589 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112590 | |
| 112591 | if(data->length % encryptionBlockSize != 0) |
| 112592 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112593 | |
| 112594 | unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8); |
| 112595 | mbedtls_aes_context aesContext; |
| 112596 | int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength); |
| 112597 | if(mbedErr) |
| 112598 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112599 | |
| 112600 | UA_ByteString ivCopy; |
| 112601 | UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy); |
| 112602 | if(retval != UA_STATUSCODE_GOOD) |
| 112603 | return retval; |
| 112604 | |
| 112605 | mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length, |
| 112606 | ivCopy.data, data->data, data->data); |
| 112607 | if(mbedErr) |
| 112608 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 112609 | UA_ByteString_clear(&ivCopy); |
| 112610 | return retval; |
| 112611 | } |
| 112612 | |
| 112613 | static UA_StatusCode |
| 112614 | sym_generateKey_sp_basic256sha256(void *policyContext, const UA_ByteString *secret, |
| 112615 | const UA_ByteString *seed, UA_ByteString *out) { |
| 112616 | if(secret == NULL || seed == NULL || out == NULL) |
| 112617 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112618 | Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)policyContext; |
| 112619 | return mbedtls_generateKey(&pc->sha256MdContext, secret, seed, out); |
| 112620 | } |
| 112621 | |
| 112622 | static UA_StatusCode |
| 112623 | sym_generateNonce_sp_basic256sha256(void *policyContext, UA_ByteString *out) { |
| 112624 | if(out == NULL) |
| 112625 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112626 | Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *)policyContext; |
| 112627 | int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length); |
| 112628 | if(mbedErr) |
| 112629 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 112630 | return UA_STATUSCODE_GOOD; |
| 112631 | } |
| 112632 | |
| 112633 | /*****************/ |
| 112634 | /* ChannelModule */ |
| 112635 | /*****************/ |
| 112636 | |
| 112637 | /* Assumes that the certificate has been verified externally */ |
| 112638 | static UA_StatusCode |
| 112639 | parseRemoteCertificate_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112640 | const UA_ByteString *remoteCertificate) { |
| 112641 | if(remoteCertificate == NULL || cc == NULL) |
| 112642 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112643 | |
| 112644 | /* Parse the certificate */ |
| 112645 | int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data, |
| 112646 | remoteCertificate->length); |
| 112647 | if(mbedErr) |
| 112648 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112649 | |
| 112650 | /* Check the key length */ |
| 112651 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 112652 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 112653 | size_t keylen = rsaContext->len; |
| 112654 | #else |
| 112655 | size_t keylen = mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 112656 | #endif |
| 112657 | if(keylen < UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH || |
| 112658 | keylen > UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH) |
| 112659 | return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; |
| 112660 | |
| 112661 | return UA_STATUSCODE_GOOD; |
| 112662 | } |
| 112663 | |
| 112664 | static void |
| 112665 | channelContext_deleteContext_sp_basic256sha256(Basic256Sha256_ChannelContext *cc) { |
| 112666 | UA_ByteString_clear(&cc->localSymSigningKey); |
| 112667 | UA_ByteString_clear(&cc->localSymEncryptingKey); |
| 112668 | UA_ByteString_clear(&cc->localSymIv); |
| 112669 | |
| 112670 | UA_ByteString_clear(&cc->remoteSymSigningKey); |
| 112671 | UA_ByteString_clear(&cc->remoteSymEncryptingKey); |
| 112672 | UA_ByteString_clear(&cc->remoteSymIv); |
| 112673 | |
| 112674 | mbedtls_x509_crt_free(&cc->remoteCertificate); |
| 112675 | |
| 112676 | UA_free(cc); |
| 112677 | } |
| 112678 | |
| 112679 | static UA_StatusCode |
| 112680 | channelContext_newContext_sp_basic256sha256(const UA_SecurityPolicy *securityPolicy, |
| 112681 | const UA_ByteString *remoteCertificate, |
| 112682 | void **pp_contextData) { |
| 112683 | if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL) |
| 112684 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112685 | |
| 112686 | /* Allocate the channel context */ |
| 112687 | *pp_contextData = UA_malloc(sizeof(Basic256Sha256_ChannelContext)); |
| 112688 | if(*pp_contextData == NULL) |
| 112689 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 112690 | |
| 112691 | Basic256Sha256_ChannelContext *cc = (Basic256Sha256_ChannelContext *)*pp_contextData; |
| 112692 | |
| 112693 | /* Initialize the channel context */ |
| 112694 | cc->policyContext = (Basic256Sha256_PolicyContext *)securityPolicy->policyContext; |
| 112695 | |
| 112696 | UA_ByteString_init(&cc->localSymSigningKey); |
| 112697 | UA_ByteString_init(&cc->localSymEncryptingKey); |
| 112698 | UA_ByteString_init(&cc->localSymIv); |
| 112699 | |
| 112700 | UA_ByteString_init(&cc->remoteSymSigningKey); |
| 112701 | UA_ByteString_init(&cc->remoteSymEncryptingKey); |
| 112702 | UA_ByteString_init(&cc->remoteSymIv); |
| 112703 | |
| 112704 | mbedtls_x509_crt_init(&cc->remoteCertificate); |
| 112705 | |
| 112706 | // TODO: this can be optimized so that we dont allocate memory before parsing the certificate |
| 112707 | UA_StatusCode retval = parseRemoteCertificate_sp_basic256sha256(cc, remoteCertificate); |
| 112708 | if(retval != UA_STATUSCODE_GOOD) { |
| 112709 | channelContext_deleteContext_sp_basic256sha256(cc); |
| 112710 | *pp_contextData = NULL; |
| 112711 | } |
| 112712 | return retval; |
| 112713 | } |
| 112714 | |
| 112715 | static UA_StatusCode |
| 112716 | channelContext_setLocalSymEncryptingKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112717 | const UA_ByteString *key) { |
| 112718 | if(key == NULL || cc == NULL) |
| 112719 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112720 | |
| 112721 | UA_ByteString_clear(&cc->localSymEncryptingKey); |
| 112722 | return UA_ByteString_copy(key, &cc->localSymEncryptingKey); |
| 112723 | } |
| 112724 | |
| 112725 | static UA_StatusCode |
| 112726 | channelContext_setLocalSymSigningKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112727 | const UA_ByteString *key) { |
| 112728 | if(key == NULL || cc == NULL) |
| 112729 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112730 | |
| 112731 | UA_ByteString_clear(&cc->localSymSigningKey); |
| 112732 | return UA_ByteString_copy(key, &cc->localSymSigningKey); |
| 112733 | } |
| 112734 | |
| 112735 | |
| 112736 | static UA_StatusCode |
| 112737 | channelContext_setLocalSymIv_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112738 | const UA_ByteString *iv) { |
| 112739 | if(iv == NULL || cc == NULL) |
| 112740 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112741 | |
| 112742 | UA_ByteString_clear(&cc->localSymIv); |
| 112743 | return UA_ByteString_copy(iv, &cc->localSymIv); |
| 112744 | } |
| 112745 | |
| 112746 | static UA_StatusCode |
| 112747 | channelContext_setRemoteSymEncryptingKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112748 | const UA_ByteString *key) { |
| 112749 | if(key == NULL || cc == NULL) |
| 112750 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112751 | |
| 112752 | UA_ByteString_clear(&cc->remoteSymEncryptingKey); |
| 112753 | return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey); |
| 112754 | } |
| 112755 | |
| 112756 | static UA_StatusCode |
| 112757 | channelContext_setRemoteSymSigningKey_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112758 | const UA_ByteString *key) { |
| 112759 | if(key == NULL || cc == NULL) |
| 112760 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112761 | |
| 112762 | UA_ByteString_clear(&cc->remoteSymSigningKey); |
| 112763 | return UA_ByteString_copy(key, &cc->remoteSymSigningKey); |
| 112764 | } |
| 112765 | |
| 112766 | static UA_StatusCode |
| 112767 | channelContext_setRemoteSymIv_sp_basic256sha256(Basic256Sha256_ChannelContext *cc, |
| 112768 | const UA_ByteString *iv) { |
| 112769 | if(iv == NULL || cc == NULL) |
| 112770 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112771 | |
| 112772 | UA_ByteString_clear(&cc->remoteSymIv); |
| 112773 | return UA_ByteString_copy(iv, &cc->remoteSymIv); |
| 112774 | } |
| 112775 | |
| 112776 | static UA_StatusCode |
| 112777 | channelContext_compareCertificate_sp_basic256sha256(const Basic256Sha256_ChannelContext *cc, |
| 112778 | const UA_ByteString *certificate) { |
| 112779 | if(cc == NULL || certificate == NULL) |
| 112780 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112781 | |
| 112782 | mbedtls_x509_crt cert; |
| 112783 | mbedtls_x509_crt_init(&cert); |
| 112784 | int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length); |
| 112785 | if(mbedErr) |
| 112786 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112787 | |
| 112788 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 112789 | if(cert.raw.len != cc->remoteCertificate.raw.len || |
| 112790 | memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0) |
| 112791 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112792 | |
| 112793 | mbedtls_x509_crt_free(&cert); |
| 112794 | return retval; |
| 112795 | } |
| 112796 | |
| 112797 | static void |
| 112798 | clear_sp_basic256sha256(UA_SecurityPolicy *securityPolicy) { |
| 112799 | if(securityPolicy == NULL) |
| 112800 | return; |
| 112801 | |
| 112802 | UA_ByteString_clear(&securityPolicy->localCertificate); |
| 112803 | |
| 112804 | if(securityPolicy->policyContext == NULL) |
| 112805 | return; |
| 112806 | |
| 112807 | /* delete all allocated members in the context */ |
| 112808 | Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *) |
| 112809 | securityPolicy->policyContext; |
| 112810 | |
| 112811 | mbedtls_ctr_drbg_free(&pc->drbgContext); |
| 112812 | mbedtls_entropy_free(&pc->entropyContext); |
| 112813 | mbedtls_pk_free(&pc->localPrivateKey); |
| 112814 | mbedtls_md_free(&pc->sha256MdContext); |
| 112815 | UA_ByteString_clear(&pc->localCertThumbprint); |
| 112816 | |
| 112817 | UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 112818 | "Deleted members of EndpointContext for sp_basic256sha256"); |
| 112819 | |
| 112820 | UA_free(pc); |
| 112821 | securityPolicy->policyContext = NULL; |
| 112822 | } |
| 112823 | |
| 112824 | static UA_StatusCode |
| 112825 | updateCertificateAndPrivateKey_sp_basic256sha256(UA_SecurityPolicy *securityPolicy, |
| 112826 | const UA_ByteString newCertificate, |
| 112827 | const UA_ByteString newPrivateKey) { |
| 112828 | if(securityPolicy == NULL) |
| 112829 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112830 | |
| 112831 | if(securityPolicy->policyContext == NULL) |
| 112832 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112833 | |
| 112834 | Basic256Sha256_PolicyContext *pc = |
| 112835 | (Basic256Sha256_PolicyContext *) securityPolicy->policyContext; |
| 112836 | |
| 112837 | UA_ByteString_clear(&securityPolicy->localCertificate); |
| 112838 | |
| 112839 | UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate); |
| 112840 | |
| 112841 | if (retval != UA_STATUSCODE_GOOD) |
| 112842 | return retval; |
| 112843 | |
| 112844 | /* Set the new private key */ |
| 112845 | mbedtls_pk_free(&pc->localPrivateKey); |
| 112846 | mbedtls_pk_init(&pc->localPrivateKey); |
| 112847 | int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext); |
| 112848 | if(mbedErr) { |
| 112849 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112850 | goto error; |
| 112851 | } |
| 112852 | |
| 112853 | retval = asym_makeThumbprint_sp_basic256sha256(securityPolicy, |
| 112854 | &securityPolicy->localCertificate, |
| 112855 | &pc->localCertThumbprint); |
| 112856 | if(retval != UA_STATUSCODE_GOOD) |
| 112857 | goto error; |
| 112858 | |
| 112859 | return retval; |
| 112860 | |
| 112861 | error: |
| 112862 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 112863 | "Could not update certificate and private key"); |
| 112864 | if(securityPolicy->policyContext != NULL) |
| 112865 | clear_sp_basic256sha256(securityPolicy); |
| 112866 | return retval; |
| 112867 | } |
| 112868 | |
| 112869 | static UA_StatusCode |
| 112870 | policyContext_newContext_sp_basic256sha256(UA_SecurityPolicy *securityPolicy, |
| 112871 | const UA_ByteString localPrivateKey) { |
| 112872 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 112873 | if(securityPolicy == NULL) |
| 112874 | return UA_STATUSCODE_BADINTERNALERROR; |
| 112875 | |
| 112876 | if (localPrivateKey.length == 0) { |
| 112877 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 112878 | "Can not initialize security policy. Private key is empty."); |
| 112879 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 112880 | } |
| 112881 | |
| 112882 | Basic256Sha256_PolicyContext *pc = (Basic256Sha256_PolicyContext *) |
| 112883 | UA_malloc(sizeof(Basic256Sha256_PolicyContext)); |
| 112884 | securityPolicy->policyContext = (void *)pc; |
| 112885 | if(!pc) { |
| 112886 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 112887 | goto error; |
| 112888 | } |
| 112889 | |
| 112890 | /* Initialize the PolicyContext */ |
| 112891 | memset(pc, 0, sizeof(Basic256Sha256_PolicyContext)); |
| 112892 | mbedtls_ctr_drbg_init(&pc->drbgContext); |
| 112893 | mbedtls_entropy_init(&pc->entropyContext); |
| 112894 | mbedtls_pk_init(&pc->localPrivateKey); |
| 112895 | mbedtls_md_init(&pc->sha256MdContext); |
| 112896 | |
| 112897 | /* Initialized the message digest */ |
| 112898 | const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); |
| 112899 | int mbedErr = mbedtls_md_setup(&pc->sha256MdContext, mdInfo, MBEDTLS_MD_SHA256); |
| 112900 | if(mbedErr) { |
| 112901 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 112902 | goto error; |
| 112903 | } |
| 112904 | |
| 112905 | mbedErr = mbedtls_entropy_self_test(0); |
| 112906 | |
| 112907 | if(mbedErr) { |
| 112908 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112909 | goto error; |
| 112910 | } |
| 112911 | |
| 112912 | /* Seed the RNG */ |
| 112913 | char *personalization = "open62541-drbg"; |
| 112914 | mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func, |
| 112915 | &pc->entropyContext, |
| 112916 | (const unsigned char *)personalization, 14); |
| 112917 | if(mbedErr) { |
| 112918 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112919 | goto error; |
| 112920 | } |
| 112921 | |
| 112922 | /* Set the private key */ |
| 112923 | mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext); |
| 112924 | if(mbedErr) { |
| 112925 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 112926 | goto error; |
| 112927 | } |
| 112928 | |
| 112929 | /* Set the local certificate thumbprint */ |
| 112930 | retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH); |
| 112931 | if(retval != UA_STATUSCODE_GOOD) |
| 112932 | goto error; |
| 112933 | retval = asym_makeThumbprint_sp_basic256sha256(securityPolicy, |
| 112934 | &securityPolicy->localCertificate, |
| 112935 | &pc->localCertThumbprint); |
| 112936 | if(retval != UA_STATUSCODE_GOOD) |
| 112937 | goto error; |
| 112938 | |
| 112939 | return UA_STATUSCODE_GOOD; |
| 112940 | |
| 112941 | error: |
| 112942 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 112943 | "Could not create securityContext: %s", UA_StatusCode_name(retval)); |
| 112944 | if(securityPolicy->policyContext != NULL) |
| 112945 | clear_sp_basic256sha256(securityPolicy); |
| 112946 | return retval; |
| 112947 | } |
| 112948 | |
| 112949 | UA_StatusCode |
| 112950 | UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy, const UA_ByteString localCertificate, |
| 112951 | const UA_ByteString localPrivateKey, const UA_Logger *logger) { |
| 112952 | memset(policy, 0, sizeof(UA_SecurityPolicy)); |
| 112953 | policy->logger = logger; |
| 112954 | |
| 112955 | policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"); |
| 112956 | |
| 112957 | UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule; |
| 112958 | UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule; |
| 112959 | UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule; |
| 112960 | |
| 112961 | UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate); |
| 112962 | |
| 112963 | if (retval != UA_STATUSCODE_GOOD) |
| 112964 | return retval; |
| 112965 | |
| 112966 | /* AsymmetricModule */ |
| 112967 | UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm = |
| 112968 | &asymmetricModule->cryptoModule.signatureAlgorithm; |
| 112969 | asym_signatureAlgorithm->uri = |
| 112970 | UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0"); |
| 112971 | asym_signatureAlgorithm->verify = |
| 112972 | (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_basic256sha256; |
| 112973 | asym_signatureAlgorithm->sign = |
| 112974 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_basic256sha256; |
| 112975 | asym_signatureAlgorithm->getLocalSignatureSize = |
| 112976 | (size_t (*)(const void *))asym_getLocalSignatureSize_sp_basic256sha256; |
| 112977 | asym_signatureAlgorithm->getRemoteSignatureSize = |
| 112978 | (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_basic256sha256; |
| 112979 | asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function |
| 112980 | asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function |
| 112981 | |
| 112982 | UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm = |
| 112983 | &asymmetricModule->cryptoModule.encryptionAlgorithm; |
| 112984 | asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0"); |
| 112985 | asym_encryptionAlgorithm->encrypt = |
| 112986 | (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_basic256sha256; |
| 112987 | asym_encryptionAlgorithm->decrypt = |
| 112988 | (UA_StatusCode(*)(void *, UA_ByteString *)) |
| 112989 | asym_decrypt_sp_basic256sha256; |
| 112990 | asym_encryptionAlgorithm->getLocalKeyLength = |
| 112991 | (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_basic256sha256; |
| 112992 | asym_encryptionAlgorithm->getRemoteKeyLength = |
| 112993 | (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_basic256sha256; |
| 112994 | asym_encryptionAlgorithm->getRemoteBlockSize = |
| 112995 | (size_t (*)(const void *))asym_getRemoteBlockSize_sp_basic256sha256; |
| 112996 | asym_encryptionAlgorithm->getRemotePlainTextBlockSize = |
| 112997 | (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_basic256sha256; |
| 112998 | |
| 112999 | asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_basic256sha256; |
| 113000 | asymmetricModule->compareCertificateThumbprint = |
| 113001 | asymmetricModule_compareCertificateThumbprint_sp_basic256sha256; |
| 113002 | |
| 113003 | /* SymmetricModule */ |
| 113004 | symmetricModule->generateKey = sym_generateKey_sp_basic256sha256; |
| 113005 | symmetricModule->generateNonce = sym_generateNonce_sp_basic256sha256; |
| 113006 | |
| 113007 | UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm = |
| 113008 | &symmetricModule->cryptoModule.signatureAlgorithm; |
| 113009 | sym_signatureAlgorithm->uri = |
| 113010 | UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0"); |
| 113011 | sym_signatureAlgorithm->verify = |
| 113012 | (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))sym_verify_sp_basic256sha256; |
| 113013 | sym_signatureAlgorithm->sign = |
| 113014 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_basic256sha256; |
| 113015 | sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_basic256sha256; |
| 113016 | sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_basic256sha256; |
| 113017 | sym_signatureAlgorithm->getLocalKeyLength = |
| 113018 | (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256sha256; |
| 113019 | sym_signatureAlgorithm->getRemoteKeyLength = |
| 113020 | (size_t (*)(const void *))sym_getSigningKeyLength_sp_basic256sha256; |
| 113021 | |
| 113022 | UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm = |
| 113023 | &symmetricModule->cryptoModule.encryptionAlgorithm; |
| 113024 | sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc"); |
| 113025 | sym_encryptionAlgorithm->encrypt = |
| 113026 | (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_basic256sha256; |
| 113027 | sym_encryptionAlgorithm->decrypt = |
| 113028 | (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_basic256sha256; |
| 113029 | sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_basic256sha256; |
| 113030 | sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_basic256sha256; |
| 113031 | sym_encryptionAlgorithm->getRemoteBlockSize = |
| 113032 | (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_basic256sha256; |
| 113033 | sym_encryptionAlgorithm->getRemotePlainTextBlockSize = |
| 113034 | (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_basic256sha256; |
| 113035 | symmetricModule->secureChannelNonceLength = 32; |
| 113036 | |
| 113037 | // Use the same signature algorithm as the asymmetric component for certificate signing (see standard) |
| 113038 | policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 113039 | |
| 113040 | /* ChannelModule */ |
| 113041 | channelModule->newContext = channelContext_newContext_sp_basic256sha256; |
| 113042 | channelModule->deleteContext = (void (*)(void *)) |
| 113043 | channelContext_deleteContext_sp_basic256sha256; |
| 113044 | |
| 113045 | channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113046 | channelContext_setLocalSymEncryptingKey_sp_basic256sha256; |
| 113047 | channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113048 | channelContext_setLocalSymSigningKey_sp_basic256sha256; |
| 113049 | channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113050 | channelContext_setLocalSymIv_sp_basic256sha256; |
| 113051 | |
| 113052 | channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113053 | channelContext_setRemoteSymEncryptingKey_sp_basic256sha256; |
| 113054 | channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113055 | channelContext_setRemoteSymSigningKey_sp_basic256sha256; |
| 113056 | channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113057 | channelContext_setRemoteSymIv_sp_basic256sha256; |
| 113058 | |
| 113059 | channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *)) |
| 113060 | channelContext_compareCertificate_sp_basic256sha256; |
| 113061 | |
| 113062 | policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic256sha256; |
| 113063 | policy->clear = clear_sp_basic256sha256; |
| 113064 | |
| 113065 | UA_StatusCode res = policyContext_newContext_sp_basic256sha256(policy, localPrivateKey); |
| 113066 | if(res != UA_STATUSCODE_GOOD) |
| 113067 | clear_sp_basic256sha256(policy); |
| 113068 | |
| 113069 | return res; |
| 113070 | } |
| 113071 | |
| 113072 | #endif |
| 113073 | |
| 113074 | /**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_aes128sha256rsaoaep.c" ****/ |
| 113075 | |
| 113076 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 113077 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 113078 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 113079 | * |
| 113080 | * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB |
| 113081 | * Copyright 2018 (c) Daniel Feist, Precitec GmbH & Co. KG |
| 113082 | * Copyright 2018 (c) HMS Industrial Networks AB (Author: Jonas Green) |
| 113083 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 113084 | */ |
| 113085 | |
| 113086 | |
| 113087 | #ifdef UA_ENABLE_ENCRYPTION_MBEDTLS |
| 113088 | |
| 113089 | |
| 113090 | #include <mbedtls/aes.h> |
| 113091 | #include <mbedtls/ctr_drbg.h> |
| 113092 | #include <mbedtls/entropy.h> |
| 113093 | #include <mbedtls/error.h> |
| 113094 | #include <mbedtls/md.h> |
| 113095 | #include <mbedtls/sha1.h> |
| 113096 | #include <mbedtls/sha256.h> |
| 113097 | #include <mbedtls/version.h> |
| 113098 | #include <mbedtls/x509_crt.h> |
| 113099 | |
| 113100 | /* Notes: |
| 113101 | * mbedTLS' AES allows in-place encryption and decryption. So we don't have to |
| 113102 | * allocate temp buffers. |
| 113103 | * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer |
| 113104 | */ |
| 113105 | |
| 113106 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN 42 |
| 113107 | #define UA_SHA1_LENGTH 20 |
| 113108 | #define UA_SHA256_LENGTH 32 |
| 113109 | #define UA_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH 32 |
| 113110 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_KEY_LENGTH 16 |
| 113111 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE 16 |
| 113112 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE 16 |
| 113113 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH 256 |
| 113114 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH 512 |
| 113115 | |
| 113116 | typedef struct { |
| 113117 | UA_ByteString localCertThumbprint; |
| 113118 | |
| 113119 | mbedtls_ctr_drbg_context drbgContext; |
| 113120 | mbedtls_entropy_context entropyContext; |
| 113121 | mbedtls_md_context_t sha256MdContext; |
| 113122 | mbedtls_pk_context localPrivateKey; |
| 113123 | } Aes128Sha256PsaOaep_PolicyContext; |
| 113124 | |
| 113125 | typedef struct { |
| 113126 | Aes128Sha256PsaOaep_PolicyContext *policyContext; |
| 113127 | |
| 113128 | UA_ByteString localSymSigningKey; |
| 113129 | UA_ByteString localSymEncryptingKey; |
| 113130 | UA_ByteString localSymIv; |
| 113131 | |
| 113132 | UA_ByteString remoteSymSigningKey; |
| 113133 | UA_ByteString remoteSymEncryptingKey; |
| 113134 | UA_ByteString remoteSymIv; |
| 113135 | |
| 113136 | mbedtls_x509_crt remoteCertificate; |
| 113137 | } Aes128Sha256PsaOaep_ChannelContext; |
| 113138 | |
| 113139 | /********************/ |
| 113140 | /* AsymmetricModule */ |
| 113141 | /********************/ |
| 113142 | |
| 113143 | /* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */ |
| 113144 | static UA_StatusCode |
| 113145 | asym_verify_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113146 | const UA_ByteString *message, |
| 113147 | const UA_ByteString *signature) { |
| 113148 | if(message == NULL || signature == NULL || cc == NULL) |
| 113149 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113150 | |
| 113151 | unsigned char hash[UA_SHA256_LENGTH]; |
| 113152 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 113153 | // TODO check return status |
| 113154 | mbedtls_sha256_ret(message->data, message->length, hash, 0); |
| 113155 | #else |
| 113156 | mbedtls_sha256(message->data, message->length, hash, 0); |
| 113157 | #endif |
| 113158 | |
| 113159 | /* Set the RSA settings */ |
| 113160 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 113161 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256); |
| 113162 | |
| 113163 | /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_verify() */ |
| 113164 | /* Alternatively, use more specific function mbedtls_rsa_rsassa_pkcs1_v15_verify(), i.e. */ |
| 113165 | /* int mbedErr = mbedtls_rsa_rsassa_pkcs1_v15_verify(rsaContext, NULL, NULL, |
| 113166 | MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, |
| 113167 | UA_SHA256_LENGTH, hash, |
| 113168 | signature->data); */ |
| 113169 | int mbedErr = mbedtls_pk_verify(&cc->remoteCertificate.pk, |
| 113170 | MBEDTLS_MD_SHA256, hash, UA_SHA256_LENGTH, |
| 113171 | signature->data, signature->length); |
| 113172 | |
| 113173 | if(mbedErr) |
| 113174 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 113175 | return UA_STATUSCODE_GOOD; |
| 113176 | } |
| 113177 | |
| 113178 | /* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */ |
| 113179 | static UA_StatusCode |
| 113180 | asym_sign_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113181 | const UA_ByteString *message, |
| 113182 | UA_ByteString *signature) { |
| 113183 | if(message == NULL || signature == NULL || cc == NULL) |
| 113184 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113185 | |
| 113186 | unsigned char hash[UA_SHA256_LENGTH]; |
| 113187 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 113188 | // TODO check return status |
| 113189 | mbedtls_sha256_ret(message->data, message->length, hash, 0); |
| 113190 | #else |
| 113191 | mbedtls_sha256(message->data, message->length, hash, 0); |
| 113192 | #endif |
| 113193 | |
| 113194 | Aes128Sha256PsaOaep_PolicyContext *pc = cc->policyContext; |
| 113195 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey); |
| 113196 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256); |
| 113197 | |
| 113198 | size_t sigLen = 0; |
| 113199 | |
| 113200 | /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_sign */ |
| 113201 | /* Alternatively use more specific function mbedtls_rsa_rsassa_pkcs1_v15_sign() */ |
| 113202 | int mbedErr = mbedtls_pk_sign(&pc->localPrivateKey, |
| 113203 | MBEDTLS_MD_SHA256, hash, |
| 113204 | UA_SHA256_LENGTH, signature->data, |
| 113205 | #if MBEDTLS_VERSION_NUMBER >= 0x03000000 |
| 113206 | signature->length, |
| 113207 | #endif |
| 113208 | &sigLen, mbedtls_ctr_drbg_random, |
| 113209 | &pc->drbgContext); |
| 113210 | if(mbedErr) |
| 113211 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113212 | return UA_STATUSCODE_GOOD; |
| 113213 | } |
| 113214 | |
| 113215 | static size_t |
| 113216 | asym_getLocalSignatureSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) { |
| 113217 | if(cc == NULL) |
| 113218 | return 0; |
| 113219 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 113220 | return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len; |
| 113221 | #else |
| 113222 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey)); |
| 113223 | #endif |
| 113224 | } |
| 113225 | |
| 113226 | static size_t |
| 113227 | asym_getRemoteSignatureSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) { |
| 113228 | if(cc == NULL) |
| 113229 | return 0; |
| 113230 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 113231 | return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len; |
| 113232 | #else |
| 113233 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 113234 | #endif |
| 113235 | } |
| 113236 | |
| 113237 | static size_t |
| 113238 | asym_getRemoteBlockSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) { |
| 113239 | if(cc == NULL) |
| 113240 | return 0; |
| 113241 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 113242 | return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len; |
| 113243 | #else |
| 113244 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 113245 | #endif |
| 113246 | } |
| 113247 | |
| 113248 | static size_t |
| 113249 | asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) { |
| 113250 | if(cc == NULL) |
| 113251 | return 0; |
| 113252 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 113253 | mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 113254 | return rsaContext->len - UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN; |
| 113255 | #else |
| 113256 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) - |
| 113257 | UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN; |
| 113258 | #endif |
| 113259 | } |
| 113260 | |
| 113261 | |
| 113262 | /* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */ |
| 113263 | static UA_StatusCode |
| 113264 | asym_encrypt_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113265 | UA_ByteString *data) { |
| 113266 | if(cc == NULL || data == NULL) |
| 113267 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113268 | |
| 113269 | const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep(cc); |
| 113270 | |
| 113271 | mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 113272 | mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA1); |
| 113273 | |
| 113274 | return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext, |
| 113275 | data, plainTextBlockSize); |
| 113276 | } |
| 113277 | |
| 113278 | /* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA1 */ |
| 113279 | static UA_StatusCode |
| 113280 | asym_decrypt_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113281 | UA_ByteString *data) { |
| 113282 | if(cc == NULL || data == NULL) |
| 113283 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113284 | return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey, |
| 113285 | &cc->policyContext->drbgContext, data, MBEDTLS_MD_SHA1); |
| 113286 | } |
| 113287 | |
| 113288 | static size_t |
| 113289 | asym_getLocalEncryptionKeyLength_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) { |
| 113290 | return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8; |
| 113291 | } |
| 113292 | |
| 113293 | static size_t |
| 113294 | asym_getRemoteEncryptionKeyLength_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc) { |
| 113295 | return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8; |
| 113296 | } |
| 113297 | |
| 113298 | static UA_StatusCode |
| 113299 | asym_makeThumbprint_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy, |
| 113300 | const UA_ByteString *certificate, |
| 113301 | UA_ByteString *thumbprint) { |
| 113302 | if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL) |
| 113303 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113304 | return mbedtls_thumbprint_sha1(certificate, thumbprint); |
| 113305 | } |
| 113306 | |
| 113307 | static UA_StatusCode |
| 113308 | asymmetricModule_compareCertificateThumbprint_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy, |
| 113309 | const UA_ByteString *certificateThumbprint) { |
| 113310 | if(securityPolicy == NULL || certificateThumbprint == NULL) |
| 113311 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113312 | |
| 113313 | Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)securityPolicy->policyContext; |
| 113314 | if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint)) |
| 113315 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 113316 | |
| 113317 | return UA_STATUSCODE_GOOD; |
| 113318 | } |
| 113319 | |
| 113320 | /*******************/ |
| 113321 | /* SymmetricModule */ |
| 113322 | /*******************/ |
| 113323 | |
| 113324 | static UA_StatusCode |
| 113325 | sym_verify_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113326 | const UA_ByteString *message, |
| 113327 | const UA_ByteString *signature) { |
| 113328 | if(cc == NULL || message == NULL || signature == NULL) |
| 113329 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113330 | |
| 113331 | /* Compute MAC */ |
| 113332 | if(signature->length != UA_SHA256_LENGTH) |
| 113333 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 113334 | Aes128Sha256PsaOaep_PolicyContext *pc = cc->policyContext; |
| 113335 | unsigned char mac[UA_SHA256_LENGTH]; |
| 113336 | mbedtls_hmac(&pc->sha256MdContext, &cc->remoteSymSigningKey, message, mac); |
| 113337 | |
| 113338 | /* Compare with Signature */ |
| 113339 | if(!UA_constantTimeEqual(signature->data, mac, UA_SHA256_LENGTH)) |
| 113340 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 113341 | return UA_STATUSCODE_GOOD; |
| 113342 | } |
| 113343 | |
| 113344 | static UA_StatusCode |
| 113345 | sym_sign_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113346 | const UA_ByteString *message, |
| 113347 | UA_ByteString *signature) { |
| 113348 | if(signature->length != UA_SHA256_LENGTH) |
| 113349 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113350 | |
| 113351 | mbedtls_hmac(&cc->policyContext->sha256MdContext, &cc->localSymSigningKey, |
| 113352 | message, signature->data); |
| 113353 | return UA_STATUSCODE_GOOD; |
| 113354 | } |
| 113355 | |
| 113356 | static size_t |
| 113357 | sym_getSignatureSize_sp_aes128sha256rsaoaep(const void *channelContext) { |
| 113358 | return UA_SHA256_LENGTH; |
| 113359 | } |
| 113360 | |
| 113361 | static size_t |
| 113362 | sym_getSigningKeyLength_sp_aes128sha256rsaoaep(const void *channelContext) { |
| 113363 | return UA_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH; |
| 113364 | } |
| 113365 | |
| 113366 | static size_t |
| 113367 | sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep(const void *channelContext) { |
| 113368 | return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_KEY_LENGTH; |
| 113369 | } |
| 113370 | |
| 113371 | static size_t |
| 113372 | sym_getEncryptionBlockSize_sp_aes128sha256rsaoaep(const void *channelContext) { |
| 113373 | return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE; |
| 113374 | } |
| 113375 | |
| 113376 | static size_t |
| 113377 | sym_getPlainTextBlockSize_sp_aes128sha256rsaoaep(const void *channelContext) { |
| 113378 | return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE; |
| 113379 | } |
| 113380 | |
| 113381 | static UA_StatusCode |
| 113382 | sym_encrypt_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113383 | UA_ByteString *data) { |
| 113384 | if(cc == NULL || data == NULL) |
| 113385 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113386 | |
| 113387 | if(cc->localSymIv.length != UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE) |
| 113388 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113389 | |
| 113390 | size_t plainTextBlockSize = UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE; |
| 113391 | |
| 113392 | if(data->length % plainTextBlockSize != 0) |
| 113393 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113394 | |
| 113395 | /* Keylength in bits */ |
| 113396 | unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8); |
| 113397 | mbedtls_aes_context aesContext; |
| 113398 | int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength); |
| 113399 | if(mbedErr) |
| 113400 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113401 | |
| 113402 | UA_ByteString ivCopy; |
| 113403 | UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy); |
| 113404 | if(retval != UA_STATUSCODE_GOOD) |
| 113405 | return retval; |
| 113406 | |
| 113407 | mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length, |
| 113408 | ivCopy.data, data->data, data->data); |
| 113409 | if(mbedErr) |
| 113410 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 113411 | UA_ByteString_clear(&ivCopy); |
| 113412 | return retval; |
| 113413 | } |
| 113414 | |
| 113415 | static UA_StatusCode |
| 113416 | sym_decrypt_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113417 | UA_ByteString *data) { |
| 113418 | if(cc == NULL || data == NULL) |
| 113419 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113420 | |
| 113421 | size_t encryptionBlockSize = UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE; |
| 113422 | |
| 113423 | if(cc->remoteSymIv.length != encryptionBlockSize) |
| 113424 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113425 | |
| 113426 | if(data->length % encryptionBlockSize != 0) |
| 113427 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113428 | |
| 113429 | unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8); |
| 113430 | mbedtls_aes_context aesContext; |
| 113431 | int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength); |
| 113432 | if(mbedErr) |
| 113433 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113434 | |
| 113435 | UA_ByteString ivCopy; |
| 113436 | UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy); |
| 113437 | if(retval != UA_STATUSCODE_GOOD) |
| 113438 | return retval; |
| 113439 | |
| 113440 | mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length, |
| 113441 | ivCopy.data, data->data, data->data); |
| 113442 | if(mbedErr) |
| 113443 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 113444 | UA_ByteString_clear(&ivCopy); |
| 113445 | return retval; |
| 113446 | } |
| 113447 | |
| 113448 | static UA_StatusCode |
| 113449 | sym_generateKey_sp_aes128sha256rsaoaep(void *policyContext, const UA_ByteString *secret, |
| 113450 | const UA_ByteString *seed, UA_ByteString *out) { |
| 113451 | if(secret == NULL || seed == NULL || out == NULL) |
| 113452 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113453 | Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *)policyContext; |
| 113454 | return mbedtls_generateKey(&pc->sha256MdContext, secret, seed, out); |
| 113455 | } |
| 113456 | |
| 113457 | static UA_StatusCode |
| 113458 | sym_generateNonce_sp_aes128sha256rsaoaep(void *policyContext, UA_ByteString *out) { |
| 113459 | if(out == NULL) |
| 113460 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113461 | Aes128Sha256PsaOaep_PolicyContext *pc = |
| 113462 | (Aes128Sha256PsaOaep_PolicyContext *)policyContext; |
| 113463 | int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length); |
| 113464 | if(mbedErr) |
| 113465 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 113466 | return UA_STATUSCODE_GOOD; |
| 113467 | } |
| 113468 | |
| 113469 | /*****************/ |
| 113470 | /* ChannelModule */ |
| 113471 | /*****************/ |
| 113472 | |
| 113473 | /* Assumes that the certificate has been verified externally */ |
| 113474 | static UA_StatusCode |
| 113475 | parseRemoteCertificate_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113476 | const UA_ByteString *remoteCertificate) { |
| 113477 | if(remoteCertificate == NULL || cc == NULL) |
| 113478 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113479 | |
| 113480 | /* Parse the certificate */ |
| 113481 | int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data, |
| 113482 | remoteCertificate->length); |
| 113483 | if(mbedErr) |
| 113484 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 113485 | |
| 113486 | /* Check the key length */ |
| 113487 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 113488 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 113489 | size_t keylen = rsaContext->len; |
| 113490 | #else |
| 113491 | size_t keylen = mbedtls_rsa_get_len(rsaContext); |
| 113492 | #endif |
| 113493 | if(keylen < UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH || |
| 113494 | keylen > UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH) |
| 113495 | return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; |
| 113496 | return UA_STATUSCODE_GOOD; |
| 113497 | } |
| 113498 | |
| 113499 | static void |
| 113500 | channelContext_deleteContext_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc) { |
| 113501 | UA_ByteString_clear(&cc->localSymSigningKey); |
| 113502 | UA_ByteString_clear(&cc->localSymEncryptingKey); |
| 113503 | UA_ByteString_clear(&cc->localSymIv); |
| 113504 | |
| 113505 | UA_ByteString_clear(&cc->remoteSymSigningKey); |
| 113506 | UA_ByteString_clear(&cc->remoteSymEncryptingKey); |
| 113507 | UA_ByteString_clear(&cc->remoteSymIv); |
| 113508 | |
| 113509 | mbedtls_x509_crt_free(&cc->remoteCertificate); |
| 113510 | |
| 113511 | UA_free(cc); |
| 113512 | } |
| 113513 | |
| 113514 | static UA_StatusCode |
| 113515 | channelContext_newContext_sp_aes128sha256rsaoaep(const UA_SecurityPolicy *securityPolicy, |
| 113516 | const UA_ByteString *remoteCertificate, |
| 113517 | void **pp_contextData) { |
| 113518 | if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL) |
| 113519 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113520 | |
| 113521 | /* Allocate the channel context */ |
| 113522 | *pp_contextData = UA_malloc(sizeof(Aes128Sha256PsaOaep_ChannelContext)); |
| 113523 | if(*pp_contextData == NULL) |
| 113524 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 113525 | |
| 113526 | Aes128Sha256PsaOaep_ChannelContext *cc = (Aes128Sha256PsaOaep_ChannelContext *)*pp_contextData; |
| 113527 | |
| 113528 | /* Initialize the channel context */ |
| 113529 | cc->policyContext = (Aes128Sha256PsaOaep_PolicyContext *)securityPolicy->policyContext; |
| 113530 | |
| 113531 | UA_ByteString_init(&cc->localSymSigningKey); |
| 113532 | UA_ByteString_init(&cc->localSymEncryptingKey); |
| 113533 | UA_ByteString_init(&cc->localSymIv); |
| 113534 | |
| 113535 | UA_ByteString_init(&cc->remoteSymSigningKey); |
| 113536 | UA_ByteString_init(&cc->remoteSymEncryptingKey); |
| 113537 | UA_ByteString_init(&cc->remoteSymIv); |
| 113538 | |
| 113539 | mbedtls_x509_crt_init(&cc->remoteCertificate); |
| 113540 | |
| 113541 | // TODO: this can be optimized so that we dont allocate memory before parsing the certificate |
| 113542 | UA_StatusCode retval = parseRemoteCertificate_sp_aes128sha256rsaoaep(cc, remoteCertificate); |
| 113543 | if(retval != UA_STATUSCODE_GOOD) { |
| 113544 | channelContext_deleteContext_sp_aes128sha256rsaoaep(cc); |
| 113545 | *pp_contextData = NULL; |
| 113546 | } |
| 113547 | return retval; |
| 113548 | } |
| 113549 | |
| 113550 | static UA_StatusCode |
| 113551 | channelContext_setLocalSymEncryptingKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113552 | const UA_ByteString *key) { |
| 113553 | if(key == NULL || cc == NULL) |
| 113554 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113555 | |
| 113556 | UA_ByteString_clear(&cc->localSymEncryptingKey); |
| 113557 | return UA_ByteString_copy(key, &cc->localSymEncryptingKey); |
| 113558 | } |
| 113559 | |
| 113560 | static UA_StatusCode |
| 113561 | channelContext_setLocalSymSigningKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113562 | const UA_ByteString *key) { |
| 113563 | if(key == NULL || cc == NULL) |
| 113564 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113565 | |
| 113566 | UA_ByteString_clear(&cc->localSymSigningKey); |
| 113567 | return UA_ByteString_copy(key, &cc->localSymSigningKey); |
| 113568 | } |
| 113569 | |
| 113570 | |
| 113571 | static UA_StatusCode |
| 113572 | channelContext_setLocalSymIv_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113573 | const UA_ByteString *iv) { |
| 113574 | if(iv == NULL || cc == NULL) |
| 113575 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113576 | |
| 113577 | UA_ByteString_clear(&cc->localSymIv); |
| 113578 | return UA_ByteString_copy(iv, &cc->localSymIv); |
| 113579 | } |
| 113580 | |
| 113581 | static UA_StatusCode |
| 113582 | channelContext_setRemoteSymEncryptingKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113583 | const UA_ByteString *key) { |
| 113584 | if(key == NULL || cc == NULL) |
| 113585 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113586 | |
| 113587 | UA_ByteString_clear(&cc->remoteSymEncryptingKey); |
| 113588 | return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey); |
| 113589 | } |
| 113590 | |
| 113591 | static UA_StatusCode |
| 113592 | channelContext_setRemoteSymSigningKey_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113593 | const UA_ByteString *key) { |
| 113594 | if(key == NULL || cc == NULL) |
| 113595 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113596 | |
| 113597 | UA_ByteString_clear(&cc->remoteSymSigningKey); |
| 113598 | return UA_ByteString_copy(key, &cc->remoteSymSigningKey); |
| 113599 | } |
| 113600 | |
| 113601 | static UA_StatusCode |
| 113602 | channelContext_setRemoteSymIv_sp_aes128sha256rsaoaep(Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113603 | const UA_ByteString *iv) { |
| 113604 | if(iv == NULL || cc == NULL) |
| 113605 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113606 | |
| 113607 | UA_ByteString_clear(&cc->remoteSymIv); |
| 113608 | return UA_ByteString_copy(iv, &cc->remoteSymIv); |
| 113609 | } |
| 113610 | |
| 113611 | static UA_StatusCode |
| 113612 | channelContext_compareCertificate_sp_aes128sha256rsaoaep(const Aes128Sha256PsaOaep_ChannelContext *cc, |
| 113613 | const UA_ByteString *certificate) { |
| 113614 | if(cc == NULL || certificate == NULL) |
| 113615 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113616 | |
| 113617 | mbedtls_x509_crt cert; |
| 113618 | mbedtls_x509_crt_init(&cert); |
| 113619 | int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length); |
| 113620 | if(mbedErr) |
| 113621 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 113622 | |
| 113623 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 113624 | if(cert.raw.len != cc->remoteCertificate.raw.len || |
| 113625 | memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0) |
| 113626 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 113627 | |
| 113628 | mbedtls_x509_crt_free(&cert); |
| 113629 | return retval; |
| 113630 | } |
| 113631 | |
| 113632 | static void |
| 113633 | clear_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy) { |
| 113634 | if(securityPolicy == NULL) |
| 113635 | return; |
| 113636 | |
| 113637 | UA_ByteString_clear(&securityPolicy->localCertificate); |
| 113638 | |
| 113639 | if(securityPolicy->policyContext == NULL) |
| 113640 | return; |
| 113641 | |
| 113642 | /* delete all allocated members in the context */ |
| 113643 | Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *) |
| 113644 | securityPolicy->policyContext; |
| 113645 | |
| 113646 | mbedtls_ctr_drbg_free(&pc->drbgContext); |
| 113647 | mbedtls_entropy_free(&pc->entropyContext); |
| 113648 | mbedtls_pk_free(&pc->localPrivateKey); |
| 113649 | mbedtls_md_free(&pc->sha256MdContext); |
| 113650 | UA_ByteString_clear(&pc->localCertThumbprint); |
| 113651 | |
| 113652 | UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 113653 | "Deleted members of EndpointContext for sp_aes128sha256rsaoaep"); |
| 113654 | |
| 113655 | UA_free(pc); |
| 113656 | securityPolicy->policyContext = NULL; |
| 113657 | } |
| 113658 | |
| 113659 | static UA_StatusCode |
| 113660 | updateCertificateAndPrivateKey_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy, |
| 113661 | const UA_ByteString newCertificate, |
| 113662 | const UA_ByteString newPrivateKey) { |
| 113663 | if(securityPolicy == NULL) |
| 113664 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113665 | |
| 113666 | if(securityPolicy->policyContext == NULL) |
| 113667 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113668 | |
| 113669 | Aes128Sha256PsaOaep_PolicyContext *pc = |
| 113670 | (Aes128Sha256PsaOaep_PolicyContext *) securityPolicy->policyContext; |
| 113671 | |
| 113672 | UA_ByteString_clear(&securityPolicy->localCertificate); |
| 113673 | |
| 113674 | UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate); |
| 113675 | |
| 113676 | if(retval != UA_STATUSCODE_GOOD) |
| 113677 | return retval; |
| 113678 | |
| 113679 | /* Set the new private key */ |
| 113680 | mbedtls_pk_free(&pc->localPrivateKey); |
| 113681 | mbedtls_pk_init(&pc->localPrivateKey); |
| 113682 | int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext); |
| 113683 | if(mbedErr) { |
| 113684 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 113685 | goto error; |
| 113686 | } |
| 113687 | |
| 113688 | retval = asym_makeThumbprint_sp_aes128sha256rsaoaep(securityPolicy, |
| 113689 | &securityPolicy->localCertificate, |
| 113690 | &pc->localCertThumbprint); |
| 113691 | if(retval != UA_STATUSCODE_GOOD) |
| 113692 | goto error; |
| 113693 | |
| 113694 | return retval; |
| 113695 | |
| 113696 | error: |
| 113697 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 113698 | "Could not update certificate and private key"); |
| 113699 | if(securityPolicy->policyContext != NULL) |
| 113700 | clear_sp_aes128sha256rsaoaep(securityPolicy); |
| 113701 | return retval; |
| 113702 | } |
| 113703 | |
| 113704 | static UA_StatusCode |
| 113705 | policyContext_newContext_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy, |
| 113706 | const UA_ByteString localPrivateKey) { |
| 113707 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 113708 | if(securityPolicy == NULL) |
| 113709 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113710 | |
| 113711 | if (localPrivateKey.length == 0) { |
| 113712 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 113713 | "Can not initialize security policy. Private key is empty."); |
| 113714 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 113715 | } |
| 113716 | |
| 113717 | Aes128Sha256PsaOaep_PolicyContext *pc = (Aes128Sha256PsaOaep_PolicyContext *) |
| 113718 | UA_malloc(sizeof(Aes128Sha256PsaOaep_PolicyContext)); |
| 113719 | securityPolicy->policyContext = (void *)pc; |
| 113720 | if(!pc) { |
| 113721 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 113722 | goto error; |
| 113723 | } |
| 113724 | |
| 113725 | /* Initialize the PolicyContext */ |
| 113726 | memset(pc, 0, sizeof(Aes128Sha256PsaOaep_PolicyContext)); |
| 113727 | mbedtls_ctr_drbg_init(&pc->drbgContext); |
| 113728 | mbedtls_entropy_init(&pc->entropyContext); |
| 113729 | mbedtls_pk_init(&pc->localPrivateKey); |
| 113730 | mbedtls_md_init(&pc->sha256MdContext); |
| 113731 | |
| 113732 | /* Initialized the message digest */ |
| 113733 | const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); |
| 113734 | int mbedErr = mbedtls_md_setup(&pc->sha256MdContext, mdInfo, MBEDTLS_MD_SHA256); |
| 113735 | if(mbedErr) { |
| 113736 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 113737 | goto error; |
| 113738 | } |
| 113739 | |
| 113740 | mbedErr = mbedtls_entropy_self_test(0); |
| 113741 | |
| 113742 | if(mbedErr) { |
| 113743 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 113744 | goto error; |
| 113745 | } |
| 113746 | |
| 113747 | /* Seed the RNG */ |
| 113748 | char *personalization = "open62541-drbg"; |
| 113749 | mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func, |
| 113750 | &pc->entropyContext, |
| 113751 | (const unsigned char *)personalization, 14); |
| 113752 | if(mbedErr) { |
| 113753 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 113754 | goto error; |
| 113755 | } |
| 113756 | |
| 113757 | /* Set the private key */ |
| 113758 | mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext); |
| 113759 | if(mbedErr) { |
| 113760 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 113761 | goto error; |
| 113762 | } |
| 113763 | |
| 113764 | /* Set the local certificate thumbprint */ |
| 113765 | retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH); |
| 113766 | if(retval != UA_STATUSCODE_GOOD) |
| 113767 | goto error; |
| 113768 | retval = asym_makeThumbprint_sp_aes128sha256rsaoaep(securityPolicy, |
| 113769 | &securityPolicy->localCertificate, |
| 113770 | &pc->localCertThumbprint); |
| 113771 | if(retval != UA_STATUSCODE_GOOD) |
| 113772 | goto error; |
| 113773 | |
| 113774 | return UA_STATUSCODE_GOOD; |
| 113775 | |
| 113776 | error: |
| 113777 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 113778 | "Could not create securityContext: %s", UA_StatusCode_name(retval)); |
| 113779 | if(securityPolicy->policyContext != NULL) |
| 113780 | clear_sp_aes128sha256rsaoaep(securityPolicy); |
| 113781 | return retval; |
| 113782 | } |
| 113783 | |
| 113784 | UA_StatusCode |
| 113785 | UA_SecurityPolicy_Aes128Sha256RsaOaep(UA_SecurityPolicy *policy, const UA_ByteString localCertificate, |
| 113786 | const UA_ByteString localPrivateKey, const UA_Logger *logger) { |
| 113787 | memset(policy, 0, sizeof(UA_SecurityPolicy)); |
| 113788 | policy->logger = logger; |
| 113789 | |
| 113790 | policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep"); |
| 113791 | |
| 113792 | UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule; |
| 113793 | UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule; |
| 113794 | UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule; |
| 113795 | |
| 113796 | UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate); |
| 113797 | |
| 113798 | if (retval != UA_STATUSCODE_GOOD) |
| 113799 | return retval; |
| 113800 | |
| 113801 | /* AsymmetricModule */ |
| 113802 | UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm = |
| 113803 | &asymmetricModule->cryptoModule.signatureAlgorithm; |
| 113804 | asym_signatureAlgorithm->uri = |
| 113805 | UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0"); |
| 113806 | asym_signatureAlgorithm->verify = |
| 113807 | (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_aes128sha256rsaoaep; |
| 113808 | asym_signatureAlgorithm->sign = |
| 113809 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_aes128sha256rsaoaep; |
| 113810 | asym_signatureAlgorithm->getLocalSignatureSize = |
| 113811 | (size_t (*)(const void *))asym_getLocalSignatureSize_sp_aes128sha256rsaoaep; |
| 113812 | asym_signatureAlgorithm->getRemoteSignatureSize = |
| 113813 | (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_aes128sha256rsaoaep; |
| 113814 | asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function |
| 113815 | asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function |
| 113816 | |
| 113817 | UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm = |
| 113818 | &asymmetricModule->cryptoModule.encryptionAlgorithm; |
| 113819 | asym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#rsa-oaep\0"); |
| 113820 | asym_encryptionAlgorithm->encrypt = |
| 113821 | (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_aes128sha256rsaoaep; |
| 113822 | asym_encryptionAlgorithm->decrypt = |
| 113823 | (UA_StatusCode(*)(void *, UA_ByteString *)) asym_decrypt_sp_aes128sha256rsaoaep; |
| 113824 | asym_encryptionAlgorithm->getLocalKeyLength = |
| 113825 | (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_aes128sha256rsaoaep; |
| 113826 | asym_encryptionAlgorithm->getRemoteKeyLength = |
| 113827 | (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_aes128sha256rsaoaep; |
| 113828 | asym_encryptionAlgorithm->getRemoteBlockSize = (size_t (*)(const void *))asym_getRemoteBlockSize_sp_aes128sha256rsaoaep; |
| 113829 | asym_encryptionAlgorithm->getRemotePlainTextBlockSize = |
| 113830 | (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_aes128sha256rsaoaep; |
| 113831 | |
| 113832 | asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_aes128sha256rsaoaep; |
| 113833 | asymmetricModule->compareCertificateThumbprint = |
| 113834 | asymmetricModule_compareCertificateThumbprint_sp_aes128sha256rsaoaep; |
| 113835 | |
| 113836 | /* SymmetricModule */ |
| 113837 | symmetricModule->generateKey = sym_generateKey_sp_aes128sha256rsaoaep; |
| 113838 | symmetricModule->generateNonce = sym_generateNonce_sp_aes128sha256rsaoaep; |
| 113839 | |
| 113840 | UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm = |
| 113841 | &symmetricModule->cryptoModule.signatureAlgorithm; |
| 113842 | sym_signatureAlgorithm->uri = |
| 113843 | UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha1\0"); |
| 113844 | sym_signatureAlgorithm->verify = |
| 113845 | (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))sym_verify_sp_aes128sha256rsaoaep; |
| 113846 | sym_signatureAlgorithm->sign = |
| 113847 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_aes128sha256rsaoaep; |
| 113848 | sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_aes128sha256rsaoaep; |
| 113849 | sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_aes128sha256rsaoaep; |
| 113850 | sym_signatureAlgorithm->getLocalKeyLength = |
| 113851 | (size_t (*)(const void *))sym_getSigningKeyLength_sp_aes128sha256rsaoaep; |
| 113852 | sym_signatureAlgorithm->getRemoteKeyLength = |
| 113853 | (size_t (*)(const void *))sym_getSigningKeyLength_sp_aes128sha256rsaoaep; |
| 113854 | |
| 113855 | UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm = |
| 113856 | &symmetricModule->cryptoModule.encryptionAlgorithm; |
| 113857 | sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes128-cbc"); |
| 113858 | sym_encryptionAlgorithm->encrypt = |
| 113859 | (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_aes128sha256rsaoaep; |
| 113860 | sym_encryptionAlgorithm->decrypt = |
| 113861 | (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_aes128sha256rsaoaep; |
| 113862 | sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep; |
| 113863 | sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_aes128sha256rsaoaep; |
| 113864 | sym_encryptionAlgorithm->getRemoteBlockSize = |
| 113865 | (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_aes128sha256rsaoaep; |
| 113866 | sym_encryptionAlgorithm->getRemotePlainTextBlockSize = |
| 113867 | (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_aes128sha256rsaoaep; |
| 113868 | symmetricModule->secureChannelNonceLength = 32; |
| 113869 | |
| 113870 | // Use the same signature algorithm as the asymmetric component for certificate signing (see standard) |
| 113871 | policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 113872 | |
| 113873 | /* ChannelModule */ |
| 113874 | channelModule->newContext = channelContext_newContext_sp_aes128sha256rsaoaep; |
| 113875 | channelModule->deleteContext = (void (*)(void *)) |
| 113876 | channelContext_deleteContext_sp_aes128sha256rsaoaep; |
| 113877 | |
| 113878 | channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113879 | channelContext_setLocalSymEncryptingKey_sp_aes128sha256rsaoaep; |
| 113880 | channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113881 | channelContext_setLocalSymSigningKey_sp_aes128sha256rsaoaep; |
| 113882 | channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113883 | channelContext_setLocalSymIv_sp_aes128sha256rsaoaep; |
| 113884 | |
| 113885 | channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113886 | channelContext_setRemoteSymEncryptingKey_sp_aes128sha256rsaoaep; |
| 113887 | channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113888 | channelContext_setRemoteSymSigningKey_sp_aes128sha256rsaoaep; |
| 113889 | channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 113890 | channelContext_setRemoteSymIv_sp_aes128sha256rsaoaep; |
| 113891 | |
| 113892 | channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *)) |
| 113893 | channelContext_compareCertificate_sp_aes128sha256rsaoaep; |
| 113894 | |
| 113895 | policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_aes128sha256rsaoaep; |
| 113896 | policy->clear = clear_sp_aes128sha256rsaoaep; |
| 113897 | |
| 113898 | UA_StatusCode res = policyContext_newContext_sp_aes128sha256rsaoaep(policy, localPrivateKey); |
| 113899 | if(res != UA_STATUSCODE_GOOD) |
| 113900 | clear_sp_aes128sha256rsaoaep(policy); |
| 113901 | |
| 113902 | return res; |
| 113903 | } |
| 113904 | |
| 113905 | #endif |
| 113906 | |
| 113907 | /**** amalgamated original file "/plugins/crypto/mbedtls/ua_securitypolicy_aes256sha256rsapss.c" ****/ |
| 113908 | |
| 113909 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 113910 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 113911 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 113912 | * |
| 113913 | * Copyright 2022 (c) Fraunhofer IOSB (Author: Noel Graf) |
| 113914 | */ |
| 113915 | |
| 113916 | |
| 113917 | #ifdef UA_ENABLE_ENCRYPTION_MBEDTLS |
| 113918 | |
| 113919 | |
| 113920 | #include <mbedtls/aes.h> |
| 113921 | #include <mbedtls/ctr_drbg.h> |
| 113922 | #include <mbedtls/entropy.h> |
| 113923 | #include <mbedtls/error.h> |
| 113924 | #include <mbedtls/md.h> |
| 113925 | #include <mbedtls/sha1.h> |
| 113926 | #include <mbedtls/sha256.h> |
| 113927 | #include <mbedtls/version.h> |
| 113928 | #include <mbedtls/x509_crt.h> |
| 113929 | |
| 113930 | /* Notes: |
| 113931 | * mbedTLS' AES allows in-place encryption and decryption. So we don't have to |
| 113932 | * allocate temp buffers. |
| 113933 | * https://tls.mbed.org/discussions/generic/in-place-decryption-with-aes256-same-input-output-buffer |
| 113934 | */ |
| 113935 | |
| 113936 | #define UA_SHA1_LENGTH 20 |
| 113937 | #define UA_SHA256_LENGTH 32 |
| 113938 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_RSAPADDING_LEN 66 /* UA_SHA256_LENGTH * 2 + 2 */ |
| 113939 | #define UA_AES256SHA256RSAPSS_SYM_SIGNING_KEY_LENGTH 32 |
| 113940 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_KEY_LENGTH 32 /*16*/ |
| 113941 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_ENCRYPTION_BLOCK_SIZE 16 |
| 113942 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_PLAIN_TEXT_BLOCK_SIZE 16 |
| 113943 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_MINASYMKEYLENGTH 256 |
| 113944 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_MAXASYMKEYLENGTH 512 |
| 113945 | |
| 113946 | typedef struct { |
| 113947 | UA_ByteString localCertThumbprint; |
| 113948 | |
| 113949 | mbedtls_ctr_drbg_context drbgContext; |
| 113950 | mbedtls_entropy_context entropyContext; |
| 113951 | mbedtls_md_context_t sha256MdContext; |
| 113952 | mbedtls_pk_context localPrivateKey; |
| 113953 | } Aes256Sha256RsaPss_PolicyContext; |
| 113954 | |
| 113955 | typedef struct { |
| 113956 | Aes256Sha256RsaPss_PolicyContext *policyContext; |
| 113957 | |
| 113958 | UA_ByteString localSymSigningKey; |
| 113959 | UA_ByteString localSymEncryptingKey; |
| 113960 | UA_ByteString localSymIv; |
| 113961 | |
| 113962 | UA_ByteString remoteSymSigningKey; |
| 113963 | UA_ByteString remoteSymEncryptingKey; |
| 113964 | UA_ByteString remoteSymIv; |
| 113965 | |
| 113966 | mbedtls_x509_crt remoteCertificate; |
| 113967 | } Aes256Sha256RsaPss_ChannelContext; |
| 113968 | |
| 113969 | /********************/ |
| 113970 | /* AsymmetricModule */ |
| 113971 | /********************/ |
| 113972 | |
| 113973 | /* VERIFY AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */ |
| 113974 | static UA_StatusCode |
| 113975 | asym_verify_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 113976 | const UA_ByteString *message, |
| 113977 | const UA_ByteString *signature) { |
| 113978 | if(message == NULL || signature == NULL || cc == NULL) |
| 113979 | return UA_STATUSCODE_BADINTERNALERROR; |
| 113980 | |
| 113981 | unsigned char hash[UA_SHA256_LENGTH]; |
| 113982 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 113983 | // TODO check return status |
| 113984 | mbedtls_sha256_ret(message->data, message->length, hash, 0); |
| 113985 | #else |
| 113986 | mbedtls_sha256(message->data, message->length, hash, 0); |
| 113987 | #endif |
| 113988 | |
| 113989 | /* Set the RSA settings */ |
| 113990 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 113991 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); |
| 113992 | |
| 113993 | #if MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 113994 | Aes256Sha256RsaPss_PolicyContext *pc = cc->policyContext; |
| 113995 | int mbedErr = mbedtls_rsa_pkcs1_verify(rsaContext, mbedtls_ctr_drbg_random, &pc->drbgContext, |
| 113996 | MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, UA_SHA256_LENGTH, |
| 113997 | hash, signature->data); |
| 113998 | #else |
| 113999 | int mbedErr = mbedtls_rsa_pkcs1_verify(rsaContext, MBEDTLS_MD_SHA256, |
| 114000 | UA_SHA256_LENGTH, hash, signature->data); |
| 114001 | #endif |
| 114002 | |
| 114003 | if(mbedErr) |
| 114004 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114005 | return UA_STATUSCODE_GOOD; |
| 114006 | } |
| 114007 | |
| 114008 | /* AsymmetricSignatureAlgorithm_RSA-PSS-SHA2-256 */ |
| 114009 | static UA_StatusCode |
| 114010 | asym_sign_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114011 | const UA_ByteString *message, |
| 114012 | UA_ByteString *signature) { |
| 114013 | if(message == NULL || signature == NULL || cc == NULL) |
| 114014 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114015 | |
| 114016 | unsigned char hash[UA_SHA256_LENGTH]; |
| 114017 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114018 | // TODO check return status |
| 114019 | mbedtls_sha256_ret(message->data, message->length, hash, 0); |
| 114020 | #else |
| 114021 | mbedtls_sha256(message->data, message->length, hash, 0); |
| 114022 | #endif |
| 114023 | |
| 114024 | Aes256Sha256RsaPss_PolicyContext *pc = cc->policyContext; |
| 114025 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey); |
| 114026 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); |
| 114027 | |
| 114028 | #if MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114029 | int mbedErr = mbedtls_rsa_pkcs1_sign(rsaContext, mbedtls_ctr_drbg_random, &pc->drbgContext, |
| 114030 | MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256, UA_SHA256_LENGTH, |
| 114031 | hash, signature->data); |
| 114032 | #else |
| 114033 | int mbedErr = mbedtls_rsa_pkcs1_sign(rsaContext, mbedtls_ctr_drbg_random, &pc->drbgContext, |
| 114034 | MBEDTLS_MD_SHA256, UA_SHA256_LENGTH, |
| 114035 | hash, signature->data); |
| 114036 | #endif |
| 114037 | |
| 114038 | |
| 114039 | if(mbedErr) |
| 114040 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114041 | return UA_STATUSCODE_GOOD; |
| 114042 | } |
| 114043 | |
| 114044 | static size_t |
| 114045 | asym_getLocalSignatureSize_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc) { |
| 114046 | if(cc == NULL) |
| 114047 | return 0; |
| 114048 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114049 | return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len; |
| 114050 | #else |
| 114051 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey)); |
| 114052 | #endif |
| 114053 | } |
| 114054 | |
| 114055 | static size_t |
| 114056 | asym_getRemoteSignatureSize_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc) { |
| 114057 | if(cc == NULL) |
| 114058 | return 0; |
| 114059 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114060 | return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len; |
| 114061 | #else |
| 114062 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 114063 | #endif |
| 114064 | } |
| 114065 | |
| 114066 | static size_t |
| 114067 | asym_getRemoteBlockSize_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc) { |
| 114068 | if(cc == NULL) |
| 114069 | return 0; |
| 114070 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114071 | return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len; |
| 114072 | #else |
| 114073 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 114074 | #endif |
| 114075 | } |
| 114076 | |
| 114077 | static size_t |
| 114078 | asym_getRemotePlainTextBlockSize_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc) { |
| 114079 | if(cc == NULL) |
| 114080 | return 0; |
| 114081 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114082 | mbedtls_rsa_context *const rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 114083 | return rsaContext->len - UA_SECURITYPOLICY_AES256SHA256RSAPSS_RSAPADDING_LEN; |
| 114084 | #else |
| 114085 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)) - |
| 114086 | UA_SECURITYPOLICY_AES256SHA256RSAPSS_RSAPADDING_LEN; |
| 114087 | #endif |
| 114088 | } |
| 114089 | |
| 114090 | |
| 114091 | /* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA2 */ |
| 114092 | static UA_StatusCode |
| 114093 | asym_encrypt_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114094 | UA_ByteString *data) { |
| 114095 | if(cc == NULL || data == NULL) |
| 114096 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114097 | |
| 114098 | const size_t plainTextBlockSize = asym_getRemotePlainTextBlockSize_sp_aes256sha256rsapss(cc); |
| 114099 | |
| 114100 | mbedtls_rsa_context *remoteRsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 114101 | mbedtls_rsa_set_padding(remoteRsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); |
| 114102 | |
| 114103 | return mbedtls_encrypt_rsaOaep(remoteRsaContext, &cc->policyContext->drbgContext, |
| 114104 | data, plainTextBlockSize); |
| 114105 | } |
| 114106 | |
| 114107 | /* AsymmetricEncryptionAlgorithm_RSA-OAEP-SHA2 */ |
| 114108 | static UA_StatusCode |
| 114109 | asym_decrypt_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114110 | UA_ByteString *data) { |
| 114111 | if(cc == NULL || data == NULL) |
| 114112 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114113 | return mbedtls_decrypt_rsaOaep(&cc->policyContext->localPrivateKey, |
| 114114 | &cc->policyContext->drbgContext, data, MBEDTLS_MD_SHA256); |
| 114115 | } |
| 114116 | |
| 114117 | static size_t |
| 114118 | asym_getLocalEncryptionKeyLength_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc) { |
| 114119 | return mbedtls_pk_get_len(&cc->policyContext->localPrivateKey) * 8; |
| 114120 | } |
| 114121 | |
| 114122 | static size_t |
| 114123 | asym_getRemoteEncryptionKeyLength_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc) { |
| 114124 | return mbedtls_pk_get_len(&cc->remoteCertificate.pk) * 8; |
| 114125 | } |
| 114126 | |
| 114127 | static UA_StatusCode |
| 114128 | asym_makeThumbprint_sp_aes256sha256rsapss(const UA_SecurityPolicy *securityPolicy, |
| 114129 | const UA_ByteString *certificate, |
| 114130 | UA_ByteString *thumbprint) { |
| 114131 | if(securityPolicy == NULL || certificate == NULL || thumbprint == NULL) |
| 114132 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114133 | return mbedtls_thumbprint_sha1(certificate, thumbprint); |
| 114134 | } |
| 114135 | |
| 114136 | static UA_StatusCode |
| 114137 | asymmetricModule_compareCertificateThumbprint_sp_aes256sha256rsapss(const UA_SecurityPolicy *securityPolicy, |
| 114138 | const UA_ByteString *certificateThumbprint) { |
| 114139 | if(securityPolicy == NULL || certificateThumbprint == NULL) |
| 114140 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114141 | |
| 114142 | Aes256Sha256RsaPss_PolicyContext *pc = (Aes256Sha256RsaPss_PolicyContext *)securityPolicy->policyContext; |
| 114143 | if(!UA_ByteString_equal(certificateThumbprint, &pc->localCertThumbprint)) |
| 114144 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 114145 | |
| 114146 | return UA_STATUSCODE_GOOD; |
| 114147 | } |
| 114148 | |
| 114149 | /*******************/ |
| 114150 | /* SymmetricModule */ |
| 114151 | /*******************/ |
| 114152 | |
| 114153 | static UA_StatusCode |
| 114154 | sym_verify_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114155 | const UA_ByteString *message, |
| 114156 | const UA_ByteString *signature) { |
| 114157 | if(cc == NULL || message == NULL || signature == NULL) |
| 114158 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114159 | |
| 114160 | /* Compute MAC */ |
| 114161 | if(signature->length != UA_SHA256_LENGTH) |
| 114162 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114163 | Aes256Sha256RsaPss_PolicyContext *pc = cc->policyContext; |
| 114164 | unsigned char mac[UA_SHA256_LENGTH]; |
| 114165 | mbedtls_hmac(&pc->sha256MdContext, &cc->remoteSymSigningKey, message, mac); |
| 114166 | |
| 114167 | /* Compare with Signature */ |
| 114168 | if(!UA_constantTimeEqual(signature->data, mac, UA_SHA256_LENGTH)) |
| 114169 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114170 | return UA_STATUSCODE_GOOD; |
| 114171 | } |
| 114172 | |
| 114173 | static UA_StatusCode |
| 114174 | sym_sign_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc, |
| 114175 | const UA_ByteString *message, |
| 114176 | UA_ByteString *signature) { |
| 114177 | if(signature->length != UA_SHA256_LENGTH) |
| 114178 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114179 | |
| 114180 | mbedtls_hmac(&cc->policyContext->sha256MdContext, &cc->localSymSigningKey, |
| 114181 | message, signature->data); |
| 114182 | return UA_STATUSCODE_GOOD; |
| 114183 | } |
| 114184 | |
| 114185 | static size_t |
| 114186 | sym_getSignatureSize_sp_aes256sha256rsapss(const void *channelContext) { |
| 114187 | return UA_SHA256_LENGTH; |
| 114188 | } |
| 114189 | |
| 114190 | static size_t |
| 114191 | sym_getSigningKeyLength_sp_aes256sha256rsapss(const void *channelContext) { |
| 114192 | return UA_AES256SHA256RSAPSS_SYM_SIGNING_KEY_LENGTH; |
| 114193 | } |
| 114194 | |
| 114195 | static size_t |
| 114196 | sym_getEncryptionKeyLength_sp_aes256sha256rsapss(const void *channelContext) { |
| 114197 | return UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_KEY_LENGTH; |
| 114198 | } |
| 114199 | |
| 114200 | static size_t |
| 114201 | sym_getEncryptionBlockSize_sp_aes256sha256rsapss(const void *channelContext) { |
| 114202 | return UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_ENCRYPTION_BLOCK_SIZE; |
| 114203 | } |
| 114204 | |
| 114205 | static size_t |
| 114206 | sym_getPlainTextBlockSize_sp_aes256sha256rsapss(const void *channelContext) { |
| 114207 | return UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_PLAIN_TEXT_BLOCK_SIZE; |
| 114208 | } |
| 114209 | |
| 114210 | static UA_StatusCode |
| 114211 | sym_encrypt_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc, |
| 114212 | UA_ByteString *data) { |
| 114213 | if(cc == NULL || data == NULL) |
| 114214 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114215 | |
| 114216 | if(cc->localSymIv.length != UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_ENCRYPTION_BLOCK_SIZE) |
| 114217 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114218 | |
| 114219 | size_t plainTextBlockSize = UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_PLAIN_TEXT_BLOCK_SIZE; |
| 114220 | |
| 114221 | if(data->length % plainTextBlockSize != 0) |
| 114222 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114223 | |
| 114224 | /* Keylength in bits */ |
| 114225 | unsigned int keylength = (unsigned int)(cc->localSymEncryptingKey.length * 8); |
| 114226 | mbedtls_aes_context aesContext; |
| 114227 | int mbedErr = mbedtls_aes_setkey_enc(&aesContext, cc->localSymEncryptingKey.data, keylength); |
| 114228 | if(mbedErr) |
| 114229 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114230 | |
| 114231 | UA_ByteString ivCopy; |
| 114232 | UA_StatusCode retval = UA_ByteString_copy(&cc->localSymIv, &ivCopy); |
| 114233 | if(retval != UA_STATUSCODE_GOOD) |
| 114234 | return retval; |
| 114235 | |
| 114236 | mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_ENCRYPT, data->length, |
| 114237 | ivCopy.data, data->data, data->data); |
| 114238 | if(mbedErr) |
| 114239 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 114240 | UA_ByteString_clear(&ivCopy); |
| 114241 | return retval; |
| 114242 | } |
| 114243 | |
| 114244 | static UA_StatusCode |
| 114245 | sym_decrypt_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc, |
| 114246 | UA_ByteString *data) { |
| 114247 | if(cc == NULL || data == NULL) |
| 114248 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114249 | |
| 114250 | size_t encryptionBlockSize = UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_ENCRYPTION_BLOCK_SIZE; |
| 114251 | |
| 114252 | if(cc->remoteSymIv.length != encryptionBlockSize) |
| 114253 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114254 | |
| 114255 | if(data->length % encryptionBlockSize != 0) |
| 114256 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114257 | |
| 114258 | unsigned int keylength = (unsigned int)(cc->remoteSymEncryptingKey.length * 8); |
| 114259 | mbedtls_aes_context aesContext; |
| 114260 | int mbedErr = mbedtls_aes_setkey_dec(&aesContext, cc->remoteSymEncryptingKey.data, keylength); |
| 114261 | if(mbedErr) |
| 114262 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114263 | |
| 114264 | UA_ByteString ivCopy; |
| 114265 | UA_StatusCode retval = UA_ByteString_copy(&cc->remoteSymIv, &ivCopy); |
| 114266 | if(retval != UA_STATUSCODE_GOOD) |
| 114267 | return retval; |
| 114268 | |
| 114269 | mbedErr = mbedtls_aes_crypt_cbc(&aesContext, MBEDTLS_AES_DECRYPT, data->length, |
| 114270 | ivCopy.data, data->data, data->data); |
| 114271 | if(mbedErr) |
| 114272 | retval = UA_STATUSCODE_BADINTERNALERROR; |
| 114273 | UA_ByteString_clear(&ivCopy); |
| 114274 | return retval; |
| 114275 | } |
| 114276 | |
| 114277 | static UA_StatusCode |
| 114278 | sym_generateKey_sp_aes256sha256rsapss(void *policyContext, const UA_ByteString *secret, |
| 114279 | const UA_ByteString *seed, UA_ByteString *out) { |
| 114280 | if(secret == NULL || seed == NULL || out == NULL) |
| 114281 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114282 | Aes256Sha256RsaPss_PolicyContext *pc = (Aes256Sha256RsaPss_PolicyContext *)policyContext; |
| 114283 | return mbedtls_generateKey(&pc->sha256MdContext, secret, seed, out); |
| 114284 | } |
| 114285 | |
| 114286 | static UA_StatusCode |
| 114287 | sym_generateNonce_sp_aes256sha256rsapss(void *policyContext, UA_ByteString *out) { |
| 114288 | if(out == NULL) |
| 114289 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114290 | Aes256Sha256RsaPss_PolicyContext *pc = |
| 114291 | (Aes256Sha256RsaPss_PolicyContext *)policyContext; |
| 114292 | int mbedErr = mbedtls_ctr_drbg_random(&pc->drbgContext, out->data, out->length); |
| 114293 | if(mbedErr) |
| 114294 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 114295 | return UA_STATUSCODE_GOOD; |
| 114296 | } |
| 114297 | |
| 114298 | /***********************************/ |
| 114299 | /* CertificateSigningAlgorithms */ |
| 114300 | /***********************************/ |
| 114301 | |
| 114302 | static UA_StatusCode |
| 114303 | asym_cert_verify_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114304 | const UA_ByteString *message, |
| 114305 | const UA_ByteString *signature) { |
| 114306 | if(message == NULL || signature == NULL || cc == NULL) |
| 114307 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114308 | |
| 114309 | unsigned char hash[UA_SHA256_LENGTH]; |
| 114310 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114311 | // TODO check return status |
| 114312 | mbedtls_sha256_ret(message->data, message->length, hash, 0); |
| 114313 | #else |
| 114314 | mbedtls_sha256(message->data, message->length, hash, 0); |
| 114315 | #endif |
| 114316 | |
| 114317 | /* Set the RSA settings */ |
| 114318 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 114319 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256); |
| 114320 | |
| 114321 | /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_verify() */ |
| 114322 | /* Alternatively, use more specific function mbedtls_rsa_rsassa_pkcs1_v15_verify(), i.e. */ |
| 114323 | /* int mbedErr = mbedtls_rsa_rsassa_pkcs1_v15_verify(rsaContext, NULL, NULL, |
| 114324 | MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, |
| 114325 | UA_SHA256_LENGTH, hash, |
| 114326 | signature->data); */ |
| 114327 | int mbedErr = mbedtls_pk_verify(&cc->remoteCertificate.pk, |
| 114328 | MBEDTLS_MD_SHA256, hash, UA_SHA256_LENGTH, |
| 114329 | signature->data, signature->length); |
| 114330 | |
| 114331 | if(mbedErr) |
| 114332 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114333 | return UA_STATUSCODE_GOOD; |
| 114334 | } |
| 114335 | |
| 114336 | /* AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */ |
| 114337 | static UA_StatusCode |
| 114338 | asym_cert_sign_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114339 | const UA_ByteString *message, |
| 114340 | UA_ByteString *signature) { |
| 114341 | if(message == NULL || signature == NULL || cc == NULL) |
| 114342 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114343 | |
| 114344 | unsigned char hash[UA_SHA256_LENGTH]; |
| 114345 | #if MBEDTLS_VERSION_NUMBER >= 0x02070000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114346 | // TODO check return status |
| 114347 | mbedtls_sha256_ret(message->data, message->length, hash, 0); |
| 114348 | #else |
| 114349 | mbedtls_sha256(message->data, message->length, hash, 0); |
| 114350 | #endif |
| 114351 | |
| 114352 | Aes256Sha256RsaPss_PolicyContext *pc = cc->policyContext; |
| 114353 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(pc->localPrivateKey); |
| 114354 | mbedtls_rsa_set_padding(rsaContext, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256); |
| 114355 | |
| 114356 | size_t sigLen = 0; |
| 114357 | |
| 114358 | /* For RSA keys, the default padding type is PKCS#1 v1.5 in mbedtls_pk_sign */ |
| 114359 | /* Alternatively use more specific function mbedtls_rsa_rsassa_pkcs1_v15_sign() */ |
| 114360 | int mbedErr = mbedtls_pk_sign(&pc->localPrivateKey, |
| 114361 | MBEDTLS_MD_SHA256, hash, |
| 114362 | UA_SHA256_LENGTH, signature->data, |
| 114363 | #if MBEDTLS_VERSION_NUMBER >= 0x03000000 |
| 114364 | signature->length, |
| 114365 | #endif |
| 114366 | &sigLen, mbedtls_ctr_drbg_random, |
| 114367 | &pc->drbgContext); |
| 114368 | if(mbedErr) |
| 114369 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114370 | return UA_STATUSCODE_GOOD; |
| 114371 | } |
| 114372 | |
| 114373 | static size_t |
| 114374 | asym_cert_getLocalSignatureSize_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc) { |
| 114375 | if(cc == NULL) |
| 114376 | return 0; |
| 114377 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114378 | return mbedtls_pk_rsa(cc->policyContext->localPrivateKey)->len; |
| 114379 | #else |
| 114380 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->policyContext->localPrivateKey)); |
| 114381 | #endif |
| 114382 | } |
| 114383 | |
| 114384 | static size_t |
| 114385 | asym_cert_getRemoteSignatureSize_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc) { |
| 114386 | if(cc == NULL) |
| 114387 | return 0; |
| 114388 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114389 | return mbedtls_pk_rsa(cc->remoteCertificate.pk)->len; |
| 114390 | #else |
| 114391 | return mbedtls_rsa_get_len(mbedtls_pk_rsa(cc->remoteCertificate.pk)); |
| 114392 | #endif |
| 114393 | } |
| 114394 | |
| 114395 | /*****************/ |
| 114396 | /* ChannelModule */ |
| 114397 | /*****************/ |
| 114398 | |
| 114399 | /* Assumes that the certificate has been verified externally */ |
| 114400 | static UA_StatusCode |
| 114401 | parseRemoteCertificate_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114402 | const UA_ByteString *remoteCertificate) { |
| 114403 | if(remoteCertificate == NULL || cc == NULL) |
| 114404 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114405 | |
| 114406 | /* Parse the certificate */ |
| 114407 | int mbedErr = mbedtls_x509_crt_parse(&cc->remoteCertificate, remoteCertificate->data, |
| 114408 | remoteCertificate->length); |
| 114409 | if(mbedErr) |
| 114410 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114411 | |
| 114412 | /* Check the key length */ |
| 114413 | mbedtls_rsa_context *rsaContext = mbedtls_pk_rsa(cc->remoteCertificate.pk); |
| 114414 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 114415 | size_t keylen = rsaContext->len; |
| 114416 | #else |
| 114417 | size_t keylen = mbedtls_rsa_get_len(rsaContext); |
| 114418 | #endif |
| 114419 | if(keylen < UA_SECURITYPOLICY_AES256SHA256RSAPSS_MINASYMKEYLENGTH || |
| 114420 | keylen > UA_SECURITYPOLICY_AES256SHA256RSAPSS_MAXASYMKEYLENGTH) |
| 114421 | return UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; |
| 114422 | return UA_STATUSCODE_GOOD; |
| 114423 | } |
| 114424 | |
| 114425 | static void |
| 114426 | channelContext_deleteContext_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc) { |
| 114427 | UA_ByteString_clear(&cc->localSymSigningKey); |
| 114428 | UA_ByteString_clear(&cc->localSymEncryptingKey); |
| 114429 | UA_ByteString_clear(&cc->localSymIv); |
| 114430 | |
| 114431 | UA_ByteString_clear(&cc->remoteSymSigningKey); |
| 114432 | UA_ByteString_clear(&cc->remoteSymEncryptingKey); |
| 114433 | UA_ByteString_clear(&cc->remoteSymIv); |
| 114434 | |
| 114435 | mbedtls_x509_crt_free(&cc->remoteCertificate); |
| 114436 | |
| 114437 | UA_free(cc); |
| 114438 | } |
| 114439 | |
| 114440 | static UA_StatusCode |
| 114441 | channelContext_newContext_sp_aes256sha256rsapss(const UA_SecurityPolicy *securityPolicy, |
| 114442 | const UA_ByteString *remoteCertificate, |
| 114443 | void **pp_contextData) { |
| 114444 | if(securityPolicy == NULL || remoteCertificate == NULL || pp_contextData == NULL) |
| 114445 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114446 | |
| 114447 | /* Allocate the channel context */ |
| 114448 | *pp_contextData = UA_malloc(sizeof(Aes256Sha256RsaPss_ChannelContext)); |
| 114449 | if(*pp_contextData == NULL) |
| 114450 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 114451 | |
| 114452 | Aes256Sha256RsaPss_ChannelContext *cc = (Aes256Sha256RsaPss_ChannelContext *)*pp_contextData; |
| 114453 | |
| 114454 | /* Initialize the channel context */ |
| 114455 | cc->policyContext = (Aes256Sha256RsaPss_PolicyContext *)securityPolicy->policyContext; |
| 114456 | |
| 114457 | UA_ByteString_init(&cc->localSymSigningKey); |
| 114458 | UA_ByteString_init(&cc->localSymEncryptingKey); |
| 114459 | UA_ByteString_init(&cc->localSymIv); |
| 114460 | |
| 114461 | UA_ByteString_init(&cc->remoteSymSigningKey); |
| 114462 | UA_ByteString_init(&cc->remoteSymEncryptingKey); |
| 114463 | UA_ByteString_init(&cc->remoteSymIv); |
| 114464 | |
| 114465 | mbedtls_x509_crt_init(&cc->remoteCertificate); |
| 114466 | |
| 114467 | // TODO: this can be optimized so that we dont allocate memory before parsing the certificate |
| 114468 | UA_StatusCode retval = parseRemoteCertificate_sp_aes256sha256rsapss(cc, remoteCertificate); |
| 114469 | if(retval != UA_STATUSCODE_GOOD) { |
| 114470 | channelContext_deleteContext_sp_aes256sha256rsapss(cc); |
| 114471 | *pp_contextData = NULL; |
| 114472 | } |
| 114473 | return retval; |
| 114474 | } |
| 114475 | |
| 114476 | static UA_StatusCode |
| 114477 | channelContext_setLocalSymEncryptingKey_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114478 | const UA_ByteString *key) { |
| 114479 | if(key == NULL || cc == NULL) |
| 114480 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114481 | |
| 114482 | UA_ByteString_clear(&cc->localSymEncryptingKey); |
| 114483 | return UA_ByteString_copy(key, &cc->localSymEncryptingKey); |
| 114484 | } |
| 114485 | |
| 114486 | static UA_StatusCode |
| 114487 | channelContext_setLocalSymSigningKey_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114488 | const UA_ByteString *key) { |
| 114489 | if(key == NULL || cc == NULL) |
| 114490 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114491 | |
| 114492 | UA_ByteString_clear(&cc->localSymSigningKey); |
| 114493 | return UA_ByteString_copy(key, &cc->localSymSigningKey); |
| 114494 | } |
| 114495 | |
| 114496 | |
| 114497 | static UA_StatusCode |
| 114498 | channelContext_setLocalSymIv_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114499 | const UA_ByteString *iv) { |
| 114500 | if(iv == NULL || cc == NULL) |
| 114501 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114502 | |
| 114503 | UA_ByteString_clear(&cc->localSymIv); |
| 114504 | return UA_ByteString_copy(iv, &cc->localSymIv); |
| 114505 | } |
| 114506 | |
| 114507 | static UA_StatusCode |
| 114508 | channelContext_setRemoteSymEncryptingKey_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114509 | const UA_ByteString *key) { |
| 114510 | if(key == NULL || cc == NULL) |
| 114511 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114512 | |
| 114513 | UA_ByteString_clear(&cc->remoteSymEncryptingKey); |
| 114514 | return UA_ByteString_copy(key, &cc->remoteSymEncryptingKey); |
| 114515 | } |
| 114516 | |
| 114517 | static UA_StatusCode |
| 114518 | channelContext_setRemoteSymSigningKey_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114519 | const UA_ByteString *key) { |
| 114520 | if(key == NULL || cc == NULL) |
| 114521 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114522 | |
| 114523 | UA_ByteString_clear(&cc->remoteSymSigningKey); |
| 114524 | return UA_ByteString_copy(key, &cc->remoteSymSigningKey); |
| 114525 | } |
| 114526 | |
| 114527 | static UA_StatusCode |
| 114528 | channelContext_setRemoteSymIv_sp_aes256sha256rsapss(Aes256Sha256RsaPss_ChannelContext *cc, |
| 114529 | const UA_ByteString *iv) { |
| 114530 | if(iv == NULL || cc == NULL) |
| 114531 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114532 | |
| 114533 | UA_ByteString_clear(&cc->remoteSymIv); |
| 114534 | return UA_ByteString_copy(iv, &cc->remoteSymIv); |
| 114535 | } |
| 114536 | |
| 114537 | static UA_StatusCode |
| 114538 | channelContext_compareCertificate_sp_aes256sha256rsapss(const Aes256Sha256RsaPss_ChannelContext *cc, |
| 114539 | const UA_ByteString *certificate) { |
| 114540 | if(cc == NULL || certificate == NULL) |
| 114541 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114542 | |
| 114543 | mbedtls_x509_crt cert; |
| 114544 | mbedtls_x509_crt_init(&cert); |
| 114545 | int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, certificate->length); |
| 114546 | if(mbedErr) |
| 114547 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114548 | |
| 114549 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 114550 | if(cert.raw.len != cc->remoteCertificate.raw.len || |
| 114551 | memcmp(cert.raw.p, cc->remoteCertificate.raw.p, cert.raw.len) != 0) |
| 114552 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114553 | |
| 114554 | mbedtls_x509_crt_free(&cert); |
| 114555 | return retval; |
| 114556 | } |
| 114557 | |
| 114558 | static void |
| 114559 | clear_sp_aes256sha256rsapss(UA_SecurityPolicy *securityPolicy) { |
| 114560 | if(securityPolicy == NULL) |
| 114561 | return; |
| 114562 | |
| 114563 | UA_ByteString_clear(&securityPolicy->localCertificate); |
| 114564 | |
| 114565 | if(securityPolicy->policyContext == NULL) |
| 114566 | return; |
| 114567 | |
| 114568 | /* delete all allocated members in the context */ |
| 114569 | Aes256Sha256RsaPss_PolicyContext *pc = (Aes256Sha256RsaPss_PolicyContext *) |
| 114570 | securityPolicy->policyContext; |
| 114571 | |
| 114572 | mbedtls_ctr_drbg_free(&pc->drbgContext); |
| 114573 | mbedtls_entropy_free(&pc->entropyContext); |
| 114574 | mbedtls_pk_free(&pc->localPrivateKey); |
| 114575 | mbedtls_md_free(&pc->sha256MdContext); |
| 114576 | UA_ByteString_clear(&pc->localCertThumbprint); |
| 114577 | |
| 114578 | UA_LOG_DEBUG(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 114579 | "Deleted members of EndpointContext for sp_aes256sha256rsapss"); |
| 114580 | |
| 114581 | UA_free(pc); |
| 114582 | securityPolicy->policyContext = NULL; |
| 114583 | } |
| 114584 | |
| 114585 | static UA_StatusCode |
| 114586 | updateCertificateAndPrivateKey_sp_aes256sha256rsapss(UA_SecurityPolicy *securityPolicy, |
| 114587 | const UA_ByteString newCertificate, |
| 114588 | const UA_ByteString newPrivateKey) { |
| 114589 | if(securityPolicy == NULL) |
| 114590 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114591 | |
| 114592 | if(securityPolicy->policyContext == NULL) |
| 114593 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114594 | |
| 114595 | Aes256Sha256RsaPss_PolicyContext *pc = |
| 114596 | (Aes256Sha256RsaPss_PolicyContext *) securityPolicy->policyContext; |
| 114597 | |
| 114598 | UA_ByteString_clear(&securityPolicy->localCertificate); |
| 114599 | |
| 114600 | UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&newCertificate, &securityPolicy->localCertificate); |
| 114601 | |
| 114602 | if(retval != UA_STATUSCODE_GOOD) |
| 114603 | return retval; |
| 114604 | |
| 114605 | /* Set the new private key */ |
| 114606 | mbedtls_pk_free(&pc->localPrivateKey); |
| 114607 | mbedtls_pk_init(&pc->localPrivateKey); |
| 114608 | int mbedErr = UA_mbedTLS_LoadPrivateKey(&newPrivateKey, &pc->localPrivateKey, &pc->entropyContext); |
| 114609 | if(mbedErr) { |
| 114610 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114611 | goto error; |
| 114612 | } |
| 114613 | |
| 114614 | retval = asym_makeThumbprint_sp_aes256sha256rsapss(securityPolicy, |
| 114615 | &securityPolicy->localCertificate, |
| 114616 | &pc->localCertThumbprint); |
| 114617 | if(retval != UA_STATUSCODE_GOOD) |
| 114618 | goto error; |
| 114619 | |
| 114620 | return retval; |
| 114621 | |
| 114622 | error: |
| 114623 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 114624 | "Could not update certificate and private key"); |
| 114625 | if(securityPolicy->policyContext != NULL) |
| 114626 | clear_sp_aes256sha256rsapss(securityPolicy); |
| 114627 | return retval; |
| 114628 | } |
| 114629 | |
| 114630 | static UA_StatusCode |
| 114631 | policyContext_newContext_sp_aes256sha256rsapss(UA_SecurityPolicy *securityPolicy, |
| 114632 | const UA_ByteString localPrivateKey) { |
| 114633 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 114634 | if(securityPolicy == NULL) |
| 114635 | return UA_STATUSCODE_BADINTERNALERROR; |
| 114636 | |
| 114637 | if (localPrivateKey.length == 0) { |
| 114638 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 114639 | "Can not initialize security policy. Private key is empty."); |
| 114640 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 114641 | } |
| 114642 | |
| 114643 | Aes256Sha256RsaPss_PolicyContext *pc = (Aes256Sha256RsaPss_PolicyContext *) |
| 114644 | UA_malloc(sizeof(Aes256Sha256RsaPss_PolicyContext)); |
| 114645 | securityPolicy->policyContext = (void *)pc; |
| 114646 | if(!pc) { |
| 114647 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 114648 | goto error; |
| 114649 | } |
| 114650 | |
| 114651 | /* Initialize the PolicyContext */ |
| 114652 | memset(pc, 0, sizeof(Aes256Sha256RsaPss_PolicyContext)); |
| 114653 | mbedtls_ctr_drbg_init(&pc->drbgContext); |
| 114654 | mbedtls_entropy_init(&pc->entropyContext); |
| 114655 | mbedtls_pk_init(&pc->localPrivateKey); |
| 114656 | mbedtls_md_init(&pc->sha256MdContext); |
| 114657 | |
| 114658 | /* Initialized the message digest */ |
| 114659 | const mbedtls_md_info_t *const mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); |
| 114660 | int mbedErr = mbedtls_md_setup(&pc->sha256MdContext, mdInfo, MBEDTLS_MD_SHA256); |
| 114661 | if(mbedErr) { |
| 114662 | retval = UA_STATUSCODE_BADOUTOFMEMORY; |
| 114663 | goto error; |
| 114664 | } |
| 114665 | |
| 114666 | mbedErr = mbedtls_entropy_self_test(0); |
| 114667 | |
| 114668 | if(mbedErr) { |
| 114669 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114670 | goto error; |
| 114671 | } |
| 114672 | |
| 114673 | /* Seed the RNG */ |
| 114674 | char *personalization = "open62541-drbg"; |
| 114675 | mbedErr = mbedtls_ctr_drbg_seed(&pc->drbgContext, mbedtls_entropy_func, |
| 114676 | &pc->entropyContext, |
| 114677 | (const unsigned char *)personalization, 14); |
| 114678 | if(mbedErr) { |
| 114679 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114680 | goto error; |
| 114681 | } |
| 114682 | |
| 114683 | /* Set the private key */ |
| 114684 | mbedErr = UA_mbedTLS_LoadPrivateKey(&localPrivateKey, &pc->localPrivateKey, &pc->entropyContext); |
| 114685 | if(mbedErr) { |
| 114686 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 114687 | goto error; |
| 114688 | } |
| 114689 | |
| 114690 | /* Set the local certificate thumbprint */ |
| 114691 | retval = UA_ByteString_allocBuffer(&pc->localCertThumbprint, UA_SHA1_LENGTH); |
| 114692 | if(retval != UA_STATUSCODE_GOOD) |
| 114693 | goto error; |
| 114694 | retval = asym_makeThumbprint_sp_aes256sha256rsapss(securityPolicy, |
| 114695 | &securityPolicy->localCertificate, |
| 114696 | &pc->localCertThumbprint); |
| 114697 | if(retval != UA_STATUSCODE_GOOD) |
| 114698 | goto error; |
| 114699 | |
| 114700 | return UA_STATUSCODE_GOOD; |
| 114701 | |
| 114702 | error: |
| 114703 | UA_LOG_ERROR(securityPolicy->logger, UA_LOGCATEGORY_SECURITYPOLICY, |
| 114704 | "Could not create securityContext: %s", UA_StatusCode_name(retval)); |
| 114705 | if(securityPolicy->policyContext != NULL) |
| 114706 | clear_sp_aes256sha256rsapss(securityPolicy); |
| 114707 | return retval; |
| 114708 | } |
| 114709 | |
| 114710 | UA_StatusCode |
| 114711 | UA_SecurityPolicy_Aes256Sha256RsaPss(UA_SecurityPolicy *policy, const UA_ByteString localCertificate, |
| 114712 | const UA_ByteString localPrivateKey, const UA_Logger *logger) { |
| 114713 | memset(policy, 0, sizeof(UA_SecurityPolicy)); |
| 114714 | policy->logger = logger; |
| 114715 | |
| 114716 | policy->policyUri = UA_STRING("http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss"); |
| 114717 | |
| 114718 | UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule; |
| 114719 | UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule; |
| 114720 | UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule; |
| 114721 | |
| 114722 | UA_StatusCode retval = UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate); |
| 114723 | |
| 114724 | if (retval != UA_STATUSCODE_GOOD) |
| 114725 | return retval; |
| 114726 | |
| 114727 | /* AsymmetricModule */ |
| 114728 | UA_SecurityPolicySignatureAlgorithm *asym_signatureAlgorithm = |
| 114729 | &asymmetricModule->cryptoModule.signatureAlgorithm; |
| 114730 | asym_signatureAlgorithm->uri = |
| 114731 | UA_STRING("http://opcfoundation.org/UA/security/rsa-pss-sha2-256\0"); |
| 114732 | asym_signatureAlgorithm->verify = |
| 114733 | (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_verify_sp_aes256sha256rsapss; |
| 114734 | asym_signatureAlgorithm->sign = |
| 114735 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_sign_sp_aes256sha256rsapss; |
| 114736 | asym_signatureAlgorithm->getLocalSignatureSize = |
| 114737 | (size_t (*)(const void *))asym_getLocalSignatureSize_sp_aes256sha256rsapss; |
| 114738 | asym_signatureAlgorithm->getRemoteSignatureSize = |
| 114739 | (size_t (*)(const void *))asym_getRemoteSignatureSize_sp_aes256sha256rsapss; |
| 114740 | asym_signatureAlgorithm->getLocalKeyLength = NULL; // TODO: Write function |
| 114741 | asym_signatureAlgorithm->getRemoteKeyLength = NULL; // TODO: Write function |
| 114742 | |
| 114743 | UA_SecurityPolicyEncryptionAlgorithm *asym_encryptionAlgorithm = |
| 114744 | &asymmetricModule->cryptoModule.encryptionAlgorithm; |
| 114745 | asym_encryptionAlgorithm->uri = UA_STRING("http://opcfoundation.org/UA/security/rsa-oaep-sha2-256\0"); |
| 114746 | asym_encryptionAlgorithm->encrypt = |
| 114747 | (UA_StatusCode(*)(void *, UA_ByteString *))asym_encrypt_sp_aes256sha256rsapss; |
| 114748 | asym_encryptionAlgorithm->decrypt = |
| 114749 | (UA_StatusCode(*)(void *, UA_ByteString *)) asym_decrypt_sp_aes256sha256rsapss; |
| 114750 | asym_encryptionAlgorithm->getLocalKeyLength = |
| 114751 | (size_t (*)(const void *))asym_getLocalEncryptionKeyLength_sp_aes256sha256rsapss; |
| 114752 | asym_encryptionAlgorithm->getRemoteKeyLength = |
| 114753 | (size_t (*)(const void *))asym_getRemoteEncryptionKeyLength_sp_aes256sha256rsapss; |
| 114754 | asym_encryptionAlgorithm->getRemoteBlockSize = (size_t (*)(const void *))asym_getRemoteBlockSize_sp_aes256sha256rsapss; |
| 114755 | asym_encryptionAlgorithm->getRemotePlainTextBlockSize = |
| 114756 | (size_t (*)(const void *))asym_getRemotePlainTextBlockSize_sp_aes256sha256rsapss; |
| 114757 | |
| 114758 | asymmetricModule->makeCertificateThumbprint = asym_makeThumbprint_sp_aes256sha256rsapss; |
| 114759 | asymmetricModule->compareCertificateThumbprint = |
| 114760 | asymmetricModule_compareCertificateThumbprint_sp_aes256sha256rsapss; |
| 114761 | |
| 114762 | /* SymmetricModule */ |
| 114763 | symmetricModule->generateKey = sym_generateKey_sp_aes256sha256rsapss; |
| 114764 | symmetricModule->generateNonce = sym_generateNonce_sp_aes256sha256rsapss; |
| 114765 | |
| 114766 | UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm = |
| 114767 | &symmetricModule->cryptoModule.signatureAlgorithm; |
| 114768 | sym_signatureAlgorithm->uri = |
| 114769 | UA_STRING("http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0"); |
| 114770 | sym_signatureAlgorithm->verify = |
| 114771 | (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))sym_verify_sp_aes256sha256rsapss; |
| 114772 | sym_signatureAlgorithm->sign = |
| 114773 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))sym_sign_sp_aes256sha256rsapss; |
| 114774 | sym_signatureAlgorithm->getLocalSignatureSize = sym_getSignatureSize_sp_aes256sha256rsapss; |
| 114775 | sym_signatureAlgorithm->getRemoteSignatureSize = sym_getSignatureSize_sp_aes256sha256rsapss; |
| 114776 | sym_signatureAlgorithm->getLocalKeyLength = |
| 114777 | (size_t (*)(const void *))sym_getSigningKeyLength_sp_aes256sha256rsapss; |
| 114778 | sym_signatureAlgorithm->getRemoteKeyLength = |
| 114779 | (size_t (*)(const void *))sym_getSigningKeyLength_sp_aes256sha256rsapss; |
| 114780 | |
| 114781 | UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm = |
| 114782 | &symmetricModule->cryptoModule.encryptionAlgorithm; |
| 114783 | sym_encryptionAlgorithm->uri = UA_STRING("http://www.w3.org/2001/04/xmlenc#aes256-cbc\0"); |
| 114784 | sym_encryptionAlgorithm->encrypt = |
| 114785 | (UA_StatusCode(*)(void *, UA_ByteString *))sym_encrypt_sp_aes256sha256rsapss; |
| 114786 | sym_encryptionAlgorithm->decrypt = |
| 114787 | (UA_StatusCode(*)(void *, UA_ByteString *))sym_decrypt_sp_aes256sha256rsapss; |
| 114788 | sym_encryptionAlgorithm->getLocalKeyLength = sym_getEncryptionKeyLength_sp_aes256sha256rsapss; |
| 114789 | sym_encryptionAlgorithm->getRemoteKeyLength = sym_getEncryptionKeyLength_sp_aes256sha256rsapss; |
| 114790 | sym_encryptionAlgorithm->getRemoteBlockSize = |
| 114791 | (size_t (*)(const void *))sym_getEncryptionBlockSize_sp_aes256sha256rsapss; |
| 114792 | sym_encryptionAlgorithm->getRemotePlainTextBlockSize = |
| 114793 | (size_t (*)(const void *))sym_getPlainTextBlockSize_sp_aes256sha256rsapss; |
| 114794 | symmetricModule->secureChannelNonceLength = 32; |
| 114795 | |
| 114796 | /* Certificate Signing Algorithm */ |
| 114797 | policy->certificateSigningAlgorithm.uri = |
| 114798 | UA_STRING("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0"); |
| 114799 | policy->certificateSigningAlgorithm.verify = |
| 114800 | (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))asym_cert_verify_sp_aes256sha256rsapss; |
| 114801 | policy->certificateSigningAlgorithm.sign = |
| 114802 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))asym_cert_sign_sp_aes256sha256rsapss; |
| 114803 | policy->certificateSigningAlgorithm.getLocalSignatureSize = |
| 114804 | (size_t (*)(const void *))asym_cert_getLocalSignatureSize_sp_aes256sha256rsapss; |
| 114805 | policy->certificateSigningAlgorithm.getRemoteSignatureSize = |
| 114806 | (size_t (*)(const void *))asym_cert_getRemoteSignatureSize_sp_aes256sha256rsapss; |
| 114807 | policy->certificateSigningAlgorithm.getLocalKeyLength = NULL; // TODO: Write function |
| 114808 | policy->certificateSigningAlgorithm.getRemoteKeyLength = NULL; // TODO: Write function |
| 114809 | |
| 114810 | /* ChannelModule */ |
| 114811 | channelModule->newContext = channelContext_newContext_sp_aes256sha256rsapss; |
| 114812 | channelModule->deleteContext = (void (*)(void *)) |
| 114813 | channelContext_deleteContext_sp_aes256sha256rsapss; |
| 114814 | |
| 114815 | channelModule->setLocalSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 114816 | channelContext_setLocalSymEncryptingKey_sp_aes256sha256rsapss; |
| 114817 | channelModule->setLocalSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 114818 | channelContext_setLocalSymSigningKey_sp_aes256sha256rsapss; |
| 114819 | channelModule->setLocalSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 114820 | channelContext_setLocalSymIv_sp_aes256sha256rsapss; |
| 114821 | |
| 114822 | channelModule->setRemoteSymEncryptingKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 114823 | channelContext_setRemoteSymEncryptingKey_sp_aes256sha256rsapss; |
| 114824 | channelModule->setRemoteSymSigningKey = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 114825 | channelContext_setRemoteSymSigningKey_sp_aes256sha256rsapss; |
| 114826 | channelModule->setRemoteSymIv = (UA_StatusCode (*)(void *, const UA_ByteString *)) |
| 114827 | channelContext_setRemoteSymIv_sp_aes256sha256rsapss; |
| 114828 | |
| 114829 | channelModule->compareCertificate = (UA_StatusCode (*)(const void *, const UA_ByteString *)) |
| 114830 | channelContext_compareCertificate_sp_aes256sha256rsapss; |
| 114831 | |
| 114832 | policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_aes256sha256rsapss; |
| 114833 | policy->clear = clear_sp_aes256sha256rsapss; |
| 114834 | |
| 114835 | UA_StatusCode res = policyContext_newContext_sp_aes256sha256rsapss(policy, localPrivateKey); |
| 114836 | if(res != UA_STATUSCODE_GOOD) |
| 114837 | clear_sp_aes256sha256rsapss(policy); |
| 114838 | |
| 114839 | return res; |
| 114840 | } |
| 114841 | |
| 114842 | #endif |
| 114843 | |
| 114844 | /**** amalgamated original file "/plugins/crypto/mbedtls/ua_mbedtls_create_certificate.c" ****/ |
| 114845 | |
| 114846 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 114847 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 114848 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 114849 | * |
| 114850 | * Copyright (c) 2023 Fraunhofer IOSB (Author: Noel Graf) |
| 114851 | * |
| 114852 | */ |
| 114853 | |
| 114854 | #include <time.h> |
| 114855 | |
| 114856 | |
| 114857 | #if defined(UA_ENABLE_ENCRYPTION_MBEDTLS) |
| 114858 | |
| 114859 | #include <mbedtls/x509_crt.h> |
| 114860 | #include <mbedtls/oid.h> |
| 114861 | #include <mbedtls/asn1write.h> |
| 114862 | #include <mbedtls/entropy.h> |
| 114863 | #include <mbedtls/ctr_drbg.h> |
| 114864 | #include <mbedtls/platform.h> |
| 114865 | #include <mbedtls/version.h> |
| 114866 | |
| 114867 | #define SET_OID(x, oid) \ |
| 114868 | do { x.len = MBEDTLS_OID_SIZE(oid); x.p = (unsigned char *) oid; } while (0) |
| 114869 | |
| 114870 | #define MBEDTLS_ASN1_CHK_CLEANUP_ADD(g, f) \ |
| 114871 | do \ |
| 114872 | { \ |
| 114873 | if ((ret = (f)) < 0) \ |
| 114874 | goto cleanup; \ |
| 114875 | else \ |
| 114876 | (g) += ret; \ |
| 114877 | } while (0) |
| 114878 | |
| 114879 | #if MBEDTLS_VERSION_NUMBER < 0x02170000 |
| 114880 | #define MBEDTLS_X509_SAN_OTHER_NAME 0 |
| 114881 | #define MBEDTLS_X509_SAN_RFC822_NAME 1 |
| 114882 | #define MBEDTLS_X509_SAN_DNS_NAME 2 |
| 114883 | #define MBEDTLS_X509_SAN_X400_ADDRESS_NAME 3 |
| 114884 | #define MBEDTLS_X509_SAN_DIRECTORY_NAME 4 |
| 114885 | #define MBEDTLS_X509_SAN_EDI_PARTY_NAME 5 |
| 114886 | #define MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER 6 |
| 114887 | #define MBEDTLS_X509_SAN_IP_ADDRESS 7 |
| 114888 | #define MBEDTLS_X509_SAN_REGISTERED_ID 8 |
| 114889 | #endif |
| 114890 | |
| 114891 | #define MBEDTLS_SAN_MAX_LEN 64 |
| 114892 | typedef struct mbedtls_write_san_node{ |
| 114893 | int type; |
| 114894 | char* host; |
| 114895 | size_t hostlen; |
| 114896 | } mbedtls_write_san_node; |
| 114897 | |
| 114898 | typedef struct mbedtls_write_san_list{ |
| 114899 | mbedtls_write_san_node node; |
| 114900 | struct mbedtls_write_san_list* next; |
| 114901 | } mbedtls_write_san_list; |
| 114902 | |
| 114903 | static size_t mbedtls_get_san_list_deep(const mbedtls_write_san_list* sanlist); |
| 114904 | |
| 114905 | int mbedtls_x509write_crt_set_subject_alt_name(mbedtls_x509write_cert *ctx, const mbedtls_write_san_list* sanlist); |
| 114906 | |
| 114907 | #if MBEDTLS_VERSION_NUMBER < 0x03030000 |
| 114908 | int mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx, |
| 114909 | const mbedtls_asn1_sequence *exts); |
| 114910 | #endif |
| 114911 | |
| 114912 | static int write_certificate(mbedtls_x509write_cert *crt, UA_CertificateFormat certFormat, |
| 114913 | UA_ByteString *outCertificate, int (*f_rng)(void *, unsigned char *, size_t), |
| 114914 | void *p_rng); |
| 114915 | |
| 114916 | static int write_private_key(mbedtls_pk_context *key, UA_CertificateFormat keyFormat, UA_ByteString *outPrivateKey); |
| 114917 | |
| 114918 | UA_StatusCode |
| 114919 | UA_CreateCertificate(const UA_Logger *logger, const UA_String *subject, |
| 114920 | size_t subjectSize, const UA_String *subjectAltName, |
| 114921 | size_t subjectAltNameSize, UA_CertificateFormat certFormat, |
| 114922 | UA_KeyValueMap *params, UA_ByteString *outPrivateKey, |
| 114923 | UA_ByteString *outCertificate) { |
| 114924 | if(!outPrivateKey || !outCertificate || !logger || !subjectAltName || !subject || |
| 114925 | subjectAltNameSize == 0 || subjectSize == 0 || |
| 114926 | (certFormat != UA_CERTIFICATEFORMAT_DER && certFormat != UA_CERTIFICATEFORMAT_PEM)) |
| 114927 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 114928 | |
| 114929 | /* Use the maximum size */ |
| 114930 | UA_UInt16 keySizeBits = 4096; |
| 114931 | /* Default to 1 year */ |
| 114932 | UA_UInt16 expiresInDays = 365; |
| 114933 | |
| 114934 | if(params) { |
| 114935 | const UA_UInt16 *keySizeBitsValue = (const UA_UInt16 *)UA_KeyValueMap_getScalar( |
| 114936 | params, UA_QUALIFIEDNAME(0, "key-size-bits"), &UA_TYPES[UA_TYPES_UINT16]); |
| 114937 | if(keySizeBitsValue) |
| 114938 | keySizeBits = *keySizeBitsValue; |
| 114939 | |
| 114940 | const UA_UInt16 *expiresInDaysValue = (const UA_UInt16 *)UA_KeyValueMap_getScalar( |
| 114941 | params, UA_QUALIFIEDNAME(0, "expires-in-days"), &UA_TYPES[UA_TYPES_UINT16]); |
| 114942 | if(expiresInDaysValue) |
| 114943 | expiresInDays = *expiresInDaysValue; |
| 114944 | } |
| 114945 | |
| 114946 | UA_ByteString_init(outPrivateKey); |
| 114947 | UA_ByteString_init(outCertificate); |
| 114948 | |
| 114949 | mbedtls_pk_context key; |
| 114950 | mbedtls_ctr_drbg_context ctr_drbg; |
| 114951 | mbedtls_entropy_context entropy; |
| 114952 | const char *pers = "gen_key"; |
| 114953 | mbedtls_x509write_cert crt; |
| 114954 | |
| 114955 | UA_StatusCode errRet = UA_STATUSCODE_GOOD; |
| 114956 | |
| 114957 | /* Set to sane values */ |
| 114958 | mbedtls_pk_init(&key); |
| 114959 | mbedtls_ctr_drbg_init(&ctr_drbg); |
| 114960 | mbedtls_entropy_init(&entropy); |
| 114961 | mbedtls_x509write_crt_init(&crt); |
| 114962 | |
| 114963 | /* Seed the random number generator */ |
| 114964 | if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers)) != 0) { |
| 114965 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 114966 | "Failed to initialize the random number generator."); |
| 114967 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 114968 | goto cleanup; |
| 114969 | } |
| 114970 | |
| 114971 | /* Generate an RSA key pair */ |
| 114972 | if (mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA)) != 0 || |
| 114973 | mbedtls_rsa_gen_key(mbedtls_pk_rsa(key), mbedtls_ctr_drbg_random, &ctr_drbg, keySizeBits, 65537) != 0) { |
| 114974 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 114975 | "Failed to generate RSA key pair."); |
| 114976 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 114977 | goto cleanup; |
| 114978 | } |
| 114979 | |
| 114980 | /* Setting certificate values */ |
| 114981 | mbedtls_x509write_crt_set_version(&crt, MBEDTLS_X509_CRT_VERSION_3); |
| 114982 | mbedtls_x509write_crt_set_md_alg(&crt, MBEDTLS_MD_SHA256); |
| 114983 | |
| 114984 | size_t subject_char_len = 0; |
| 114985 | for(size_t i = 0; i < subjectSize; i++) { |
| 114986 | subject_char_len += subject[i].length; |
| 114987 | } |
| 114988 | char *subject_char = (char*)UA_malloc(subject_char_len + subjectSize); |
| 114989 | if(!subject_char) { |
| 114990 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 114991 | "Cannot allocate memory for subject. Out of memory."); |
| 114992 | errRet = UA_STATUSCODE_BADOUTOFMEMORY; |
| 114993 | goto cleanup; |
| 114994 | } |
| 114995 | |
| 114996 | size_t pos = 0; |
| 114997 | for(size_t i = 0; i < subjectSize; i++) { |
| 114998 | subject_char_len += subject[i].length; |
| 114999 | memcpy(subject_char + pos, subject[i].data, subject[i].length); |
| 115000 | pos += subject[i].length; |
| 115001 | if(i < subjectSize - 1) |
| 115002 | subject_char[pos++] = ','; |
| 115003 | else |
| 115004 | subject_char[pos++] = '\0'; |
| 115005 | } |
| 115006 | |
| 115007 | if((mbedtls_x509write_crt_set_subject_name(&crt, subject_char)) != 0) { |
| 115008 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 115009 | "Setting subject failed."); |
| 115010 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 115011 | UA_free(subject_char); |
| 115012 | goto cleanup; |
| 115013 | } |
| 115014 | |
| 115015 | if((mbedtls_x509write_crt_set_issuer_name(&crt, subject_char)) != 0) { |
| 115016 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 115017 | "Setting issuer failed."); |
| 115018 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 115019 | UA_free(subject_char); |
| 115020 | goto cleanup; |
| 115021 | } |
| 115022 | |
| 115023 | UA_free(subject_char); |
| 115024 | |
| 115025 | mbedtls_write_san_list *cur = NULL; |
| 115026 | mbedtls_write_san_list *cur_tmp = NULL; |
| 115027 | mbedtls_write_san_list *head = NULL; |
| 115028 | for(size_t i = 0; i < subjectAltNameSize; i++) { |
| 115029 | char *sanType; |
| 115030 | char *sanValue; |
| 115031 | size_t sanValueLength; |
| 115032 | char *subAlt = (char *)UA_malloc(subjectAltName[i].length + 1); |
| 115033 | memcpy(subAlt, subjectAltName[i].data, subjectAltName[i].length); |
| 115034 | |
| 115035 | /* null-terminate the copied string */ |
| 115036 | subAlt[subjectAltName[i].length] = 0; |
| 115037 | /* split into SAN type and value */ |
| 115038 | sanType = strtok(subAlt, ":"); |
| 115039 | sanValue = (char *)subjectAltName[i].data + strlen(sanType) + 1; |
| 115040 | sanValueLength = subjectAltName[i].length - strlen(sanType) - 1; |
| 115041 | |
| 115042 | if(sanType) { |
| 115043 | cur_tmp = (mbedtls_write_san_list*)mbedtls_calloc(1, sizeof(mbedtls_write_san_list)); |
| 115044 | cur_tmp->next = NULL; |
| 115045 | cur_tmp->node.host = sanValue; |
| 115046 | cur_tmp->node.hostlen = sanValueLength; |
| 115047 | |
| 115048 | if(strcmp(sanType, "DNS") == 0) { |
| 115049 | cur_tmp->node.type = MBEDTLS_X509_SAN_DNS_NAME; |
| 115050 | } else if(strcmp(sanType, "URI") == 0) { |
| 115051 | cur_tmp->node.type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER; |
| 115052 | } else if(strcmp(sanType, "IP") == 0) { |
| 115053 | uint8_t ip[4] = {0}; |
| 115054 | if(UA_inet_pton(AF_INET, sanValue, ip) <= 0) { |
| 115055 | UA_LOG_WARNING(logger, UA_LOGCATEGORY_SECURECHANNEL, "IP SAN preparation failed"); |
| 115056 | mbedtls_free(cur_tmp); |
| 115057 | UA_free(subAlt); |
| 115058 | continue; |
| 115059 | } |
| 115060 | cur_tmp->node.type = MBEDTLS_X509_SAN_IP_ADDRESS; |
| 115061 | cur_tmp->node.host = (char *)ip; |
| 115062 | cur_tmp->node.hostlen = sizeof(ip); |
| 115063 | } else if(strcmp(sanType, "RFC822") == 0) { |
| 115064 | cur_tmp->node.type = MBEDTLS_X509_SAN_RFC822_NAME; |
| 115065 | } else { |
| 115066 | UA_LOG_WARNING(logger, UA_LOGCATEGORY_SECURECHANNEL, "Given an unsupported SAN"); |
| 115067 | mbedtls_free(cur_tmp); |
| 115068 | UA_free(subAlt); |
| 115069 | continue; |
| 115070 | } |
| 115071 | } else { |
| 115072 | UA_LOG_WARNING(logger, UA_LOGCATEGORY_SECURECHANNEL, "Invalid Input format"); |
| 115073 | UA_free(subAlt); |
| 115074 | continue; |
| 115075 | } |
| 115076 | |
| 115077 | if(!cur) { |
| 115078 | cur = cur_tmp; |
| 115079 | head = cur_tmp; |
| 115080 | } else { |
| 115081 | cur->next = cur_tmp; |
| 115082 | cur = cur->next; |
| 115083 | } |
| 115084 | |
| 115085 | UA_free(subAlt); |
| 115086 | } |
| 115087 | |
| 115088 | if((mbedtls_x509write_crt_set_subject_alt_name(&crt, head)) != 0) { |
| 115089 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 115090 | "Setting subject alternative name failed."); |
| 115091 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 115092 | while(head != NULL) { |
| 115093 | cur_tmp = head->next; |
| 115094 | mbedtls_free(head); |
| 115095 | head = cur_tmp; |
| 115096 | } |
| 115097 | goto cleanup; |
| 115098 | } |
| 115099 | |
| 115100 | while(head != NULL) { |
| 115101 | cur_tmp = head->next; |
| 115102 | mbedtls_free(head); |
| 115103 | head = cur_tmp; |
| 115104 | } |
| 115105 | |
| 115106 | #if MBEDTLS_VERSION_NUMBER >= 0x03040000 |
| 115107 | unsigned char *serial = (unsigned char *)"1"; |
| 115108 | size_t serial_len = 1; |
| 115109 | mbedtls_x509write_crt_set_serial_raw(&crt, serial, serial_len); |
| 115110 | #else |
| 115111 | mbedtls_mpi serial_mpi; |
| 115112 | mbedtls_mpi_init(&serial_mpi); |
| 115113 | mbedtls_mpi_lset(&serial_mpi, 1); |
| 115114 | mbedtls_x509write_crt_set_serial(&crt, &serial_mpi); |
| 115115 | mbedtls_mpi_free(&serial_mpi); |
| 115116 | #endif |
| 115117 | |
| 115118 | /* Get the current time */ |
| 115119 | time_t rawTime; |
| 115120 | struct tm *timeInfo; |
| 115121 | time(&rawTime); |
| 115122 | timeInfo = gmtime(&rawTime); |
| 115123 | |
| 115124 | /* Format the current timestamp */ |
| 115125 | char current_timestamp[15]; // YYYYMMDDhhmmss + '\0' |
| 115126 | strftime(current_timestamp, sizeof(current_timestamp), "%Y%m%d%H%M%S", timeInfo); |
| 115127 | |
| 115128 | /* Calculate the future timestamp */ |
| 115129 | timeInfo->tm_mday += expiresInDays; |
| 115130 | time_t future_time = mktime(timeInfo); |
| 115131 | |
| 115132 | /* Format the future timestamp */ |
| 115133 | char future_timestamp[15]; // YYYYMMDDhhmmss + '\0' |
| 115134 | strftime(future_timestamp, sizeof(future_timestamp), "%Y%m%d%H%M%S", gmtime(&future_time)); |
| 115135 | |
| 115136 | if(mbedtls_x509write_crt_set_validity(&crt, current_timestamp, future_timestamp) != 0) { |
| 115137 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 115138 | "Setting 'not before' and 'not after' failed."); |
| 115139 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 115140 | goto cleanup; |
| 115141 | } |
| 115142 | |
| 115143 | if(mbedtls_x509write_crt_set_basic_constraints(&crt, 0, -1) != 0) { |
| 115144 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 115145 | "Setting basic constraints failed."); |
| 115146 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 115147 | goto cleanup; |
| 115148 | } |
| 115149 | |
| 115150 | if(mbedtls_x509write_crt_set_key_usage(&crt, MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_NON_REPUDIATION |
| 115151 | | MBEDTLS_X509_KU_KEY_ENCIPHERMENT | MBEDTLS_X509_KU_DATA_ENCIPHERMENT |
| 115152 | | MBEDTLS_X509_KU_KEY_CERT_SIGN | MBEDTLS_X509_KU_CRL_SIGN) != 0) { |
| 115153 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 115154 | "Setting key usage failed."); |
| 115155 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 115156 | goto cleanup; |
| 115157 | } |
| 115158 | |
| 115159 | mbedtls_asn1_sequence *ext_key_usage; |
| 115160 | ext_key_usage = (mbedtls_asn1_sequence *)mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); |
| 115161 | ext_key_usage->buf.tag = MBEDTLS_ASN1_OID; |
| 115162 | SET_OID(ext_key_usage->buf, MBEDTLS_OID_SERVER_AUTH); |
| 115163 | ext_key_usage->next = (mbedtls_asn1_sequence *)mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); |
| 115164 | ext_key_usage->next->buf.tag = MBEDTLS_ASN1_OID; |
| 115165 | SET_OID(ext_key_usage->next->buf, MBEDTLS_OID_CLIENT_AUTH); |
| 115166 | |
| 115167 | if(mbedtls_x509write_crt_set_ext_key_usage(&crt, ext_key_usage) != 0) { |
| 115168 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 115169 | "Setting extended key usage failed."); |
| 115170 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 115171 | mbedtls_free(ext_key_usage->next); |
| 115172 | mbedtls_free(ext_key_usage); |
| 115173 | goto cleanup; |
| 115174 | } |
| 115175 | |
| 115176 | mbedtls_free(ext_key_usage->next); |
| 115177 | mbedtls_free(ext_key_usage); |
| 115178 | |
| 115179 | mbedtls_x509write_crt_set_subject_key(&crt, &key); |
| 115180 | mbedtls_x509write_crt_set_issuer_key(&crt, &key); |
| 115181 | |
| 115182 | |
| 115183 | /* Write private key */ |
| 115184 | if ((write_private_key(&key, certFormat, outPrivateKey)) != 0) { |
| 115185 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 115186 | "Create Certificate: Writing private key failed."); |
| 115187 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 115188 | goto cleanup; |
| 115189 | } |
| 115190 | |
| 115191 | /* Write Certificate */ |
| 115192 | if ((write_certificate(&crt, certFormat, outCertificate, |
| 115193 | mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) { |
| 115194 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 115195 | "Create Certificate: Writing certificate failed."); |
| 115196 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 115197 | goto cleanup; |
| 115198 | } |
| 115199 | |
| 115200 | mbedtls_ctr_drbg_free(&ctr_drbg); |
| 115201 | mbedtls_entropy_free(&entropy); |
| 115202 | mbedtls_x509write_crt_free(&crt); |
| 115203 | mbedtls_pk_free(&key); |
| 115204 | |
| 115205 | cleanup: |
| 115206 | mbedtls_ctr_drbg_free(&ctr_drbg); |
| 115207 | mbedtls_entropy_free(&entropy); |
| 115208 | mbedtls_x509write_crt_free(&crt); |
| 115209 | mbedtls_pk_free(&key); |
| 115210 | return errRet; |
| 115211 | } |
| 115212 | |
| 115213 | static int write_private_key(mbedtls_pk_context *key, UA_CertificateFormat keyFormat, UA_ByteString *outPrivateKey) { |
| 115214 | int ret; |
| 115215 | unsigned char output_buf[16000]; |
| 115216 | unsigned char *c = output_buf; |
| 115217 | size_t len = 0; |
| 115218 | |
| 115219 | memset(output_buf, 0, sizeof(output_buf)); |
| 115220 | switch(keyFormat) { |
| 115221 | case UA_CERTIFICATEFORMAT_DER: { |
| 115222 | if((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) { |
| 115223 | return ret; |
| 115224 | } |
| 115225 | |
| 115226 | len = ret; |
| 115227 | c = output_buf + sizeof(output_buf) - len; |
| 115228 | break; |
| 115229 | } |
| 115230 | case UA_CERTIFICATEFORMAT_PEM: { |
| 115231 | if((ret = mbedtls_pk_write_key_pem(key, output_buf, sizeof(output_buf))) != 0) { |
| 115232 | return ret; |
| 115233 | } |
| 115234 | |
| 115235 | len = strlen((char *)output_buf); |
| 115236 | break; |
| 115237 | } |
| 115238 | } |
| 115239 | |
| 115240 | outPrivateKey->length = len; |
| 115241 | UA_ByteString_allocBuffer(outPrivateKey, outPrivateKey->length); |
| 115242 | memcpy(outPrivateKey->data, c, outPrivateKey->length); |
| 115243 | |
| 115244 | return 0; |
| 115245 | } |
| 115246 | |
| 115247 | static int write_certificate(mbedtls_x509write_cert *crt, UA_CertificateFormat certFormat, |
| 115248 | UA_ByteString *outCertificate, int (*f_rng)(void *, unsigned char *, size_t), |
| 115249 | void *p_rng) { |
| 115250 | int ret; |
| 115251 | unsigned char output_buf[4096]; |
| 115252 | unsigned char *c = output_buf; |
| 115253 | size_t len = 0; |
| 115254 | |
| 115255 | memset(output_buf, 0, sizeof(output_buf)); |
| 115256 | switch(certFormat) { |
| 115257 | case UA_CERTIFICATEFORMAT_DER: { |
| 115258 | if((ret = mbedtls_x509write_crt_der(crt, output_buf, sizeof(output_buf), f_rng, p_rng)) < 0) { |
| 115259 | return ret; |
| 115260 | } |
| 115261 | |
| 115262 | len = ret; |
| 115263 | c = output_buf + sizeof(output_buf) - len; |
| 115264 | break; |
| 115265 | } |
| 115266 | case UA_CERTIFICATEFORMAT_PEM: { |
| 115267 | if((ret = mbedtls_x509write_crt_pem(crt, output_buf, sizeof(output_buf), f_rng, p_rng)) < 0) { |
| 115268 | return ret; |
| 115269 | } |
| 115270 | |
| 115271 | len = strlen((char *)output_buf); |
| 115272 | break; |
| 115273 | } |
| 115274 | } |
| 115275 | |
| 115276 | outCertificate->length = len; |
| 115277 | UA_ByteString_allocBuffer(outCertificate, outCertificate->length); |
| 115278 | memcpy(outCertificate->data, c, outCertificate->length); |
| 115279 | |
| 115280 | return 0; |
| 115281 | } |
| 115282 | |
| 115283 | #if MBEDTLS_VERSION_NUMBER < 0x03030000 |
| 115284 | int mbedtls_x509write_crt_set_ext_key_usage(mbedtls_x509write_cert *ctx, |
| 115285 | const mbedtls_asn1_sequence *exts) { |
| 115286 | unsigned char buf[256]; |
| 115287 | unsigned char *c = buf + sizeof(buf); |
| 115288 | int ret; |
| 115289 | size_t len = 0; |
| 115290 | const mbedtls_asn1_sequence *last_ext = NULL; |
| 115291 | const mbedtls_asn1_sequence *ext; |
| 115292 | |
| 115293 | memset(buf, 0, sizeof(buf)); |
| 115294 | |
| 115295 | /* We need at least one extension: SEQUENCE SIZE (1..MAX) OF KeyPurposeId */ |
| 115296 | if(!exts) { |
| 115297 | return MBEDTLS_ERR_X509_BAD_INPUT_DATA; |
| 115298 | } |
| 115299 | |
| 115300 | /* Iterate over exts backwards, so we write them out in the requested order */ |
| 115301 | while(last_ext != exts) { |
| 115302 | for(ext = exts; ext->next != last_ext; ext = ext->next) { |
| 115303 | } |
| 115304 | if(ext->buf.tag != MBEDTLS_ASN1_OID) { |
| 115305 | return MBEDTLS_ERR_X509_BAD_INPUT_DATA; |
| 115306 | } |
| 115307 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(&c, buf, ext->buf.p, ext->buf.len)); |
| 115308 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, ext->buf.len)); |
| 115309 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_OID)); |
| 115310 | last_ext = ext; |
| 115311 | } |
| 115312 | |
| 115313 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); |
| 115314 | MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); |
| 115315 | |
| 115316 | return mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_EXTENDED_KEY_USAGE, |
| 115317 | MBEDTLS_OID_SIZE(MBEDTLS_OID_EXTENDED_KEY_USAGE), 1, c, len); |
| 115318 | } |
| 115319 | |
| 115320 | #endif |
| 115321 | |
| 115322 | static size_t mbedtls_get_san_list_deep(const mbedtls_write_san_list* sanlist) { |
| 115323 | size_t ret = 0; |
| 115324 | const mbedtls_write_san_list* cur = sanlist; |
| 115325 | while (cur) { |
| 115326 | ++ret; |
| 115327 | cur = cur->next; |
| 115328 | } |
| 115329 | |
| 115330 | return ret; |
| 115331 | } |
| 115332 | |
| 115333 | int mbedtls_x509write_crt_set_subject_alt_name(mbedtls_x509write_cert *ctx, const mbedtls_write_san_list* sanlist) { |
| 115334 | int ret = 0; |
| 115335 | size_t sandeep = 0; |
| 115336 | const mbedtls_write_san_list* cur = sanlist; |
| 115337 | unsigned char* buf; |
| 115338 | unsigned char* pc; |
| 115339 | size_t len; |
| 115340 | size_t buflen = 0; |
| 115341 | |
| 115342 | /* How many alt names to be written */ |
| 115343 | sandeep = mbedtls_get_san_list_deep(sanlist); |
| 115344 | if (sandeep == 0) |
| 115345 | return ret; |
| 115346 | |
| 115347 | buflen = MBEDTLS_SAN_MAX_LEN * sandeep + sandeep; |
| 115348 | buf = (unsigned char *)mbedtls_calloc(1, buflen); |
| 115349 | if(!buf) |
| 115350 | return MBEDTLS_ERR_ASN1_ALLOC_FAILED; |
| 115351 | |
| 115352 | memset(buf, 0, buflen); |
| 115353 | pc = buf + buflen; |
| 115354 | |
| 115355 | len = 0; |
| 115356 | while(cur) { |
| 115357 | switch (cur->node.type) { |
| 115358 | case MBEDTLS_X509_SAN_DNS_NAME: |
| 115359 | case MBEDTLS_X509_SAN_RFC822_NAME: |
| 115360 | case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: |
| 115361 | case MBEDTLS_X509_SAN_IP_ADDRESS: |
| 115362 | MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, |
| 115363 | mbedtls_asn1_write_raw_buffer(&pc, buf, (const unsigned char *)cur->node.host, |
| 115364 | cur->node.hostlen)); |
| 115365 | MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&pc, buf, cur->node.hostlen)); |
| 115366 | MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_tag(&pc, buf, |
| 115367 | MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type)); |
| 115368 | break; |
| 115369 | default: |
| 115370 | /* Error out on an unsupported SAN */ |
| 115371 | ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE; |
| 115372 | goto cleanup; |
| 115373 | } |
| 115374 | |
| 115375 | cur = cur->next; |
| 115376 | } |
| 115377 | |
| 115378 | MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&pc, buf, len)); |
| 115379 | MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_tag(&pc, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); |
| 115380 | |
| 115381 | ret = mbedtls_x509write_crt_set_extension(ctx, MBEDTLS_OID_SUBJECT_ALT_NAME, |
| 115382 | MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME), 0, buf + buflen - len, len); |
| 115383 | |
| 115384 | mbedtls_free(buf); |
| 115385 | return ret; |
| 115386 | |
| 115387 | cleanup: |
| 115388 | mbedtls_free(buf); |
| 115389 | return ret; |
| 115390 | } |
| 115391 | |
| 115392 | #endif |
| 115393 | |
| 115394 | /**** amalgamated original file "/plugins/crypto/mbedtls/ua_pki_mbedtls.c" ****/ |
| 115395 | |
| 115396 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 115397 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 115398 | * |
| 115399 | * Copyright 2018 (c) Mark Giraud, Fraunhofer IOSB |
| 115400 | * Copyright 2019 (c) Kalycito Infotech Private Limited |
| 115401 | * Copyright 2019, 2024 (c) Julius Pfrommer, Fraunhofer IOSB |
| 115402 | */ |
| 115403 | |
| 115404 | |
| 115405 | #ifdef UA_ENABLE_ENCRYPTION_MBEDTLS |
| 115406 | |
| 115407 | |
| 115408 | #include <mbedtls/x509.h> |
| 115409 | #include <mbedtls/oid.h> |
| 115410 | #include <mbedtls/x509_crt.h> |
| 115411 | #include <mbedtls/entropy.h> |
| 115412 | #include <mbedtls/error.h> |
| 115413 | #include <mbedtls/version.h> |
| 115414 | #include <string.h> |
| 115415 | |
| 115416 | #define UA_MBEDTLS_MAX_CHAIN_LENGTH 10 |
| 115417 | #define UA_MBEDTLS_MAX_DN_LENGTH 256 |
| 115418 | |
| 115419 | /* Find binary substring. Taken and adjusted from |
| 115420 | * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */ |
| 115421 | |
| 115422 | static const unsigned char * |
| 115423 | bstrchr(const unsigned char *s, const unsigned char ch, size_t l) { |
| 115424 | /* find first occurrence of c in char s[] for length l*/ |
| 115425 | for(; l > 0; ++s, --l) { |
| 115426 | if(*s == ch) |
| 115427 | return s; |
| 115428 | } |
| 115429 | return NULL; |
| 115430 | } |
| 115431 | |
| 115432 | static const unsigned char * |
| 115433 | UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2) { |
| 115434 | /* find first occurrence of s2[] in s1[] for length l1*/ |
| 115435 | const unsigned char *ss1 = s1; |
| 115436 | const unsigned char *ss2 = s2; |
| 115437 | /* handle special case */ |
| 115438 | if(l1 == 0) |
| 115439 | return (NULL); |
| 115440 | if(l2 == 0) |
| 115441 | return s1; |
| 115442 | |
| 115443 | /* match prefix */ |
| 115444 | for (; (s1 = bstrchr(s1, *s2, (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1)) != NULL && |
| 115445 | (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1 != 0; ++s1) { |
| 115446 | |
| 115447 | /* match rest of prefix */ |
| 115448 | const unsigned char *sc1, *sc2; |
| 115449 | for (sc1 = s1, sc2 = s2; ;) |
| 115450 | if (++sc2 >= ss2+l2) |
| 115451 | return s1; |
| 115452 | else if (*++sc1 != *sc2) |
| 115453 | break; |
| 115454 | } |
| 115455 | return NULL; |
| 115456 | } |
| 115457 | |
| 115458 | // mbedTLS expects PEM data to be null terminated |
| 115459 | // The data length parameter must include the null terminator |
| 115460 | static UA_ByteString copyDataFormatAware(const UA_ByteString *data) |
| 115461 | { |
| 115462 | UA_ByteString result; |
| 115463 | UA_ByteString_init(&result); |
| 115464 | |
| 115465 | if (!data->length) |
| 115466 | return result; |
| 115467 | |
| 115468 | if (data->length && data->data[0] == '-') { |
| 115469 | UA_ByteString_allocBuffer(&result, data->length + 1); |
| 115470 | memcpy(result.data, data->data, data->length); |
| 115471 | result.data[data->length] = '\0'; |
| 115472 | } else { |
| 115473 | UA_ByteString_copy(data, &result); |
| 115474 | } |
| 115475 | |
| 115476 | return result; |
| 115477 | } |
| 115478 | |
| 115479 | typedef struct { |
| 115480 | UA_CertificateVerification *cv; |
| 115481 | |
| 115482 | /* If the folders are defined, we use them to reload the certificates during |
| 115483 | * runtime */ |
| 115484 | UA_String trustListFolder; |
| 115485 | UA_String issuerListFolder; |
| 115486 | UA_String revocationListFolder; |
| 115487 | UA_String rejectedListFolder; |
| 115488 | |
| 115489 | mbedtls_x509_crt certificateTrustList; |
| 115490 | mbedtls_x509_crt certificateIssuerList; |
| 115491 | mbedtls_x509_crl certificateRevocationList; |
| 115492 | } CertInfo; |
| 115493 | |
| 115494 | #ifdef __linux__ /* Linux only so far */ |
| 115495 | |
| 115496 | #include <dirent.h> |
| 115497 | #include <limits.h> |
| 115498 | |
| 115499 | static UA_StatusCode |
| 115500 | fileNamesFromFolder(const UA_String *folder, size_t *pathsSize, UA_String **paths) { |
| 115501 | char buf[PATH_MAX + 1]; |
| 115502 | if(folder->length > PATH_MAX) |
| 115503 | return UA_STATUSCODE_BADINTERNALERROR; |
| 115504 | |
| 115505 | memcpy(buf, folder->data, folder->length); |
| 115506 | buf[folder->length] = 0; |
| 115507 | |
| 115508 | DIR *dir = opendir(buf); |
| 115509 | if(!dir) |
| 115510 | return UA_STATUSCODE_BADINTERNALERROR; |
| 115511 | |
| 115512 | *paths = (UA_String*)UA_Array_new(256, &UA_TYPES[UA_TYPES_STRING]); |
| 115513 | if(*paths == NULL) { |
| 115514 | closedir(dir); |
| 115515 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 115516 | } |
| 115517 | |
| 115518 | struct dirent *ent; |
| 115519 | char buf2[PATH_MAX + 1]; |
| 115520 | char *res = realpath(buf, buf2); |
| 115521 | if(!res) { |
| 115522 | closedir(dir); |
| 115523 | return UA_STATUSCODE_BADINTERNALERROR; |
| 115524 | } |
| 115525 | size_t pathlen = strlen(buf2); |
| 115526 | *pathsSize = 0; |
| 115527 | while((ent = readdir (dir)) != NULL && *pathsSize < 256) { |
| 115528 | if(ent->d_type != DT_REG) |
| 115529 | continue; |
| 115530 | buf2[pathlen] = '/'; |
| 115531 | buf2[pathlen+1] = 0; |
| 115532 | strcat(buf2, ent->d_name); |
| 115533 | (*paths)[*pathsSize] = UA_STRING_ALLOC(buf2); |
| 115534 | *pathsSize += 1; |
| 115535 | } |
| 115536 | closedir(dir); |
| 115537 | |
| 115538 | if(*pathsSize == 0) { |
| 115539 | UA_free(*paths); |
| 115540 | *paths = NULL; |
| 115541 | } |
| 115542 | return UA_STATUSCODE_GOOD; |
| 115543 | } |
| 115544 | |
| 115545 | static UA_StatusCode |
| 115546 | reloadCertificates(const UA_CertificateVerification *cv, CertInfo *ci) { |
| 115547 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 115548 | int err = 0; |
| 115549 | int internalErrorFlag = 0; |
| 115550 | |
| 115551 | /* Load the trustlists */ |
| 115552 | if(ci->trustListFolder.length > 0) { |
| 115553 | UA_LOG_INFO(cv->logging, UA_LOGCATEGORY_SERVER, "Reloading the trust-list"); |
| 115554 | mbedtls_x509_crt_free(&ci->certificateTrustList); |
| 115555 | mbedtls_x509_crt_init(&ci->certificateTrustList); |
| 115556 | |
| 115557 | char f[PATH_MAX]; |
| 115558 | memcpy(f, ci->trustListFolder.data, ci->trustListFolder.length); |
| 115559 | f[ci->trustListFolder.length] = 0; |
| 115560 | err = mbedtls_x509_crt_parse_path(&ci->certificateTrustList, f); |
| 115561 | if(err == 0) { |
| 115562 | UA_LOG_INFO(cv->logging, UA_LOGCATEGORY_SERVER, |
| 115563 | "Loaded certificate from %s", f); |
| 115564 | } else { |
| 115565 | char errBuff[300]; |
| 115566 | mbedtls_strerror(err, errBuff, 300); |
| 115567 | UA_LOG_INFO(cv->logging, UA_LOGCATEGORY_SERVER, |
| 115568 | "Failed to load certificate from %s, mbedTLS error: %s (error code: %d)", f, errBuff, err); |
| 115569 | internalErrorFlag = 1; |
| 115570 | } |
| 115571 | } |
| 115572 | |
| 115573 | /* Load the revocationlists */ |
| 115574 | if(ci->revocationListFolder.length > 0) { |
| 115575 | UA_LOG_INFO(cv->logging, UA_LOGCATEGORY_SERVER, "Reloading the revocation-list"); |
| 115576 | size_t pathsSize = 0; |
| 115577 | UA_String *paths = NULL; |
| 115578 | retval = fileNamesFromFolder(&ci->revocationListFolder, &pathsSize, &paths); |
| 115579 | if(retval != UA_STATUSCODE_GOOD) |
| 115580 | return retval; |
| 115581 | mbedtls_x509_crl_free(&ci->certificateRevocationList); |
| 115582 | mbedtls_x509_crl_init(&ci->certificateRevocationList); |
| 115583 | for(size_t i = 0; i < pathsSize; i++) { |
| 115584 | char f[PATH_MAX]; |
| 115585 | memcpy(f, paths[i].data, paths[i].length); |
| 115586 | f[paths[i].length] = 0; |
| 115587 | err = mbedtls_x509_crl_parse_file(&ci->certificateRevocationList, f); |
| 115588 | if(err == 0) { |
| 115589 | UA_LOG_INFO(cv->logging, UA_LOGCATEGORY_SERVER, |
| 115590 | "Loaded certificate from %.*s", |
| 115591 | (int)paths[i].length, paths[i].data); |
| 115592 | } else { |
| 115593 | char errBuff[300]; |
| 115594 | mbedtls_strerror(err, errBuff, 300); |
| 115595 | UA_LOG_INFO(cv->logging, UA_LOGCATEGORY_SERVER, |
| 115596 | "Failed to load certificate from %.*s, mbedTLS error: %s (error code: %d)", |
| 115597 | (int)paths[i].length, paths[i].data, errBuff, err); |
| 115598 | internalErrorFlag = 1; |
| 115599 | } |
| 115600 | } |
| 115601 | UA_Array_delete(paths, pathsSize, &UA_TYPES[UA_TYPES_STRING]); |
| 115602 | paths = NULL; |
| 115603 | pathsSize = 0; |
| 115604 | } |
| 115605 | |
| 115606 | /* Load the issuerlists */ |
| 115607 | if(ci->issuerListFolder.length > 0) { |
| 115608 | UA_LOG_INFO(cv->logging, UA_LOGCATEGORY_SERVER, "Reloading the issuer-list"); |
| 115609 | mbedtls_x509_crt_free(&ci->certificateIssuerList); |
| 115610 | mbedtls_x509_crt_init(&ci->certificateIssuerList); |
| 115611 | char f[PATH_MAX]; |
| 115612 | memcpy(f, ci->issuerListFolder.data, ci->issuerListFolder.length); |
| 115613 | f[ci->issuerListFolder.length] = 0; |
| 115614 | err = mbedtls_x509_crt_parse_path(&ci->certificateIssuerList, f); |
| 115615 | if(err == 0) { |
| 115616 | UA_LOG_INFO(cv->logging, UA_LOGCATEGORY_SERVER, |
| 115617 | "Loaded certificate from %s", f); |
| 115618 | } else { |
| 115619 | char errBuff[300]; |
| 115620 | mbedtls_strerror(err, errBuff, 300); |
| 115621 | UA_LOG_INFO(cv->logging, UA_LOGCATEGORY_SERVER, |
| 115622 | "Failed to load certificate from %s, mbedTLS error: %s (error code: %d)", |
| 115623 | f, errBuff, err); |
| 115624 | internalErrorFlag = 1; |
| 115625 | } |
| 115626 | } |
| 115627 | |
| 115628 | return (internalErrorFlag) ? UA_STATUSCODE_BADINTERNALERROR : retval; |
| 115629 | } |
| 115630 | |
| 115631 | #endif |
| 115632 | |
| 115633 | /* We need to access some private fields below */ |
| 115634 | #ifndef MBEDTLS_PRIVATE |
| 115635 | #define MBEDTLS_PRIVATE(x) x |
| 115636 | #endif |
| 115637 | |
| 115638 | /* Is the certificate a CA? */ |
| 115639 | static UA_Boolean |
| 115640 | mbedtlsCheckCA(mbedtls_x509_crt *cert) { |
| 115641 | /* The Basic Constraints extension must be set and the cert acts as CA */ |
| 115642 | if(!(cert->MBEDTLS_PRIVATE(ext_types) & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) || |
| 115643 | !cert->MBEDTLS_PRIVATE(ca_istrue)) |
| 115644 | return false; |
| 115645 | |
| 115646 | /* The Key Usage extension must be set to cert signing and CRL issuing */ |
| 115647 | if(!(cert->MBEDTLS_PRIVATE(ext_types) & MBEDTLS_X509_EXT_KEY_USAGE) || |
| 115648 | mbedtls_x509_crt_check_key_usage(cert, MBEDTLS_X509_KU_KEY_CERT_SIGN) != 0 || |
| 115649 | mbedtls_x509_crt_check_key_usage(cert, MBEDTLS_X509_KU_CRL_SIGN) != 0) |
| 115650 | return false; |
| 115651 | |
| 115652 | return true; |
| 115653 | } |
| 115654 | |
| 115655 | static UA_Boolean |
| 115656 | mbedtlsSameName(UA_String name, const mbedtls_x509_name *name2) { |
| 115657 | char buf[UA_MBEDTLS_MAX_DN_LENGTH]; |
| 115658 | int len = mbedtls_x509_dn_gets(buf, UA_MBEDTLS_MAX_DN_LENGTH, name2); |
| 115659 | if(len < 0) |
| 115660 | return false; |
| 115661 | UA_String nameString = {(size_t)len, (UA_Byte*)buf}; |
| 115662 | return UA_String_equal(&name, &nameString); |
| 115663 | } |
| 115664 | |
| 115665 | static UA_Boolean |
| 115666 | mbedtlsSameBuf(mbedtls_x509_buf *a, mbedtls_x509_buf *b) { |
| 115667 | if(a->len != b->len) |
| 115668 | return false; |
| 115669 | return (memcmp(a->p, b->p, a->len) == 0); |
| 115670 | } |
| 115671 | |
| 115672 | /* Return the first matching issuer candidate AFTER prev. |
| 115673 | * This can return the cert itself if self-signed. */ |
| 115674 | static mbedtls_x509_crt * |
| 115675 | mbedtlsFindNextIssuer(CertInfo *ci, mbedtls_x509_crt *stack, |
| 115676 | mbedtls_x509_crt *cert, mbedtls_x509_crt *prev) { |
| 115677 | char inbuf[UA_MBEDTLS_MAX_DN_LENGTH]; |
| 115678 | int nameLen = mbedtls_x509_dn_gets(inbuf, UA_MBEDTLS_MAX_DN_LENGTH, &cert->issuer); |
| 115679 | if(nameLen < 0) |
| 115680 | return NULL; |
| 115681 | UA_String issuerName = {(size_t)nameLen, (UA_Byte*)inbuf}; |
| 115682 | do { |
| 115683 | for(mbedtls_x509_crt *i = stack; i; i = i->next) { |
| 115684 | if(prev) { |
| 115685 | if(prev == i) |
| 115686 | prev = NULL; /* This was the last issuer we tried to verify */ |
| 115687 | continue; |
| 115688 | } |
| 115689 | /* Compare issuer name and subject name. |
| 115690 | * Skip when the key does not match the signature. */ |
| 115691 | if(mbedtlsSameName(issuerName, &i->subject) && |
| 115692 | mbedtls_pk_can_do(&i->pk, cert->MBEDTLS_PRIVATE(sig_pk))) |
| 115693 | return i; |
| 115694 | } |
| 115695 | |
| 115696 | /* Switch from the stack that came with the cert to the issuer list and |
| 115697 | * then to the trust list. */ |
| 115698 | if(stack == &ci->certificateTrustList) |
| 115699 | stack = NULL; |
| 115700 | else if(stack == &ci->certificateIssuerList) |
| 115701 | stack = &ci->certificateTrustList; |
| 115702 | else |
| 115703 | stack = &ci->certificateIssuerList; |
| 115704 | } while(stack); |
| 115705 | return NULL; |
| 115706 | } |
| 115707 | |
| 115708 | static UA_StatusCode |
| 115709 | mbedtlsCheckRevoked(CertInfo *ci, mbedtls_x509_crt *cert) { |
| 115710 | /* Parse the Issuer Name */ |
| 115711 | char inbuf[UA_MBEDTLS_MAX_DN_LENGTH]; |
| 115712 | int nameLen = mbedtls_x509_dn_gets(inbuf, UA_MBEDTLS_MAX_DN_LENGTH, &cert->issuer); |
| 115713 | if(nameLen < 0) |
| 115714 | return UA_STATUSCODE_BADINTERNALERROR; |
| 115715 | UA_String issuerName = {(size_t)nameLen, (UA_Byte*)inbuf}; |
| 115716 | |
| 115717 | if(ci->certificateRevocationList.raw.len == 0) { |
| 115718 | UA_LOG_WARNING(ci->cv->logging, UA_LOGCATEGORY_SECURITYPOLICY, |
| 115719 | "Zero revocation lists have been loaded. " |
| 115720 | "This seems intentional - omitting the check."); |
| 115721 | return UA_STATUSCODE_GOOD; |
| 115722 | } |
| 115723 | |
| 115724 | /* Loop over the crl and match the Issuer Name */ |
| 115725 | UA_StatusCode res = UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN; |
| 115726 | for(mbedtls_x509_crl *crl = &ci->certificateRevocationList; crl; crl = crl->next) { |
| 115727 | /* Is the CRL for certificates from the cert issuer? |
| 115728 | * Is the serial number of the certificate contained in the CRL? */ |
| 115729 | if(mbedtlsSameName(issuerName, &crl->issuer)) { |
| 115730 | if(mbedtls_x509_crt_is_revoked(cert, crl) != 0) |
| 115731 | return UA_STATUSCODE_BADCERTIFICATEREVOKED; |
| 115732 | res = UA_STATUSCODE_GOOD; /* There was at least one crl that did not revoke (so far) */ |
| 115733 | } |
| 115734 | } |
| 115735 | return res; |
| 115736 | } |
| 115737 | |
| 115738 | /* Verify that the public key of the issuer was used to sign the certificate */ |
| 115739 | static UA_Boolean |
| 115740 | mbedtlsCheckSignature(const mbedtls_x509_crt *cert, mbedtls_x509_crt *issuer) { |
| 115741 | size_t hash_len; |
| 115742 | unsigned char hash[MBEDTLS_MD_MAX_SIZE]; |
| 115743 | mbedtls_md_type_t md = cert->MBEDTLS_PRIVATE(sig_md); |
| 115744 | #if !defined(MBEDTLS_USE_PSA_CRYPTO) |
| 115745 | const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md); |
| 115746 | hash_len = mbedtls_md_get_size(md_info); |
| 115747 | if(mbedtls_md(md_info, cert->tbs.p, cert->tbs.len, hash) != 0) |
| 115748 | return false; |
| 115749 | #else |
| 115750 | if(psa_hash_compute(mbedtls_md_psa_alg_from_type(md), cert->tbs.p, |
| 115751 | cert->tbs.len, hash, sizeof(hash), &hash_len) != PSA_SUCCESS) |
| 115752 | return false; |
| 115753 | #endif |
| 115754 | const mbedtls_x509_buf *sig = &cert->MBEDTLS_PRIVATE(sig); |
| 115755 | void *sig_opts = cert->MBEDTLS_PRIVATE(sig_opts); |
| 115756 | mbedtls_pk_type_t pktype = cert->MBEDTLS_PRIVATE(sig_pk); |
| 115757 | return (mbedtls_pk_verify_ext(pktype, sig_opts, &issuer->pk, md, |
| 115758 | hash, hash_len, sig->p, sig->len) == 0); |
| 115759 | } |
| 115760 | |
| 115761 | static UA_StatusCode |
| 115762 | mbedtlsVerifyChain(CertInfo *ci, mbedtls_x509_crt *stack, mbedtls_x509_crt **old_issuers, |
| 115763 | mbedtls_x509_crt *cert, int depth) { |
| 115764 | /* Maxiumum chain length */ |
| 115765 | if(depth == UA_MBEDTLS_MAX_CHAIN_LENGTH) |
| 115766 | return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; |
| 115767 | |
| 115768 | /* Verification Step: Validity Period */ |
| 115769 | if(mbedtls_x509_time_is_future(&cert->valid_from) || |
| 115770 | mbedtls_x509_time_is_past(&cert->valid_to)) |
| 115771 | return (depth == 0) ? UA_STATUSCODE_BADCERTIFICATETIMEINVALID : |
| 115772 | UA_STATUSCODE_BADCERTIFICATEISSUERTIMEINVALID; |
| 115773 | |
| 115774 | /* Return the most specific error code. BADCERTIFICATECHAININCOMPLETE is |
| 115775 | * returned only if all possible chains are incomplete. */ |
| 115776 | mbedtls_x509_crt *issuer = NULL; |
| 115777 | UA_StatusCode ret = UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; |
| 115778 | while(ret != UA_STATUSCODE_GOOD) { |
| 115779 | /* Find the issuer. This can return the same certificate if it is |
| 115780 | * self-signed (subject == issuer). We come back here to try a different |
| 115781 | * "path" if a subsequent verification fails. */ |
| 115782 | issuer = mbedtlsFindNextIssuer(ci, stack, cert, issuer); |
| 115783 | if(!issuer) |
| 115784 | break; |
| 115785 | |
| 115786 | /* Verification Step: Certificate Usage |
| 115787 | * Can the issuer act as CA? Omit for self-signed leaf certificates. */ |
| 115788 | if((depth > 0 || issuer != cert) && !mbedtlsCheckCA(issuer)) { |
| 115789 | ret = UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED; |
| 115790 | continue; |
| 115791 | } |
| 115792 | |
| 115793 | /* Verification Step: Signature */ |
| 115794 | if(!mbedtlsCheckSignature(cert, issuer)) { |
| 115795 | ret = UA_STATUSCODE_BADCERTIFICATEINVALID; /* Wrong issuer, try again */ |
| 115796 | continue; |
| 115797 | } |
| 115798 | |
| 115799 | /* The certificate is self-signed. We have arrived at the top of the |
| 115800 | * chain. We check whether the certificate is trusted below. This is the |
| 115801 | * only place where we return UA_STATUSCODE_BADCERTIFICATEUNTRUSTED. |
| 115802 | * This signals that the chain is complete (but can be still |
| 115803 | * untrusted). |
| 115804 | * |
| 115805 | * Break here as we have reached the end of the chain. Omit the |
| 115806 | * Revocation Check for self-signed certificates. */ |
| 115807 | if(issuer == cert || mbedtlsSameBuf(&cert->tbs, &issuer->tbs)) { |
| 115808 | ret = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED; |
| 115809 | break; |
| 115810 | } |
| 115811 | |
| 115812 | /* Verification Step: Revocation Check */ |
| 115813 | ret = mbedtlsCheckRevoked(ci, cert); |
| 115814 | if(depth > 0) { |
| 115815 | if(ret == UA_STATUSCODE_BADCERTIFICATEREVOKED) |
| 115816 | ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED; |
| 115817 | if(ret == UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN) |
| 115818 | ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN; |
| 115819 | } |
| 115820 | if(ret != UA_STATUSCODE_GOOD) |
| 115821 | continue; |
| 115822 | |
| 115823 | /* Detect (endless) loops of issuers */ |
| 115824 | for(int i = 0; i < depth; i++) { |
| 115825 | if(old_issuers[i] == issuer) |
| 115826 | return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; |
| 115827 | } |
| 115828 | old_issuers[depth] = issuer; |
| 115829 | |
| 115830 | /* We have found the issuer certificate used for the signature. Recurse |
| 115831 | * to the next certificate in the chain (verify the current issuer). */ |
| 115832 | ret = mbedtlsVerifyChain(ci, stack, old_issuers, issuer, depth + 1); |
| 115833 | } |
| 115834 | |
| 115835 | /* The chain is complete, but we haven't yet identified a trusted |
| 115836 | * certificate "on the way down". Can we trust this certificate? */ |
| 115837 | if(ret == UA_STATUSCODE_BADCERTIFICATEUNTRUSTED) { |
| 115838 | for(mbedtls_x509_crt *t = &ci->certificateTrustList; t; t = t->next) { |
| 115839 | if(mbedtlsSameBuf(&cert->tbs, &t->tbs)) |
| 115840 | return UA_STATUSCODE_GOOD; |
| 115841 | } |
| 115842 | } |
| 115843 | |
| 115844 | return ret; |
| 115845 | } |
| 115846 | |
| 115847 | /* This follows Part 6, 6.1.3 Determining if a Certificate is trusted. |
| 115848 | * It defines a sequence of steps for certificate verification. */ |
| 115849 | static UA_StatusCode |
| 115850 | certificateVerification_verify(const UA_CertificateVerification *cv, |
| 115851 | const UA_ByteString *certificate) { |
| 115852 | if(!cv || !certificate) |
| 115853 | return UA_STATUSCODE_BADINTERNALERROR; |
| 115854 | |
| 115855 | CertInfo *ci = (CertInfo*)cv->context; |
| 115856 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 115857 | mbedtls_x509_crt *old_issuers[UA_MBEDTLS_MAX_CHAIN_LENGTH]; |
| 115858 | |
| 115859 | #ifdef __linux__ /* Reload certificates if folder paths are specified */ |
| 115860 | ret = reloadCertificates(cv, ci); |
| 115861 | if(ret != UA_STATUSCODE_GOOD) |
| 115862 | return ret; |
| 115863 | #endif |
| 115864 | |
| 115865 | /* Verification Step: Certificate Structure |
| 115866 | * This parses the entire certificate chain contained in the bytestring. */ |
| 115867 | mbedtls_x509_crt cert; |
| 115868 | mbedtls_x509_crt_init(&cert); |
| 115869 | int mbedErr = mbedtls_x509_crt_parse(&cert, certificate->data, |
| 115870 | certificate->length); |
| 115871 | if(mbedErr) { |
| 115872 | ret = UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 115873 | goto errout; |
| 115874 | } |
| 115875 | |
| 115876 | /* Verification Step: Certificate Usage |
| 115877 | * Check whether the certificate is a User certificate or a CA certificate. |
| 115878 | * Refer the test case CTT/Security/Security Certificate Validation/029.js |
| 115879 | * for more details. */ |
| 115880 | if(mbedtlsCheckCA(&cert)) { |
| 115881 | ret = UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; |
| 115882 | goto errout; |
| 115883 | } |
| 115884 | |
| 115885 | /* These steps are performed outside of this method. |
| 115886 | * Because we need the server or client context. |
| 115887 | * - Security Policy |
| 115888 | * - Host Name |
| 115889 | * - URI */ |
| 115890 | |
| 115891 | /* Verification Step: Build Certificate Chain |
| 115892 | * We perform the checks for each certificate inside. */ |
| 115893 | ret = mbedtlsVerifyChain(ci, &cert, old_issuers, &cert, 0); |
| 115894 | |
| 115895 | errout: |
| 115896 | mbedtls_x509_crt_free(&cert); |
| 115897 | |
| 115898 | #ifdef UA_ENABLE_CERT_REJECTED_DIR |
| 115899 | if(ret != UA_STATUSCODE_GOOD && |
| 115900 | ci->rejectedListFolder.length > 0) { |
| 115901 | char rejectedFileName[256] = {0}; |
| 115902 | UA_ByteString thumbprint; |
| 115903 | UA_ByteString_allocBuffer(&thumbprint, UA_SHA1_LENGTH); |
| 115904 | if(mbedtls_thumbprint_sha1(certificate, &thumbprint) == UA_STATUSCODE_GOOD) { |
| 115905 | static const char hex2char[] = "0123456789ABCDEF"; |
| 115906 | for(size_t pos = 0, namePos = 0; pos < thumbprint.length; pos++) { |
| 115907 | rejectedFileName[namePos++] = hex2char[(thumbprint.data[pos] & 0xf0) >> 4]; |
| 115908 | rejectedFileName[namePos++] = hex2char[thumbprint.data[pos] & 0x0f]; |
| 115909 | } |
| 115910 | strcat(rejectedFileName, ".der"); |
| 115911 | } else { |
| 115912 | UA_UInt64 dt = (UA_UInt64) UA_DateTime_now(); |
| 115913 | sprintf(rejectedFileName, "cert_%"PRIu64 ".der", dt); |
| 115914 | } |
| 115915 | UA_ByteString_clear(&thumbprint); |
| 115916 | char *rejectedFullFileName = (char *) |
| 115917 | calloc(ci->rejectedListFolder.length + 1 /* '/' */ + strlen(rejectedFileName) + 1, sizeof(char)); |
| 115918 | if(!rejectedFullFileName) |
| 115919 | return ret; |
| 115920 | memcpy(rejectedFullFileName, ci->rejectedListFolder.data, ci->rejectedListFolder.length); |
| 115921 | rejectedFullFileName[ci->rejectedListFolder.length] = '/'; |
| 115922 | memcpy(&rejectedFullFileName[ci->rejectedListFolder.length + 1], rejectedFileName, strlen(rejectedFileName)); |
| 115923 | FILE * fp_rejectedFile = fopen(rejectedFullFileName, "wb"); |
| 115924 | if(fp_rejectedFile) { |
| 115925 | fwrite(certificate->data, sizeof(certificate->data[0]), certificate->length, fp_rejectedFile); |
| 115926 | fclose(fp_rejectedFile); |
| 115927 | } |
| 115928 | free(rejectedFullFileName); |
| 115929 | } |
| 115930 | #endif |
| 115931 | |
| 115932 | return ret; |
| 115933 | } |
| 115934 | |
| 115935 | static UA_StatusCode |
| 115936 | certificateVerification_verifyApplicationURI(const UA_CertificateVerification *cv, |
| 115937 | const UA_ByteString *certificate, |
| 115938 | const UA_String *applicationURI) { |
| 115939 | CertInfo *ci; |
| 115940 | if(!cv) |
| 115941 | return UA_STATUSCODE_BADINTERNALERROR; |
| 115942 | ci = (CertInfo*)cv->context; |
| 115943 | if(!ci) |
| 115944 | return UA_STATUSCODE_BADINTERNALERROR; |
| 115945 | |
| 115946 | /* Parse the certificate */ |
| 115947 | mbedtls_x509_crt remoteCertificate; |
| 115948 | mbedtls_x509_crt_init(&remoteCertificate); |
| 115949 | int mbedErr = mbedtls_x509_crt_parse(&remoteCertificate, certificate->data, |
| 115950 | certificate->length); |
| 115951 | if(mbedErr) |
| 115952 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 115953 | |
| 115954 | /* Poor man's ApplicationUri verification. mbedTLS does not parse all fields |
| 115955 | * of the Alternative Subject Name. Instead test whether the URI-string is |
| 115956 | * present in the v3_ext field in general. |
| 115957 | * |
| 115958 | * TODO: Improve parsing of the Alternative Subject Name */ |
| 115959 | UA_StatusCode retval = UA_STATUSCODE_GOOD; |
| 115960 | if(UA_Bstrstr(remoteCertificate.v3_ext.p, remoteCertificate.v3_ext.len, |
| 115961 | applicationURI->data, applicationURI->length) == NULL) |
| 115962 | retval = UA_STATUSCODE_BADCERTIFICATEURIINVALID; |
| 115963 | |
| 115964 | mbedtls_x509_crt_free(&remoteCertificate); |
| 115965 | return retval; |
| 115966 | } |
| 115967 | |
| 115968 | static void |
| 115969 | certificateVerification_clear(UA_CertificateVerification *cv) { |
| 115970 | CertInfo *ci = (CertInfo*)cv->context; |
| 115971 | if(!ci) |
| 115972 | return; |
| 115973 | mbedtls_x509_crt_free(&ci->certificateTrustList); |
| 115974 | mbedtls_x509_crl_free(&ci->certificateRevocationList); |
| 115975 | mbedtls_x509_crt_free(&ci->certificateIssuerList); |
| 115976 | UA_String_clear(&ci->trustListFolder); |
| 115977 | UA_String_clear(&ci->issuerListFolder); |
| 115978 | UA_String_clear(&ci->revocationListFolder); |
| 115979 | UA_String_clear(&ci->rejectedListFolder); |
| 115980 | UA_free(ci); |
| 115981 | cv->context = NULL; |
| 115982 | } |
| 115983 | |
| 115984 | static UA_StatusCode |
| 115985 | getCertificate_ExpirationDate(UA_DateTime *expiryDateTime, |
| 115986 | UA_ByteString *certificate) { |
| 115987 | mbedtls_x509_crt publicKey; |
| 115988 | mbedtls_x509_crt_init(&publicKey); |
| 115989 | int mbedErr = mbedtls_x509_crt_parse(&publicKey, certificate->data, certificate->length); |
| 115990 | if(mbedErr) |
| 115991 | return UA_STATUSCODE_BADINTERNALERROR; |
| 115992 | UA_DateTimeStruct ts; |
| 115993 | ts.year = (UA_Int16)publicKey.valid_to.year; |
| 115994 | ts.month = (UA_UInt16)publicKey.valid_to.mon; |
| 115995 | ts.day = (UA_UInt16)publicKey.valid_to.day; |
| 115996 | ts.hour = (UA_UInt16)publicKey.valid_to.hour; |
| 115997 | ts.min = (UA_UInt16)publicKey.valid_to.min; |
| 115998 | ts.sec = (UA_UInt16)publicKey.valid_to.sec; |
| 115999 | ts.milliSec = 0; |
| 116000 | ts.microSec = 0; |
| 116001 | ts.nanoSec = 0; |
| 116002 | *expiryDateTime = UA_DateTime_fromStruct(ts); |
| 116003 | mbedtls_x509_crt_free(&publicKey); |
| 116004 | return UA_STATUSCODE_GOOD; |
| 116005 | } |
| 116006 | |
| 116007 | static UA_StatusCode |
| 116008 | getCertificate_SubjectName(UA_String *subjectName, |
| 116009 | UA_ByteString *certificate) { |
| 116010 | mbedtls_x509_crt publicKey; |
| 116011 | mbedtls_x509_crt_init(&publicKey); |
| 116012 | int mbedErr = mbedtls_x509_crt_parse(&publicKey, certificate->data, certificate->length); |
| 116013 | if(mbedErr) |
| 116014 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116015 | char buf[1024]; |
| 116016 | int res = mbedtls_x509_dn_gets(buf, 1024, &publicKey.subject); |
| 116017 | mbedtls_x509_crt_free(&publicKey); |
| 116018 | if(res < 0) |
| 116019 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116020 | UA_String tmp = {(size_t)res, (UA_Byte*)buf}; |
| 116021 | return UA_String_copy(&tmp, subjectName); |
| 116022 | } |
| 116023 | |
| 116024 | UA_StatusCode |
| 116025 | UA_CertificateVerification_Trustlist(UA_CertificateVerification *cv, |
| 116026 | const UA_ByteString *certificateTrustList, |
| 116027 | size_t certificateTrustListSize, |
| 116028 | const UA_ByteString *certificateIssuerList, |
| 116029 | size_t certificateIssuerListSize, |
| 116030 | const UA_ByteString *certificateRevocationList, |
| 116031 | size_t certificateRevocationListSize) { |
| 116032 | |
| 116033 | if(cv == NULL) { |
| 116034 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116035 | } |
| 116036 | |
| 116037 | /* Clear if the plugin is already initialized */ |
| 116038 | if(cv->clear) |
| 116039 | cv->clear(cv); |
| 116040 | |
| 116041 | CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo)); |
| 116042 | if(!ci) |
| 116043 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 116044 | memset(ci, 0, sizeof(CertInfo)); |
| 116045 | ci->cv = cv; |
| 116046 | mbedtls_x509_crt_init(&ci->certificateTrustList); |
| 116047 | mbedtls_x509_crl_init(&ci->certificateRevocationList); |
| 116048 | mbedtls_x509_crt_init(&ci->certificateIssuerList); |
| 116049 | |
| 116050 | cv->context = (void*)ci; |
| 116051 | cv->verifyCertificate = certificateVerification_verify; |
| 116052 | cv->clear = certificateVerification_clear; |
| 116053 | cv->verifyApplicationURI = certificateVerification_verifyApplicationURI; |
| 116054 | cv->getExpirationDate = getCertificate_ExpirationDate; |
| 116055 | cv->getSubjectName = getCertificate_SubjectName; |
| 116056 | |
| 116057 | int err; |
| 116058 | UA_ByteString data; |
| 116059 | UA_ByteString_init(&data); |
| 116060 | |
| 116061 | for(size_t i = 0; i < certificateTrustListSize; i++) { |
| 116062 | data = copyDataFormatAware(&certificateTrustList[i]); |
| 116063 | err = mbedtls_x509_crt_parse(&ci->certificateTrustList, |
| 116064 | data.data, |
| 116065 | data.length); |
| 116066 | UA_ByteString_clear(&data); |
| 116067 | if(err) |
| 116068 | goto error; |
| 116069 | } |
| 116070 | for(size_t i = 0; i < certificateIssuerListSize; i++) { |
| 116071 | data = copyDataFormatAware(&certificateIssuerList[i]); |
| 116072 | err = mbedtls_x509_crt_parse(&ci->certificateIssuerList, |
| 116073 | data.data, |
| 116074 | data.length); |
| 116075 | UA_ByteString_clear(&data); |
| 116076 | if(err) |
| 116077 | goto error; |
| 116078 | } |
| 116079 | for(size_t i = 0; i < certificateRevocationListSize; i++) { |
| 116080 | data = copyDataFormatAware(&certificateRevocationList[i]); |
| 116081 | err = mbedtls_x509_crl_parse(&ci->certificateRevocationList, |
| 116082 | data.data, |
| 116083 | data.length); |
| 116084 | UA_ByteString_clear(&data); |
| 116085 | if(err) |
| 116086 | goto error; |
| 116087 | } |
| 116088 | |
| 116089 | return UA_STATUSCODE_GOOD; |
| 116090 | error: |
| 116091 | certificateVerification_clear(cv); |
| 116092 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116093 | } |
| 116094 | |
| 116095 | #ifdef __linux__ /* Linux only so far */ |
| 116096 | |
| 116097 | #ifdef UA_ENABLE_CERT_REJECTED_DIR |
| 116098 | UA_StatusCode |
| 116099 | UA_CertificateVerification_CertFolders(UA_CertificateVerification *cv, |
| 116100 | const char *trustListFolder, |
| 116101 | const char *issuerListFolder, |
| 116102 | const char *revocationListFolder, |
| 116103 | const char *rejectedListFolder) { |
| 116104 | #else |
| 116105 | UA_StatusCode |
| 116106 | UA_CertificateVerification_CertFolders(UA_CertificateVerification *cv, |
| 116107 | const char *trustListFolder, |
| 116108 | const char *issuerListFolder, |
| 116109 | const char *revocationListFolder) { |
| 116110 | #endif |
| 116111 | UA_StatusCode ret; |
| 116112 | if(cv == NULL) { |
| 116113 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116114 | } |
| 116115 | if(cv->logging == NULL) { |
| 116116 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116117 | } |
| 116118 | |
| 116119 | /* Clear if the plugin is already initialized */ |
| 116120 | if(cv->clear) |
| 116121 | cv->clear(cv); |
| 116122 | |
| 116123 | CertInfo *ci = (CertInfo*)UA_malloc(sizeof(CertInfo)); |
| 116124 | if(!ci) |
| 116125 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 116126 | memset(ci, 0, sizeof(CertInfo)); |
| 116127 | ci->cv = cv; |
| 116128 | mbedtls_x509_crt_init(&ci->certificateTrustList); |
| 116129 | mbedtls_x509_crl_init(&ci->certificateRevocationList); |
| 116130 | mbedtls_x509_crt_init(&ci->certificateIssuerList); |
| 116131 | |
| 116132 | /* Only set the folder paths. They will be reloaded during runtime. |
| 116133 | * TODO: Add a more efficient reloading of only the changes */ |
| 116134 | ci->trustListFolder = UA_STRING_ALLOC(trustListFolder); |
| 116135 | ci->issuerListFolder = UA_STRING_ALLOC(issuerListFolder); |
| 116136 | ci->revocationListFolder = UA_STRING_ALLOC(revocationListFolder); |
| 116137 | #ifdef UA_ENABLE_CERT_REJECTED_DIR |
| 116138 | ci->rejectedListFolder = UA_STRING_ALLOC(rejectedListFolder); |
| 116139 | #endif |
| 116140 | |
| 116141 | cv->context = (void*)ci; |
| 116142 | cv->verifyCertificate = certificateVerification_verify; |
| 116143 | cv->clear = certificateVerification_clear; |
| 116144 | cv->verifyApplicationURI = certificateVerification_verifyApplicationURI; |
| 116145 | |
| 116146 | ret = reloadCertificates(cv, ci); |
| 116147 | |
| 116148 | return ret; |
| 116149 | } |
| 116150 | |
| 116151 | #endif |
| 116152 | |
| 116153 | UA_StatusCode |
| 116154 | UA_PKI_decryptPrivateKey(const UA_ByteString privateKey, |
| 116155 | const UA_ByteString password, |
| 116156 | UA_ByteString *outDerKey) { |
| 116157 | if(!outDerKey) |
| 116158 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116159 | |
| 116160 | if (privateKey.length == 0) { |
| 116161 | *outDerKey = UA_BYTESTRING_NULL; |
| 116162 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 116163 | } |
| 116164 | |
| 116165 | /* Already in DER format -> return verbatim */ |
| 116166 | if(privateKey.length > 1 && privateKey.data[0] == 0x30 && privateKey.data[1] == 0x82) |
| 116167 | return UA_ByteString_copy(&privateKey, outDerKey); |
| 116168 | |
| 116169 | /* Create a null-terminated string */ |
| 116170 | UA_ByteString nullTerminatedKey = UA_mbedTLS_CopyDataFormatAware(&privateKey); |
| 116171 | if(nullTerminatedKey.length != privateKey.length + 1) |
| 116172 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 116173 | |
| 116174 | /* Create the private-key context */ |
| 116175 | mbedtls_pk_context ctx; |
| 116176 | mbedtls_pk_init(&ctx); |
| 116177 | #if MBEDTLS_VERSION_NUMBER >= 0x02060000 && MBEDTLS_VERSION_NUMBER < 0x03000000 |
| 116178 | int err = mbedtls_pk_parse_key(&ctx, nullTerminatedKey.data, |
| 116179 | nullTerminatedKey.length, |
| 116180 | password.data, password.length); |
| 116181 | #else |
| 116182 | mbedtls_entropy_context entropy; |
| 116183 | mbedtls_entropy_init(&entropy); |
| 116184 | int err = mbedtls_pk_parse_key(&ctx, nullTerminatedKey.data, |
| 116185 | nullTerminatedKey.length, |
| 116186 | password.data, password.length, |
| 116187 | mbedtls_entropy_func, &entropy); |
| 116188 | mbedtls_entropy_free(&entropy); |
| 116189 | #endif |
| 116190 | UA_ByteString_clear(&nullTerminatedKey); |
| 116191 | if(err != 0) { |
| 116192 | mbedtls_pk_free(&ctx); |
| 116193 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 116194 | } |
| 116195 | |
| 116196 | /* Write the DER-encoded key into a local buffer */ |
| 116197 | unsigned char buf[1 << 14]; |
| 116198 | size_t pos = (size_t)mbedtls_pk_write_key_der(&ctx, buf, sizeof(buf)); |
| 116199 | |
| 116200 | /* Allocate memory */ |
| 116201 | UA_StatusCode res = UA_ByteString_allocBuffer(outDerKey, pos); |
| 116202 | if(res != UA_STATUSCODE_GOOD) { |
| 116203 | mbedtls_pk_free(&ctx); |
| 116204 | return res; |
| 116205 | } |
| 116206 | |
| 116207 | /* Copy to the output */ |
| 116208 | memcpy(outDerKey->data, &buf[sizeof(buf) - pos], pos); |
| 116209 | mbedtls_pk_free(&ctx); |
| 116210 | return UA_STATUSCODE_GOOD; |
| 116211 | } |
| 116212 | |
| 116213 | #endif /* UA_ENABLE_ENCRYPTION_MBEDTLS */ |
| 116214 | |
| 116215 | /**** amalgamated original file "/plugins/crypto/openssl/securitypolicy_openssl_common.h" ****/ |
| 116216 | |
| 116217 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 116218 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 116219 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 116220 | * |
| 116221 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 116222 | * Copyright 2020 (c) basysKom GmbH |
| 116223 | * |
| 116224 | */ |
| 116225 | |
| 116226 | |
| 116227 | |
| 116228 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 116229 | |
| 116230 | #include <openssl/x509.h> |
| 116231 | #include <openssl/evp.h> |
| 116232 | |
| 116233 | #define UA_SHA1_LENGTH 20 |
| 116234 | |
| 116235 | _UA_BEGIN_DECLS |
| 116236 | |
| 116237 | void saveDataToFile(const char *fileName, const UA_ByteString *str); |
| 116238 | void UA_Openssl_Init(void); |
| 116239 | |
| 116240 | UA_StatusCode |
| 116241 | UA_copyCertificate(UA_ByteString *dst, const UA_ByteString *src); |
| 116242 | |
| 116243 | UA_StatusCode |
| 116244 | UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(const UA_ByteString *msg, |
| 116245 | X509 *publicKeyX509, |
| 116246 | const UA_ByteString *signature); |
| 116247 | |
| 116248 | UA_StatusCode |
| 116249 | UA_OpenSSL_RSA_PSS_SHA256_Verify (const UA_ByteString * msg, |
| 116250 | X509 *publicKeyX509, |
| 116251 | const UA_ByteString * signature); |
| 116252 | |
| 116253 | UA_StatusCode |
| 116254 | UA_Openssl_X509_GetCertificateThumbprint(const UA_ByteString *certficate, |
| 116255 | UA_ByteString *pThumbprint, |
| 116256 | bool bThumbPrint); |
| 116257 | UA_StatusCode |
| 116258 | UA_Openssl_RSA_Oaep_Decrypt(UA_ByteString *data, |
| 116259 | EVP_PKEY *privateKey); |
| 116260 | |
| 116261 | UA_StatusCode |
| 116262 | UA_Openssl_RSA_Oaep_Sha2_Decrypt (UA_ByteString *data, |
| 116263 | EVP_PKEY *privateKey); |
| 116264 | |
| 116265 | UA_StatusCode |
| 116266 | UA_Openssl_RSA_OAEP_Encrypt(UA_ByteString *data, /* The data that is encrypted. |
| 116267 | The encrypted data will overwrite |
| 116268 | the data that was supplied. */ |
| 116269 | size_t paddingSize, X509 *publicX509); |
| 116270 | |
| 116271 | UA_StatusCode |
| 116272 | UA_Openssl_RSA_OAEP_SHA2_Encrypt (UA_ByteString * data, |
| 116273 | size_t paddingSize, |
| 116274 | X509 * publicX509); |
| 116275 | |
| 116276 | UA_StatusCode |
| 116277 | UA_Openssl_Random_Key_PSHA256_Derive(const UA_ByteString *secret, |
| 116278 | const UA_ByteString *seed, |
| 116279 | UA_ByteString *out); |
| 116280 | |
| 116281 | UA_StatusCode |
| 116282 | UA_Openssl_RSA_Public_GetKeyLength(X509 *publicKeyX509, UA_Int32 *keyLen); |
| 116283 | |
| 116284 | UA_StatusCode |
| 116285 | UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(const UA_ByteString *data, |
| 116286 | EVP_PKEY *privateKey, |
| 116287 | UA_ByteString *outSignature); |
| 116288 | |
| 116289 | UA_StatusCode |
| 116290 | UA_Openssl_RSA_PSS_SHA256_Sign (const UA_ByteString * message, |
| 116291 | EVP_PKEY * privateKey, |
| 116292 | UA_ByteString * outSignature); |
| 116293 | |
| 116294 | UA_StatusCode |
| 116295 | UA_OpenSSL_HMAC_SHA256_Verify(const UA_ByteString *message, |
| 116296 | const UA_ByteString *key, |
| 116297 | const UA_ByteString *signature); |
| 116298 | |
| 116299 | UA_StatusCode |
| 116300 | UA_OpenSSL_HMAC_SHA256_Sign(const UA_ByteString *message, |
| 116301 | const UA_ByteString *key, |
| 116302 | UA_ByteString *signature); |
| 116303 | |
| 116304 | UA_StatusCode |
| 116305 | UA_OpenSSL_AES_256_CBC_Decrypt(const UA_ByteString *iv, |
| 116306 | const UA_ByteString *key, |
| 116307 | UA_ByteString *data /* [in/out]*/); |
| 116308 | |
| 116309 | UA_StatusCode |
| 116310 | UA_OpenSSL_AES_256_CBC_Encrypt(const UA_ByteString *iv, |
| 116311 | const UA_ByteString *key, |
| 116312 | UA_ByteString *data /* [in/out]*/); |
| 116313 | |
| 116314 | UA_StatusCode |
| 116315 | UA_OpenSSL_X509_compare(const UA_ByteString *cert, const X509 *b); |
| 116316 | |
| 116317 | UA_StatusCode |
| 116318 | UA_Openssl_RSA_Private_GetKeyLength(EVP_PKEY *privateKey, |
| 116319 | UA_Int32 *keyLen) ; |
| 116320 | |
| 116321 | UA_StatusCode |
| 116322 | UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify(const UA_ByteString *msg, |
| 116323 | X509 *publicKeyX509, |
| 116324 | const UA_ByteString *signature); |
| 116325 | |
| 116326 | UA_StatusCode |
| 116327 | UA_Openssl_RSA_PKCS1_V15_SHA1_Sign(const UA_ByteString *message, |
| 116328 | EVP_PKEY *privateKey, |
| 116329 | UA_ByteString *outSignature); |
| 116330 | UA_StatusCode |
| 116331 | UA_Openssl_Random_Key_PSHA1_Derive(const UA_ByteString *secret, |
| 116332 | const UA_ByteString *seed, |
| 116333 | UA_ByteString *out); |
| 116334 | UA_StatusCode |
| 116335 | UA_OpenSSL_HMAC_SHA1_Verify(const UA_ByteString *message, |
| 116336 | const UA_ByteString *key, |
| 116337 | const UA_ByteString *signature); |
| 116338 | |
| 116339 | UA_StatusCode |
| 116340 | UA_OpenSSL_HMAC_SHA1_Sign(const UA_ByteString *message, |
| 116341 | const UA_ByteString *key, |
| 116342 | UA_ByteString *signature); |
| 116343 | |
| 116344 | UA_StatusCode |
| 116345 | UA_Openssl_RSA_PKCS1_V15_Decrypt(UA_ByteString *data, |
| 116346 | EVP_PKEY *privateKey); |
| 116347 | |
| 116348 | UA_StatusCode |
| 116349 | UA_Openssl_RSA_PKCS1_V15_Encrypt(UA_ByteString *data, |
| 116350 | size_t paddingSize, |
| 116351 | X509 *publicX509); |
| 116352 | |
| 116353 | UA_StatusCode |
| 116354 | UA_OpenSSL_AES_128_CBC_Decrypt(const UA_ByteString *iv, |
| 116355 | const UA_ByteString *key, |
| 116356 | UA_ByteString *data /* [in/out]*/); |
| 116357 | |
| 116358 | UA_StatusCode |
| 116359 | UA_OpenSSL_AES_128_CBC_Encrypt(const UA_ByteString *iv, |
| 116360 | const UA_ByteString *key, |
| 116361 | UA_ByteString *data /* [in/out]*/); |
| 116362 | |
| 116363 | EVP_PKEY * |
| 116364 | UA_OpenSSL_LoadPrivateKey(const UA_ByteString *privateKey); |
| 116365 | |
| 116366 | X509 * |
| 116367 | UA_OpenSSL_LoadCertificate(const UA_ByteString *certificate); |
| 116368 | |
| 116369 | X509 * |
| 116370 | UA_OpenSSL_LoadDerCertificate(const UA_ByteString *certificate); |
| 116371 | |
| 116372 | X509 * |
| 116373 | UA_OpenSSL_LoadPemCertificate(const UA_ByteString *certificate); |
| 116374 | |
| 116375 | UA_StatusCode |
| 116376 | UA_OpenSSL_LoadLocalCertificate(const UA_ByteString *certificate, UA_ByteString *target); |
| 116377 | |
| 116378 | _UA_END_DECLS |
| 116379 | |
| 116380 | #endif /* defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */ |
| 116381 | |
| 116382 | |
| 116383 | /**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_version_abstraction.h" ****/ |
| 116384 | |
| 116385 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 116386 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 116387 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 116388 | * |
| 116389 | * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 116390 | * |
| 116391 | */ |
| 116392 | |
| 116393 | |
| 116394 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 116395 | |
| 116396 | #include <openssl/x509.h> |
| 116397 | |
| 116398 | #if !defined(OPENSSL_VERSION_NUMBER) |
| 116399 | #error "OPENSSL_VERSION_NUMBER is not defined." |
| 116400 | #endif |
| 116401 | |
| 116402 | #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) |
| 116403 | #define X509_STORE_CTX_set0_trusted_stack(STORE_CTX, CTX_SKTRUSTED) X509_STORE_CTX_trusted_stack(STORE_CTX, CTX_SKTRUSTED) |
| 116404 | #endif |
| 116405 | |
| 116406 | #if OPENSSL_VERSION_NUMBER < 0x1010000fL || ( defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050000fL) |
| 116407 | #define X509_STORE_CTX_get_check_issued(STORE_CTX) STORE_CTX->check_issued |
| 116408 | #endif |
| 116409 | |
| 116410 | #if OPENSSL_VERSION_NUMBER < 0x1010000fL || ( defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050000fL) |
| 116411 | #define get_pkey_rsa(evp) ((evp)->pkey.rsa) |
| 116412 | #else |
| 116413 | #define get_pkey_rsa(evp) EVP_PKEY_get0_RSA(evp) |
| 116414 | #endif |
| 116415 | |
| 116416 | #if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(LIBRESSL_VERSION_NUMBER) |
| 116417 | #define X509_get0_subject_key_id(PX509_CERT) (const ASN1_OCTET_STRING *)X509_get_ext_d2i(PX509_CERT, NID_subject_key_identifier, NULL, NULL); |
| 116418 | #endif |
| 116419 | |
| 116420 | #if OPENSSL_VERSION_NUMBER < 0x2000000fL || defined(LIBRESSL_VERSION_NUMBER) |
| 116421 | #define get_error_line_data(pFile, pLine, pData, pFlags) ERR_get_error_line_data(pFile, pLine, pData, pFlags) |
| 116422 | #else |
| 116423 | #define get_error_line_data(pFile, pLine, pData, pFlags) ERR_get_error_all(pFile, pLine, NULL, pData, pFlags) |
| 116424 | #endif |
| 116425 | |
| 116426 | #endif /* defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */ |
| 116427 | |
| 116428 | /**** amalgamated original file "/plugins/crypto/openssl/securitypolicy_openssl_common.c" ****/ |
| 116429 | |
| 116430 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 116431 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 116432 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 116433 | * |
| 116434 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 116435 | * Copyright 2020 (c) basysKom GmbH |
| 116436 | * Copyright 2022 (c) Wind River Systems, Inc. |
| 116437 | * Copyright 2022 (c) Fraunhofer IOSB (Author: Noel Graf) |
| 116438 | */ |
| 116439 | |
| 116440 | /* |
| 116441 | modification history |
| 116442 | -------------------- |
| 116443 | 01feb20,lan written |
| 116444 | */ |
| 116445 | |
| 116446 | |
| 116447 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 116448 | |
| 116449 | #include <openssl/rsa.h> |
| 116450 | #include <openssl/evp.h> |
| 116451 | #include <openssl/err.h> |
| 116452 | #include <openssl/sha.h> |
| 116453 | #include <openssl/x509.h> |
| 116454 | #include <openssl/hmac.h> |
| 116455 | #include <openssl/aes.h> |
| 116456 | #include <openssl/pem.h> |
| 116457 | |
| 116458 | |
| 116459 | #define SHA1_DIGEST_LENGTH 20 /* 160 bits */ |
| 116460 | #define RSA_DECRYPT_BUFFER_LENGTH 2048 /* bytes */ |
| 116461 | |
| 116462 | /* Cast to prevent warnings in LibreSSL */ |
| 116463 | #define SHA256EVP() ((EVP_MD *)(uintptr_t)EVP_sha256()) |
| 116464 | |
| 116465 | |
| 116466 | /** P_SHA256 Context */ |
| 116467 | typedef struct UA_Openssl_P_SHA256_Ctx_ { |
| 116468 | size_t seedLen; |
| 116469 | size_t secretLen; |
| 116470 | UA_Byte A[32]; /* 32 bytes of SHA256 output */ |
| 116471 | /* |
| 116472 | char seed[seedLen]; |
| 116473 | char secret[secretLen]; */ |
| 116474 | } UA_Openssl_P_SHA256_Ctx; |
| 116475 | |
| 116476 | #define UA_Openssl_P_SHA256_SEED(ctx) ((ctx)->A+32) |
| 116477 | #define UA_Openssl_P_SHA256_SECRET(ctx) ((ctx)->A+32+(ctx)->seedLen) |
| 116478 | |
| 116479 | /** P_SHA1 Context */ |
| 116480 | typedef struct UA_Openssl_P_SHA1_Ctx_ { |
| 116481 | size_t seedLen; |
| 116482 | size_t secretLen; |
| 116483 | UA_Byte A[SHA1_DIGEST_LENGTH]; /* 20 bytes of SHA1 output */ |
| 116484 | /* |
| 116485 | char seed[seedLen]; |
| 116486 | char secret[secretLen]; */ |
| 116487 | } UA_Openssl_P_SHA1_Ctx; |
| 116488 | |
| 116489 | #define UA_Openssl_P_SHA1_SEED(ctx) ((ctx)->A + SHA1_DIGEST_LENGTH) |
| 116490 | #define UA_Openssl_P_SHA1_SECRET(ctx) ((ctx)->A + SHA1_DIGEST_LENGTH +(ctx)->seedLen) |
| 116491 | |
| 116492 | void |
| 116493 | UA_Openssl_Init (void) { |
| 116494 | /* VxWorks7 has initialized the openssl. */ |
| 116495 | #ifndef __VXWORKS__ |
| 116496 | static UA_Int16 bInit = 0; |
| 116497 | if (bInit == 1) |
| 116498 | return; |
| 116499 | #if defined(OPENSSL_API_COMPAT) && (OPENSSL_API_COMPAT < 0x10100000L) |
| 116500 | /* only needed, if OpenSSL < V1.1 */ |
| 116501 | OpenSSL_add_all_algorithms (); |
| 116502 | ERR_load_crypto_strings (); |
| 116503 | #endif |
| 116504 | bInit = 1; |
| 116505 | #endif |
| 116506 | } |
| 116507 | |
| 116508 | static int UA_OpenSSL_RSA_Key_Size (EVP_PKEY * key){ |
| 116509 | #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) |
| 116510 | return EVP_PKEY_get_size (pkey: key); |
| 116511 | #else |
| 116512 | return RSA_size (get_pkey_rsa(key)); |
| 116513 | #endif |
| 116514 | } |
| 116515 | |
| 116516 | /* UA_copyCertificate - allocalte the buffer, copy the certificate and |
| 116517 | * add a NULL to the end |
| 116518 | */ |
| 116519 | |
| 116520 | UA_StatusCode |
| 116521 | UA_copyCertificate (UA_ByteString * dst, |
| 116522 | const UA_ByteString * src) { |
| 116523 | UA_StatusCode retval = UA_ByteString_allocBuffer (bs: dst, length: src->length + 1); |
| 116524 | if (retval != UA_STATUSCODE_GOOD) |
| 116525 | return retval; |
| 116526 | (void) memcpy (dest: dst->data, src: src->data, n: src->length); |
| 116527 | dst->data[dst->length - 1] = '\0'; |
| 116528 | dst->length--; |
| 116529 | |
| 116530 | return UA_STATUSCODE_GOOD; |
| 116531 | } |
| 116532 | |
| 116533 | static UA_StatusCode |
| 116534 | UA_OpenSSL_RSA_Public_Verify(const UA_ByteString *message, |
| 116535 | const EVP_MD *evpMd, X509 *publicKeyX509, |
| 116536 | UA_Int16 padding, const UA_ByteString *signature) { |
| 116537 | EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); |
| 116538 | if(!mdctx) |
| 116539 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 116540 | |
| 116541 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 116542 | EVP_PKEY *evpPublicKey = X509_get_pubkey(x: publicKeyX509); |
| 116543 | if(!evpPublicKey) { |
| 116544 | ret = UA_STATUSCODE_BADOUTOFMEMORY; |
| 116545 | goto errout; |
| 116546 | } |
| 116547 | |
| 116548 | EVP_PKEY_CTX *evpKeyCtx; |
| 116549 | int opensslRet = EVP_DigestVerifyInit(ctx: mdctx, pctx: &evpKeyCtx, type: evpMd, |
| 116550 | NULL, pkey: evpPublicKey); |
| 116551 | if(opensslRet != 1) { |
| 116552 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116553 | goto errout; |
| 116554 | } |
| 116555 | |
| 116556 | opensslRet = EVP_PKEY_CTX_set_rsa_padding(ctx: evpKeyCtx, pad_mode: padding); |
| 116557 | if(opensslRet != 1) { |
| 116558 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116559 | goto errout; |
| 116560 | } |
| 116561 | |
| 116562 | if(padding == RSA_PKCS1_PSS_PADDING) { |
| 116563 | opensslRet = EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx: evpKeyCtx, RSA_PSS_SALTLEN_DIGEST); |
| 116564 | if(opensslRet != 1) { |
| 116565 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116566 | goto errout; |
| 116567 | } |
| 116568 | opensslRet = EVP_PKEY_CTX_set_rsa_mgf1_md(ctx: evpKeyCtx, SHA256EVP()); |
| 116569 | if(opensslRet != 1) { |
| 116570 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116571 | goto errout; |
| 116572 | } |
| 116573 | } |
| 116574 | |
| 116575 | opensslRet = EVP_DigestVerifyUpdate (ctx: mdctx, data: message->data, dsize: message->length); |
| 116576 | if(opensslRet != 1) { |
| 116577 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116578 | goto errout; |
| 116579 | } |
| 116580 | |
| 116581 | opensslRet = EVP_DigestVerifyFinal(ctx: mdctx, sig: signature->data, siglen: signature->length); |
| 116582 | if(opensslRet != 1) { |
| 116583 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116584 | goto errout; |
| 116585 | } |
| 116586 | |
| 116587 | errout: |
| 116588 | if(evpPublicKey) |
| 116589 | EVP_PKEY_free(pkey: evpPublicKey); |
| 116590 | if(mdctx) |
| 116591 | EVP_MD_CTX_destroy(mdctx); |
| 116592 | return ret; |
| 116593 | } |
| 116594 | |
| 116595 | UA_StatusCode |
| 116596 | UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify (const UA_ByteString * msg, |
| 116597 | X509 * publicKeyX509, |
| 116598 | const UA_ByteString * signature |
| 116599 | ) { |
| 116600 | return UA_OpenSSL_RSA_Public_Verify (message: msg, evpMd: EVP_sha256(), publicKeyX509, |
| 116601 | RSA_PKCS1_PADDING, signature); |
| 116602 | } |
| 116603 | |
| 116604 | UA_StatusCode |
| 116605 | UA_OpenSSL_RSA_PSS_SHA256_Verify (const UA_ByteString * msg, |
| 116606 | X509 * publicKeyX509, |
| 116607 | const UA_ByteString * signature |
| 116608 | ) { |
| 116609 | return UA_OpenSSL_RSA_Public_Verify (message: msg, evpMd: EVP_sha256(), publicKeyX509, |
| 116610 | RSA_PKCS1_PSS_PADDING, signature); |
| 116611 | } |
| 116612 | |
| 116613 | /* Get certificate thumbprint, and allocate the buffer. */ |
| 116614 | |
| 116615 | UA_StatusCode |
| 116616 | UA_Openssl_X509_GetCertificateThumbprint (const UA_ByteString * certficate, |
| 116617 | UA_ByteString * pThumbprint, |
| 116618 | bool bThumbPrint) { |
| 116619 | if (bThumbPrint) { |
| 116620 | pThumbprint->length = SHA_DIGEST_LENGTH; |
| 116621 | UA_StatusCode ret = UA_ByteString_allocBuffer (bs: pThumbprint, length: pThumbprint->length); |
| 116622 | if (ret != UA_STATUSCODE_GOOD) { |
| 116623 | return ret; |
| 116624 | } |
| 116625 | } |
| 116626 | else { |
| 116627 | if (pThumbprint->length != SHA_DIGEST_LENGTH) { |
| 116628 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116629 | } |
| 116630 | } |
| 116631 | X509 * x509Certificate = UA_OpenSSL_LoadCertificate(certificate: certficate); |
| 116632 | |
| 116633 | if (x509Certificate == NULL) { |
| 116634 | if (bThumbPrint) { |
| 116635 | UA_ByteString_clear (p: pThumbprint); |
| 116636 | } |
| 116637 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116638 | } |
| 116639 | |
| 116640 | if (X509_digest (data: x509Certificate, type: EVP_sha1(), md: pThumbprint->data, NULL) |
| 116641 | != 1) { |
| 116642 | if (bThumbPrint) { |
| 116643 | UA_ByteString_clear (p: pThumbprint); |
| 116644 | } |
| 116645 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116646 | } |
| 116647 | X509_free(a: x509Certificate); |
| 116648 | |
| 116649 | return UA_STATUSCODE_GOOD; |
| 116650 | } |
| 116651 | |
| 116652 | static UA_StatusCode |
| 116653 | UA_Openssl_RSA_Private_Decrypt (UA_ByteString * data, |
| 116654 | EVP_PKEY * privateKey, |
| 116655 | UA_Int16 padding, |
| 116656 | UA_Boolean withSha256) { |
| 116657 | if (data == NULL || privateKey == NULL) { |
| 116658 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 116659 | } |
| 116660 | |
| 116661 | if (privateKey == NULL) { |
| 116662 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 116663 | } |
| 116664 | |
| 116665 | size_t keySize = (size_t) UA_OpenSSL_RSA_Key_Size (key: privateKey); |
| 116666 | size_t cipherOffset = 0; |
| 116667 | size_t outOffset = 0; |
| 116668 | unsigned char buf[RSA_DECRYPT_BUFFER_LENGTH]; |
| 116669 | size_t decryptedBytes; |
| 116670 | EVP_PKEY_CTX * ctx; |
| 116671 | int opensslRet; |
| 116672 | |
| 116673 | ctx = EVP_PKEY_CTX_new (pkey: privateKey, NULL); |
| 116674 | if (ctx == NULL) { |
| 116675 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 116676 | } |
| 116677 | opensslRet = EVP_PKEY_decrypt_init (ctx); |
| 116678 | if (opensslRet != 1) { |
| 116679 | EVP_PKEY_CTX_free (ctx); |
| 116680 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116681 | } |
| 116682 | opensslRet = EVP_PKEY_CTX_set_rsa_padding (ctx, pad_mode: padding); |
| 116683 | if (opensslRet != 1) { |
| 116684 | EVP_PKEY_CTX_free (ctx); |
| 116685 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116686 | } |
| 116687 | if(withSha256) { |
| 116688 | opensslRet = EVP_PKEY_CTX_set_rsa_oaep_md(ctx, SHA256EVP()); |
| 116689 | if (opensslRet != 1) { |
| 116690 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116691 | } |
| 116692 | opensslRet = EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, SHA256EVP()); |
| 116693 | if (opensslRet != 1) { |
| 116694 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116695 | } |
| 116696 | } |
| 116697 | |
| 116698 | while (cipherOffset < data->length) { |
| 116699 | decryptedBytes = RSA_DECRYPT_BUFFER_LENGTH; |
| 116700 | opensslRet = EVP_PKEY_decrypt (ctx, |
| 116701 | out: buf, /* where to decrypt */ |
| 116702 | outlen: &decryptedBytes, |
| 116703 | in: data->data + cipherOffset, /* what to decrypt */ |
| 116704 | inlen: keySize |
| 116705 | ); |
| 116706 | if (opensslRet != 1) { |
| 116707 | EVP_PKEY_CTX_free (ctx); |
| 116708 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 116709 | } |
| 116710 | (void) memcpy(dest: data->data + outOffset, src: buf, n: decryptedBytes); |
| 116711 | cipherOffset += (size_t) keySize; |
| 116712 | outOffset += decryptedBytes; |
| 116713 | } |
| 116714 | data->length = outOffset; |
| 116715 | EVP_PKEY_CTX_free (ctx); |
| 116716 | |
| 116717 | return UA_STATUSCODE_GOOD; |
| 116718 | } |
| 116719 | |
| 116720 | UA_StatusCode |
| 116721 | UA_Openssl_RSA_Oaep_Decrypt (UA_ByteString * data, |
| 116722 | EVP_PKEY * privateKey) { |
| 116723 | return UA_Openssl_RSA_Private_Decrypt (data, privateKey, |
| 116724 | RSA_PKCS1_OAEP_PADDING, false); |
| 116725 | } |
| 116726 | |
| 116727 | UA_StatusCode |
| 116728 | UA_Openssl_RSA_Oaep_Sha2_Decrypt (UA_ByteString * data, |
| 116729 | EVP_PKEY * privateKey) { |
| 116730 | return UA_Openssl_RSA_Private_Decrypt (data, privateKey, |
| 116731 | RSA_PKCS1_OAEP_PADDING, true); |
| 116732 | } |
| 116733 | |
| 116734 | static UA_StatusCode |
| 116735 | UA_Openssl_RSA_Public_Encrypt (const UA_ByteString * message, |
| 116736 | X509 * publicX509, |
| 116737 | UA_Int16 padding, |
| 116738 | size_t paddingSize, |
| 116739 | UA_ByteString * encrypted, |
| 116740 | UA_Boolean withSha256) { |
| 116741 | EVP_PKEY_CTX * ctx = NULL; |
| 116742 | EVP_PKEY * evpPublicKey = NULL; |
| 116743 | int opensslRet; |
| 116744 | UA_StatusCode ret; |
| 116745 | size_t encryptedTextLen = 0; |
| 116746 | size_t dataPos = 0; |
| 116747 | size_t encryptedPos = 0; |
| 116748 | size_t bytesToEncrypt = 0; |
| 116749 | size_t encryptedBlockSize = 0; |
| 116750 | size_t keySize = 0; |
| 116751 | |
| 116752 | evpPublicKey = X509_get_pubkey (x: publicX509); |
| 116753 | if (evpPublicKey == NULL) { |
| 116754 | ret = UA_STATUSCODE_BADOUTOFMEMORY; |
| 116755 | goto errout; |
| 116756 | } |
| 116757 | ctx = EVP_PKEY_CTX_new (pkey: evpPublicKey, NULL); |
| 116758 | if (ctx == NULL) { |
| 116759 | ret = UA_STATUSCODE_BADOUTOFMEMORY; |
| 116760 | goto errout; |
| 116761 | } |
| 116762 | opensslRet = EVP_PKEY_encrypt_init (ctx); |
| 116763 | if (opensslRet != 1) { |
| 116764 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116765 | goto errout; |
| 116766 | } |
| 116767 | opensslRet = EVP_PKEY_CTX_set_rsa_padding (ctx, pad_mode: padding); |
| 116768 | if (opensslRet != 1) { |
| 116769 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116770 | goto errout; |
| 116771 | } |
| 116772 | if(withSha256) { |
| 116773 | opensslRet = EVP_PKEY_CTX_set_rsa_oaep_md(ctx, SHA256EVP()); |
| 116774 | if (opensslRet != 1) { |
| 116775 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116776 | goto errout; |
| 116777 | } |
| 116778 | opensslRet = EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, SHA256EVP()); |
| 116779 | if (opensslRet != 1) { |
| 116780 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116781 | goto errout; |
| 116782 | } |
| 116783 | } |
| 116784 | |
| 116785 | /* get the encrypted block size */ |
| 116786 | |
| 116787 | keySize = (size_t) UA_OpenSSL_RSA_Key_Size (key: evpPublicKey); |
| 116788 | if (keySize == 0) { |
| 116789 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116790 | goto errout; |
| 116791 | } |
| 116792 | |
| 116793 | switch (padding) { |
| 116794 | case RSA_PKCS1_OAEP_PADDING: |
| 116795 | case RSA_PKCS1_PADDING: |
| 116796 | if (keySize <= paddingSize) { |
| 116797 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116798 | goto errout; |
| 116799 | } |
| 116800 | encryptedBlockSize = keySize - paddingSize; |
| 116801 | break; |
| 116802 | default: |
| 116803 | ret = UA_STATUSCODE_BADNOTSUPPORTED; |
| 116804 | goto errout; |
| 116805 | break; |
| 116806 | } |
| 116807 | |
| 116808 | /* encrypt in reverse order so that [data] may alias [encrypted] */ |
| 116809 | |
| 116810 | dataPos = message->length; |
| 116811 | encryptedPos = ((dataPos - 1) / encryptedBlockSize + 1) * keySize; |
| 116812 | bytesToEncrypt = (dataPos - 1) % encryptedBlockSize + 1; |
| 116813 | encryptedTextLen = encryptedPos; |
| 116814 | |
| 116815 | while (dataPos > 0) { |
| 116816 | size_t outlen = keySize; |
| 116817 | encryptedPos -= keySize; |
| 116818 | dataPos -= bytesToEncrypt; |
| 116819 | opensslRet = EVP_PKEY_encrypt (ctx, out: encrypted->data + encryptedPos, outlen: &outlen, |
| 116820 | in: message->data + dataPos, inlen: bytesToEncrypt); |
| 116821 | |
| 116822 | if (opensslRet != 1) { |
| 116823 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 116824 | goto errout; |
| 116825 | } |
| 116826 | bytesToEncrypt = encryptedBlockSize; |
| 116827 | } |
| 116828 | encrypted->length = encryptedTextLen; |
| 116829 | |
| 116830 | ret = UA_STATUSCODE_GOOD; |
| 116831 | errout: |
| 116832 | if (evpPublicKey != NULL) { |
| 116833 | EVP_PKEY_free (pkey: evpPublicKey); |
| 116834 | } |
| 116835 | if (ctx != NULL) { |
| 116836 | EVP_PKEY_CTX_free (ctx); |
| 116837 | } |
| 116838 | return ret; |
| 116839 | } |
| 116840 | |
| 116841 | UA_StatusCode |
| 116842 | UA_Openssl_RSA_OAEP_Encrypt (UA_ByteString * data, |
| 116843 | size_t paddingSize, |
| 116844 | X509 * publicX509) { |
| 116845 | UA_ByteString message; |
| 116846 | UA_StatusCode ret; |
| 116847 | |
| 116848 | ret = UA_ByteString_copy (src: data, dst: &message); |
| 116849 | if (ret != UA_STATUSCODE_GOOD) { |
| 116850 | return ret; |
| 116851 | } |
| 116852 | ret = UA_Openssl_RSA_Public_Encrypt (message: &message, publicX509, |
| 116853 | RSA_PKCS1_OAEP_PADDING, |
| 116854 | paddingSize, |
| 116855 | encrypted: data, false); |
| 116856 | UA_ByteString_clear (p: &message); |
| 116857 | return ret; |
| 116858 | } |
| 116859 | |
| 116860 | UA_StatusCode |
| 116861 | UA_Openssl_RSA_OAEP_SHA2_Encrypt (UA_ByteString * data, |
| 116862 | size_t paddingSize, |
| 116863 | X509 * publicX509) { |
| 116864 | UA_ByteString message; |
| 116865 | UA_StatusCode ret; |
| 116866 | |
| 116867 | ret = UA_ByteString_copy (src: data, dst: &message); |
| 116868 | if (ret != UA_STATUSCODE_GOOD) { |
| 116869 | return ret; |
| 116870 | } |
| 116871 | ret = UA_Openssl_RSA_Public_Encrypt (message: &message, publicX509, |
| 116872 | RSA_PKCS1_OAEP_PADDING, |
| 116873 | paddingSize, |
| 116874 | encrypted: data, true); |
| 116875 | UA_ByteString_clear (p: &message); |
| 116876 | return ret; |
| 116877 | } |
| 116878 | |
| 116879 | static UA_Openssl_P_SHA256_Ctx * |
| 116880 | P_SHA256_Ctx_Create (const UA_ByteString * secret, |
| 116881 | const UA_ByteString * seed) { |
| 116882 | size_t size = (UA_Int32)sizeof (UA_Openssl_P_SHA256_Ctx) + secret->length + |
| 116883 | seed->length; |
| 116884 | UA_Openssl_P_SHA256_Ctx * ctx = (UA_Openssl_P_SHA256_Ctx *) UA_malloc (size: size); |
| 116885 | if (ctx == NULL) { |
| 116886 | return NULL; |
| 116887 | } |
| 116888 | ctx->secretLen = secret->length; |
| 116889 | ctx->seedLen = seed->length; |
| 116890 | (void) memcpy (UA_Openssl_P_SHA256_SEED(ctx), src: seed->data, n: seed->length); |
| 116891 | (void) memcpy (UA_Openssl_P_SHA256_SECRET(ctx), src: secret->data, n: secret->length); |
| 116892 | /* A(0) = seed |
| 116893 | A(n) = HMAC_HASH(secret, A(n-1)) */ |
| 116894 | |
| 116895 | if (HMAC (evp_md: EVP_sha256(), key: secret->data, key_len: (int) secret->length, data: seed->data, |
| 116896 | data_len: seed->length, md: ctx->A, NULL) == NULL) { |
| 116897 | UA_free (ptr: ctx); |
| 116898 | return NULL; |
| 116899 | } |
| 116900 | |
| 116901 | return ctx; |
| 116902 | } |
| 116903 | |
| 116904 | static UA_StatusCode |
| 116905 | P_SHA256_Hash_Generate (UA_Openssl_P_SHA256_Ctx * ctx, |
| 116906 | UA_Byte * pHas |
| 116907 | ) { |
| 116908 | /* Calculate P_SHA256(n) = HMAC_SHA256(secret, A(n)+seed) */ |
| 116909 | if (HMAC (evp_md: EVP_sha256(),UA_Openssl_P_SHA256_SECRET(ctx), key_len: (int) ctx->secretLen, |
| 116910 | data: ctx->A, data_len: sizeof (ctx->A) + ctx->seedLen, md: pHas, NULL) == NULL) { |
| 116911 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116912 | } |
| 116913 | |
| 116914 | /* Calculate A(n) = HMAC_SHA256(secret, A(n-1)) */ |
| 116915 | if (HMAC (evp_md: EVP_sha256(),UA_Openssl_P_SHA256_SECRET(ctx), key_len: (int) ctx->secretLen, |
| 116916 | data: ctx->A, data_len: sizeof (ctx->A), md: ctx->A, NULL) == NULL) { |
| 116917 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116918 | } |
| 116919 | return UA_STATUSCODE_GOOD; |
| 116920 | } |
| 116921 | |
| 116922 | UA_StatusCode |
| 116923 | UA_Openssl_Random_Key_PSHA256_Derive (const UA_ByteString * secret, |
| 116924 | const UA_ByteString * seed, |
| 116925 | UA_ByteString * out) { |
| 116926 | size_t keyLen = out->length; |
| 116927 | size_t iter = keyLen/32 + ((keyLen%32)?1:0); |
| 116928 | size_t bufferLen = iter * 32; |
| 116929 | size_t i; |
| 116930 | UA_StatusCode st; |
| 116931 | |
| 116932 | UA_Byte * pBuffer = (UA_Byte *) UA_malloc (size: bufferLen); |
| 116933 | if (pBuffer == NULL) { |
| 116934 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 116935 | } |
| 116936 | |
| 116937 | UA_Openssl_P_SHA256_Ctx * ctx = P_SHA256_Ctx_Create (secret, seed); |
| 116938 | if (ctx == NULL) { |
| 116939 | UA_free (ptr: pBuffer); |
| 116940 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 116941 | } |
| 116942 | |
| 116943 | for (i = 0; i < iter; i++) { |
| 116944 | st = P_SHA256_Hash_Generate (ctx, pHas: pBuffer + (i * 32)); |
| 116945 | if (st != UA_STATUSCODE_GOOD) { |
| 116946 | UA_free (ptr: pBuffer); |
| 116947 | UA_free (ptr: ctx); |
| 116948 | return st; |
| 116949 | } |
| 116950 | } |
| 116951 | |
| 116952 | (void) memcpy (dest: out->data, src: pBuffer, n: keyLen); |
| 116953 | UA_free (ptr: pBuffer); |
| 116954 | UA_free (ptr: ctx); |
| 116955 | return UA_STATUSCODE_GOOD; |
| 116956 | } |
| 116957 | |
| 116958 | /* return the key bytes */ |
| 116959 | UA_StatusCode |
| 116960 | UA_Openssl_RSA_Public_GetKeyLength (X509 * publicKeyX509, |
| 116961 | UA_Int32 * keyLen) { |
| 116962 | EVP_PKEY * evpKey = X509_get_pubkey (x: publicKeyX509); |
| 116963 | if (evpKey == NULL) { |
| 116964 | return UA_STATUSCODE_BADINTERNALERROR; |
| 116965 | } |
| 116966 | *keyLen = UA_OpenSSL_RSA_Key_Size (key: evpKey); |
| 116967 | |
| 116968 | EVP_PKEY_free (pkey: evpKey); |
| 116969 | |
| 116970 | return UA_STATUSCODE_GOOD; |
| 116971 | } |
| 116972 | |
| 116973 | UA_StatusCode |
| 116974 | UA_Openssl_RSA_Private_GetKeyLength (EVP_PKEY * privateKey, |
| 116975 | UA_Int32 * keyLen) { |
| 116976 | if (privateKey == NULL) { |
| 116977 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 116978 | } |
| 116979 | *keyLen = UA_OpenSSL_RSA_Key_Size (key: privateKey); |
| 116980 | |
| 116981 | return UA_STATUSCODE_GOOD; |
| 116982 | } |
| 116983 | |
| 116984 | static UA_StatusCode |
| 116985 | UA_Openssl_RSA_Private_Sign (const UA_ByteString * message, |
| 116986 | EVP_PKEY * privateKey, |
| 116987 | const EVP_MD * evpMd, |
| 116988 | UA_Int16 padding, |
| 116989 | UA_ByteString * outSignature) { |
| 116990 | EVP_MD_CTX * mdctx = NULL; |
| 116991 | int opensslRet; |
| 116992 | EVP_PKEY_CTX * evpKeyCtx; |
| 116993 | UA_StatusCode ret; |
| 116994 | |
| 116995 | mdctx = EVP_MD_CTX_create (); |
| 116996 | if (mdctx == NULL) { |
| 116997 | ret = UA_STATUSCODE_BADOUTOFMEMORY; |
| 116998 | goto errout; |
| 116999 | } |
| 117000 | |
| 117001 | if (privateKey == NULL) { |
| 117002 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117003 | } |
| 117004 | opensslRet = EVP_DigestSignInit (ctx: mdctx, pctx: &evpKeyCtx, type: evpMd, NULL, pkey: privateKey); |
| 117005 | if (opensslRet != 1) { |
| 117006 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117007 | goto errout; |
| 117008 | } |
| 117009 | EVP_PKEY_CTX_set_rsa_padding (ctx: evpKeyCtx, pad_mode: padding); |
| 117010 | if(padding == RSA_PKCS1_PSS_PADDING) { |
| 117011 | opensslRet = EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx: evpKeyCtx, RSA_PSS_SALTLEN_DIGEST); //RSA_PSS_SALTLEN_DIGEST |
| 117012 | if (opensslRet != 1) { |
| 117013 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117014 | goto errout; |
| 117015 | } |
| 117016 | opensslRet = EVP_PKEY_CTX_set_rsa_mgf1_md(ctx: evpKeyCtx, SHA256EVP()); |
| 117017 | if (opensslRet != 1) { |
| 117018 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117019 | goto errout; |
| 117020 | } |
| 117021 | } |
| 117022 | opensslRet = EVP_DigestSignUpdate (ctx: mdctx, data: message->data, dsize: message->length); |
| 117023 | if (opensslRet != 1) { |
| 117024 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117025 | goto errout; |
| 117026 | } |
| 117027 | opensslRet = EVP_DigestSignFinal (ctx: mdctx, sigret: outSignature->data, siglen: &outSignature->length); |
| 117028 | if (opensslRet != 1) { |
| 117029 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117030 | goto errout; |
| 117031 | } |
| 117032 | |
| 117033 | ret = UA_STATUSCODE_GOOD; |
| 117034 | errout: |
| 117035 | if (mdctx != NULL) { |
| 117036 | EVP_MD_CTX_destroy (mdctx); |
| 117037 | } |
| 117038 | return ret; |
| 117039 | } |
| 117040 | |
| 117041 | UA_StatusCode |
| 117042 | UA_Openssl_RSA_PKCS1_V15_SHA256_Sign (const UA_ByteString * message, |
| 117043 | EVP_PKEY * privateKey, |
| 117044 | UA_ByteString * outSignature) { |
| 117045 | return UA_Openssl_RSA_Private_Sign (message, privateKey, evpMd: EVP_sha256(), |
| 117046 | RSA_PKCS1_PADDING , outSignature); |
| 117047 | } |
| 117048 | |
| 117049 | UA_StatusCode |
| 117050 | UA_Openssl_RSA_PSS_SHA256_Sign (const UA_ByteString * message, |
| 117051 | EVP_PKEY * privateKey, |
| 117052 | UA_ByteString * outSignature) { |
| 117053 | return UA_Openssl_RSA_Private_Sign (message, privateKey, evpMd: EVP_sha256(), |
| 117054 | RSA_PKCS1_PSS_PADDING, outSignature); |
| 117055 | } |
| 117056 | |
| 117057 | UA_StatusCode |
| 117058 | UA_OpenSSL_HMAC_SHA256_Verify (const UA_ByteString * message, |
| 117059 | const UA_ByteString * key, |
| 117060 | const UA_ByteString * signature |
| 117061 | ) { |
| 117062 | unsigned char buf[SHA256_DIGEST_LENGTH] = {0}; |
| 117063 | UA_ByteString mac = {SHA256_DIGEST_LENGTH, buf}; |
| 117064 | |
| 117065 | if (HMAC (evp_md: EVP_sha256(), key: key->data, key_len: (int) key->length, data: message->data, data_len: message->length, |
| 117066 | md: mac.data, md_len: (unsigned int *) &mac.length) == NULL) { |
| 117067 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117068 | } |
| 117069 | if (UA_ByteString_equal (p1: signature, p2: &mac)) { |
| 117070 | return UA_STATUSCODE_GOOD; |
| 117071 | } |
| 117072 | else { |
| 117073 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117074 | } |
| 117075 | } |
| 117076 | |
| 117077 | UA_StatusCode |
| 117078 | UA_OpenSSL_HMAC_SHA256_Sign (const UA_ByteString * message, |
| 117079 | const UA_ByteString * key, |
| 117080 | UA_ByteString * signature |
| 117081 | ) { |
| 117082 | if (HMAC (evp_md: EVP_sha256(), key: key->data, key_len: (int) key->length, data: message->data, |
| 117083 | data_len: message->length, |
| 117084 | md: signature->data, md_len: (unsigned int *) &(signature->length)) == NULL) { |
| 117085 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117086 | } |
| 117087 | return UA_STATUSCODE_GOOD; |
| 117088 | } |
| 117089 | |
| 117090 | static UA_StatusCode |
| 117091 | UA_OpenSSL_Decrypt (const UA_ByteString * iv, |
| 117092 | const UA_ByteString * key, |
| 117093 | const EVP_CIPHER * cipherAlg, |
| 117094 | UA_ByteString * data /* [in/out]*/) { |
| 117095 | UA_ByteString ivCopy = {0, NULL}; |
| 117096 | UA_ByteString cipherTxt = {0, NULL}; |
| 117097 | EVP_CIPHER_CTX * ctx = NULL; |
| 117098 | UA_StatusCode ret; |
| 117099 | int opensslRet; |
| 117100 | int outLen; |
| 117101 | int tmpLen; |
| 117102 | |
| 117103 | /* copy the IV because the AES_cbc_encrypt function overwrites it. */ |
| 117104 | |
| 117105 | ret = UA_ByteString_copy (src: iv, dst: &ivCopy); |
| 117106 | if (ret != UA_STATUSCODE_GOOD) { |
| 117107 | goto errout; |
| 117108 | } |
| 117109 | |
| 117110 | ret = UA_ByteString_copy (src: data, dst: &cipherTxt); |
| 117111 | if (ret != UA_STATUSCODE_GOOD) { |
| 117112 | goto errout; |
| 117113 | } |
| 117114 | |
| 117115 | ctx = EVP_CIPHER_CTX_new (); |
| 117116 | if (ctx == NULL) { |
| 117117 | ret = UA_STATUSCODE_BADOUTOFMEMORY; |
| 117118 | goto errout; |
| 117119 | } |
| 117120 | |
| 117121 | /* call EVP_* to decrypt */ |
| 117122 | |
| 117123 | opensslRet = EVP_DecryptInit_ex (ctx, cipher: cipherAlg, NULL, key: key->data, iv: ivCopy.data); |
| 117124 | if (opensslRet != 1) { |
| 117125 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117126 | goto errout; |
| 117127 | } |
| 117128 | /* EVP_DecryptFinal() will return an error code if padding is enabled |
| 117129 | * and the final block is not correctly formatted. |
| 117130 | */ |
| 117131 | EVP_CIPHER_CTX_set_padding (c: ctx, pad: 0); |
| 117132 | opensslRet = EVP_DecryptUpdate (ctx, out: data->data, outl: &outLen, |
| 117133 | in: cipherTxt.data, inl: (int) cipherTxt.length); |
| 117134 | if (opensslRet != 1) { |
| 117135 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117136 | goto errout; |
| 117137 | } |
| 117138 | opensslRet = EVP_DecryptFinal_ex (ctx, outm: data->data + outLen, outl: &tmpLen); |
| 117139 | if (opensslRet != 1) { |
| 117140 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117141 | goto errout; |
| 117142 | } |
| 117143 | outLen += tmpLen; |
| 117144 | data->length = (size_t) outLen; |
| 117145 | ret = UA_STATUSCODE_GOOD; |
| 117146 | |
| 117147 | errout: |
| 117148 | UA_ByteString_clear (p: &ivCopy); |
| 117149 | UA_ByteString_clear (p: &cipherTxt); |
| 117150 | if (ctx != NULL) { |
| 117151 | EVP_CIPHER_CTX_free(c: ctx); |
| 117152 | } |
| 117153 | return ret; |
| 117154 | } |
| 117155 | |
| 117156 | static UA_StatusCode |
| 117157 | UA_OpenSSL_Encrypt (const UA_ByteString * iv, |
| 117158 | const UA_ByteString * key, |
| 117159 | const EVP_CIPHER * cipherAlg, |
| 117160 | UA_ByteString * data /* [in/out]*/ |
| 117161 | ) { |
| 117162 | |
| 117163 | UA_ByteString ivCopy = {0, NULL}; |
| 117164 | UA_ByteString plainTxt = {0, NULL}; |
| 117165 | EVP_CIPHER_CTX * ctx = NULL; |
| 117166 | UA_StatusCode ret; |
| 117167 | int opensslRet; |
| 117168 | int outLen; |
| 117169 | int tmpLen; |
| 117170 | |
| 117171 | /* copy the IV because the AES_cbc_encrypt function overwrites it. */ |
| 117172 | |
| 117173 | ret = UA_ByteString_copy (src: iv, dst: &ivCopy); |
| 117174 | if (ret != UA_STATUSCODE_GOOD) { |
| 117175 | goto errout; |
| 117176 | } |
| 117177 | |
| 117178 | ret = UA_ByteString_copy (src: data, dst: &plainTxt); |
| 117179 | if (ret != UA_STATUSCODE_GOOD) { |
| 117180 | goto errout; |
| 117181 | } |
| 117182 | |
| 117183 | ctx = EVP_CIPHER_CTX_new (); |
| 117184 | if (ctx == NULL) { |
| 117185 | ret = UA_STATUSCODE_BADOUTOFMEMORY; |
| 117186 | goto errout; |
| 117187 | } |
| 117188 | |
| 117189 | /* call EVP_* to encrypt */ |
| 117190 | |
| 117191 | opensslRet = EVP_EncryptInit_ex (ctx, cipher: cipherAlg, NULL, key: key->data, iv: ivCopy.data); |
| 117192 | if (opensslRet != 1) { |
| 117193 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117194 | goto errout; |
| 117195 | } |
| 117196 | |
| 117197 | /* Disable padding. Padding is done in the stack before calling encryption. |
| 117198 | * Ensure that we have a multiple of the block size */ |
| 117199 | if(data->length % (size_t)EVP_CIPHER_CTX_block_size(ctx)) { |
| 117200 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117201 | goto errout; |
| 117202 | } |
| 117203 | opensslRet = EVP_CIPHER_CTX_set_padding(c: ctx, pad: 0); |
| 117204 | if (opensslRet != 1) { |
| 117205 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117206 | goto errout; |
| 117207 | } |
| 117208 | |
| 117209 | /* Encrypt the data */ |
| 117210 | opensslRet = EVP_EncryptUpdate (ctx, out: data->data, outl: &outLen, |
| 117211 | in: plainTxt.data, inl: (int) plainTxt.length); |
| 117212 | if (opensslRet != 1) { |
| 117213 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117214 | goto errout; |
| 117215 | } |
| 117216 | |
| 117217 | /* Encrypt-final does nothing as padding is disabled */ |
| 117218 | opensslRet = EVP_EncryptFinal_ex(ctx, out: data->data + outLen, outl: &tmpLen); |
| 117219 | if (opensslRet != 1) { |
| 117220 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 117221 | goto errout; |
| 117222 | } |
| 117223 | outLen += tmpLen; |
| 117224 | data->length = (size_t) outLen; |
| 117225 | ret = UA_STATUSCODE_GOOD; |
| 117226 | |
| 117227 | errout: |
| 117228 | UA_ByteString_clear (p: &ivCopy); |
| 117229 | UA_ByteString_clear (p: &plainTxt); |
| 117230 | if (ctx != NULL) { |
| 117231 | EVP_CIPHER_CTX_free(c: ctx); |
| 117232 | } |
| 117233 | return ret; |
| 117234 | } |
| 117235 | |
| 117236 | UA_StatusCode |
| 117237 | UA_OpenSSL_AES_256_CBC_Decrypt (const UA_ByteString * iv, |
| 117238 | const UA_ByteString * key, |
| 117239 | UA_ByteString * data /* [in/out]*/ |
| 117240 | ) { |
| 117241 | return UA_OpenSSL_Decrypt (iv, key, cipherAlg: EVP_aes_256_cbc (), data); |
| 117242 | } |
| 117243 | |
| 117244 | UA_StatusCode |
| 117245 | UA_OpenSSL_AES_256_CBC_Encrypt (const UA_ByteString * iv, |
| 117246 | const UA_ByteString * key, |
| 117247 | UA_ByteString * data /* [in/out]*/ |
| 117248 | ) { |
| 117249 | return UA_OpenSSL_Encrypt (iv, key, cipherAlg: EVP_aes_256_cbc (), data); |
| 117250 | } |
| 117251 | |
| 117252 | UA_StatusCode |
| 117253 | UA_OpenSSL_X509_compare (const UA_ByteString * cert, |
| 117254 | const X509 * bcert) { |
| 117255 | X509 * acert = UA_OpenSSL_LoadCertificate(certificate: cert); |
| 117256 | if (acert == NULL) { |
| 117257 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 117258 | } |
| 117259 | int opensslRet = X509_cmp (a: acert, b: bcert); |
| 117260 | X509_free (a: acert); |
| 117261 | |
| 117262 | if (opensslRet == 0) |
| 117263 | return UA_STATUSCODE_GOOD; |
| 117264 | return UA_STATUSCODE_UNCERTAINSUBNORMAL; |
| 117265 | } |
| 117266 | |
| 117267 | UA_StatusCode |
| 117268 | UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (const UA_ByteString * msg, |
| 117269 | X509 * publicKeyX509, |
| 117270 | const UA_ByteString * signature) { |
| 117271 | return UA_OpenSSL_RSA_Public_Verify(message: msg, evpMd: EVP_sha1(), publicKeyX509, |
| 117272 | RSA_PKCS1_PADDING, signature); |
| 117273 | } |
| 117274 | |
| 117275 | UA_StatusCode |
| 117276 | UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (const UA_ByteString * message, |
| 117277 | EVP_PKEY * privateKey, |
| 117278 | UA_ByteString * outSignature) { |
| 117279 | return UA_Openssl_RSA_Private_Sign(message, privateKey, evpMd: EVP_sha1(), |
| 117280 | RSA_PKCS1_PADDING, outSignature); |
| 117281 | } |
| 117282 | |
| 117283 | static UA_Openssl_P_SHA1_Ctx * |
| 117284 | P_SHA1_Ctx_Create (const UA_ByteString * secret, |
| 117285 | const UA_ByteString * seed) { |
| 117286 | size_t size = (UA_Int32)sizeof (UA_Openssl_P_SHA1_Ctx) + secret->length + |
| 117287 | seed->length; |
| 117288 | UA_Openssl_P_SHA1_Ctx * ctx = (UA_Openssl_P_SHA1_Ctx *) UA_malloc (size: size); |
| 117289 | if (ctx == NULL) { |
| 117290 | return NULL; |
| 117291 | } |
| 117292 | |
| 117293 | ctx->secretLen = secret->length; |
| 117294 | ctx->seedLen = seed->length; |
| 117295 | (void) memcpy (UA_Openssl_P_SHA1_SEED(ctx), src: seed->data, n: seed->length); |
| 117296 | (void) memcpy (UA_Openssl_P_SHA1_SECRET(ctx), src: secret->data, n: secret->length); |
| 117297 | /* A(0) = seed |
| 117298 | A(n) = HMAC_HASH(secret, A(n-1)) */ |
| 117299 | |
| 117300 | if (HMAC (evp_md: EVP_sha1(), key: secret->data, key_len: (int) secret->length, data: seed->data, |
| 117301 | data_len: seed->length, md: ctx->A, NULL) == NULL) { |
| 117302 | UA_free (ptr: ctx); |
| 117303 | return NULL; |
| 117304 | } |
| 117305 | |
| 117306 | return ctx; |
| 117307 | } |
| 117308 | |
| 117309 | static UA_StatusCode |
| 117310 | P_SHA1_Hash_Generate (UA_Openssl_P_SHA1_Ctx * ctx, |
| 117311 | UA_Byte * pHas |
| 117312 | ) { |
| 117313 | /* Calculate P_SHA1(n) = HMAC_SHA1(secret, A(n)+seed) */ |
| 117314 | if (HMAC (evp_md: EVP_sha1 (), UA_Openssl_P_SHA1_SECRET(ctx), key_len: (int) ctx->secretLen, |
| 117315 | data: ctx->A, data_len: sizeof (ctx->A) + ctx->seedLen, md: pHas, NULL) == NULL) { |
| 117316 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117317 | } |
| 117318 | |
| 117319 | /* Calculate A(n) = HMAC_SHA1(secret, A(n-1)) */ |
| 117320 | if (HMAC (evp_md: EVP_sha1(), UA_Openssl_P_SHA1_SECRET(ctx), key_len: (int) ctx->secretLen, |
| 117321 | data: ctx->A, data_len: sizeof (ctx->A), md: ctx->A, NULL) == NULL) { |
| 117322 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117323 | } |
| 117324 | return UA_STATUSCODE_GOOD; |
| 117325 | } |
| 117326 | |
| 117327 | UA_StatusCode |
| 117328 | UA_Openssl_Random_Key_PSHA1_Derive (const UA_ByteString * secret, |
| 117329 | const UA_ByteString * seed, |
| 117330 | UA_ByteString * out) { |
| 117331 | size_t keyLen = out->length; |
| 117332 | size_t iter = keyLen / SHA1_DIGEST_LENGTH + ((keyLen % SHA1_DIGEST_LENGTH)?1:0); |
| 117333 | size_t bufferLen = iter * SHA1_DIGEST_LENGTH; |
| 117334 | UA_Byte * pBuffer = (UA_Byte *) UA_malloc (size: bufferLen); |
| 117335 | if (pBuffer == NULL) { |
| 117336 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 117337 | } |
| 117338 | |
| 117339 | UA_Openssl_P_SHA1_Ctx * ctx = P_SHA1_Ctx_Create (secret, seed); |
| 117340 | if (ctx == NULL) { |
| 117341 | UA_free (ptr: pBuffer); |
| 117342 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 117343 | } |
| 117344 | |
| 117345 | size_t i; |
| 117346 | UA_StatusCode st; |
| 117347 | |
| 117348 | for (i = 0; i < iter; i++) { |
| 117349 | st = P_SHA1_Hash_Generate (ctx, pHas: pBuffer + (i * SHA1_DIGEST_LENGTH)); |
| 117350 | if (st != UA_STATUSCODE_GOOD) { |
| 117351 | UA_free (ptr: pBuffer); |
| 117352 | UA_free (ptr: ctx); |
| 117353 | return st; |
| 117354 | } |
| 117355 | } |
| 117356 | |
| 117357 | (void) memcpy (dest: out->data, src: pBuffer, n: keyLen); |
| 117358 | UA_free (ptr: pBuffer); |
| 117359 | UA_free (ptr: ctx); |
| 117360 | |
| 117361 | return UA_STATUSCODE_GOOD; |
| 117362 | } |
| 117363 | |
| 117364 | UA_StatusCode |
| 117365 | UA_OpenSSL_HMAC_SHA1_Verify (const UA_ByteString * message, |
| 117366 | const UA_ByteString * key, |
| 117367 | const UA_ByteString * signature |
| 117368 | ) { |
| 117369 | unsigned char buf[SHA1_DIGEST_LENGTH] = {0}; |
| 117370 | UA_ByteString mac = {SHA1_DIGEST_LENGTH, buf}; |
| 117371 | |
| 117372 | if(HMAC (evp_md: EVP_sha1(), key: key->data, key_len: (int) key->length, data: message->data, data_len: message->length, |
| 117373 | md: mac.data, md_len: (unsigned int *) &mac.length) == NULL) { |
| 117374 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117375 | } |
| 117376 | if (UA_ByteString_equal (p1: signature, p2: &mac)) { |
| 117377 | return UA_STATUSCODE_GOOD; |
| 117378 | } |
| 117379 | else { |
| 117380 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117381 | } |
| 117382 | } |
| 117383 | |
| 117384 | UA_StatusCode |
| 117385 | UA_OpenSSL_HMAC_SHA1_Sign (const UA_ByteString * message, |
| 117386 | const UA_ByteString * key, |
| 117387 | UA_ByteString * signature |
| 117388 | ) { |
| 117389 | if (HMAC (evp_md: EVP_sha1(), key: key->data, key_len: (int) key->length, data: message->data, |
| 117390 | data_len: message->length, |
| 117391 | md: signature->data, md_len: (unsigned int *) &(signature->length)) == NULL) { |
| 117392 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117393 | } |
| 117394 | return UA_STATUSCODE_GOOD; |
| 117395 | } |
| 117396 | |
| 117397 | UA_StatusCode |
| 117398 | UA_Openssl_RSA_PKCS1_V15_Decrypt (UA_ByteString * data, |
| 117399 | EVP_PKEY * privateKey) { |
| 117400 | return UA_Openssl_RSA_Private_Decrypt (data, privateKey, |
| 117401 | RSA_PKCS1_PADDING, false); |
| 117402 | } |
| 117403 | |
| 117404 | UA_StatusCode |
| 117405 | UA_Openssl_RSA_PKCS1_V15_Encrypt (UA_ByteString * data, |
| 117406 | size_t paddingSize, |
| 117407 | X509 * publicX509) { |
| 117408 | UA_ByteString message; |
| 117409 | UA_StatusCode ret = UA_ByteString_copy (src: data, dst: &message); |
| 117410 | if (ret != UA_STATUSCODE_GOOD) { |
| 117411 | return ret; |
| 117412 | } |
| 117413 | ret = UA_Openssl_RSA_Public_Encrypt (message: &message, publicX509, |
| 117414 | RSA_PKCS1_PADDING, |
| 117415 | paddingSize, |
| 117416 | encrypted: data, false); |
| 117417 | UA_ByteString_clear (p: &message); |
| 117418 | return ret; |
| 117419 | } |
| 117420 | |
| 117421 | UA_StatusCode |
| 117422 | UA_OpenSSL_AES_128_CBC_Decrypt (const UA_ByteString * iv, |
| 117423 | const UA_ByteString * key, |
| 117424 | UA_ByteString * data /* [in/out]*/ |
| 117425 | ) { |
| 117426 | return UA_OpenSSL_Decrypt (iv, key, cipherAlg: EVP_aes_128_cbc (), data); |
| 117427 | } |
| 117428 | |
| 117429 | UA_StatusCode |
| 117430 | UA_OpenSSL_AES_128_CBC_Encrypt (const UA_ByteString * iv, |
| 117431 | const UA_ByteString * key, |
| 117432 | UA_ByteString * data /* [in/out]*/ |
| 117433 | ) { |
| 117434 | return UA_OpenSSL_Encrypt (iv, key, cipherAlg: EVP_aes_128_cbc (), data); |
| 117435 | } |
| 117436 | |
| 117437 | EVP_PKEY * |
| 117438 | UA_OpenSSL_LoadPrivateKey(const UA_ByteString *privateKey) { |
| 117439 | const unsigned char * pkData = privateKey->data; |
| 117440 | long len = (long) privateKey->length; |
| 117441 | if(len == 0) |
| 117442 | return NULL; |
| 117443 | |
| 117444 | EVP_PKEY *result = NULL; |
| 117445 | |
| 117446 | if (len > 1 && pkData[0] == 0x30 && pkData[1] == 0x82) { // Magic number for DER encoded keys |
| 117447 | result = d2i_PrivateKey(EVP_PKEY_RSA, NULL, |
| 117448 | pp: &pkData, length: len); |
| 117449 | } else { |
| 117450 | BIO *bio = NULL; |
| 117451 | bio = BIO_new_mem_buf(buf: (void *) privateKey->data, len: (int) privateKey->length); |
| 117452 | result = PEM_read_bio_PrivateKey(out: bio, NULL, NULL, NULL); |
| 117453 | BIO_free(a: bio); |
| 117454 | } |
| 117455 | |
| 117456 | return result; |
| 117457 | } |
| 117458 | |
| 117459 | X509 * |
| 117460 | UA_OpenSSL_LoadCertificate(const UA_ByteString *certificate) { |
| 117461 | X509 * result = NULL; |
| 117462 | const unsigned char *pData = certificate->data; |
| 117463 | |
| 117464 | if (certificate->length > 1 && pData[0] == 0x30 && pData[1] == 0x82) { // Magic number for DER encoded files |
| 117465 | result = UA_OpenSSL_LoadDerCertificate(certificate); |
| 117466 | } else { |
| 117467 | result = UA_OpenSSL_LoadPemCertificate(certificate); |
| 117468 | } |
| 117469 | |
| 117470 | return result; |
| 117471 | } |
| 117472 | |
| 117473 | X509 * |
| 117474 | UA_OpenSSL_LoadDerCertificate(const UA_ByteString *certificate) { |
| 117475 | const unsigned char *pData = certificate->data; |
| 117476 | return d2i_X509(NULL, in: &pData, len: (long) certificate->length); |
| 117477 | } |
| 117478 | |
| 117479 | X509 * |
| 117480 | UA_OpenSSL_LoadPemCertificate(const UA_ByteString *certificate) { |
| 117481 | X509 * result = NULL; |
| 117482 | |
| 117483 | BIO* bio = NULL; |
| 117484 | bio = BIO_new_mem_buf(buf: (void *) certificate->data, len: (int) certificate->length); |
| 117485 | result = PEM_read_bio_X509(out: bio, NULL, NULL, NULL); |
| 117486 | BIO_free(a: bio); |
| 117487 | |
| 117488 | return result; |
| 117489 | } |
| 117490 | |
| 117491 | UA_StatusCode |
| 117492 | UA_OpenSSL_LoadLocalCertificate(const UA_ByteString *certificate, UA_ByteString *target) { |
| 117493 | X509 *cert = UA_OpenSSL_LoadCertificate(certificate); |
| 117494 | |
| 117495 | if (!cert) { |
| 117496 | UA_ByteString_init(p: target); |
| 117497 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117498 | } |
| 117499 | |
| 117500 | unsigned char *derData = NULL; |
| 117501 | int length = i2d_X509(a: cert, out: &derData); |
| 117502 | X509_free(a: cert); |
| 117503 | |
| 117504 | if (length > 0) { |
| 117505 | UA_ByteString temp; |
| 117506 | temp.length = (size_t) length; |
| 117507 | temp.data = derData; |
| 117508 | UA_ByteString_copy(src: &temp, dst: target); |
| 117509 | OPENSSL_free(derData); |
| 117510 | return UA_STATUSCODE_GOOD; |
| 117511 | } else { |
| 117512 | UA_ByteString_init(p: target); |
| 117513 | } |
| 117514 | |
| 117515 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117516 | } |
| 117517 | |
| 117518 | #endif |
| 117519 | |
| 117520 | /**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic128rsa15.c" ****/ |
| 117521 | |
| 117522 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 117523 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 117524 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 117525 | * |
| 117526 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 117527 | * Copyright 2020 (c) basysKom GmbH |
| 117528 | */ |
| 117529 | |
| 117530 | |
| 117531 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 117532 | |
| 117533 | |
| 117534 | #include <openssl/x509.h> |
| 117535 | #include <openssl/rand.h> |
| 117536 | #include <openssl/evp.h> |
| 117537 | |
| 117538 | #define UA_SHA1_LENGTH 20 |
| 117539 | #define UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN 11 |
| 117540 | #define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH 16 |
| 117541 | #define UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE 16 |
| 117542 | #define UA_SECURITYPOLICY_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH 16 |
| 117543 | #define UA_SHA1_LENGTH 20 |
| 117544 | |
| 117545 | typedef struct { |
| 117546 | EVP_PKEY * localPrivateKey; |
| 117547 | UA_ByteString localCertThumbprint; |
| 117548 | const UA_Logger * logger; |
| 117549 | } Policy_Context_Basic128Rsa15; |
| 117550 | |
| 117551 | typedef struct { |
| 117552 | UA_ByteString localSymSigningKey; |
| 117553 | UA_ByteString localSymEncryptingKey; |
| 117554 | UA_ByteString localSymIv; |
| 117555 | UA_ByteString remoteSymSigningKey; |
| 117556 | UA_ByteString remoteSymEncryptingKey; |
| 117557 | UA_ByteString remoteSymIv; |
| 117558 | |
| 117559 | Policy_Context_Basic128Rsa15 * policyContext; |
| 117560 | UA_ByteString remoteCertificate; |
| 117561 | X509 * remoteCertificateX509; |
| 117562 | } Channel_Context_Basic128Rsa15; |
| 117563 | |
| 117564 | static UA_StatusCode |
| 117565 | UA_Policy_Basic128Rsa15_New_Context (UA_SecurityPolicy * securityPolicy, |
| 117566 | const UA_ByteString localPrivateKey, |
| 117567 | const UA_Logger * logger) { |
| 117568 | Policy_Context_Basic128Rsa15 * context = (Policy_Context_Basic128Rsa15 *) |
| 117569 | UA_malloc (size: sizeof (Policy_Context_Basic128Rsa15)); |
| 117570 | if (context == NULL) { |
| 117571 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 117572 | } |
| 117573 | |
| 117574 | context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey); |
| 117575 | |
| 117576 | if (!context->localPrivateKey) { |
| 117577 | UA_free(ptr: context); |
| 117578 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117579 | } |
| 117580 | |
| 117581 | UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint ( |
| 117582 | certficate: &securityPolicy->localCertificate, |
| 117583 | pThumbprint: &context->localCertThumbprint, true |
| 117584 | ); |
| 117585 | if (retval != UA_STATUSCODE_GOOD) { |
| 117586 | EVP_PKEY_free(pkey: context->localPrivateKey); |
| 117587 | UA_free (ptr: context); |
| 117588 | return retval; |
| 117589 | } |
| 117590 | |
| 117591 | context->logger = logger; |
| 117592 | securityPolicy->policyContext = context; |
| 117593 | |
| 117594 | return UA_STATUSCODE_GOOD; |
| 117595 | } |
| 117596 | |
| 117597 | static void |
| 117598 | UA_Policy_Basic128Rsa15_Clear_Context (UA_SecurityPolicy *policy) { |
| 117599 | if (policy == NULL) { |
| 117600 | return; |
| 117601 | } |
| 117602 | UA_ByteString_clear(p: &policy->localCertificate); |
| 117603 | |
| 117604 | Policy_Context_Basic128Rsa15 * ctx = (Policy_Context_Basic128Rsa15 *) policy->policyContext; |
| 117605 | if (ctx == NULL) { |
| 117606 | return; |
| 117607 | } |
| 117608 | |
| 117609 | /* delete all allocated members in the context */ |
| 117610 | |
| 117611 | EVP_PKEY_free(pkey: ctx->localPrivateKey); |
| 117612 | UA_ByteString_clear(p: &ctx->localCertThumbprint); |
| 117613 | UA_free (ptr: ctx); |
| 117614 | |
| 117615 | return; |
| 117616 | } |
| 117617 | |
| 117618 | static UA_StatusCode |
| 117619 | updateCertificateAndPrivateKey_sp_basic128rsa15(UA_SecurityPolicy *securityPolicy, |
| 117620 | const UA_ByteString newCertificate, |
| 117621 | const UA_ByteString newPrivateKey) { |
| 117622 | if(securityPolicy == NULL) |
| 117623 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117624 | |
| 117625 | if(securityPolicy->policyContext == NULL) |
| 117626 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117627 | |
| 117628 | Policy_Context_Basic128Rsa15 *pc = |
| 117629 | (Policy_Context_Basic128Rsa15 *)securityPolicy->policyContext; |
| 117630 | |
| 117631 | UA_ByteString_clear(p: &securityPolicy->localCertificate); |
| 117632 | |
| 117633 | UA_StatusCode retval = UA_OpenSSL_LoadLocalCertificate( |
| 117634 | certificate: &newCertificate, target: &securityPolicy->localCertificate); |
| 117635 | |
| 117636 | if(retval != UA_STATUSCODE_GOOD) |
| 117637 | return retval; |
| 117638 | |
| 117639 | /* Set the new private key */ |
| 117640 | EVP_PKEY_free(pkey: pc->localPrivateKey); |
| 117641 | |
| 117642 | pc->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &newPrivateKey); |
| 117643 | |
| 117644 | if(!pc->localPrivateKey) { |
| 117645 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 117646 | goto error; |
| 117647 | } |
| 117648 | |
| 117649 | UA_ByteString_clear(p: &pc->localCertThumbprint); |
| 117650 | |
| 117651 | retval = UA_Openssl_X509_GetCertificateThumbprint(certficate: &securityPolicy->localCertificate, |
| 117652 | pThumbprint: &pc->localCertThumbprint, true); |
| 117653 | if(retval != UA_STATUSCODE_GOOD) { |
| 117654 | goto error; |
| 117655 | } |
| 117656 | |
| 117657 | return retval; |
| 117658 | |
| 117659 | error: |
| 117660 | UA_LOG_ERROR(logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 117661 | msg: "Could not update certificate and private key"); |
| 117662 | if(securityPolicy->policyContext != NULL) |
| 117663 | UA_Policy_Basic128Rsa15_Clear_Context(policy: securityPolicy); |
| 117664 | return retval; |
| 117665 | } |
| 117666 | |
| 117667 | /* create the channel context */ |
| 117668 | |
| 117669 | static UA_StatusCode |
| 117670 | UA_ChannelModule_Basic128Rsa15_New_Context (const UA_SecurityPolicy * securityPolicy, |
| 117671 | const UA_ByteString * remoteCertificate, |
| 117672 | void ** channelContext) { |
| 117673 | if (securityPolicy == NULL || remoteCertificate == NULL || |
| 117674 | channelContext == NULL) { |
| 117675 | return UA_STATUSCODE_BADINTERNALERROR; |
| 117676 | } |
| 117677 | Channel_Context_Basic128Rsa15 * context = (Channel_Context_Basic128Rsa15 *) |
| 117678 | UA_malloc (size: sizeof (Channel_Context_Basic128Rsa15)); |
| 117679 | if (context == NULL) { |
| 117680 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 117681 | } |
| 117682 | |
| 117683 | UA_ByteString_init(p: &context->localSymSigningKey); |
| 117684 | UA_ByteString_init(p: &context->localSymEncryptingKey); |
| 117685 | UA_ByteString_init(p: &context->localSymIv); |
| 117686 | UA_ByteString_init(p: &context->remoteSymSigningKey); |
| 117687 | UA_ByteString_init(p: &context->remoteSymEncryptingKey); |
| 117688 | UA_ByteString_init(p: &context->remoteSymIv); |
| 117689 | |
| 117690 | UA_StatusCode retval = UA_copyCertificate (dst: &context->remoteCertificate, |
| 117691 | src: remoteCertificate); |
| 117692 | if (retval != UA_STATUSCODE_GOOD) { |
| 117693 | UA_free (ptr: context); |
| 117694 | return retval; |
| 117695 | } |
| 117696 | |
| 117697 | /* decode to X509 */ |
| 117698 | context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate); |
| 117699 | if (context->remoteCertificateX509 == NULL) { |
| 117700 | UA_ByteString_clear (p: &context->remoteCertificate); |
| 117701 | UA_free (ptr: context); |
| 117702 | return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; |
| 117703 | } |
| 117704 | |
| 117705 | context->policyContext = (Policy_Context_Basic128Rsa15 *) |
| 117706 | (securityPolicy->policyContext); |
| 117707 | |
| 117708 | *channelContext = context; |
| 117709 | |
| 117710 | UA_LOG_INFO (logger: securityPolicy->logger, |
| 117711 | category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 117712 | msg: "The Basic128Rsa15 security policy channel with openssl is created."); |
| 117713 | |
| 117714 | return UA_STATUSCODE_GOOD; |
| 117715 | } |
| 117716 | |
| 117717 | /* delete the channel context */ |
| 117718 | |
| 117719 | static void |
| 117720 | UA_ChannelModule_Basic128Rsa15_Delete_Context (void * channelContext) { |
| 117721 | if (channelContext != NULL) { |
| 117722 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) |
| 117723 | channelContext; |
| 117724 | X509_free (a: cc->remoteCertificateX509); |
| 117725 | UA_ByteString_clear (p: &cc->remoteCertificate); |
| 117726 | UA_ByteString_clear (p: &cc->localSymSigningKey); |
| 117727 | UA_ByteString_clear (p: &cc->localSymEncryptingKey); |
| 117728 | UA_ByteString_clear (p: &cc->localSymIv); |
| 117729 | UA_ByteString_clear (p: &cc->remoteSymSigningKey); |
| 117730 | UA_ByteString_clear (p: &cc->remoteSymEncryptingKey); |
| 117731 | UA_ByteString_clear (p: &cc->remoteSymIv); |
| 117732 | UA_LOG_INFO (logger: cc->policyContext->logger, |
| 117733 | category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 117734 | msg: "The Basic128Rsa15 security policy channel with openssl is deleted."); |
| 117735 | |
| 117736 | UA_free (ptr: cc); |
| 117737 | } |
| 117738 | } |
| 117739 | |
| 117740 | static UA_StatusCode |
| 117741 | UA_ChannelModule_Basic128Rsa15_setLocalSymSigningKey (void * channelContext, |
| 117742 | const UA_ByteString * key) { |
| 117743 | if (key == NULL || channelContext == NULL) { |
| 117744 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117745 | } |
| 117746 | |
| 117747 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 117748 | UA_ByteString_clear(p: &cc->localSymSigningKey); |
| 117749 | return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey); |
| 117750 | } |
| 117751 | |
| 117752 | static UA_StatusCode |
| 117753 | UA_ChannelModule_Basic128Rsa15_setLocalSymEncryptingKey (void * channelContext, |
| 117754 | const UA_ByteString * key) { |
| 117755 | if (key == NULL || channelContext == NULL) { |
| 117756 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117757 | } |
| 117758 | |
| 117759 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 117760 | UA_ByteString_clear(p: &cc->localSymEncryptingKey); |
| 117761 | return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey); |
| 117762 | } |
| 117763 | |
| 117764 | static UA_StatusCode |
| 117765 | UA_ChannelModule_Basic128Rsa15_setLocalSymIv (void * channelContext, |
| 117766 | const UA_ByteString * iv) { |
| 117767 | if (iv == NULL || channelContext == NULL) { |
| 117768 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117769 | } |
| 117770 | |
| 117771 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 117772 | UA_ByteString_clear(p: &cc->localSymIv); |
| 117773 | return UA_ByteString_copy(src: iv, dst: &cc->localSymIv); |
| 117774 | } |
| 117775 | |
| 117776 | static UA_StatusCode |
| 117777 | UA_ChannelModule_Basic128Rsa15_setRemoteSymSigningKey (void * channelContext, |
| 117778 | const UA_ByteString * key) { |
| 117779 | if (key == NULL || channelContext == NULL) { |
| 117780 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117781 | } |
| 117782 | |
| 117783 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 117784 | UA_ByteString_clear(p: &cc->remoteSymSigningKey); |
| 117785 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey); |
| 117786 | } |
| 117787 | |
| 117788 | static UA_StatusCode |
| 117789 | UA_ChannelModule_Basic128Rsa15_setRemoteSymEncryptingKey (void * channelContext, |
| 117790 | const UA_ByteString * key) { |
| 117791 | if (key == NULL || channelContext == NULL) { |
| 117792 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117793 | } |
| 117794 | |
| 117795 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 117796 | UA_ByteString_clear(p: &cc->remoteSymEncryptingKey); |
| 117797 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey); |
| 117798 | } |
| 117799 | |
| 117800 | static UA_StatusCode |
| 117801 | UA_ChannelModule_Basic128Rsa15_setRemoteSymIv (void * channelContext, |
| 117802 | const UA_ByteString * key) { |
| 117803 | if (key == NULL || channelContext == NULL) { |
| 117804 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117805 | } |
| 117806 | |
| 117807 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 117808 | UA_ByteString_clear(p: &cc->remoteSymIv); |
| 117809 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv); |
| 117810 | } |
| 117811 | |
| 117812 | static UA_StatusCode |
| 117813 | UA_ChannelModule_Basic128Rsa15_compareCertificate (const void * channelContext, |
| 117814 | const UA_ByteString * certificate) { |
| 117815 | if(channelContext == NULL || certificate == NULL) { |
| 117816 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117817 | } |
| 117818 | |
| 117819 | const Channel_Context_Basic128Rsa15 * cc = |
| 117820 | (const Channel_Context_Basic128Rsa15 *) channelContext; |
| 117821 | return UA_OpenSSL_X509_compare (cert: certificate, bcert: cc->remoteCertificateX509); |
| 117822 | } |
| 117823 | |
| 117824 | static UA_StatusCode |
| 117825 | UA_Asy_Basic128Rsa15_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy, |
| 117826 | const UA_ByteString * certificateThumbprint) { |
| 117827 | if (securityPolicy == NULL || certificateThumbprint == NULL) { |
| 117828 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117829 | } |
| 117830 | Policy_Context_Basic128Rsa15 *pc = (Policy_Context_Basic128Rsa15 *) |
| 117831 | securityPolicy->policyContext; |
| 117832 | if(!UA_ByteString_equal(p1: certificateThumbprint, p2: &pc->localCertThumbprint)) { |
| 117833 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 117834 | } |
| 117835 | return UA_STATUSCODE_GOOD; |
| 117836 | } |
| 117837 | |
| 117838 | /* Generates a thumbprint for the specified certificate */ |
| 117839 | |
| 117840 | static UA_StatusCode |
| 117841 | UA_Asy_Basic128Rsa15_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy, |
| 117842 | const UA_ByteString * certificate, |
| 117843 | UA_ByteString * thumbprint) { |
| 117844 | return UA_Openssl_X509_GetCertificateThumbprint (certficate: certificate, |
| 117845 | pThumbprint: thumbprint, false); |
| 117846 | } |
| 117847 | |
| 117848 | static size_t |
| 117849 | UA_AsySig_Basic128Rsa15_getRemoteSignatureSize (const void * channelContext) { |
| 117850 | if (channelContext == NULL) { |
| 117851 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117852 | } |
| 117853 | |
| 117854 | const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext; |
| 117855 | UA_Int32 keyLen = 0; |
| 117856 | UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 117857 | return (size_t) keyLen; |
| 117858 | } |
| 117859 | |
| 117860 | static size_t |
| 117861 | UA_AsySig_Basic128Rsa15_getLocalSignatureSize (const void * channelContext) { |
| 117862 | if (channelContext == NULL) { |
| 117863 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117864 | } |
| 117865 | |
| 117866 | const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext; |
| 117867 | Policy_Context_Basic128Rsa15 * pc = (Policy_Context_Basic128Rsa15 *) cc->policyContext; |
| 117868 | UA_Int32 keyLen = 0; |
| 117869 | UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 117870 | |
| 117871 | return (size_t) keyLen; |
| 117872 | } |
| 117873 | |
| 117874 | static UA_StatusCode |
| 117875 | UA_AsySig_Basic128Rsa15_Verify (void * channelContext, |
| 117876 | const UA_ByteString * message, |
| 117877 | const UA_ByteString * signature) { |
| 117878 | if (message == NULL || signature == NULL || |
| 117879 | channelContext == NULL) { |
| 117880 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117881 | } |
| 117882 | |
| 117883 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 117884 | UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (msg: message, |
| 117885 | publicKeyX509: cc->remoteCertificateX509, signature); |
| 117886 | |
| 117887 | return retval; |
| 117888 | } |
| 117889 | |
| 117890 | static UA_StatusCode |
| 117891 | UA_AsySig_Basic128Rsa15_Sign (void * channelContext, |
| 117892 | const UA_ByteString * message, |
| 117893 | UA_ByteString * signature) { |
| 117894 | if (channelContext == NULL || message == NULL || signature == NULL) { |
| 117895 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117896 | } |
| 117897 | |
| 117898 | const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext; |
| 117899 | Policy_Context_Basic128Rsa15 *pc = cc->policyContext; |
| 117900 | return UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (message, privateKey: pc->localPrivateKey, outSignature: signature); |
| 117901 | } |
| 117902 | |
| 117903 | static size_t |
| 117904 | UA_AsymEn_Basic128Rsa15_getRemotePlainTextBlockSize (const void *channelContext) { |
| 117905 | if (channelContext == NULL) { |
| 117906 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117907 | } |
| 117908 | |
| 117909 | const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext; |
| 117910 | UA_Int32 keyLen = 0; |
| 117911 | UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 117912 | return (size_t) keyLen - UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN; |
| 117913 | } |
| 117914 | |
| 117915 | static size_t |
| 117916 | UA_AsymEn_Basic128Rsa15_getRemoteBlockSize (const void *channelContext) { |
| 117917 | if (channelContext == NULL) { |
| 117918 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117919 | } |
| 117920 | |
| 117921 | const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext; |
| 117922 | UA_Int32 keyLen = 0; |
| 117923 | UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 117924 | return (size_t) keyLen; |
| 117925 | } |
| 117926 | |
| 117927 | static size_t |
| 117928 | UA_AsymEn_Basic128Rsa15_getRemoteKeyLength (const void *channelContext) { |
| 117929 | if (channelContext == NULL) |
| 117930 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117931 | |
| 117932 | const Channel_Context_Basic128Rsa15 * cc = (const Channel_Context_Basic128Rsa15 *) channelContext; |
| 117933 | UA_Int32 keyLen = 0; |
| 117934 | UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 117935 | return (size_t) keyLen * 8; |
| 117936 | } |
| 117937 | |
| 117938 | static size_t |
| 117939 | UA_AsymEn_Basic128Rsa15_getLocalKeyLength (const void *channelContext) { |
| 117940 | if (channelContext == NULL) |
| 117941 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117942 | |
| 117943 | const Channel_Context_Basic128Rsa15 *cc = (const Channel_Context_Basic128Rsa15 *) channelContext; |
| 117944 | Policy_Context_Basic128Rsa15 *pc = cc->policyContext; |
| 117945 | UA_Int32 keyLen = 0; |
| 117946 | UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 117947 | return (size_t) keyLen * 8; |
| 117948 | } |
| 117949 | |
| 117950 | static UA_StatusCode |
| 117951 | UA_AsymEn_Basic128Rsa15_Decrypt (void * channelContext, |
| 117952 | UA_ByteString * data) { |
| 117953 | if (channelContext == NULL || data == NULL) { |
| 117954 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117955 | } |
| 117956 | |
| 117957 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 117958 | UA_StatusCode ret = UA_Openssl_RSA_PKCS1_V15_Decrypt (data, |
| 117959 | privateKey: cc->policyContext->localPrivateKey); |
| 117960 | return ret; |
| 117961 | } |
| 117962 | |
| 117963 | static UA_StatusCode |
| 117964 | UA_AsymEn_Basic128Rsa15_Encrypt (void * channelContext, |
| 117965 | UA_ByteString * data) { |
| 117966 | if (channelContext == NULL || data == NULL) |
| 117967 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 117968 | |
| 117969 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 117970 | return UA_Openssl_RSA_PKCS1_V15_Encrypt (data, |
| 117971 | UA_SECURITYPOLICY_BASIC128RSA15_RSAPADDING_LEN, |
| 117972 | publicX509: cc->remoteCertificateX509); |
| 117973 | } |
| 117974 | |
| 117975 | static UA_StatusCode |
| 117976 | UA_Sym_Basic128Rsa15_generateNonce(void *policyContext, |
| 117977 | UA_ByteString *out) { |
| 117978 | UA_Int32 rc = RAND_bytes(buf: out->data, num: (int) out->length); |
| 117979 | if (rc != 1) { |
| 117980 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 117981 | } |
| 117982 | return UA_STATUSCODE_GOOD; |
| 117983 | } |
| 117984 | |
| 117985 | static UA_StatusCode |
| 117986 | UA_Sym_Basic128Rsa15_generateKey(void *policyContext, |
| 117987 | const UA_ByteString *secret, |
| 117988 | const UA_ByteString *seed, |
| 117989 | UA_ByteString *out) { |
| 117990 | return UA_Openssl_Random_Key_PSHA1_Derive(secret, seed, out); |
| 117991 | } |
| 117992 | |
| 117993 | static size_t |
| 117994 | UA_SymEn_Basic128Rsa15_getLocalKeyLength (const void *channelContext) { |
| 117995 | /* 16 bytes 128 bits */ |
| 117996 | return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH; |
| 117997 | } |
| 117998 | |
| 117999 | static size_t |
| 118000 | UA_SymEn_Basic128Rsa15_getBlockSize (const void *channelContext) { |
| 118001 | return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_BLOCK_SIZE; |
| 118002 | } |
| 118003 | |
| 118004 | static size_t |
| 118005 | UA_SymEn_Basic128Rsa15_getRemoteKeyLength (const void * channelContext) { |
| 118006 | return UA_SECURITYPOLICY_BASIC128RSA15_SYM_ENCRYPTION_KEY_LENGTH; |
| 118007 | } |
| 118008 | |
| 118009 | static UA_StatusCode |
| 118010 | UA_SymEn_Basic128Rsa15_Encrypt (void *channelContext, |
| 118011 | UA_ByteString *data) { |
| 118012 | if(channelContext == NULL || data == NULL) |
| 118013 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118014 | |
| 118015 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 118016 | return UA_OpenSSL_AES_128_CBC_Encrypt (iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, data); |
| 118017 | } |
| 118018 | |
| 118019 | static UA_StatusCode |
| 118020 | UA_SymEn_Basic128Rsa15_Decrypt (void * channelContext, |
| 118021 | UA_ByteString * data) { |
| 118022 | if(channelContext == NULL || data == NULL) |
| 118023 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118024 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 118025 | return UA_OpenSSL_AES_128_CBC_Decrypt (iv: &cc->remoteSymIv, key: &cc->remoteSymEncryptingKey, data); |
| 118026 | } |
| 118027 | |
| 118028 | static size_t |
| 118029 | UA_SymSig_Basic128Rsa15_getKeyLength (const void *channelContext) { |
| 118030 | return UA_SECURITYPOLICY_BASIC128RSA15_SYM_SIGNING_KEY_LENGTH; |
| 118031 | } |
| 118032 | |
| 118033 | static size_t |
| 118034 | UA_SymSig_Basic128Rsa15_getSignatureSize (const void *channelContext) { |
| 118035 | return UA_SHA1_LENGTH; |
| 118036 | } |
| 118037 | |
| 118038 | static UA_StatusCode |
| 118039 | UA_SymSig_Basic128Rsa15_Verify (void * channelContext, |
| 118040 | const UA_ByteString * message, |
| 118041 | const UA_ByteString * signature) { |
| 118042 | if (channelContext == NULL || message == NULL || signature == NULL) |
| 118043 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118044 | |
| 118045 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 118046 | return UA_OpenSSL_HMAC_SHA1_Verify (message, |
| 118047 | key: &cc->remoteSymSigningKey, |
| 118048 | signature); |
| 118049 | } |
| 118050 | |
| 118051 | static UA_StatusCode |
| 118052 | UA_SymSig_Basic128Rsa15_Sign (void * channelContext, |
| 118053 | const UA_ByteString * message, |
| 118054 | UA_ByteString * signature) { |
| 118055 | if (channelContext == NULL || message == NULL || signature == NULL) |
| 118056 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118057 | |
| 118058 | Channel_Context_Basic128Rsa15 * cc = (Channel_Context_Basic128Rsa15 *) channelContext; |
| 118059 | return UA_OpenSSL_HMAC_SHA1_Sign (message, key: &cc->localSymSigningKey, signature); |
| 118060 | } |
| 118061 | |
| 118062 | /* the main entry of Basic128Rsa15 */ |
| 118063 | |
| 118064 | UA_StatusCode |
| 118065 | UA_SecurityPolicy_Basic128Rsa15 (UA_SecurityPolicy * policy, |
| 118066 | const UA_ByteString localCertificate, |
| 118067 | const UA_ByteString localPrivateKey, |
| 118068 | const UA_Logger * logger) { |
| 118069 | |
| 118070 | UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 118071 | msg: "!! WARNING !! The Basic128Rsa15 SecurityPolicy is unsecure. " |
| 118072 | "There are known attacks that break the encryption."); |
| 118073 | |
| 118074 | UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule; |
| 118075 | UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule; |
| 118076 | UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule; |
| 118077 | UA_StatusCode retval; |
| 118078 | |
| 118079 | UA_LOG_INFO (logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 118080 | msg: "The Basic128Rsa15 security policy with openssl is added."); |
| 118081 | |
| 118082 | UA_Openssl_Init (); |
| 118083 | memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy)); |
| 118084 | policy->logger = logger; |
| 118085 | policy->policyUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic128Rsa15\0"); |
| 118086 | |
| 118087 | /* set ChannelModule context */ |
| 118088 | |
| 118089 | channelModule->newContext = UA_ChannelModule_Basic128Rsa15_New_Context; |
| 118090 | channelModule->deleteContext = UA_ChannelModule_Basic128Rsa15_Delete_Context; |
| 118091 | |
| 118092 | channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic128Rsa15_setLocalSymSigningKey; |
| 118093 | channelModule->setLocalSymEncryptingKey = UA_ChannelModule_Basic128Rsa15_setLocalSymEncryptingKey; |
| 118094 | channelModule->setLocalSymIv = UA_ChannelModule_Basic128Rsa15_setLocalSymIv; |
| 118095 | channelModule->setRemoteSymSigningKey = UA_ChannelModule_Basic128Rsa15_setRemoteSymSigningKey; |
| 118096 | channelModule->setRemoteSymEncryptingKey = UA_ChannelModule_Basic128Rsa15_setRemoteSymEncryptingKey; |
| 118097 | channelModule->setRemoteSymIv = UA_ChannelModule_Basic128Rsa15_setRemoteSymIv; |
| 118098 | channelModule->compareCertificate = UA_ChannelModule_Basic128Rsa15_compareCertificate; |
| 118099 | |
| 118100 | retval = UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate); |
| 118101 | |
| 118102 | if (retval != UA_STATUSCODE_GOOD) |
| 118103 | return retval; |
| 118104 | |
| 118105 | /* asymmetricModule */ |
| 118106 | |
| 118107 | asymmetricModule->compareCertificateThumbprint = UA_Asy_Basic128Rsa15_compareCertificateThumbprint; |
| 118108 | asymmetricModule->makeCertificateThumbprint = UA_Asy_Basic128Rsa15_makeCertificateThumbprint; |
| 118109 | |
| 118110 | /* AsymmetricModule - signature algorithm */ |
| 118111 | |
| 118112 | UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm = |
| 118113 | &asymmetricModule->cryptoModule.signatureAlgorithm; |
| 118114 | asySigAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#rsa-sha1\0"); |
| 118115 | asySigAlgorithm->getRemoteSignatureSize = UA_AsySig_Basic128Rsa15_getRemoteSignatureSize; |
| 118116 | asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic128Rsa15_getLocalSignatureSize; |
| 118117 | asySigAlgorithm->getLocalKeyLength = NULL; |
| 118118 | asySigAlgorithm->getRemoteKeyLength = NULL; |
| 118119 | asySigAlgorithm->verify = UA_AsySig_Basic128Rsa15_Verify; |
| 118120 | asySigAlgorithm->sign = UA_AsySig_Basic128Rsa15_Sign; |
| 118121 | |
| 118122 | /* AsymmetricModule encryption algorithm */ |
| 118123 | |
| 118124 | UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg = |
| 118125 | &asymmetricModule->cryptoModule.encryptionAlgorithm; |
| 118126 | asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-1_5\0"); |
| 118127 | asymEncryAlg->getRemotePlainTextBlockSize = UA_AsymEn_Basic128Rsa15_getRemotePlainTextBlockSize; |
| 118128 | asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic128Rsa15_getRemoteBlockSize; |
| 118129 | asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic128Rsa15_getRemoteKeyLength; |
| 118130 | asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic128Rsa15_getLocalKeyLength; |
| 118131 | asymEncryAlg->decrypt = UA_AsymEn_Basic128Rsa15_Decrypt; |
| 118132 | asymEncryAlg->encrypt = UA_AsymEn_Basic128Rsa15_Encrypt; |
| 118133 | |
| 118134 | /* SymmetricModule */ |
| 118135 | |
| 118136 | symmetricModule->secureChannelNonceLength = 16; /* 128 bits*/ |
| 118137 | symmetricModule->generateNonce = UA_Sym_Basic128Rsa15_generateNonce; |
| 118138 | symmetricModule->generateKey = UA_Sym_Basic128Rsa15_generateKey; |
| 118139 | |
| 118140 | /* Symmetric encryption Algorithm */ |
| 118141 | |
| 118142 | UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm = |
| 118143 | &symmetricModule->cryptoModule.encryptionAlgorithm; |
| 118144 | symEncryptionAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes128-cbc\0"); |
| 118145 | symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic128Rsa15_getLocalKeyLength; |
| 118146 | symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic128Rsa15_getRemoteKeyLength; |
| 118147 | symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic128Rsa15_getBlockSize; |
| 118148 | symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic128Rsa15_getBlockSize; |
| 118149 | symEncryptionAlgorithm->decrypt = UA_SymEn_Basic128Rsa15_Decrypt; |
| 118150 | symEncryptionAlgorithm->encrypt = UA_SymEn_Basic128Rsa15_Encrypt; |
| 118151 | |
| 118152 | /* Symmetric signature Algorithm */ |
| 118153 | |
| 118154 | UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm = |
| 118155 | &symmetricModule->cryptoModule.signatureAlgorithm; |
| 118156 | symSignatureAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha1\0"); |
| 118157 | symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic128Rsa15_getKeyLength; |
| 118158 | symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic128Rsa15_getKeyLength; |
| 118159 | symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Basic128Rsa15_getSignatureSize; |
| 118160 | symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic128Rsa15_getSignatureSize; |
| 118161 | |
| 118162 | symSignatureAlgorithm->verify = UA_SymSig_Basic128Rsa15_Verify; |
| 118163 | symSignatureAlgorithm->sign = UA_SymSig_Basic128Rsa15_Sign; |
| 118164 | |
| 118165 | /* set the policy context */ |
| 118166 | |
| 118167 | retval = UA_Policy_Basic128Rsa15_New_Context (securityPolicy: policy, localPrivateKey, logger); |
| 118168 | if (retval != UA_STATUSCODE_GOOD) { |
| 118169 | UA_ByteString_clear (p: &policy->localCertificate); |
| 118170 | return retval; |
| 118171 | } |
| 118172 | policy->updateCertificateAndPrivateKey = |
| 118173 | updateCertificateAndPrivateKey_sp_basic128rsa15; |
| 118174 | policy->clear = UA_Policy_Basic128Rsa15_Clear_Context; |
| 118175 | |
| 118176 | /* Use the same signature algorithm as the asymmetric component for |
| 118177 | certificate signing (see standard) */ |
| 118178 | policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 118179 | |
| 118180 | return UA_STATUSCODE_GOOD; |
| 118181 | } |
| 118182 | |
| 118183 | #endif |
| 118184 | |
| 118185 | /**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic256.c" ****/ |
| 118186 | |
| 118187 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 118188 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 118189 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 118190 | * |
| 118191 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 118192 | * Copyright 2020 (c) basysKom GmbH |
| 118193 | */ |
| 118194 | |
| 118195 | |
| 118196 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 118197 | |
| 118198 | |
| 118199 | #include <openssl/x509.h> |
| 118200 | #include <openssl/rand.h> |
| 118201 | |
| 118202 | #define UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN 42 |
| 118203 | #define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH 32 |
| 118204 | #define UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE 16 |
| 118205 | #define UA_SECURITYPOLICY_BASIC256_SYM_SIGNING_KEY_LENGTH 24 |
| 118206 | #define UA_SHA1_LENGTH 20 |
| 118207 | |
| 118208 | typedef struct { |
| 118209 | EVP_PKEY * localPrivateKey; |
| 118210 | UA_ByteString localCertThumbprint; |
| 118211 | const UA_Logger * logger; |
| 118212 | } Policy_Context_Basic256; |
| 118213 | |
| 118214 | typedef struct { |
| 118215 | UA_ByteString localSymSigningKey; |
| 118216 | UA_ByteString localSymEncryptingKey; |
| 118217 | UA_ByteString localSymIv; |
| 118218 | UA_ByteString remoteSymSigningKey; |
| 118219 | UA_ByteString remoteSymEncryptingKey; |
| 118220 | UA_ByteString remoteSymIv; |
| 118221 | |
| 118222 | Policy_Context_Basic256 * policyContext; |
| 118223 | UA_ByteString remoteCertificate; |
| 118224 | X509 * remoteCertificateX509; |
| 118225 | } Channel_Context_Basic256; |
| 118226 | |
| 118227 | static UA_StatusCode |
| 118228 | UA_Policy_Basic256_New_Context (UA_SecurityPolicy * securityPolicy, |
| 118229 | const UA_ByteString localPrivateKey, |
| 118230 | const UA_Logger * logger) { |
| 118231 | Policy_Context_Basic256 * context = (Policy_Context_Basic256 *) |
| 118232 | UA_malloc (size: sizeof (Policy_Context_Basic256)); |
| 118233 | if (context == NULL) { |
| 118234 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 118235 | } |
| 118236 | |
| 118237 | context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey); |
| 118238 | |
| 118239 | if (!context->localPrivateKey) { |
| 118240 | UA_free (ptr: context); |
| 118241 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118242 | } |
| 118243 | |
| 118244 | UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint ( |
| 118245 | certficate: &securityPolicy->localCertificate, |
| 118246 | pThumbprint: &context->localCertThumbprint, true |
| 118247 | ); |
| 118248 | if (retval != UA_STATUSCODE_GOOD) { |
| 118249 | EVP_PKEY_free(pkey: context->localPrivateKey); |
| 118250 | UA_free (ptr: context); |
| 118251 | return retval; |
| 118252 | } |
| 118253 | |
| 118254 | context->logger = logger; |
| 118255 | securityPolicy->policyContext = context; |
| 118256 | |
| 118257 | return UA_STATUSCODE_GOOD; |
| 118258 | } |
| 118259 | |
| 118260 | static void |
| 118261 | UA_Policy_Basic256_Clear_Context (UA_SecurityPolicy *policy) { |
| 118262 | if (policy == NULL) { |
| 118263 | return; |
| 118264 | } |
| 118265 | UA_ByteString_clear(p: &policy->localCertificate); |
| 118266 | |
| 118267 | Policy_Context_Basic256 * ctx = (Policy_Context_Basic256 *) policy->policyContext; |
| 118268 | if (ctx == NULL) { |
| 118269 | return; |
| 118270 | } |
| 118271 | |
| 118272 | /* delete all allocated members in the context */ |
| 118273 | |
| 118274 | EVP_PKEY_free(pkey: ctx->localPrivateKey); |
| 118275 | UA_ByteString_clear(p: &ctx->localCertThumbprint); |
| 118276 | UA_free (ptr: ctx); |
| 118277 | |
| 118278 | return; |
| 118279 | } |
| 118280 | |
| 118281 | static UA_StatusCode |
| 118282 | updateCertificateAndPrivateKey_sp_basic256(UA_SecurityPolicy *securityPolicy, |
| 118283 | const UA_ByteString newCertificate, |
| 118284 | const UA_ByteString newPrivateKey) { |
| 118285 | if(securityPolicy == NULL) |
| 118286 | return UA_STATUSCODE_BADINTERNALERROR; |
| 118287 | |
| 118288 | if(securityPolicy->policyContext == NULL) |
| 118289 | return UA_STATUSCODE_BADINTERNALERROR; |
| 118290 | |
| 118291 | Policy_Context_Basic256 *pc = |
| 118292 | (Policy_Context_Basic256 *)securityPolicy->policyContext; |
| 118293 | |
| 118294 | UA_ByteString_clear(p: &securityPolicy->localCertificate); |
| 118295 | |
| 118296 | UA_StatusCode retval = UA_OpenSSL_LoadLocalCertificate( |
| 118297 | certificate: &newCertificate, target: &securityPolicy->localCertificate); |
| 118298 | |
| 118299 | if(retval != UA_STATUSCODE_GOOD) |
| 118300 | return retval; |
| 118301 | |
| 118302 | /* Set the new private key */ |
| 118303 | EVP_PKEY_free(pkey: pc->localPrivateKey); |
| 118304 | |
| 118305 | pc->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &newPrivateKey); |
| 118306 | |
| 118307 | if(!pc->localPrivateKey) { |
| 118308 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 118309 | goto error; |
| 118310 | } |
| 118311 | |
| 118312 | UA_ByteString_clear(p: &pc->localCertThumbprint); |
| 118313 | |
| 118314 | retval = UA_Openssl_X509_GetCertificateThumbprint(certficate: &securityPolicy->localCertificate, |
| 118315 | pThumbprint: &pc->localCertThumbprint, true); |
| 118316 | if(retval != UA_STATUSCODE_GOOD) { |
| 118317 | goto error; |
| 118318 | } |
| 118319 | |
| 118320 | return retval; |
| 118321 | |
| 118322 | error: |
| 118323 | UA_LOG_ERROR(logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 118324 | msg: "Could not update certificate and private key"); |
| 118325 | if(securityPolicy->policyContext != NULL) |
| 118326 | UA_Policy_Basic256_Clear_Context(policy: securityPolicy); |
| 118327 | return retval; |
| 118328 | } |
| 118329 | |
| 118330 | /* create the channel context */ |
| 118331 | |
| 118332 | static UA_StatusCode |
| 118333 | UA_ChannelModule_Basic256_New_Context (const UA_SecurityPolicy * securityPolicy, |
| 118334 | const UA_ByteString * remoteCertificate, |
| 118335 | void ** channelContext) { |
| 118336 | if (securityPolicy == NULL || remoteCertificate == NULL || |
| 118337 | channelContext == NULL) { |
| 118338 | return UA_STATUSCODE_BADINTERNALERROR; |
| 118339 | } |
| 118340 | Channel_Context_Basic256 * context = (Channel_Context_Basic256 *) |
| 118341 | UA_malloc (size: sizeof (Channel_Context_Basic256)); |
| 118342 | if (context == NULL) { |
| 118343 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 118344 | } |
| 118345 | |
| 118346 | UA_ByteString_init(p: &context->localSymSigningKey); |
| 118347 | UA_ByteString_init(p: &context->localSymEncryptingKey); |
| 118348 | UA_ByteString_init(p: &context->localSymIv); |
| 118349 | UA_ByteString_init(p: &context->remoteSymSigningKey); |
| 118350 | UA_ByteString_init(p: &context->remoteSymEncryptingKey); |
| 118351 | UA_ByteString_init(p: &context->remoteSymIv); |
| 118352 | |
| 118353 | UA_StatusCode retval = UA_copyCertificate (dst: &context->remoteCertificate, |
| 118354 | src: remoteCertificate); |
| 118355 | if (retval != UA_STATUSCODE_GOOD) { |
| 118356 | UA_free (ptr: context); |
| 118357 | return retval; |
| 118358 | } |
| 118359 | |
| 118360 | /* decode to X509 */ |
| 118361 | context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate); |
| 118362 | if (context->remoteCertificateX509 == NULL) { |
| 118363 | UA_ByteString_clear (p: &context->remoteCertificate); |
| 118364 | UA_free (ptr: context); |
| 118365 | return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; |
| 118366 | } |
| 118367 | |
| 118368 | context->policyContext = (Policy_Context_Basic256 *) |
| 118369 | (securityPolicy->policyContext); |
| 118370 | |
| 118371 | *channelContext = context; |
| 118372 | |
| 118373 | UA_LOG_INFO (logger: securityPolicy->logger, |
| 118374 | category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 118375 | msg: "The basic256 security policy channel with openssl is created."); |
| 118376 | |
| 118377 | return UA_STATUSCODE_GOOD; |
| 118378 | } |
| 118379 | |
| 118380 | /* delete the channel context */ |
| 118381 | |
| 118382 | static void |
| 118383 | UA_ChannelModule_Basic256_Delete_Context (void * channelContext) { |
| 118384 | if (channelContext != NULL) { |
| 118385 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) |
| 118386 | channelContext; |
| 118387 | X509_free (a: cc->remoteCertificateX509); |
| 118388 | UA_ByteString_clear (p: &cc->remoteCertificate); |
| 118389 | UA_ByteString_clear (p: &cc->localSymSigningKey); |
| 118390 | UA_ByteString_clear (p: &cc->localSymEncryptingKey); |
| 118391 | UA_ByteString_clear (p: &cc->localSymIv); |
| 118392 | UA_ByteString_clear (p: &cc->remoteSymSigningKey); |
| 118393 | UA_ByteString_clear (p: &cc->remoteSymEncryptingKey); |
| 118394 | UA_ByteString_clear (p: &cc->remoteSymIv); |
| 118395 | UA_LOG_INFO (logger: cc->policyContext->logger, |
| 118396 | category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 118397 | msg: "The basic256 security policy channel with openssl is deleted."); |
| 118398 | |
| 118399 | UA_free (ptr: cc); |
| 118400 | } |
| 118401 | } |
| 118402 | |
| 118403 | /* Compares the supplied certificate with the certificate |
| 118404 | * in the endpoint context |
| 118405 | */ |
| 118406 | |
| 118407 | static UA_StatusCode |
| 118408 | UA_Asy_Basic256_compareCertificateThumbprint (const UA_SecurityPolicy * securityPolicy, |
| 118409 | const UA_ByteString * certificateThumbprint) { |
| 118410 | if (securityPolicy == NULL || certificateThumbprint == NULL) { |
| 118411 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118412 | } |
| 118413 | Policy_Context_Basic256 *pc = (Policy_Context_Basic256 *) |
| 118414 | securityPolicy->policyContext; |
| 118415 | if(!UA_ByteString_equal(p1: certificateThumbprint, p2: &pc->localCertThumbprint)) { |
| 118416 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 118417 | } |
| 118418 | return UA_STATUSCODE_GOOD; |
| 118419 | } |
| 118420 | |
| 118421 | /* Generates a thumbprint for the specified certificate */ |
| 118422 | |
| 118423 | static UA_StatusCode |
| 118424 | UA_Asy_Basic256_makeCertificateThumbprint (const UA_SecurityPolicy * securityPolicy, |
| 118425 | const UA_ByteString * certificate, |
| 118426 | UA_ByteString * thumbprint) { |
| 118427 | return UA_Openssl_X509_GetCertificateThumbprint (certficate: certificate, |
| 118428 | pThumbprint: thumbprint, false); |
| 118429 | } |
| 118430 | |
| 118431 | static UA_StatusCode |
| 118432 | UA_ChannelModule_Basic256_setLocalSymSigningKey (void * channelContext, |
| 118433 | const UA_ByteString * key) { |
| 118434 | if (key == NULL || channelContext == NULL) { |
| 118435 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118436 | } |
| 118437 | |
| 118438 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118439 | UA_ByteString_clear(p: &cc->localSymSigningKey); |
| 118440 | return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey); |
| 118441 | } |
| 118442 | |
| 118443 | static UA_StatusCode |
| 118444 | UA_ChannelModule_Basic256_setLocalSymEncryptingKey (void * channelContext, |
| 118445 | const UA_ByteString * key) { |
| 118446 | if (key == NULL || channelContext == NULL) { |
| 118447 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118448 | } |
| 118449 | |
| 118450 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118451 | UA_ByteString_clear(p: &cc->localSymEncryptingKey); |
| 118452 | return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey); |
| 118453 | } |
| 118454 | |
| 118455 | static UA_StatusCode |
| 118456 | UA_ChannelModule_Basic256_setLocalSymIv (void * channelContext, |
| 118457 | const UA_ByteString * iv) { |
| 118458 | if (iv == NULL || channelContext == NULL) { |
| 118459 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118460 | } |
| 118461 | |
| 118462 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118463 | UA_ByteString_clear(p: &cc->localSymIv); |
| 118464 | return UA_ByteString_copy(src: iv, dst: &cc->localSymIv); |
| 118465 | } |
| 118466 | |
| 118467 | static UA_StatusCode |
| 118468 | UA_ChannelModule_Basic256_setRemoteSymSigningKey (void * channelContext, |
| 118469 | const UA_ByteString * key) { |
| 118470 | if (key == NULL || channelContext == NULL) { |
| 118471 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118472 | } |
| 118473 | |
| 118474 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118475 | UA_ByteString_clear(p: &cc->remoteSymSigningKey); |
| 118476 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey); |
| 118477 | } |
| 118478 | |
| 118479 | static UA_StatusCode |
| 118480 | UA_ChannelModule_Basic256_setRemoteSymEncryptingKey (void * channelContext, |
| 118481 | const UA_ByteString * key) { |
| 118482 | if (key == NULL || channelContext == NULL) { |
| 118483 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118484 | } |
| 118485 | |
| 118486 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118487 | UA_ByteString_clear(p: &cc->remoteSymEncryptingKey); |
| 118488 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey); |
| 118489 | } |
| 118490 | |
| 118491 | static UA_StatusCode |
| 118492 | UA_ChannelModule_Basic256_setRemoteSymIv (void * channelContext, |
| 118493 | const UA_ByteString * key) { |
| 118494 | if (key == NULL || channelContext == NULL) { |
| 118495 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118496 | } |
| 118497 | |
| 118498 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118499 | UA_ByteString_clear(p: &cc->remoteSymIv); |
| 118500 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv); |
| 118501 | } |
| 118502 | |
| 118503 | static UA_StatusCode |
| 118504 | UA_ChannelModule_Basic256_compareCertificate (const void * channelContext, |
| 118505 | const UA_ByteString * certificate) { |
| 118506 | if(channelContext == NULL || certificate == NULL) { |
| 118507 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118508 | } |
| 118509 | |
| 118510 | const Channel_Context_Basic256 * cc = |
| 118511 | (const Channel_Context_Basic256 *) channelContext; |
| 118512 | return UA_OpenSSL_X509_compare (cert: certificate, bcert: cc->remoteCertificateX509); |
| 118513 | } |
| 118514 | |
| 118515 | static size_t |
| 118516 | UA_AsySig_Basic256_getRemoteSignatureSize (const void *channelContext) { |
| 118517 | if (channelContext == NULL) { |
| 118518 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118519 | } |
| 118520 | |
| 118521 | const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext; |
| 118522 | UA_Int32 keyLen = 0; |
| 118523 | UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 118524 | return (size_t) keyLen; |
| 118525 | } |
| 118526 | |
| 118527 | static size_t |
| 118528 | UA_AsySig_Basic256_getLocalSignatureSize (const void *channelContext) { |
| 118529 | if (channelContext == NULL) { |
| 118530 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118531 | } |
| 118532 | |
| 118533 | const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext; |
| 118534 | Policy_Context_Basic256 * pc = cc->policyContext; |
| 118535 | UA_Int32 keyLen = 0; |
| 118536 | UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 118537 | |
| 118538 | return (size_t) keyLen; |
| 118539 | } |
| 118540 | |
| 118541 | static UA_StatusCode |
| 118542 | UA_AsySig_Basic256_Verify (void * channelContext, |
| 118543 | const UA_ByteString * message, |
| 118544 | const UA_ByteString * signature) { |
| 118545 | if (message == NULL || signature == NULL || channelContext == NULL) { |
| 118546 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118547 | } |
| 118548 | |
| 118549 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118550 | UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA1_Verify (msg: message, |
| 118551 | publicKeyX509: cc->remoteCertificateX509, signature); |
| 118552 | return retval; |
| 118553 | } |
| 118554 | |
| 118555 | static UA_StatusCode |
| 118556 | UA_AsySig_Basic256_Sign (void * channelContext, |
| 118557 | const UA_ByteString * message, |
| 118558 | UA_ByteString * signature) { |
| 118559 | if (channelContext == NULL || message == NULL || signature == NULL) { |
| 118560 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118561 | } |
| 118562 | |
| 118563 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118564 | Policy_Context_Basic256 * pc = cc->policyContext; |
| 118565 | return UA_Openssl_RSA_PKCS1_V15_SHA1_Sign (message, privateKey: pc->localPrivateKey, |
| 118566 | outSignature: signature); |
| 118567 | } |
| 118568 | |
| 118569 | static size_t |
| 118570 | UA_AsymEn_Basic256_getRemotePlainTextBlockSize (const void *channelContext) { |
| 118571 | if (channelContext == NULL) { |
| 118572 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118573 | } |
| 118574 | |
| 118575 | const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext; |
| 118576 | UA_Int32 keyLen = 0; |
| 118577 | UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 118578 | return (size_t) keyLen - UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN; |
| 118579 | } |
| 118580 | |
| 118581 | static size_t |
| 118582 | UA_AsymEn_Basic256_getRemoteBlockSize (const void *channelContext) { |
| 118583 | if (channelContext == NULL) { |
| 118584 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118585 | } |
| 118586 | |
| 118587 | const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext; |
| 118588 | UA_Int32 keyLen = 0; |
| 118589 | UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 118590 | return (size_t) keyLen; |
| 118591 | } |
| 118592 | |
| 118593 | static size_t |
| 118594 | UA_AsymEn_Basic256_getRemoteKeyLength (const void *channelContext) { |
| 118595 | if (channelContext == NULL) |
| 118596 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118597 | |
| 118598 | const Channel_Context_Basic256 * cc = (const Channel_Context_Basic256 *) channelContext; |
| 118599 | UA_Int32 keyLen = 0; |
| 118600 | UA_Openssl_RSA_Public_GetKeyLength (publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 118601 | return (size_t) keyLen * 8; |
| 118602 | } |
| 118603 | |
| 118604 | static size_t |
| 118605 | UA_AsymEn_Basic256_getLocalKeyLength (const void *channelContext) { |
| 118606 | if (channelContext == NULL) |
| 118607 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118608 | |
| 118609 | const Channel_Context_Basic256 *cc = (const Channel_Context_Basic256 *) channelContext; |
| 118610 | Policy_Context_Basic256 *pc = cc->policyContext; |
| 118611 | UA_Int32 keyLen = 0; |
| 118612 | UA_Openssl_RSA_Private_GetKeyLength (privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 118613 | |
| 118614 | return (size_t) keyLen * 8; |
| 118615 | } |
| 118616 | |
| 118617 | static UA_StatusCode |
| 118618 | UA_AsymEn_Basic256_Decrypt (void * channelContext, |
| 118619 | UA_ByteString * data) { |
| 118620 | if (channelContext == NULL || data == NULL) { |
| 118621 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118622 | } |
| 118623 | |
| 118624 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118625 | UA_StatusCode ret = UA_Openssl_RSA_Oaep_Decrypt (data, |
| 118626 | privateKey: cc->policyContext->localPrivateKey); |
| 118627 | return ret; |
| 118628 | } |
| 118629 | |
| 118630 | static UA_StatusCode |
| 118631 | UA_AsymEn_Basic256_Encrypt (void * channelContext, |
| 118632 | UA_ByteString * data) { |
| 118633 | if (channelContext == NULL || data == NULL) { |
| 118634 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118635 | } |
| 118636 | |
| 118637 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118638 | return UA_Openssl_RSA_OAEP_Encrypt (data, UA_SECURITYPOLICY_BASIC256SHA1_RSAPADDING_LEN, |
| 118639 | publicX509: cc->remoteCertificateX509); |
| 118640 | } |
| 118641 | |
| 118642 | static UA_StatusCode |
| 118643 | UA_Sym_Basic256_generateNonce(void *policyContext, |
| 118644 | UA_ByteString *out) { |
| 118645 | UA_Int32 rc = RAND_bytes(buf: out->data, num: (int) out->length); |
| 118646 | if (rc != 1) { |
| 118647 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 118648 | } |
| 118649 | return UA_STATUSCODE_GOOD; |
| 118650 | } |
| 118651 | |
| 118652 | static UA_StatusCode |
| 118653 | UA_Sym_Basic256_generateKey(void *policyContext, const UA_ByteString *secret, |
| 118654 | const UA_ByteString *seed, UA_ByteString *out) { |
| 118655 | return UA_Openssl_Random_Key_PSHA1_Derive(secret, seed, out); |
| 118656 | } |
| 118657 | |
| 118658 | static size_t |
| 118659 | UA_SymEn_Basic256_getLocalKeyLength (const void * channelContext) { |
| 118660 | /* 32 bytes 256 bits */ |
| 118661 | return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH; |
| 118662 | } |
| 118663 | |
| 118664 | static size_t |
| 118665 | UA_SymEn_Basic256_getBlockSize (const void * channelContext) { |
| 118666 | return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_BLOCK_SIZE; |
| 118667 | } |
| 118668 | |
| 118669 | static size_t |
| 118670 | UA_SymEn_Basic256_getRemoteKeyLength (const void * channelContext) { |
| 118671 | /* 32 bytes 256 bits */ |
| 118672 | return UA_SECURITYPOLICY_BASIC256_SYM_ENCRYPTION_KEY_LENGTH; |
| 118673 | } |
| 118674 | |
| 118675 | static UA_StatusCode |
| 118676 | UA_SymEn_Basic256_Encrypt (void * channelContext, |
| 118677 | UA_ByteString * data) { |
| 118678 | if(channelContext == NULL || data == NULL) |
| 118679 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118680 | |
| 118681 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118682 | return UA_OpenSSL_AES_256_CBC_Encrypt (iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, data); |
| 118683 | } |
| 118684 | |
| 118685 | static UA_StatusCode |
| 118686 | UA_SymEn_Basic256_Decrypt (void * channelContext, |
| 118687 | UA_ByteString * data) { |
| 118688 | if(channelContext == NULL || data == NULL) |
| 118689 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118690 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118691 | return UA_OpenSSL_AES_256_CBC_Decrypt (iv: &cc->remoteSymIv, key: &cc->remoteSymEncryptingKey, data); |
| 118692 | } |
| 118693 | |
| 118694 | static size_t |
| 118695 | UA_SymSig_Basic256_getKeyLength (const void * channelContext) { |
| 118696 | return UA_SECURITYPOLICY_BASIC256_SYM_SIGNING_KEY_LENGTH; |
| 118697 | } |
| 118698 | |
| 118699 | static size_t |
| 118700 | UA_SymSig_Basic256_getSignatureSize (const void * channelContext) { |
| 118701 | return UA_SHA1_LENGTH; |
| 118702 | } |
| 118703 | |
| 118704 | static UA_StatusCode |
| 118705 | UA_SymSig_Basic256_Verify (void * channelContext, |
| 118706 | const UA_ByteString * message, |
| 118707 | const UA_ByteString * signature) { |
| 118708 | if (channelContext == NULL || |
| 118709 | message == NULL || signature == NULL) |
| 118710 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118711 | |
| 118712 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118713 | return UA_OpenSSL_HMAC_SHA1_Verify (message, |
| 118714 | key: &cc->remoteSymSigningKey, |
| 118715 | signature); |
| 118716 | } |
| 118717 | |
| 118718 | static UA_StatusCode |
| 118719 | UA_SymSig_Basic256_Sign (void * channelContext, |
| 118720 | const UA_ByteString * message, |
| 118721 | UA_ByteString * signature) { |
| 118722 | if (channelContext == NULL || message == NULL || signature == NULL) |
| 118723 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118724 | |
| 118725 | Channel_Context_Basic256 * cc = (Channel_Context_Basic256 *) channelContext; |
| 118726 | return UA_OpenSSL_HMAC_SHA1_Sign (message, key: &cc->localSymSigningKey, signature); |
| 118727 | } |
| 118728 | |
| 118729 | /* the main entry of Basic256 */ |
| 118730 | |
| 118731 | UA_StatusCode |
| 118732 | UA_SecurityPolicy_Basic256 (UA_SecurityPolicy * policy, |
| 118733 | const UA_ByteString localCertificate, |
| 118734 | const UA_ByteString localPrivateKey, |
| 118735 | const UA_Logger * logger) { |
| 118736 | |
| 118737 | UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 118738 | msg: "!! WARNING !! The Basic256 SecurityPolicy is unsecure. " |
| 118739 | "There are known attacks that break the encryption."); |
| 118740 | |
| 118741 | UA_SecurityPolicyAsymmetricModule * const asymmetricModule = &policy->asymmetricModule; |
| 118742 | UA_SecurityPolicySymmetricModule * const symmetricModule = &policy->symmetricModule; |
| 118743 | UA_SecurityPolicyChannelModule * const channelModule = &policy->channelModule; |
| 118744 | UA_StatusCode retval; |
| 118745 | |
| 118746 | UA_LOG_INFO (logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 118747 | msg: "The basic256 security policy with openssl is added."); |
| 118748 | |
| 118749 | UA_Openssl_Init (); |
| 118750 | memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy)); |
| 118751 | policy->logger = logger; |
| 118752 | policy->policyUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic256\0"); |
| 118753 | |
| 118754 | /* set ChannelModule context */ |
| 118755 | |
| 118756 | channelModule->newContext = UA_ChannelModule_Basic256_New_Context; |
| 118757 | channelModule->deleteContext = UA_ChannelModule_Basic256_Delete_Context; |
| 118758 | |
| 118759 | channelModule->setLocalSymSigningKey = UA_ChannelModule_Basic256_setLocalSymSigningKey; |
| 118760 | channelModule->setLocalSymEncryptingKey = UA_ChannelModule_Basic256_setLocalSymEncryptingKey; |
| 118761 | channelModule->setLocalSymIv = UA_ChannelModule_Basic256_setLocalSymIv; |
| 118762 | channelModule->setRemoteSymSigningKey = UA_ChannelModule_Basic256_setRemoteSymSigningKey; |
| 118763 | channelModule->setRemoteSymEncryptingKey = UA_ChannelModule_Basic256_setRemoteSymEncryptingKey; |
| 118764 | channelModule->setRemoteSymIv = UA_ChannelModule_Basic256_setRemoteSymIv; |
| 118765 | channelModule->compareCertificate = UA_ChannelModule_Basic256_compareCertificate; |
| 118766 | |
| 118767 | retval = UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate); |
| 118768 | |
| 118769 | if (retval != UA_STATUSCODE_GOOD) |
| 118770 | return retval; |
| 118771 | |
| 118772 | /* asymmetricModule */ |
| 118773 | |
| 118774 | asymmetricModule->compareCertificateThumbprint = UA_Asy_Basic256_compareCertificateThumbprint; |
| 118775 | asymmetricModule->makeCertificateThumbprint = UA_Asy_Basic256_makeCertificateThumbprint; |
| 118776 | |
| 118777 | /* AsymmetricModule - signature algorithm */ |
| 118778 | |
| 118779 | UA_SecurityPolicySignatureAlgorithm * asySigAlgorithm = |
| 118780 | &asymmetricModule->cryptoModule.signatureAlgorithm; |
| 118781 | asySigAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#rsa-sha1\0"); |
| 118782 | asySigAlgorithm->getRemoteSignatureSize = UA_AsySig_Basic256_getRemoteSignatureSize; |
| 118783 | asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic256_getLocalSignatureSize; |
| 118784 | asySigAlgorithm->verify = UA_AsySig_Basic256_Verify; |
| 118785 | asySigAlgorithm->sign = UA_AsySig_Basic256_Sign; |
| 118786 | asySigAlgorithm->getLocalKeyLength = NULL; |
| 118787 | asySigAlgorithm->getRemoteKeyLength = NULL; |
| 118788 | |
| 118789 | /* AsymmetricModule encryption algorithm */ |
| 118790 | |
| 118791 | UA_SecurityPolicyEncryptionAlgorithm * asymEncryAlg = |
| 118792 | &asymmetricModule->cryptoModule.encryptionAlgorithm; |
| 118793 | asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-oaep\0"); |
| 118794 | asymEncryAlg->getRemotePlainTextBlockSize = UA_AsymEn_Basic256_getRemotePlainTextBlockSize; |
| 118795 | asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic256_getRemoteBlockSize; |
| 118796 | asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic256_getRemoteKeyLength; |
| 118797 | asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic256_getLocalKeyLength; |
| 118798 | asymEncryAlg->decrypt = UA_AsymEn_Basic256_Decrypt; |
| 118799 | asymEncryAlg->encrypt = UA_AsymEn_Basic256_Encrypt; |
| 118800 | |
| 118801 | /* SymmetricModule */ |
| 118802 | |
| 118803 | symmetricModule->secureChannelNonceLength = 32; |
| 118804 | symmetricModule->generateNonce = UA_Sym_Basic256_generateNonce; |
| 118805 | symmetricModule->generateKey = UA_Sym_Basic256_generateKey; |
| 118806 | |
| 118807 | /* Symmetric encryption Algorithm */ |
| 118808 | |
| 118809 | UA_SecurityPolicyEncryptionAlgorithm * symEncryptionAlgorithm = |
| 118810 | &symmetricModule->cryptoModule.encryptionAlgorithm; |
| 118811 | symEncryptionAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes256-cbc\0"); |
| 118812 | symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic256_getLocalKeyLength; |
| 118813 | symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic256_getRemoteKeyLength; |
| 118814 | symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic256_getBlockSize; |
| 118815 | symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic256_getBlockSize; |
| 118816 | symEncryptionAlgorithm->decrypt = UA_SymEn_Basic256_Decrypt; |
| 118817 | symEncryptionAlgorithm->encrypt = UA_SymEn_Basic256_Encrypt; |
| 118818 | |
| 118819 | /* Symmetric signature Algorithm */ |
| 118820 | |
| 118821 | UA_SecurityPolicySignatureAlgorithm * symSignatureAlgorithm = |
| 118822 | &symmetricModule->cryptoModule.signatureAlgorithm; |
| 118823 | symSignatureAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha1\0"); |
| 118824 | symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Basic256_getKeyLength; |
| 118825 | symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Basic256_getKeyLength; |
| 118826 | symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Basic256_getSignatureSize; |
| 118827 | symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Basic256_getSignatureSize; |
| 118828 | symSignatureAlgorithm->verify = UA_SymSig_Basic256_Verify; |
| 118829 | symSignatureAlgorithm->sign = UA_SymSig_Basic256_Sign; |
| 118830 | |
| 118831 | /* set the policy context */ |
| 118832 | |
| 118833 | retval = UA_Policy_Basic256_New_Context (securityPolicy: policy, localPrivateKey, logger); |
| 118834 | if (retval != UA_STATUSCODE_GOOD) { |
| 118835 | UA_ByteString_clear (p: &policy->localCertificate); |
| 118836 | return retval; |
| 118837 | } |
| 118838 | policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_basic256; |
| 118839 | policy->clear = UA_Policy_Basic256_Clear_Context; |
| 118840 | |
| 118841 | /* Use the same signature algorithm as the asymmetric component for |
| 118842 | certificate signing (see standard) */ |
| 118843 | policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 118844 | |
| 118845 | return UA_STATUSCODE_GOOD; |
| 118846 | } |
| 118847 | |
| 118848 | #endif |
| 118849 | |
| 118850 | /**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_basic256sha256.c" ****/ |
| 118851 | |
| 118852 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 118853 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 118854 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 118855 | * |
| 118856 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 118857 | * Copyright 2020 (c) basysKom GmbH |
| 118858 | */ |
| 118859 | |
| 118860 | |
| 118861 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 118862 | |
| 118863 | |
| 118864 | #include <openssl/hmac.h> |
| 118865 | #include <openssl/sha.h> |
| 118866 | #include <openssl/rsa.h> |
| 118867 | #include <openssl/x509.h> |
| 118868 | #include <openssl/rand.h> |
| 118869 | #include <openssl/rsa.h> |
| 118870 | |
| 118871 | #define UA_SHA256_LENGTH 32 /* 256 bit */ |
| 118872 | #define UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN 42 |
| 118873 | #define UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH 32 |
| 118874 | #define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH 32 |
| 118875 | #define UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE 16 |
| 118876 | #define UA_SECURITYPOLICY_BASIC256SHA256_SYM_PLAIN_TEXT_BLOCK_SIZE 16 |
| 118877 | #define UA_SECURITYPOLICY_BASIC256SHA256_MINASYMKEYLENGTH 256 |
| 118878 | #define UA_SECURITYPOLICY_BASIC256SHA256_MAXASYMKEYLENGTH 512 |
| 118879 | |
| 118880 | typedef struct { |
| 118881 | EVP_PKEY *localPrivateKey; |
| 118882 | UA_ByteString localCertThumbprint; |
| 118883 | const UA_Logger *logger; |
| 118884 | } Policy_Context_Basic256Sha256; |
| 118885 | |
| 118886 | typedef struct { |
| 118887 | UA_ByteString localSymSigningKey; |
| 118888 | UA_ByteString localSymEncryptingKey; |
| 118889 | UA_ByteString localSymIv; |
| 118890 | UA_ByteString remoteSymSigningKey; |
| 118891 | UA_ByteString remoteSymEncryptingKey; |
| 118892 | UA_ByteString remoteSymIv; |
| 118893 | |
| 118894 | Policy_Context_Basic256Sha256 *policyContext; |
| 118895 | UA_ByteString remoteCertificate; |
| 118896 | X509 *remoteCertificateX509; /* X509 */ |
| 118897 | } Channel_Context_Basic256Sha256; |
| 118898 | |
| 118899 | /* create the policy context */ |
| 118900 | |
| 118901 | static UA_StatusCode |
| 118902 | UA_Policy_New_Context(UA_SecurityPolicy * securityPolicy, |
| 118903 | const UA_ByteString localPrivateKey, |
| 118904 | const UA_Logger *logger) { |
| 118905 | Policy_Context_Basic256Sha256 *context = (Policy_Context_Basic256Sha256 *) |
| 118906 | UA_malloc(size: sizeof(Policy_Context_Basic256Sha256)); |
| 118907 | if(context == NULL) |
| 118908 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 118909 | context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey); |
| 118910 | |
| 118911 | if(!context->localPrivateKey) { |
| 118912 | UA_free(ptr: context); |
| 118913 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 118914 | } |
| 118915 | |
| 118916 | UA_StatusCode retval = |
| 118917 | UA_Openssl_X509_GetCertificateThumbprint(certficate: &securityPolicy->localCertificate, |
| 118918 | pThumbprint: &context->localCertThumbprint, true); |
| 118919 | if(retval != UA_STATUSCODE_GOOD) { |
| 118920 | EVP_PKEY_free(pkey: context->localPrivateKey); |
| 118921 | UA_free(ptr: context); |
| 118922 | return retval; |
| 118923 | } |
| 118924 | |
| 118925 | context->logger = logger; |
| 118926 | securityPolicy->policyContext = context; |
| 118927 | return UA_STATUSCODE_GOOD; |
| 118928 | } |
| 118929 | |
| 118930 | /* Clear the policy context */ |
| 118931 | static void |
| 118932 | UA_Policy_Clear_Context(UA_SecurityPolicy *policy) { |
| 118933 | if(policy == NULL) |
| 118934 | return; |
| 118935 | |
| 118936 | UA_ByteString_clear(p: &policy->localCertificate); |
| 118937 | |
| 118938 | /* Delete all allocated members in the context */ |
| 118939 | Policy_Context_Basic256Sha256 *pc = |
| 118940 | (Policy_Context_Basic256Sha256 *) policy->policyContext; |
| 118941 | EVP_PKEY_free(pkey: pc->localPrivateKey); |
| 118942 | UA_ByteString_clear(p: &pc->localCertThumbprint); |
| 118943 | UA_free(ptr: pc); |
| 118944 | return; |
| 118945 | } |
| 118946 | |
| 118947 | static UA_StatusCode |
| 118948 | updateCertificateAndPrivateKey_sp_basic256sha256(UA_SecurityPolicy *securityPolicy, |
| 118949 | const UA_ByteString newCertificate, |
| 118950 | const UA_ByteString newPrivateKey) { |
| 118951 | if(securityPolicy == NULL) |
| 118952 | return UA_STATUSCODE_BADINTERNALERROR; |
| 118953 | |
| 118954 | if(securityPolicy->policyContext == NULL) |
| 118955 | return UA_STATUSCODE_BADINTERNALERROR; |
| 118956 | |
| 118957 | Policy_Context_Basic256Sha256 *pc = |
| 118958 | (Policy_Context_Basic256Sha256 *)securityPolicy->policyContext; |
| 118959 | |
| 118960 | UA_ByteString_clear(p: &securityPolicy->localCertificate); |
| 118961 | |
| 118962 | UA_StatusCode retval = UA_OpenSSL_LoadLocalCertificate( |
| 118963 | certificate: &newCertificate, target: &securityPolicy->localCertificate); |
| 118964 | |
| 118965 | if(retval != UA_STATUSCODE_GOOD) |
| 118966 | return retval; |
| 118967 | |
| 118968 | /* Set the new private key */ |
| 118969 | EVP_PKEY_free(pkey: pc->localPrivateKey); |
| 118970 | |
| 118971 | pc->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &newPrivateKey); |
| 118972 | |
| 118973 | if(!pc->localPrivateKey) { |
| 118974 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 118975 | goto error; |
| 118976 | } |
| 118977 | |
| 118978 | UA_ByteString_clear(p: &pc->localCertThumbprint); |
| 118979 | |
| 118980 | retval = UA_Openssl_X509_GetCertificateThumbprint(certficate: &securityPolicy->localCertificate, |
| 118981 | pThumbprint: &pc->localCertThumbprint, true); |
| 118982 | if(retval != UA_STATUSCODE_GOOD) { |
| 118983 | goto error; |
| 118984 | } |
| 118985 | |
| 118986 | return retval; |
| 118987 | |
| 118988 | error: |
| 118989 | UA_LOG_ERROR(logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 118990 | msg: "Could not update certificate and private key"); |
| 118991 | if(securityPolicy->policyContext != NULL) |
| 118992 | UA_Policy_Clear_Context(policy: securityPolicy); |
| 118993 | return retval; |
| 118994 | } |
| 118995 | |
| 118996 | /* create the channel context */ |
| 118997 | |
| 118998 | static UA_StatusCode |
| 118999 | UA_ChannelModule_New_Context(const UA_SecurityPolicy * securityPolicy, |
| 119000 | const UA_ByteString * remoteCertificate, |
| 119001 | void ** channelContext) { |
| 119002 | if(securityPolicy == NULL || remoteCertificate == NULL || channelContext == NULL) |
| 119003 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119004 | |
| 119005 | Channel_Context_Basic256Sha256 *context = (Channel_Context_Basic256Sha256 *) |
| 119006 | UA_malloc(size: sizeof(Channel_Context_Basic256Sha256)); |
| 119007 | if(context == NULL) |
| 119008 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 119009 | |
| 119010 | UA_ByteString_init(p: &context->localSymSigningKey); |
| 119011 | UA_ByteString_init(p: &context->localSymEncryptingKey); |
| 119012 | UA_ByteString_init(p: &context->localSymIv); |
| 119013 | UA_ByteString_init(p: &context->remoteSymSigningKey); |
| 119014 | UA_ByteString_init(p: &context->remoteSymEncryptingKey); |
| 119015 | UA_ByteString_init(p: &context->remoteSymIv); |
| 119016 | |
| 119017 | UA_StatusCode retval = |
| 119018 | UA_copyCertificate(dst: &context->remoteCertificate, src: remoteCertificate); |
| 119019 | if(retval != UA_STATUSCODE_GOOD) { |
| 119020 | UA_free(ptr: context); |
| 119021 | return retval; |
| 119022 | } |
| 119023 | |
| 119024 | /* decode to X509 */ |
| 119025 | context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate); |
| 119026 | if(context->remoteCertificateX509 == NULL) { |
| 119027 | UA_ByteString_clear(p: &context->remoteCertificate); |
| 119028 | UA_free(ptr: context); |
| 119029 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119030 | } |
| 119031 | |
| 119032 | context->policyContext = |
| 119033 | (Policy_Context_Basic256Sha256 *)securityPolicy->policyContext; |
| 119034 | *channelContext = context; |
| 119035 | |
| 119036 | UA_LOG_INFO(logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 119037 | msg: "The basic256sha256 security policy channel with openssl is created."); |
| 119038 | |
| 119039 | return UA_STATUSCODE_GOOD; |
| 119040 | } |
| 119041 | |
| 119042 | /* delete the channel context */ |
| 119043 | |
| 119044 | static void |
| 119045 | UA_ChannelModule_Delete_Context(void * channelContext) { |
| 119046 | if(!channelContext) |
| 119047 | return; |
| 119048 | |
| 119049 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *)channelContext; |
| 119050 | X509_free(a: cc->remoteCertificateX509); |
| 119051 | UA_ByteString_clear(p: &cc->remoteCertificate); |
| 119052 | UA_ByteString_clear(p: &cc->localSymSigningKey); |
| 119053 | UA_ByteString_clear(p: &cc->localSymEncryptingKey); |
| 119054 | UA_ByteString_clear(p: &cc->localSymIv); |
| 119055 | UA_ByteString_clear(p: &cc->remoteSymSigningKey); |
| 119056 | UA_ByteString_clear(p: &cc->remoteSymEncryptingKey); |
| 119057 | UA_ByteString_clear(p: &cc->remoteSymIv); |
| 119058 | |
| 119059 | UA_LOG_INFO(logger: cc->policyContext->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 119060 | msg: "The basic256sha256 security policy channel with openssl is deleted."); |
| 119061 | UA_free(ptr: cc); |
| 119062 | } |
| 119063 | |
| 119064 | /* Verifies the signature of the message using the provided keys in the context. |
| 119065 | * AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 */ |
| 119066 | static UA_StatusCode |
| 119067 | UA_AsySig_Basic256Sha256_Verify(void *channelContext, |
| 119068 | const UA_ByteString *message, |
| 119069 | const UA_ByteString *signature) { |
| 119070 | if(message == NULL || signature == NULL || channelContext == NULL) |
| 119071 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119072 | |
| 119073 | Channel_Context_Basic256Sha256 * cc = |
| 119074 | (Channel_Context_Basic256Sha256 *) channelContext; |
| 119075 | return UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify(msg: message, publicKeyX509: cc->remoteCertificateX509, |
| 119076 | signature); |
| 119077 | } |
| 119078 | |
| 119079 | /* Compares the supplied certificate with the certificate |
| 119080 | * in the endpoint context |
| 119081 | */ |
| 119082 | |
| 119083 | static UA_StatusCode |
| 119084 | UA_compareCertificateThumbprint(const UA_SecurityPolicy * securityPolicy, |
| 119085 | const UA_ByteString * certificateThumbprint) { |
| 119086 | if(securityPolicy == NULL || certificateThumbprint == NULL) |
| 119087 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 119088 | Policy_Context_Basic256Sha256 *pc = (Policy_Context_Basic256Sha256 *) |
| 119089 | securityPolicy->policyContext; |
| 119090 | if(!UA_ByteString_equal(p1: certificateThumbprint, p2: &pc->localCertThumbprint)) |
| 119091 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 119092 | return UA_STATUSCODE_GOOD; |
| 119093 | } |
| 119094 | |
| 119095 | /* Generates a thumbprint for the specified certificate */ |
| 119096 | |
| 119097 | static UA_StatusCode |
| 119098 | UA_makeCertificateThumbprint(const UA_SecurityPolicy * securityPolicy, |
| 119099 | const UA_ByteString * certificate, |
| 119100 | UA_ByteString * thumbprint) { |
| 119101 | return UA_Openssl_X509_GetCertificateThumbprint(certficate: certificate, pThumbprint: thumbprint, false); |
| 119102 | } |
| 119103 | |
| 119104 | static UA_StatusCode |
| 119105 | UA_Asym_Basic256Sha256_Decrypt(void * channelContext, UA_ByteString * data) { |
| 119106 | if(channelContext == NULL || data == NULL) |
| 119107 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 119108 | |
| 119109 | Channel_Context_Basic256Sha256 * cc = |
| 119110 | (Channel_Context_Basic256Sha256 *) channelContext; |
| 119111 | return UA_Openssl_RSA_Oaep_Decrypt(data, privateKey: cc->policyContext->localPrivateKey); |
| 119112 | } |
| 119113 | |
| 119114 | static size_t |
| 119115 | UA_Asym_Basic256Sha256_getRemoteSignatureSize(const void *channelContext) { |
| 119116 | if(channelContext == NULL) |
| 119117 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119118 | |
| 119119 | const Channel_Context_Basic256Sha256 * cc = |
| 119120 | (const Channel_Context_Basic256Sha256 *) channelContext; |
| 119121 | UA_Int32 keyLen = 0; |
| 119122 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 119123 | return (size_t) keyLen; |
| 119124 | } |
| 119125 | |
| 119126 | static size_t |
| 119127 | UA_AsySig_Basic256Sha256_getLocalSignatureSize(const void *channelContext) { |
| 119128 | if(channelContext == NULL) |
| 119129 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119130 | |
| 119131 | const Channel_Context_Basic256Sha256 *cc = |
| 119132 | (const Channel_Context_Basic256Sha256 *) channelContext; |
| 119133 | Policy_Context_Basic256Sha256 * pc = cc->policyContext; |
| 119134 | UA_Int32 keyLen = 0; |
| 119135 | UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 119136 | return (size_t) keyLen; |
| 119137 | } |
| 119138 | |
| 119139 | static size_t |
| 119140 | UA_AsymEn_Basic256Sha256_getRemotePlainTextBlockSize(const void *channelContext) { |
| 119141 | if(channelContext == NULL) |
| 119142 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119143 | |
| 119144 | const Channel_Context_Basic256Sha256 *cc = |
| 119145 | (const Channel_Context_Basic256Sha256 *) channelContext; |
| 119146 | UA_Int32 keyLen = 0; |
| 119147 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 119148 | return (size_t) keyLen - UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN; |
| 119149 | } |
| 119150 | |
| 119151 | static size_t |
| 119152 | UA_AsymEn_Basic256Sha256_getRemoteBlockSize(const void *channelContext) { |
| 119153 | if(channelContext == NULL) |
| 119154 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119155 | |
| 119156 | const Channel_Context_Basic256Sha256 * cc = |
| 119157 | (const Channel_Context_Basic256Sha256 *) channelContext; |
| 119158 | UA_Int32 keyLen = 0; |
| 119159 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 119160 | return (size_t) keyLen; |
| 119161 | } |
| 119162 | |
| 119163 | static size_t |
| 119164 | UA_AsymEn_Basic256Sha256_getRemoteKeyLength(const void *channelContext) { |
| 119165 | if(channelContext == NULL) |
| 119166 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119167 | |
| 119168 | const Channel_Context_Basic256Sha256 *cc = |
| 119169 | (const Channel_Context_Basic256Sha256 *) channelContext; |
| 119170 | UA_Int32 keyLen = 0; |
| 119171 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 119172 | return (size_t) keyLen * 8; |
| 119173 | } |
| 119174 | |
| 119175 | static UA_StatusCode |
| 119176 | UA_Sym_Basic256Sha256_generateNonce(void *policyContext, |
| 119177 | UA_ByteString *out) { |
| 119178 | UA_Int32 rc = RAND_bytes(buf: out->data, num: (int) out->length); |
| 119179 | if(rc != 1) |
| 119180 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 119181 | return UA_STATUSCODE_GOOD; |
| 119182 | } |
| 119183 | |
| 119184 | static size_t |
| 119185 | UA_SymEn_Basic256Sha256_getLocalKeyLength(const void *channelContext) { |
| 119186 | /* 32 bytes 256 bits */ |
| 119187 | return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH; |
| 119188 | } |
| 119189 | |
| 119190 | static size_t |
| 119191 | UA_SymSig_Basic256Sha256_getLocalKeyLength(const void *channelContext) { |
| 119192 | /* 32 bytes 256 bits */ |
| 119193 | return UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH; |
| 119194 | } |
| 119195 | |
| 119196 | static UA_StatusCode |
| 119197 | UA_Sym_Basic256Sha256_generateKey(void *policyContext, |
| 119198 | const UA_ByteString *secret, |
| 119199 | const UA_ByteString *seed, |
| 119200 | UA_ByteString *out) { |
| 119201 | return UA_Openssl_Random_Key_PSHA256_Derive(secret, seed, out); |
| 119202 | } |
| 119203 | |
| 119204 | static UA_StatusCode |
| 119205 | UA_ChannelModule_Basic256Sha256_setLocalSymSigningKey(void * channelContext, |
| 119206 | const UA_ByteString * key) { |
| 119207 | if(key == NULL || channelContext == NULL) |
| 119208 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119209 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119210 | UA_ByteString_clear(p: &cc->localSymSigningKey); |
| 119211 | return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey); |
| 119212 | } |
| 119213 | |
| 119214 | static UA_StatusCode |
| 119215 | UA_ChannelM_Basic256Sha256_setLocalSymEncryptingKey(void * channelContext, |
| 119216 | const UA_ByteString * key) { |
| 119217 | if(key == NULL || channelContext == NULL) |
| 119218 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119219 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119220 | UA_ByteString_clear(p: &cc->localSymEncryptingKey); |
| 119221 | return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey); |
| 119222 | } |
| 119223 | |
| 119224 | static UA_StatusCode |
| 119225 | UA_ChannelM_Basic256Sha256_setLocalSymIv(void * channelContext, |
| 119226 | const UA_ByteString * iv) { |
| 119227 | if(iv == NULL || channelContext == NULL) |
| 119228 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119229 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119230 | UA_ByteString_clear(p: &cc->localSymIv); |
| 119231 | return UA_ByteString_copy(src: iv, dst: &cc->localSymIv); |
| 119232 | } |
| 119233 | |
| 119234 | static size_t |
| 119235 | UA_SymEn_Basic256Sha256_getRemoteKeyLength(const void * channelContext) { |
| 119236 | /* 32 bytes 256 bits */ |
| 119237 | return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_KEY_LENGTH; |
| 119238 | } |
| 119239 | |
| 119240 | static size_t |
| 119241 | UA_SymEn_Basic256Sha256_getBlockSize(const void *channelContext) { |
| 119242 | return UA_SECURITYPOLICY_BASIC256SHA256_SYM_ENCRYPTION_BLOCK_SIZE; |
| 119243 | } |
| 119244 | |
| 119245 | static size_t |
| 119246 | UA_SymSig_Basic256Sha256_getRemoteKeyLength(const void * channelContext) { |
| 119247 | /* 32 bytes 256 bits */ |
| 119248 | return UA_SECURITYPOLICY_BASIC256SHA256_SYM_SIGNING_KEY_LENGTH; |
| 119249 | } |
| 119250 | |
| 119251 | static UA_StatusCode |
| 119252 | UA_ChannelM_Basic256Sha256_setRemoteSymSigningKey(void *channelContext, |
| 119253 | const UA_ByteString * key) { |
| 119254 | if(key == NULL || channelContext == NULL) |
| 119255 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119256 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119257 | UA_ByteString_clear(p: &cc->remoteSymSigningKey); |
| 119258 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey); |
| 119259 | } |
| 119260 | |
| 119261 | static UA_StatusCode |
| 119262 | UA_ChannelM_Basic256Sha256_setRemoteSymEncryptingKey(void *channelContext, |
| 119263 | const UA_ByteString * key) { |
| 119264 | if(key == NULL || channelContext == NULL) |
| 119265 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119266 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119267 | UA_ByteString_clear(p: &cc->remoteSymEncryptingKey); |
| 119268 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey); |
| 119269 | } |
| 119270 | |
| 119271 | static UA_StatusCode |
| 119272 | UA_ChannelM_Basic256Sha256_setRemoteSymIv(void *channelContext, |
| 119273 | const UA_ByteString * key) { |
| 119274 | if(key == NULL || channelContext == NULL) |
| 119275 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119276 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119277 | UA_ByteString_clear(p: &cc->remoteSymIv); |
| 119278 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv); |
| 119279 | } |
| 119280 | |
| 119281 | static UA_StatusCode |
| 119282 | UA_AsySig_Basic256Sha256_sign(void *channelContext, const UA_ByteString * message, |
| 119283 | UA_ByteString *signature) { |
| 119284 | if(channelContext == NULL || message == NULL || signature == NULL) |
| 119285 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119286 | Channel_Context_Basic256Sha256 *cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119287 | Policy_Context_Basic256Sha256 *pc = cc->policyContext; |
| 119288 | return UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(message, privateKey: pc->localPrivateKey, outSignature: signature); |
| 119289 | } |
| 119290 | |
| 119291 | static UA_StatusCode |
| 119292 | UA_AsymEn_Basic256Sha256_encrypt(void *channelContext, UA_ByteString *data) { |
| 119293 | if(channelContext == NULL || data == NULL) |
| 119294 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119295 | Channel_Context_Basic256Sha256 * cc = |
| 119296 | (Channel_Context_Basic256Sha256 *) channelContext; |
| 119297 | return UA_Openssl_RSA_OAEP_Encrypt(data, UA_SECURITYPOLICY_BASIC256SHA256_RSAPADDING_LEN, |
| 119298 | publicX509: cc->remoteCertificateX509); |
| 119299 | } |
| 119300 | |
| 119301 | static size_t |
| 119302 | UA_SymSig_Basic256Sha256_getRemoteSignatureSize(const void *channelContext) { |
| 119303 | return UA_SHA256_LENGTH; |
| 119304 | } |
| 119305 | |
| 119306 | static UA_StatusCode |
| 119307 | UA_SymSig_Basic256Sha256_verify(void *channelContext, const UA_ByteString *message, |
| 119308 | const UA_ByteString *signature) { |
| 119309 | if(channelContext == NULL || message == NULL || signature == NULL) |
| 119310 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119311 | |
| 119312 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119313 | return UA_OpenSSL_HMAC_SHA256_Verify(message, key: &cc->remoteSymSigningKey, signature); |
| 119314 | } |
| 119315 | |
| 119316 | static UA_StatusCode |
| 119317 | UA_SymSig_Basic256Sha256_sign(void *channelContext, const UA_ByteString *message, |
| 119318 | UA_ByteString *signature) { |
| 119319 | if(channelContext == NULL || message == NULL || signature == NULL) |
| 119320 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119321 | |
| 119322 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119323 | return UA_OpenSSL_HMAC_SHA256_Sign(message, key: &cc->localSymSigningKey, signature); |
| 119324 | } |
| 119325 | |
| 119326 | static size_t |
| 119327 | UA_SymSig_Basic256Sha256_getLocalSignatureSize(const void * channelContext) { |
| 119328 | return UA_SHA256_LENGTH; |
| 119329 | } |
| 119330 | |
| 119331 | static UA_StatusCode |
| 119332 | UA_SymEn_Basic256Sha256_decrypt(void *channelContext, UA_ByteString *data) { |
| 119333 | if(channelContext == NULL || data == NULL) |
| 119334 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119335 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119336 | return UA_OpenSSL_AES_256_CBC_Decrypt(iv: &cc->remoteSymIv, |
| 119337 | key: &cc->remoteSymEncryptingKey, data); |
| 119338 | } |
| 119339 | |
| 119340 | static UA_StatusCode |
| 119341 | UA_SymEn_Basic256Sha256_encrypt(void *channelContext, UA_ByteString *data) { |
| 119342 | if(channelContext == NULL || data == NULL) |
| 119343 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119344 | |
| 119345 | Channel_Context_Basic256Sha256 * cc = (Channel_Context_Basic256Sha256 *) channelContext; |
| 119346 | return UA_OpenSSL_AES_256_CBC_Encrypt(iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, data); |
| 119347 | } |
| 119348 | |
| 119349 | static UA_StatusCode |
| 119350 | UA_ChannelM_Basic256Sha256_compareCertificate(const void *channelContext, |
| 119351 | const UA_ByteString *certificate) { |
| 119352 | if(channelContext == NULL || certificate == NULL) |
| 119353 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119354 | |
| 119355 | const Channel_Context_Basic256Sha256 * cc = |
| 119356 | (const Channel_Context_Basic256Sha256 *) channelContext; |
| 119357 | return UA_OpenSSL_X509_compare(cert: certificate, bcert: cc->remoteCertificateX509); |
| 119358 | } |
| 119359 | |
| 119360 | static size_t |
| 119361 | UA_AsymEn_Basic256Sha256_getLocalKeyLength(const void *channelContext) { |
| 119362 | if(channelContext == NULL) |
| 119363 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119364 | |
| 119365 | const Channel_Context_Basic256Sha256 * cc = |
| 119366 | (const Channel_Context_Basic256Sha256 *) channelContext; |
| 119367 | Policy_Context_Basic256Sha256 *pc = cc->policyContext; |
| 119368 | UA_Int32 keyLen = 0; |
| 119369 | UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 119370 | return (size_t) keyLen * 8; |
| 119371 | } |
| 119372 | |
| 119373 | /* the main entry of Basic256Sha256 */ |
| 119374 | |
| 119375 | UA_StatusCode |
| 119376 | UA_SecurityPolicy_Basic256Sha256(UA_SecurityPolicy *policy, |
| 119377 | const UA_ByteString localCertificate, |
| 119378 | const UA_ByteString localPrivateKey, |
| 119379 | const UA_Logger *logger) { |
| 119380 | UA_SecurityPolicyAsymmetricModule *asymmetricModule = &policy->asymmetricModule; |
| 119381 | UA_SecurityPolicySymmetricModule *symmetricModule = &policy->symmetricModule; |
| 119382 | UA_SecurityPolicyChannelModule *channelModule = &policy->channelModule; |
| 119383 | UA_LOG_INFO(logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 119384 | msg: "The basic256sha256 security policy with openssl is added."); |
| 119385 | |
| 119386 | UA_Openssl_Init(); |
| 119387 | memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy)); |
| 119388 | policy->logger = logger; |
| 119389 | policy->policyUri = |
| 119390 | UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256\0"); |
| 119391 | |
| 119392 | /* Set ChannelModule context */ |
| 119393 | channelModule->newContext = UA_ChannelModule_New_Context; |
| 119394 | channelModule->deleteContext = UA_ChannelModule_Delete_Context; |
| 119395 | channelModule->setLocalSymSigningKey = |
| 119396 | UA_ChannelModule_Basic256Sha256_setLocalSymSigningKey; |
| 119397 | channelModule->setLocalSymEncryptingKey = |
| 119398 | UA_ChannelM_Basic256Sha256_setLocalSymEncryptingKey; |
| 119399 | channelModule->setLocalSymIv = UA_ChannelM_Basic256Sha256_setLocalSymIv; |
| 119400 | channelModule->setRemoteSymSigningKey = |
| 119401 | UA_ChannelM_Basic256Sha256_setRemoteSymSigningKey; |
| 119402 | channelModule->setRemoteSymEncryptingKey = |
| 119403 | UA_ChannelM_Basic256Sha256_setRemoteSymEncryptingKey; |
| 119404 | channelModule->setRemoteSymIv = UA_ChannelM_Basic256Sha256_setRemoteSymIv; |
| 119405 | channelModule->compareCertificate = UA_ChannelM_Basic256Sha256_compareCertificate; |
| 119406 | UA_StatusCode retval = |
| 119407 | UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate); |
| 119408 | if(retval != UA_STATUSCODE_GOOD) |
| 119409 | return retval; |
| 119410 | |
| 119411 | /* AsymmetricModule - signature algorithm */ |
| 119412 | UA_SecurityPolicySignatureAlgorithm *asySigAlgorithm = |
| 119413 | &asymmetricModule->cryptoModule.signatureAlgorithm; |
| 119414 | asySigAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0"); |
| 119415 | asySigAlgorithm->verify = UA_AsySig_Basic256Sha256_Verify; |
| 119416 | asySigAlgorithm->sign = UA_AsySig_Basic256Sha256_sign; |
| 119417 | asySigAlgorithm->getLocalSignatureSize = UA_AsySig_Basic256Sha256_getLocalSignatureSize; |
| 119418 | asySigAlgorithm->getRemoteSignatureSize = UA_Asym_Basic256Sha256_getRemoteSignatureSize; |
| 119419 | asySigAlgorithm->getLocalKeyLength = NULL; |
| 119420 | asySigAlgorithm->getRemoteKeyLength = NULL; |
| 119421 | |
| 119422 | /* AsymmetricModule encryption algorithm */ |
| 119423 | UA_SecurityPolicyEncryptionAlgorithm *asymEncryAlg = |
| 119424 | &asymmetricModule->cryptoModule.encryptionAlgorithm; |
| 119425 | asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-oaep\0"); |
| 119426 | asymEncryAlg->encrypt = UA_AsymEn_Basic256Sha256_encrypt; |
| 119427 | asymEncryAlg->decrypt = UA_Asym_Basic256Sha256_Decrypt; |
| 119428 | asymEncryAlg->getLocalKeyLength = UA_AsymEn_Basic256Sha256_getLocalKeyLength; |
| 119429 | asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Basic256Sha256_getRemoteKeyLength; |
| 119430 | asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Basic256Sha256_getRemoteBlockSize; |
| 119431 | asymEncryAlg->getRemotePlainTextBlockSize = |
| 119432 | UA_AsymEn_Basic256Sha256_getRemotePlainTextBlockSize; |
| 119433 | |
| 119434 | /* AsymmetricModule */ |
| 119435 | asymmetricModule->compareCertificateThumbprint = UA_compareCertificateThumbprint; |
| 119436 | asymmetricModule->makeCertificateThumbprint = UA_makeCertificateThumbprint; |
| 119437 | |
| 119438 | /* SymmetricModule */ |
| 119439 | symmetricModule->secureChannelNonceLength = 32; |
| 119440 | symmetricModule->generateNonce = UA_Sym_Basic256Sha256_generateNonce; |
| 119441 | symmetricModule->generateKey = UA_Sym_Basic256Sha256_generateKey; |
| 119442 | |
| 119443 | /* Symmetric encryption Algorithm */ |
| 119444 | UA_SecurityPolicyEncryptionAlgorithm *symEncryptionAlgorithm = |
| 119445 | &symmetricModule->cryptoModule.encryptionAlgorithm; |
| 119446 | symEncryptionAlgorithm->uri = |
| 119447 | UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes256-cbc\0"); |
| 119448 | symEncryptionAlgorithm->encrypt = UA_SymEn_Basic256Sha256_encrypt; |
| 119449 | symEncryptionAlgorithm->decrypt = UA_SymEn_Basic256Sha256_decrypt; |
| 119450 | symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Basic256Sha256_getLocalKeyLength; |
| 119451 | symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Basic256Sha256_getRemoteKeyLength; |
| 119452 | symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Basic256Sha256_getBlockSize; |
| 119453 | symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Basic256Sha256_getBlockSize; |
| 119454 | |
| 119455 | /* Symmetric signature Algorithm */ |
| 119456 | UA_SecurityPolicySignatureAlgorithm *symSignatureAlgorithm = |
| 119457 | &symmetricModule->cryptoModule.signatureAlgorithm; |
| 119458 | symSignatureAlgorithm->uri = |
| 119459 | UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0"); |
| 119460 | symSignatureAlgorithm->verify = UA_SymSig_Basic256Sha256_verify; |
| 119461 | symSignatureAlgorithm->sign = UA_SymSig_Basic256Sha256_sign; |
| 119462 | symSignatureAlgorithm->getLocalSignatureSize = |
| 119463 | UA_SymSig_Basic256Sha256_getLocalSignatureSize; |
| 119464 | symSignatureAlgorithm->getRemoteSignatureSize = |
| 119465 | UA_SymSig_Basic256Sha256_getRemoteSignatureSize; |
| 119466 | symSignatureAlgorithm->getLocalKeyLength = |
| 119467 | UA_SymSig_Basic256Sha256_getLocalKeyLength; |
| 119468 | symSignatureAlgorithm->getRemoteKeyLength = |
| 119469 | UA_SymSig_Basic256Sha256_getRemoteKeyLength; |
| 119470 | |
| 119471 | policy->updateCertificateAndPrivateKey = |
| 119472 | updateCertificateAndPrivateKey_sp_basic256sha256; |
| 119473 | policy->clear = UA_Policy_Clear_Context; |
| 119474 | retval = UA_Policy_New_Context(securityPolicy: policy, localPrivateKey, logger); |
| 119475 | if(retval != UA_STATUSCODE_GOOD) { |
| 119476 | UA_ByteString_clear(p: &policy->localCertificate); |
| 119477 | return retval; |
| 119478 | } |
| 119479 | |
| 119480 | /* Use the same signature algorithm as the asymmetric component for |
| 119481 | * certificate signing (see standard) */ |
| 119482 | policy->certificateSigningAlgorithm = |
| 119483 | policy->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 119484 | |
| 119485 | return UA_STATUSCODE_GOOD; |
| 119486 | } |
| 119487 | |
| 119488 | #endif |
| 119489 | |
| 119490 | /**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_aes128sha256rsaoaep.c" ****/ |
| 119491 | |
| 119492 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 119493 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 119494 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 119495 | * |
| 119496 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 119497 | */ |
| 119498 | |
| 119499 | |
| 119500 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 119501 | |
| 119502 | |
| 119503 | #include <openssl/hmac.h> |
| 119504 | #include <openssl/sha.h> |
| 119505 | #include <openssl/rsa.h> |
| 119506 | #include <openssl/x509.h> |
| 119507 | #include <openssl/rand.h> |
| 119508 | #include <openssl/rsa.h> |
| 119509 | |
| 119510 | #define UA_SHA256_LENGTH 32 /* 256 bit */ |
| 119511 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN 42 |
| 119512 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH 32 |
| 119513 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH 16 |
| 119514 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE 16 |
| 119515 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_PLAIN_TEXT_BLOCK_SIZE 16 |
| 119516 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MINASYMKEYLENGTH 256 |
| 119517 | #define UA_SECURITYPOLICY_AES128SHA256RSAOAEP_MAXASYMKEYLENGTH 512 |
| 119518 | |
| 119519 | typedef struct { |
| 119520 | EVP_PKEY *localPrivateKey; |
| 119521 | UA_ByteString localCertThumbprint; |
| 119522 | const UA_Logger *logger; |
| 119523 | } Policy_Context_Aes128Sha256RsaOaep; |
| 119524 | |
| 119525 | typedef struct { |
| 119526 | UA_ByteString localSymSigningKey; |
| 119527 | UA_ByteString localSymEncryptingKey; |
| 119528 | UA_ByteString localSymIv; |
| 119529 | UA_ByteString remoteSymSigningKey; |
| 119530 | UA_ByteString remoteSymEncryptingKey; |
| 119531 | UA_ByteString remoteSymIv; |
| 119532 | |
| 119533 | Policy_Context_Aes128Sha256RsaOaep *policyContext; |
| 119534 | UA_ByteString remoteCertificate; |
| 119535 | X509 *remoteCertificateX509; /* X509 */ |
| 119536 | } Channel_Context_Aes128Sha256RsaOaep; |
| 119537 | |
| 119538 | /* create the policy context */ |
| 119539 | |
| 119540 | static UA_StatusCode |
| 119541 | UA_Policy_Aes128Sha256RsaOaep_New_Context(UA_SecurityPolicy *securityPolicy, |
| 119542 | const UA_ByteString localPrivateKey, |
| 119543 | const UA_Logger *logger) { |
| 119544 | Policy_Context_Aes128Sha256RsaOaep *context = |
| 119545 | (Policy_Context_Aes128Sha256RsaOaep *)UA_malloc( |
| 119546 | size: sizeof(Policy_Context_Aes128Sha256RsaOaep)); |
| 119547 | if(context == NULL) { |
| 119548 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 119549 | } |
| 119550 | |
| 119551 | context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey); |
| 119552 | if (!context->localPrivateKey) { |
| 119553 | UA_free(ptr: context); |
| 119554 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 119555 | } |
| 119556 | |
| 119557 | UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint( |
| 119558 | certficate: &securityPolicy->localCertificate, pThumbprint: &context->localCertThumbprint, true); |
| 119559 | if(retval != UA_STATUSCODE_GOOD) { |
| 119560 | EVP_PKEY_free(pkey: context->localPrivateKey); |
| 119561 | UA_free(ptr: context); |
| 119562 | return retval; |
| 119563 | } |
| 119564 | |
| 119565 | context->logger = logger; |
| 119566 | securityPolicy->policyContext = context; |
| 119567 | |
| 119568 | return UA_STATUSCODE_GOOD; |
| 119569 | } |
| 119570 | |
| 119571 | /* clear the policy context */ |
| 119572 | |
| 119573 | static void |
| 119574 | UA_Policy_Aes128Sha256RsaOaep_Clear_Context(UA_SecurityPolicy *policy) { |
| 119575 | if(policy == NULL) |
| 119576 | return; |
| 119577 | |
| 119578 | UA_ByteString_clear(p: &policy->localCertificate); |
| 119579 | |
| 119580 | /* delete all allocated members in the context */ |
| 119581 | |
| 119582 | Policy_Context_Aes128Sha256RsaOaep *pc = |
| 119583 | (Policy_Context_Aes128Sha256RsaOaep *)policy->policyContext; |
| 119584 | if (pc == NULL) { |
| 119585 | return; |
| 119586 | } |
| 119587 | |
| 119588 | EVP_PKEY_free(pkey: pc->localPrivateKey); |
| 119589 | UA_ByteString_clear(p: &pc->localCertThumbprint); |
| 119590 | UA_free(ptr: pc); |
| 119591 | |
| 119592 | return; |
| 119593 | } |
| 119594 | |
| 119595 | static UA_StatusCode |
| 119596 | updateCertificateAndPrivateKey_sp_aes128sha256rsaoaep(UA_SecurityPolicy *securityPolicy, |
| 119597 | const UA_ByteString newCertificate, |
| 119598 | const UA_ByteString newPrivateKey) { |
| 119599 | if(securityPolicy == NULL) |
| 119600 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119601 | |
| 119602 | if(securityPolicy->policyContext == NULL) |
| 119603 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119604 | |
| 119605 | Policy_Context_Aes128Sha256RsaOaep *pc = |
| 119606 | (Policy_Context_Aes128Sha256RsaOaep *)securityPolicy->policyContext; |
| 119607 | |
| 119608 | UA_ByteString_clear(p: &securityPolicy->localCertificate); |
| 119609 | |
| 119610 | UA_StatusCode retval = UA_OpenSSL_LoadLocalCertificate( |
| 119611 | certificate: &newCertificate, target: &securityPolicy->localCertificate); |
| 119612 | |
| 119613 | if(retval != UA_STATUSCODE_GOOD) |
| 119614 | return retval; |
| 119615 | |
| 119616 | /* Set the new private key */ |
| 119617 | EVP_PKEY_free(pkey: pc->localPrivateKey); |
| 119618 | |
| 119619 | pc->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &newPrivateKey); |
| 119620 | |
| 119621 | if(!pc->localPrivateKey) { |
| 119622 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 119623 | goto error; |
| 119624 | } |
| 119625 | |
| 119626 | UA_ByteString_clear(p: &pc->localCertThumbprint); |
| 119627 | |
| 119628 | retval = UA_Openssl_X509_GetCertificateThumbprint(certficate: &securityPolicy->localCertificate, |
| 119629 | pThumbprint: &pc->localCertThumbprint, true); |
| 119630 | if(retval != UA_STATUSCODE_GOOD) { |
| 119631 | goto error; |
| 119632 | } |
| 119633 | |
| 119634 | return retval; |
| 119635 | |
| 119636 | error: |
| 119637 | UA_LOG_ERROR(logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 119638 | msg: "Could not update certificate and private key"); |
| 119639 | if(securityPolicy->policyContext != NULL) |
| 119640 | UA_Policy_Aes128Sha256RsaOaep_Clear_Context(policy: securityPolicy); |
| 119641 | return retval; |
| 119642 | } |
| 119643 | |
| 119644 | /* create the channel context */ |
| 119645 | |
| 119646 | static UA_StatusCode |
| 119647 | UA_ChannelModule_Aes128Sha256RsaOaep_New_Context(const UA_SecurityPolicy *securityPolicy, |
| 119648 | const UA_ByteString *remoteCertificate, |
| 119649 | void **channelContext) { |
| 119650 | if(securityPolicy == NULL || remoteCertificate == NULL || channelContext == NULL) { |
| 119651 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119652 | } |
| 119653 | Channel_Context_Aes128Sha256RsaOaep *context = |
| 119654 | (Channel_Context_Aes128Sha256RsaOaep *)UA_malloc( |
| 119655 | size: sizeof(Channel_Context_Aes128Sha256RsaOaep)); |
| 119656 | if(context == NULL) { |
| 119657 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 119658 | } |
| 119659 | |
| 119660 | UA_ByteString_init(p: &context->localSymSigningKey); |
| 119661 | UA_ByteString_init(p: &context->localSymEncryptingKey); |
| 119662 | UA_ByteString_init(p: &context->localSymIv); |
| 119663 | UA_ByteString_init(p: &context->remoteSymSigningKey); |
| 119664 | UA_ByteString_init(p: &context->remoteSymEncryptingKey); |
| 119665 | UA_ByteString_init(p: &context->remoteSymIv); |
| 119666 | |
| 119667 | UA_StatusCode retval = |
| 119668 | UA_copyCertificate(dst: &context->remoteCertificate, src: remoteCertificate); |
| 119669 | if(retval != UA_STATUSCODE_GOOD) { |
| 119670 | UA_free(ptr: context); |
| 119671 | return retval; |
| 119672 | } |
| 119673 | |
| 119674 | /* decode to X509 */ |
| 119675 | context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate); |
| 119676 | if (context->remoteCertificateX509 == NULL) { |
| 119677 | UA_ByteString_clear (p: &context->remoteCertificate); |
| 119678 | UA_free (ptr: context); |
| 119679 | return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; |
| 119680 | } |
| 119681 | |
| 119682 | context->policyContext = |
| 119683 | (Policy_Context_Aes128Sha256RsaOaep *)(securityPolicy->policyContext); |
| 119684 | |
| 119685 | *channelContext = context; |
| 119686 | |
| 119687 | UA_LOG_INFO( |
| 119688 | logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 119689 | msg: "The Aes128Sha256RsaOaep security policy channel with openssl is created."); |
| 119690 | |
| 119691 | return UA_STATUSCODE_GOOD; |
| 119692 | } |
| 119693 | |
| 119694 | /* delete the channel context */ |
| 119695 | |
| 119696 | static void |
| 119697 | UA_ChannelModule_Aes128Sha256RsaOaep_Delete_Context(void *channelContext) { |
| 119698 | if(channelContext != NULL) { |
| 119699 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119700 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119701 | X509_free(a: cc->remoteCertificateX509); |
| 119702 | UA_ByteString_clear(p: &cc->remoteCertificate); |
| 119703 | UA_ByteString_clear(p: &cc->localSymSigningKey); |
| 119704 | UA_ByteString_clear(p: &cc->localSymEncryptingKey); |
| 119705 | UA_ByteString_clear(p: &cc->localSymIv); |
| 119706 | UA_ByteString_clear(p: &cc->remoteSymSigningKey); |
| 119707 | UA_ByteString_clear(p: &cc->remoteSymEncryptingKey); |
| 119708 | UA_ByteString_clear(p: &cc->remoteSymIv); |
| 119709 | |
| 119710 | UA_LOG_INFO( |
| 119711 | logger: cc->policyContext->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 119712 | msg: "The Aes128Sha256RsaOaep security policy channel with openssl is deleted."); |
| 119713 | UA_free(ptr: cc); |
| 119714 | } |
| 119715 | } |
| 119716 | |
| 119717 | /* Verifies the signature of the message using the provided keys in the context. |
| 119718 | * AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 |
| 119719 | */ |
| 119720 | |
| 119721 | static UA_StatusCode |
| 119722 | UA_AsySig_Aes128Sha256RsaOaep_Verify(void *channelContext, const UA_ByteString *message, |
| 119723 | const UA_ByteString *signature) { |
| 119724 | if(message == NULL || signature == NULL || channelContext == NULL) { |
| 119725 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119726 | } |
| 119727 | |
| 119728 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119729 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119730 | UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify( |
| 119731 | msg: message, publicKeyX509: cc->remoteCertificateX509, signature); |
| 119732 | |
| 119733 | return retval; |
| 119734 | } |
| 119735 | |
| 119736 | /* Compares the supplied certificate with the certificate |
| 119737 | * in the endpoint context |
| 119738 | */ |
| 119739 | |
| 119740 | static UA_StatusCode |
| 119741 | UA_compareCertificateThumbprint_Aes128Sha256RsaOaep(const UA_SecurityPolicy *securityPolicy, |
| 119742 | const UA_ByteString *certificateThumbprint) { |
| 119743 | if(securityPolicy == NULL || certificateThumbprint == NULL) { |
| 119744 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 119745 | } |
| 119746 | Policy_Context_Aes128Sha256RsaOaep *pc = |
| 119747 | (Policy_Context_Aes128Sha256RsaOaep *)securityPolicy->policyContext; |
| 119748 | if(!UA_ByteString_equal(p1: certificateThumbprint, p2: &pc->localCertThumbprint)) |
| 119749 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 119750 | return UA_STATUSCODE_GOOD; |
| 119751 | } |
| 119752 | |
| 119753 | /* Generates a thumbprint for the specified certificate */ |
| 119754 | |
| 119755 | static UA_StatusCode |
| 119756 | UA_makeCertificateThumbprint_Aes128Sha256RsaOaep(const UA_SecurityPolicy *securityPolicy, |
| 119757 | const UA_ByteString *certificate, |
| 119758 | UA_ByteString *thumbprint) { |
| 119759 | return UA_Openssl_X509_GetCertificateThumbprint(certficate: certificate, pThumbprint: thumbprint, false); |
| 119760 | } |
| 119761 | |
| 119762 | static UA_StatusCode |
| 119763 | UA_Asym_Aes128Sha256RsaOaep_Decrypt(void *channelContext, UA_ByteString *data) { |
| 119764 | if(channelContext == NULL || data == NULL) |
| 119765 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 119766 | |
| 119767 | Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119768 | UA_StatusCode ret = UA_Openssl_RSA_Oaep_Decrypt(data, privateKey: cc->policyContext->localPrivateKey); |
| 119769 | return ret; |
| 119770 | } |
| 119771 | |
| 119772 | static size_t |
| 119773 | UA_Asym_Aes128Sha256RsaOaep_getRemoteSignatureSize(const void *channelContext) { |
| 119774 | if(channelContext == NULL) |
| 119775 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119776 | |
| 119777 | const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119778 | UA_Int32 keyLen = 0; |
| 119779 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 119780 | return (size_t)keyLen; |
| 119781 | } |
| 119782 | |
| 119783 | static size_t |
| 119784 | UA_AsySig_Aes128Sha256RsaOaep_getLocalSignatureSize(const void *channelContext) { |
| 119785 | if(channelContext == NULL) |
| 119786 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119787 | |
| 119788 | const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119789 | Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext; |
| 119790 | UA_Int32 keyLen = 0; |
| 119791 | UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 119792 | return (size_t)keyLen; |
| 119793 | } |
| 119794 | |
| 119795 | static size_t |
| 119796 | UA_AsymEn_Aes128Sha256RsaOaep_getRemotePlainTextBlockSize(const void *channelContext) { |
| 119797 | if(channelContext == NULL) |
| 119798 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119799 | |
| 119800 | const Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119801 | (const Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119802 | UA_Int32 keyLen = 0; |
| 119803 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 119804 | return (size_t)keyLen - UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN; |
| 119805 | } |
| 119806 | |
| 119807 | static size_t |
| 119808 | UA_AsymEn_Aes128Sha256RsaOaep_getRemoteBlockSize(const void *channelContext) { |
| 119809 | if(channelContext == NULL) |
| 119810 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119811 | |
| 119812 | const Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119813 | (const Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119814 | UA_Int32 keyLen = 0; |
| 119815 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 119816 | return (size_t)keyLen; |
| 119817 | } |
| 119818 | |
| 119819 | static size_t |
| 119820 | UA_AsymEn_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) { |
| 119821 | if(channelContext == NULL) |
| 119822 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119823 | |
| 119824 | const Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119825 | (const Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119826 | UA_Int32 keyLen = 0; |
| 119827 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 119828 | return (size_t)keyLen * 8; |
| 119829 | } |
| 119830 | |
| 119831 | static UA_StatusCode |
| 119832 | UA_Sym_Aes128Sha256RsaOaep_generateNonce(void *policyContext, |
| 119833 | UA_ByteString *out) { |
| 119834 | UA_Int32 rc = RAND_bytes(buf: out->data, num: (int)out->length); |
| 119835 | if(rc != 1) { |
| 119836 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 119837 | } |
| 119838 | return UA_STATUSCODE_GOOD; |
| 119839 | } |
| 119840 | |
| 119841 | static size_t |
| 119842 | UA_SymEn_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) { |
| 119843 | /* 32 bytes 256 bits */ |
| 119844 | return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH; |
| 119845 | } |
| 119846 | |
| 119847 | static size_t |
| 119848 | UA_SymSig_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) { |
| 119849 | /* 32 bytes 256 bits */ |
| 119850 | return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH; |
| 119851 | } |
| 119852 | |
| 119853 | static UA_StatusCode |
| 119854 | UA_Sym_Aes128Sha256RsaOaep_generateKey(void *policyContext, |
| 119855 | const UA_ByteString *secret, |
| 119856 | const UA_ByteString *seed, UA_ByteString *out) { |
| 119857 | return UA_Openssl_Random_Key_PSHA256_Derive(secret, seed, out); |
| 119858 | } |
| 119859 | |
| 119860 | static UA_StatusCode |
| 119861 | UA_ChannelModule_Aes128Sha256RsaOaep_setLocalSymSigningKey(void *channelContext, |
| 119862 | const UA_ByteString *key) { |
| 119863 | if(key == NULL || channelContext == NULL) |
| 119864 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119865 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119866 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119867 | UA_ByteString_clear(p: &cc->localSymSigningKey); |
| 119868 | return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey); |
| 119869 | } |
| 119870 | |
| 119871 | static UA_StatusCode |
| 119872 | UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymEncryptingKey(void *channelContext, |
| 119873 | const UA_ByteString *key) { |
| 119874 | if(key == NULL || channelContext == NULL) |
| 119875 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119876 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119877 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119878 | UA_ByteString_clear(p: &cc->localSymEncryptingKey); |
| 119879 | return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey); |
| 119880 | } |
| 119881 | |
| 119882 | static UA_StatusCode |
| 119883 | UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymIv(void *channelContext, |
| 119884 | const UA_ByteString *iv) { |
| 119885 | if(iv == NULL || channelContext == NULL) |
| 119886 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119887 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119888 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119889 | UA_ByteString_clear(p: &cc->localSymIv); |
| 119890 | return UA_ByteString_copy(src: iv, dst: &cc->localSymIv); |
| 119891 | } |
| 119892 | |
| 119893 | static size_t |
| 119894 | UA_SymEn_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) { |
| 119895 | /* 32 bytes 256 bits */ |
| 119896 | return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_KEY_LENGTH; |
| 119897 | } |
| 119898 | |
| 119899 | static size_t |
| 119900 | UA_SymEn_Aes128Sha256RsaOaep_getBlockSize(const void *channelContext) { |
| 119901 | return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_ENCRYPTION_BLOCK_SIZE; |
| 119902 | } |
| 119903 | |
| 119904 | static size_t |
| 119905 | UA_SymSig_Aes128Sha256RsaOaep_getRemoteKeyLength(const void *channelContext) { |
| 119906 | /* 32 bytes 256 bits */ |
| 119907 | return UA_SECURITYPOLICY_AES128SHA256RSAOAEP_SYM_SIGNING_KEY_LENGTH; |
| 119908 | } |
| 119909 | |
| 119910 | static UA_StatusCode |
| 119911 | UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymSigningKey(void *channelContext, |
| 119912 | const UA_ByteString *key) { |
| 119913 | if(key == NULL || channelContext == NULL) |
| 119914 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119915 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119916 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119917 | UA_ByteString_clear(p: &cc->remoteSymSigningKey); |
| 119918 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey); |
| 119919 | } |
| 119920 | |
| 119921 | static UA_StatusCode |
| 119922 | UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymEncryptingKey(void *channelContext, |
| 119923 | const UA_ByteString *key) { |
| 119924 | if(key == NULL || channelContext == NULL) |
| 119925 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119926 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119927 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119928 | UA_ByteString_clear(p: &cc->remoteSymEncryptingKey); |
| 119929 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey); |
| 119930 | } |
| 119931 | |
| 119932 | static UA_StatusCode |
| 119933 | UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymIv(void *channelContext, |
| 119934 | const UA_ByteString *key) { |
| 119935 | if(key == NULL || channelContext == NULL) |
| 119936 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119937 | Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119938 | UA_ByteString_clear(p: &cc->remoteSymIv); |
| 119939 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv); |
| 119940 | } |
| 119941 | |
| 119942 | static UA_StatusCode |
| 119943 | UA_AsySig_Aes128Sha256RsaOaep_sign(void *channelContext, const UA_ByteString *message, |
| 119944 | UA_ByteString *signature) { |
| 119945 | if(channelContext == NULL || message == NULL || |
| 119946 | signature == NULL) |
| 119947 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119948 | Channel_Context_Aes128Sha256RsaOaep *cc = (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119949 | Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext; |
| 119950 | return UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(message, privateKey: pc->localPrivateKey, outSignature: signature); |
| 119951 | } |
| 119952 | |
| 119953 | static UA_StatusCode |
| 119954 | UA_AsymEn_Aes128Sha256RsaOaep_encrypt(void *channelContext, UA_ByteString *data) { |
| 119955 | if(channelContext == NULL || data == NULL) |
| 119956 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119957 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119958 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119959 | return UA_Openssl_RSA_OAEP_Encrypt( |
| 119960 | data, UA_SECURITYPOLICY_AES128SHA256RSAOAEP_RSAPADDING_LEN, |
| 119961 | publicX509: cc->remoteCertificateX509); |
| 119962 | } |
| 119963 | |
| 119964 | static size_t |
| 119965 | UA_SymSig_Aes128Sha256RsaOaep_getRemoteSignatureSize(const void *channelContext) { |
| 119966 | return UA_SHA256_LENGTH; |
| 119967 | } |
| 119968 | |
| 119969 | static UA_StatusCode |
| 119970 | UA_SymSig_Aes128Sha256RsaOaep_verify(void *channelContext, const UA_ByteString *message, |
| 119971 | const UA_ByteString *signature) { |
| 119972 | if(channelContext == NULL || message == NULL || |
| 119973 | signature == NULL) |
| 119974 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119975 | |
| 119976 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119977 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119978 | return UA_OpenSSL_HMAC_SHA256_Verify(message, key: &cc->remoteSymSigningKey, signature); |
| 119979 | } |
| 119980 | |
| 119981 | static UA_StatusCode |
| 119982 | UA_SymSig_Aes128Sha256RsaOaep_sign(void *channelContext, const UA_ByteString *message, |
| 119983 | UA_ByteString *signature) { |
| 119984 | if(channelContext == NULL || message == NULL || |
| 119985 | signature == NULL) |
| 119986 | return UA_STATUSCODE_BADINTERNALERROR; |
| 119987 | |
| 119988 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 119989 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 119990 | return UA_OpenSSL_HMAC_SHA256_Sign(message, key: &cc->localSymSigningKey, signature); |
| 119991 | } |
| 119992 | |
| 119993 | static size_t |
| 119994 | UA_SymSig_Aes128Sha256RsaOaep_getLocalSignatureSize(const void *channelContext) { |
| 119995 | return UA_SHA256_LENGTH; |
| 119996 | } |
| 119997 | |
| 119998 | static UA_StatusCode |
| 119999 | UA_SymEn_Aes128Sha256RsaOaep_decrypt(void *channelContext, UA_ByteString *data) { |
| 120000 | if(channelContext == NULL || data == NULL) |
| 120001 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120002 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 120003 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 120004 | return UA_OpenSSL_AES_128_CBC_Decrypt(iv: &cc->remoteSymIv, key: &cc->remoteSymEncryptingKey, |
| 120005 | data); |
| 120006 | } |
| 120007 | |
| 120008 | static UA_StatusCode |
| 120009 | UA_SymEn_Aes128Sha256RsaOaep_encrypt(void *channelContext, UA_ByteString *data) { |
| 120010 | if(channelContext == NULL || data == NULL) |
| 120011 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120012 | |
| 120013 | Channel_Context_Aes128Sha256RsaOaep *cc = |
| 120014 | (Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 120015 | return UA_OpenSSL_AES_128_CBC_Encrypt(iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, |
| 120016 | data); |
| 120017 | } |
| 120018 | |
| 120019 | static UA_StatusCode |
| 120020 | UA_ChannelM_Aes128Sha256RsaOaep_compareCertificate(const void *channelContext, |
| 120021 | const UA_ByteString *certificate) { |
| 120022 | if(channelContext == NULL || certificate == NULL) |
| 120023 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120024 | |
| 120025 | const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 120026 | return UA_OpenSSL_X509_compare(cert: certificate, bcert: cc->remoteCertificateX509); |
| 120027 | } |
| 120028 | |
| 120029 | static size_t |
| 120030 | UA_AsymEn_Aes128Sha256RsaOaep_getLocalKeyLength(const void *channelContext) { |
| 120031 | if(channelContext == NULL) |
| 120032 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120033 | |
| 120034 | const Channel_Context_Aes128Sha256RsaOaep *cc = (const Channel_Context_Aes128Sha256RsaOaep *)channelContext; |
| 120035 | Policy_Context_Aes128Sha256RsaOaep *pc = cc->policyContext; |
| 120036 | UA_Int32 keyLen = 0; |
| 120037 | UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 120038 | return (size_t)keyLen * 8; |
| 120039 | } |
| 120040 | |
| 120041 | /* the main entry of Aes128Sha256RsaOaep */ |
| 120042 | |
| 120043 | UA_StatusCode |
| 120044 | UA_SecurityPolicy_Aes128Sha256RsaOaep(UA_SecurityPolicy *policy, |
| 120045 | const UA_ByteString localCertificate, |
| 120046 | const UA_ByteString localPrivateKey, |
| 120047 | const UA_Logger *logger) { |
| 120048 | |
| 120049 | UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule; |
| 120050 | UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule; |
| 120051 | UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule; |
| 120052 | UA_StatusCode retval; |
| 120053 | |
| 120054 | UA_LOG_INFO(logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 120055 | msg: "The Aes128Sha256RsaOaep security policy with openssl is added."); |
| 120056 | |
| 120057 | UA_Openssl_Init(); |
| 120058 | memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy)); |
| 120059 | policy->logger = logger; |
| 120060 | policy->policyUri = |
| 120061 | UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep\0"); |
| 120062 | |
| 120063 | /* set ChannelModule context */ |
| 120064 | |
| 120065 | channelModule->newContext = UA_ChannelModule_Aes128Sha256RsaOaep_New_Context; |
| 120066 | channelModule->deleteContext = UA_ChannelModule_Aes128Sha256RsaOaep_Delete_Context; |
| 120067 | channelModule->setLocalSymSigningKey = |
| 120068 | UA_ChannelModule_Aes128Sha256RsaOaep_setLocalSymSigningKey; |
| 120069 | channelModule->setLocalSymEncryptingKey = |
| 120070 | UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymEncryptingKey; |
| 120071 | channelModule->setLocalSymIv = UA_ChannelM_Aes128Sha256RsaOaep_setLocalSymIv; |
| 120072 | channelModule->setRemoteSymSigningKey = |
| 120073 | UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymSigningKey; |
| 120074 | channelModule->setRemoteSymEncryptingKey = |
| 120075 | UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymEncryptingKey; |
| 120076 | channelModule->setRemoteSymIv = UA_ChannelM_Aes128Sha256RsaOaep_setRemoteSymIv; |
| 120077 | channelModule->compareCertificate = |
| 120078 | UA_ChannelM_Aes128Sha256RsaOaep_compareCertificate; |
| 120079 | |
| 120080 | /* Load and convert to DER if necessary */ |
| 120081 | retval = |
| 120082 | UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate); |
| 120083 | if(retval != UA_STATUSCODE_GOOD) |
| 120084 | return retval; |
| 120085 | |
| 120086 | /* AsymmetricModule - signature algorithm */ |
| 120087 | |
| 120088 | UA_SecurityPolicySignatureAlgorithm *asySigAlgorithm = |
| 120089 | &asymmetricModule->cryptoModule.signatureAlgorithm; |
| 120090 | asySigAlgorithm->uri = |
| 120091 | UA_STRING(chars: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0"); |
| 120092 | asySigAlgorithm->verify = UA_AsySig_Aes128Sha256RsaOaep_Verify; |
| 120093 | asySigAlgorithm->getRemoteSignatureSize = |
| 120094 | UA_Asym_Aes128Sha256RsaOaep_getRemoteSignatureSize; |
| 120095 | asySigAlgorithm->getLocalSignatureSize = |
| 120096 | UA_AsySig_Aes128Sha256RsaOaep_getLocalSignatureSize; |
| 120097 | asySigAlgorithm->sign = UA_AsySig_Aes128Sha256RsaOaep_sign; |
| 120098 | asySigAlgorithm->getLocalKeyLength = NULL; |
| 120099 | asySigAlgorithm->getRemoteKeyLength = NULL; |
| 120100 | |
| 120101 | /* AsymmetricModule encryption algorithm */ |
| 120102 | |
| 120103 | UA_SecurityPolicyEncryptionAlgorithm *asymEncryAlg = |
| 120104 | &asymmetricModule->cryptoModule.encryptionAlgorithm; |
| 120105 | asymEncryAlg->uri = UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#rsa-oaep\0"); |
| 120106 | asymEncryAlg->decrypt = UA_Asym_Aes128Sha256RsaOaep_Decrypt; |
| 120107 | asymEncryAlg->getRemotePlainTextBlockSize = |
| 120108 | UA_AsymEn_Aes128Sha256RsaOaep_getRemotePlainTextBlockSize; |
| 120109 | asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Aes128Sha256RsaOaep_getRemoteBlockSize; |
| 120110 | asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Aes128Sha256RsaOaep_getRemoteKeyLength; |
| 120111 | asymEncryAlg->encrypt = UA_AsymEn_Aes128Sha256RsaOaep_encrypt; |
| 120112 | asymEncryAlg->getLocalKeyLength = UA_AsymEn_Aes128Sha256RsaOaep_getLocalKeyLength; |
| 120113 | |
| 120114 | /* asymmetricModule */ |
| 120115 | |
| 120116 | asymmetricModule->compareCertificateThumbprint = |
| 120117 | UA_compareCertificateThumbprint_Aes128Sha256RsaOaep; |
| 120118 | asymmetricModule->makeCertificateThumbprint = |
| 120119 | UA_makeCertificateThumbprint_Aes128Sha256RsaOaep; |
| 120120 | |
| 120121 | /* SymmetricModule */ |
| 120122 | |
| 120123 | symmetricModule->secureChannelNonceLength = 32; |
| 120124 | symmetricModule->generateNonce = UA_Sym_Aes128Sha256RsaOaep_generateNonce; |
| 120125 | symmetricModule->generateKey = UA_Sym_Aes128Sha256RsaOaep_generateKey; |
| 120126 | |
| 120127 | /* Symmetric encryption Algorithm */ |
| 120128 | |
| 120129 | UA_SecurityPolicyEncryptionAlgorithm *symEncryptionAlgorithm = |
| 120130 | &symmetricModule->cryptoModule.encryptionAlgorithm; |
| 120131 | symEncryptionAlgorithm->uri = |
| 120132 | UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes128-cbc\0"); |
| 120133 | symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Aes128Sha256RsaOaep_getLocalKeyLength; |
| 120134 | symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Aes128Sha256RsaOaep_getRemoteKeyLength; |
| 120135 | symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Aes128Sha256RsaOaep_getBlockSize; |
| 120136 | symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Aes128Sha256RsaOaep_getBlockSize; |
| 120137 | symEncryptionAlgorithm->decrypt = UA_SymEn_Aes128Sha256RsaOaep_decrypt; |
| 120138 | symEncryptionAlgorithm->encrypt = UA_SymEn_Aes128Sha256RsaOaep_encrypt; |
| 120139 | |
| 120140 | /* Symmetric signature Algorithm */ |
| 120141 | |
| 120142 | UA_SecurityPolicySignatureAlgorithm *symSignatureAlgorithm = |
| 120143 | &symmetricModule->cryptoModule.signatureAlgorithm; |
| 120144 | symSignatureAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0"); |
| 120145 | symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Aes128Sha256RsaOaep_getLocalKeyLength; |
| 120146 | symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Aes128Sha256RsaOaep_getRemoteKeyLength; |
| 120147 | symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Aes128Sha256RsaOaep_getRemoteSignatureSize; |
| 120148 | symSignatureAlgorithm->verify = UA_SymSig_Aes128Sha256RsaOaep_verify; |
| 120149 | symSignatureAlgorithm->sign = UA_SymSig_Aes128Sha256RsaOaep_sign; |
| 120150 | symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Aes128Sha256RsaOaep_getLocalSignatureSize; |
| 120151 | |
| 120152 | retval = UA_Policy_Aes128Sha256RsaOaep_New_Context(securityPolicy: policy, localPrivateKey, logger); |
| 120153 | if(retval != UA_STATUSCODE_GOOD) { |
| 120154 | UA_ByteString_clear(p: &policy->localCertificate); |
| 120155 | return retval; |
| 120156 | } |
| 120157 | policy->updateCertificateAndPrivateKey = |
| 120158 | updateCertificateAndPrivateKey_sp_aes128sha256rsaoaep; |
| 120159 | policy->clear = UA_Policy_Aes128Sha256RsaOaep_Clear_Context; |
| 120160 | |
| 120161 | /* Use the same signature algorithm as the asymmetric component for |
| 120162 | certificate signing (see standard) */ |
| 120163 | |
| 120164 | policy->certificateSigningAlgorithm = |
| 120165 | policy->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 120166 | |
| 120167 | return UA_STATUSCODE_GOOD; |
| 120168 | } |
| 120169 | |
| 120170 | #endif |
| 120171 | |
| 120172 | /**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_aes256sha256rsapss.c" ****/ |
| 120173 | |
| 120174 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 120175 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 120176 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 120177 | * |
| 120178 | * Copyright 2022 (c) Fraunhofer IOSB (Author: Noel Graf) |
| 120179 | */ |
| 120180 | |
| 120181 | |
| 120182 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 120183 | |
| 120184 | |
| 120185 | #include <openssl/hmac.h> |
| 120186 | #include <openssl/sha.h> |
| 120187 | #include <openssl/rsa.h> |
| 120188 | #include <openssl/x509.h> |
| 120189 | #include <openssl/rand.h> |
| 120190 | #include <openssl/rsa.h> |
| 120191 | |
| 120192 | #define UA_SHA256_LENGTH 32 /* 256 bit */ |
| 120193 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_RSAPADDING_LEN 66 |
| 120194 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_SIGNING_KEY_LENGTH 32 |
| 120195 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_ENCRYPTION_KEY_LENGTH 32 |
| 120196 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_ENCRYPTION_BLOCK_SIZE 16 |
| 120197 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_PLAIN_TEXT_BLOCK_SIZE 16 |
| 120198 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_MINASYMKEYLENGTH 256 |
| 120199 | #define UA_SECURITYPOLICY_AES256SHA256RSAPSS_MAXASYMKEYLENGTH 512 |
| 120200 | |
| 120201 | typedef struct { |
| 120202 | EVP_PKEY *localPrivateKey; |
| 120203 | UA_ByteString localCertThumbprint; |
| 120204 | const UA_Logger *logger; |
| 120205 | } Policy_Context_Aes256Sha256RsaPss; |
| 120206 | |
| 120207 | typedef struct { |
| 120208 | UA_ByteString localSymSigningKey; |
| 120209 | UA_ByteString localSymEncryptingKey; |
| 120210 | UA_ByteString localSymIv; |
| 120211 | UA_ByteString remoteSymSigningKey; |
| 120212 | UA_ByteString remoteSymEncryptingKey; |
| 120213 | UA_ByteString remoteSymIv; |
| 120214 | |
| 120215 | Policy_Context_Aes256Sha256RsaPss *policyContext; |
| 120216 | UA_ByteString remoteCertificate; |
| 120217 | X509 *remoteCertificateX509; /* X509 */ |
| 120218 | } Channel_Context_Aes256Sha256RsaPss; |
| 120219 | |
| 120220 | /* create the policy context */ |
| 120221 | |
| 120222 | static UA_StatusCode |
| 120223 | UA_Policy_Aes256Sha256RsaPss_New_Context(UA_SecurityPolicy *securityPolicy, |
| 120224 | const UA_ByteString localPrivateKey, |
| 120225 | const UA_Logger *logger) { |
| 120226 | Policy_Context_Aes256Sha256RsaPss *context = |
| 120227 | (Policy_Context_Aes256Sha256RsaPss *)UA_malloc( |
| 120228 | size: sizeof(Policy_Context_Aes256Sha256RsaPss)); |
| 120229 | if(context == NULL) { |
| 120230 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 120231 | } |
| 120232 | |
| 120233 | context->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &localPrivateKey); |
| 120234 | if (!context->localPrivateKey) { |
| 120235 | UA_free(ptr: context); |
| 120236 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 120237 | } |
| 120238 | |
| 120239 | UA_StatusCode retval = UA_Openssl_X509_GetCertificateThumbprint( |
| 120240 | certficate: &securityPolicy->localCertificate, pThumbprint: &context->localCertThumbprint, true); |
| 120241 | if(retval != UA_STATUSCODE_GOOD) { |
| 120242 | EVP_PKEY_free(pkey: context->localPrivateKey); |
| 120243 | UA_free(ptr: context); |
| 120244 | return retval; |
| 120245 | } |
| 120246 | |
| 120247 | context->logger = logger; |
| 120248 | securityPolicy->policyContext = context; |
| 120249 | |
| 120250 | return UA_STATUSCODE_GOOD; |
| 120251 | } |
| 120252 | |
| 120253 | /* clear the policy context */ |
| 120254 | |
| 120255 | static void |
| 120256 | UA_Policy_Aes256Sha256RsaPss_Clear_Context(UA_SecurityPolicy *policy) { |
| 120257 | if(policy == NULL) |
| 120258 | return; |
| 120259 | |
| 120260 | UA_ByteString_clear(p: &policy->localCertificate); |
| 120261 | |
| 120262 | /* delete all allocated members in the context */ |
| 120263 | |
| 120264 | Policy_Context_Aes256Sha256RsaPss *pc = |
| 120265 | (Policy_Context_Aes256Sha256RsaPss *)policy->policyContext; |
| 120266 | if (pc == NULL) { |
| 120267 | return; |
| 120268 | } |
| 120269 | |
| 120270 | EVP_PKEY_free(pkey: pc->localPrivateKey); |
| 120271 | UA_ByteString_clear(p: &pc->localCertThumbprint); |
| 120272 | UA_free(ptr: pc); |
| 120273 | |
| 120274 | return; |
| 120275 | } |
| 120276 | |
| 120277 | static UA_StatusCode |
| 120278 | updateCertificateAndPrivateKey_sp_aes128sha256rsapss(UA_SecurityPolicy *securityPolicy, |
| 120279 | const UA_ByteString newCertificate, |
| 120280 | const UA_ByteString newPrivateKey) { |
| 120281 | if(securityPolicy == NULL) |
| 120282 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120283 | |
| 120284 | if(securityPolicy->policyContext == NULL) |
| 120285 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120286 | |
| 120287 | Policy_Context_Aes256Sha256RsaPss *pc = |
| 120288 | (Policy_Context_Aes256Sha256RsaPss *)securityPolicy->policyContext; |
| 120289 | |
| 120290 | UA_ByteString_clear(p: &securityPolicy->localCertificate); |
| 120291 | |
| 120292 | UA_StatusCode retval = UA_OpenSSL_LoadLocalCertificate( |
| 120293 | certificate: &newCertificate, target: &securityPolicy->localCertificate); |
| 120294 | |
| 120295 | if(retval != UA_STATUSCODE_GOOD) |
| 120296 | return retval; |
| 120297 | |
| 120298 | /* Set the new private key */ |
| 120299 | EVP_PKEY_free(pkey: pc->localPrivateKey); |
| 120300 | |
| 120301 | pc->localPrivateKey = UA_OpenSSL_LoadPrivateKey(privateKey: &newPrivateKey); |
| 120302 | if(!pc->localPrivateKey) { |
| 120303 | retval = UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 120304 | goto error; |
| 120305 | } |
| 120306 | |
| 120307 | UA_ByteString_clear(p: &pc->localCertThumbprint); |
| 120308 | |
| 120309 | retval = UA_Openssl_X509_GetCertificateThumbprint(certficate: &securityPolicy->localCertificate, |
| 120310 | pThumbprint: &pc->localCertThumbprint, true); |
| 120311 | if(retval != UA_STATUSCODE_GOOD) { |
| 120312 | goto error; |
| 120313 | } |
| 120314 | |
| 120315 | return retval; |
| 120316 | |
| 120317 | error: |
| 120318 | UA_LOG_ERROR(logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 120319 | msg: "Could not update certificate and private key"); |
| 120320 | if(securityPolicy->policyContext != NULL) |
| 120321 | UA_Policy_Aes256Sha256RsaPss_Clear_Context(policy: securityPolicy); |
| 120322 | return retval; |
| 120323 | } |
| 120324 | |
| 120325 | /* create the channel context */ |
| 120326 | |
| 120327 | static UA_StatusCode |
| 120328 | UA_ChannelModule_Aes256Sha256RsaPss_New_Context(const UA_SecurityPolicy *securityPolicy, |
| 120329 | const UA_ByteString *remoteCertificate, |
| 120330 | void **channelContext) { |
| 120331 | if(securityPolicy == NULL || remoteCertificate == NULL || channelContext == NULL) { |
| 120332 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120333 | } |
| 120334 | Channel_Context_Aes256Sha256RsaPss *context = |
| 120335 | (Channel_Context_Aes256Sha256RsaPss *)UA_malloc( |
| 120336 | size: sizeof(Channel_Context_Aes256Sha256RsaPss)); |
| 120337 | if(context == NULL) { |
| 120338 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 120339 | } |
| 120340 | |
| 120341 | UA_ByteString_init(p: &context->localSymSigningKey); |
| 120342 | UA_ByteString_init(p: &context->localSymEncryptingKey); |
| 120343 | UA_ByteString_init(p: &context->localSymIv); |
| 120344 | UA_ByteString_init(p: &context->remoteSymSigningKey); |
| 120345 | UA_ByteString_init(p: &context->remoteSymEncryptingKey); |
| 120346 | UA_ByteString_init(p: &context->remoteSymIv); |
| 120347 | |
| 120348 | UA_StatusCode retval = |
| 120349 | UA_copyCertificate(dst: &context->remoteCertificate, src: remoteCertificate); |
| 120350 | if(retval != UA_STATUSCODE_GOOD) { |
| 120351 | UA_free(ptr: context); |
| 120352 | return retval; |
| 120353 | } |
| 120354 | |
| 120355 | /* decode to X509 */ |
| 120356 | context->remoteCertificateX509 = UA_OpenSSL_LoadCertificate(certificate: &context->remoteCertificate); |
| 120357 | if (context->remoteCertificateX509 == NULL) { |
| 120358 | UA_ByteString_clear (p: &context->remoteCertificate); |
| 120359 | UA_free (ptr: context); |
| 120360 | return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; |
| 120361 | } |
| 120362 | |
| 120363 | context->policyContext = |
| 120364 | (Policy_Context_Aes256Sha256RsaPss *)(securityPolicy->policyContext); |
| 120365 | |
| 120366 | *channelContext = context; |
| 120367 | |
| 120368 | UA_LOG_INFO( |
| 120369 | logger: securityPolicy->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 120370 | msg: "The Aes256Sha256RsaPss security policy channel with openssl is created."); |
| 120371 | |
| 120372 | return UA_STATUSCODE_GOOD; |
| 120373 | } |
| 120374 | |
| 120375 | /* delete the channel context */ |
| 120376 | |
| 120377 | static void |
| 120378 | UA_ChannelModule_Aes256Sha256RsaPss_Delete_Context(void *channelContext) { |
| 120379 | if(channelContext != NULL) { |
| 120380 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120381 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120382 | X509_free(a: cc->remoteCertificateX509); |
| 120383 | UA_ByteString_clear(p: &cc->remoteCertificate); |
| 120384 | UA_ByteString_clear(p: &cc->localSymSigningKey); |
| 120385 | UA_ByteString_clear(p: &cc->localSymEncryptingKey); |
| 120386 | UA_ByteString_clear(p: &cc->localSymIv); |
| 120387 | UA_ByteString_clear(p: &cc->remoteSymSigningKey); |
| 120388 | UA_ByteString_clear(p: &cc->remoteSymEncryptingKey); |
| 120389 | UA_ByteString_clear(p: &cc->remoteSymIv); |
| 120390 | |
| 120391 | UA_LOG_INFO( |
| 120392 | logger: cc->policyContext->logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 120393 | msg: "The Aes256Sha256RsaPss security policy channel with openssl is deleted."); |
| 120394 | UA_free(ptr: cc); |
| 120395 | } |
| 120396 | } |
| 120397 | |
| 120398 | /* Verifies the signature of the message using the provided keys in the context. |
| 120399 | * AsymmetricSignatureAlgorithm_RSA-PKCS15-SHA2-256 |
| 120400 | */ |
| 120401 | |
| 120402 | static UA_StatusCode |
| 120403 | UA_AsySig_Aes256Sha256RsaPss_Verify(void *channelContext, const UA_ByteString *message, |
| 120404 | const UA_ByteString *signature) { |
| 120405 | if(message == NULL || signature == NULL || channelContext == NULL) { |
| 120406 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120407 | } |
| 120408 | |
| 120409 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120410 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120411 | UA_StatusCode retval = UA_OpenSSL_RSA_PSS_SHA256_Verify( |
| 120412 | msg: message, publicKeyX509: cc->remoteCertificateX509, signature); |
| 120413 | |
| 120414 | return retval; |
| 120415 | } |
| 120416 | |
| 120417 | /* Compares the supplied certificate with the certificate |
| 120418 | * in the endpoint context |
| 120419 | */ |
| 120420 | |
| 120421 | static UA_StatusCode |
| 120422 | UA_compareCertificateThumbprint_Aes256Sha256RsaPss(const UA_SecurityPolicy *securityPolicy, |
| 120423 | const UA_ByteString *certificateThumbprint) { |
| 120424 | if(securityPolicy == NULL || certificateThumbprint == NULL) { |
| 120425 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 120426 | } |
| 120427 | Policy_Context_Aes256Sha256RsaPss *pc = |
| 120428 | (Policy_Context_Aes256Sha256RsaPss *)securityPolicy->policyContext; |
| 120429 | if(!UA_ByteString_equal(p1: certificateThumbprint, p2: &pc->localCertThumbprint)) |
| 120430 | return UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 120431 | return UA_STATUSCODE_GOOD; |
| 120432 | } |
| 120433 | |
| 120434 | /* Generates a thumbprint for the specified certificate */ |
| 120435 | |
| 120436 | static UA_StatusCode |
| 120437 | UA_makeCertificateThumbprint_Aes256Sha256RsaPss(const UA_SecurityPolicy *securityPolicy, |
| 120438 | const UA_ByteString *certificate, |
| 120439 | UA_ByteString *thumbprint) { |
| 120440 | return UA_Openssl_X509_GetCertificateThumbprint(certficate: certificate, pThumbprint: thumbprint, false); |
| 120441 | } |
| 120442 | |
| 120443 | static UA_StatusCode |
| 120444 | UA_Asym_Aes256Sha256RsaPss_Decrypt(void *channelContext, UA_ByteString *data) { |
| 120445 | if(channelContext == NULL || data == NULL) |
| 120446 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 120447 | |
| 120448 | Channel_Context_Aes256Sha256RsaPss *cc = (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120449 | UA_StatusCode ret = UA_Openssl_RSA_Oaep_Sha2_Decrypt(data, privateKey: cc->policyContext->localPrivateKey); |
| 120450 | return ret; |
| 120451 | } |
| 120452 | |
| 120453 | static size_t |
| 120454 | UA_Asym_Aes256Sha256RsaPss_getRemoteSignatureSize(const void *channelContext) { |
| 120455 | if(channelContext == NULL) |
| 120456 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120457 | |
| 120458 | const Channel_Context_Aes256Sha256RsaPss *cc = (const Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120459 | UA_Int32 keyLen = 0; |
| 120460 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 120461 | return (size_t)keyLen; |
| 120462 | } |
| 120463 | |
| 120464 | static size_t |
| 120465 | UA_AsySig_Aes256Sha256RsaPss_getLocalSignatureSize(const void *channelContext) { |
| 120466 | if(channelContext == NULL) |
| 120467 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120468 | |
| 120469 | const Channel_Context_Aes256Sha256RsaPss *cc = (const Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120470 | Policy_Context_Aes256Sha256RsaPss *pc = cc->policyContext; |
| 120471 | UA_Int32 keyLen = 0; |
| 120472 | UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 120473 | return (size_t)keyLen; |
| 120474 | } |
| 120475 | |
| 120476 | static size_t |
| 120477 | UA_AsymEn_Aes256Sha256RsaPss_getRemotePlainTextBlockSize(const void *channelContext) { |
| 120478 | if(channelContext == NULL) |
| 120479 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120480 | |
| 120481 | const Channel_Context_Aes256Sha256RsaPss *cc = |
| 120482 | (const Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120483 | UA_Int32 keyLen = 0; |
| 120484 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 120485 | return (size_t)keyLen - UA_SECURITYPOLICY_AES256SHA256RSAPSS_RSAPADDING_LEN; |
| 120486 | } |
| 120487 | |
| 120488 | static size_t |
| 120489 | UA_AsymEn_Aes256Sha256RsaPss_getRemoteBlockSize(const void *channelContext) { |
| 120490 | if(channelContext == NULL) |
| 120491 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120492 | |
| 120493 | const Channel_Context_Aes256Sha256RsaPss *cc = |
| 120494 | (const Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120495 | UA_Int32 keyLen = 0; |
| 120496 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 120497 | return (size_t)keyLen; |
| 120498 | } |
| 120499 | |
| 120500 | static size_t |
| 120501 | UA_AsymEn_Aes256Sha256RsaPss_getRemoteKeyLength(const void *channelContext) { |
| 120502 | if(channelContext == NULL) |
| 120503 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120504 | |
| 120505 | const Channel_Context_Aes256Sha256RsaPss *cc = |
| 120506 | (const Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120507 | UA_Int32 keyLen = 0; |
| 120508 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 120509 | return (size_t)keyLen * 8; |
| 120510 | } |
| 120511 | |
| 120512 | static UA_StatusCode |
| 120513 | UA_Sym_Aes256Sha256RsaPss_generateNonce(void *policyContext, |
| 120514 | UA_ByteString *out) { |
| 120515 | UA_Int32 rc = RAND_bytes(buf: out->data, num: (int)out->length); |
| 120516 | if(rc != 1) { |
| 120517 | return UA_STATUSCODE_BADUNEXPECTEDERROR; |
| 120518 | } |
| 120519 | return UA_STATUSCODE_GOOD; |
| 120520 | } |
| 120521 | |
| 120522 | static size_t |
| 120523 | UA_SymEn_Aes256Sha256RsaPss_getLocalKeyLength(const void *channelContext) { |
| 120524 | /* 32 bytes 256 bits */ |
| 120525 | return UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_ENCRYPTION_KEY_LENGTH; |
| 120526 | } |
| 120527 | |
| 120528 | static size_t |
| 120529 | UA_SymSig_Aes256Sha256RsaPss_getLocalKeyLength(const void *channelContext) { |
| 120530 | /* 32 bytes 256 bits */ |
| 120531 | return UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_SIGNING_KEY_LENGTH; |
| 120532 | } |
| 120533 | |
| 120534 | static UA_StatusCode |
| 120535 | UA_Sym_Aes256Sha256RsaPss_generateKey(void *policyContext, |
| 120536 | const UA_ByteString *secret, |
| 120537 | const UA_ByteString *seed, UA_ByteString *out) { |
| 120538 | return UA_Openssl_Random_Key_PSHA256_Derive(secret, seed, out); |
| 120539 | } |
| 120540 | |
| 120541 | static UA_StatusCode |
| 120542 | UA_CertSig_Aes256Sha256RsaPss_Verify(void *channelContext, const UA_ByteString *message, |
| 120543 | const UA_ByteString *signature) { |
| 120544 | if(message == NULL || signature == NULL || channelContext == NULL) { |
| 120545 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120546 | } |
| 120547 | |
| 120548 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120549 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120550 | UA_StatusCode retval = UA_OpenSSL_RSA_PKCS1_V15_SHA256_Verify( |
| 120551 | msg: message, publicKeyX509: cc->remoteCertificateX509, signature); |
| 120552 | |
| 120553 | return retval; |
| 120554 | } |
| 120555 | |
| 120556 | static UA_StatusCode |
| 120557 | UA_CertSig_Aes256Sha256RsaPss_sign(void *channelContext, const UA_ByteString *message, |
| 120558 | UA_ByteString *signature) { |
| 120559 | if(channelContext == NULL || message == NULL || |
| 120560 | signature == NULL) |
| 120561 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120562 | Channel_Context_Aes256Sha256RsaPss *cc = (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120563 | Policy_Context_Aes256Sha256RsaPss *pc = cc->policyContext; |
| 120564 | return UA_Openssl_RSA_PKCS1_V15_SHA256_Sign(message, privateKey: pc->localPrivateKey, outSignature: signature); |
| 120565 | } |
| 120566 | |
| 120567 | static size_t |
| 120568 | UA_CertSig_Aes256Sha256RsaPss_getRemoteSignatureSize(const void *channelContext) { |
| 120569 | if(channelContext == NULL) |
| 120570 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120571 | |
| 120572 | const Channel_Context_Aes256Sha256RsaPss *cc = (const Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120573 | UA_Int32 keyLen = 0; |
| 120574 | UA_Openssl_RSA_Public_GetKeyLength(publicKeyX509: cc->remoteCertificateX509, keyLen: &keyLen); |
| 120575 | return (size_t)keyLen; |
| 120576 | } |
| 120577 | |
| 120578 | static size_t |
| 120579 | UA_CertSig_Aes256Sha256RsaPss_getLocalSignatureSize(const void *channelContext) { |
| 120580 | if(channelContext == NULL) |
| 120581 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120582 | |
| 120583 | const Channel_Context_Aes256Sha256RsaPss *cc = (const Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120584 | Policy_Context_Aes256Sha256RsaPss *pc = cc->policyContext; |
| 120585 | UA_Int32 keyLen = 0; |
| 120586 | UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 120587 | return (size_t)keyLen; |
| 120588 | } |
| 120589 | |
| 120590 | static UA_StatusCode |
| 120591 | UA_ChannelModule_Aes256Sha256RsaPss_setLocalSymSigningKey(void *channelContext, |
| 120592 | const UA_ByteString *key) { |
| 120593 | if(key == NULL || channelContext == NULL) |
| 120594 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120595 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120596 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120597 | UA_ByteString_clear(p: &cc->localSymSigningKey); |
| 120598 | return UA_ByteString_copy(src: key, dst: &cc->localSymSigningKey); |
| 120599 | } |
| 120600 | |
| 120601 | static UA_StatusCode |
| 120602 | UA_ChannelM_Aes256Sha256RsaPss_setLocalSymEncryptingKey(void *channelContext, |
| 120603 | const UA_ByteString *key) { |
| 120604 | if(key == NULL || channelContext == NULL) |
| 120605 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120606 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120607 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120608 | UA_ByteString_clear(p: &cc->localSymEncryptingKey); |
| 120609 | return UA_ByteString_copy(src: key, dst: &cc->localSymEncryptingKey); |
| 120610 | } |
| 120611 | |
| 120612 | static UA_StatusCode |
| 120613 | UA_ChannelM_Aes256Sha256RsaPss_setLocalSymIv(void *channelContext, |
| 120614 | const UA_ByteString *iv) { |
| 120615 | if(iv == NULL || channelContext == NULL) |
| 120616 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120617 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120618 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120619 | UA_ByteString_clear(p: &cc->localSymIv); |
| 120620 | return UA_ByteString_copy(src: iv, dst: &cc->localSymIv); |
| 120621 | } |
| 120622 | |
| 120623 | static size_t |
| 120624 | UA_SymEn_Aes256Sha256RsaPss_getRemoteKeyLength(const void *channelContext) { |
| 120625 | /* 32 bytes 256 bits */ |
| 120626 | return UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_ENCRYPTION_KEY_LENGTH; |
| 120627 | } |
| 120628 | |
| 120629 | static size_t |
| 120630 | UA_SymEn_Aes256Sha256RsaPss_getBlockSize(const void *channelContext) { |
| 120631 | return UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_ENCRYPTION_BLOCK_SIZE; |
| 120632 | } |
| 120633 | |
| 120634 | static size_t |
| 120635 | UA_SymSig_Aes256Sha256RsaPss_getRemoteKeyLength(const void *channelContext) { |
| 120636 | /* 32 bytes 256 bits */ |
| 120637 | return UA_SECURITYPOLICY_AES256SHA256RSAPSS_SYM_SIGNING_KEY_LENGTH; |
| 120638 | } |
| 120639 | |
| 120640 | static UA_StatusCode |
| 120641 | UA_ChannelM_Aes256Sha256RsaPss_setRemoteSymSigningKey(void *channelContext, |
| 120642 | const UA_ByteString *key) { |
| 120643 | if(key == NULL || channelContext == NULL) |
| 120644 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120645 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120646 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120647 | UA_ByteString_clear(p: &cc->remoteSymSigningKey); |
| 120648 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymSigningKey); |
| 120649 | } |
| 120650 | |
| 120651 | static UA_StatusCode |
| 120652 | UA_ChannelM_Aes256Sha256RsaPss_setRemoteSymEncryptingKey(void *channelContext, |
| 120653 | const UA_ByteString *key) { |
| 120654 | if(key == NULL || channelContext == NULL) |
| 120655 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120656 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120657 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120658 | UA_ByteString_clear(p: &cc->remoteSymEncryptingKey); |
| 120659 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymEncryptingKey); |
| 120660 | } |
| 120661 | |
| 120662 | static UA_StatusCode |
| 120663 | UA_ChannelM_Aes256Sha256RsaPss_setRemoteSymIv(void *channelContext, |
| 120664 | const UA_ByteString *key) { |
| 120665 | if(key == NULL || channelContext == NULL) |
| 120666 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120667 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120668 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120669 | UA_ByteString_clear(p: &cc->remoteSymIv); |
| 120670 | return UA_ByteString_copy(src: key, dst: &cc->remoteSymIv); |
| 120671 | } |
| 120672 | |
| 120673 | static UA_StatusCode |
| 120674 | UA_AsySig_Aes256Sha256RsaPss_sign(void *channelContext, const UA_ByteString *message, |
| 120675 | UA_ByteString *signature) { |
| 120676 | if(channelContext == NULL || message == NULL || |
| 120677 | signature == NULL) |
| 120678 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120679 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120680 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120681 | Policy_Context_Aes256Sha256RsaPss *pc = cc->policyContext; |
| 120682 | return UA_Openssl_RSA_PSS_SHA256_Sign(message, privateKey: pc->localPrivateKey, outSignature: signature); |
| 120683 | } |
| 120684 | |
| 120685 | static UA_StatusCode |
| 120686 | UA_AsymEn_Aes256Sha256RsaPss_encrypt(void *channelContext, UA_ByteString *data) { |
| 120687 | if(channelContext == NULL || data == NULL) |
| 120688 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120689 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120690 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120691 | return UA_Openssl_RSA_OAEP_SHA2_Encrypt( |
| 120692 | data, UA_SECURITYPOLICY_AES256SHA256RSAPSS_RSAPADDING_LEN, |
| 120693 | publicX509: cc->remoteCertificateX509); |
| 120694 | } |
| 120695 | |
| 120696 | static size_t |
| 120697 | UA_SymSig_Aes256Sha256RsaPss_getRemoteSignatureSize(const void *channelContext) { |
| 120698 | return UA_SHA256_LENGTH; |
| 120699 | } |
| 120700 | |
| 120701 | static UA_StatusCode |
| 120702 | UA_SymSig_Aes256Sha256RsaPss_verify(void *channelContext, const UA_ByteString *message, |
| 120703 | const UA_ByteString *signature) { |
| 120704 | if(channelContext == NULL || message == NULL || |
| 120705 | signature == NULL) |
| 120706 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120707 | |
| 120708 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120709 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120710 | return UA_OpenSSL_HMAC_SHA256_Verify(message, key: &cc->remoteSymSigningKey, signature); |
| 120711 | } |
| 120712 | |
| 120713 | static UA_StatusCode |
| 120714 | UA_SymSig_Aes256Sha256RsaPss_sign(void *channelContext, const UA_ByteString *message, |
| 120715 | UA_ByteString *signature) { |
| 120716 | if(channelContext == NULL || message == NULL || |
| 120717 | signature == NULL) |
| 120718 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120719 | |
| 120720 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120721 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120722 | return UA_OpenSSL_HMAC_SHA256_Sign(message, key: &cc->localSymSigningKey, signature); |
| 120723 | } |
| 120724 | |
| 120725 | static size_t |
| 120726 | UA_SymSig_Aes256Sha256RsaPss_getLocalSignatureSize(const void *channelContext) { |
| 120727 | return UA_SHA256_LENGTH; |
| 120728 | } |
| 120729 | |
| 120730 | static UA_StatusCode |
| 120731 | UA_SymEn_Aes256Sha256RsaPss_decrypt(void *channelContext, UA_ByteString *data) { |
| 120732 | if(channelContext == NULL || data == NULL) |
| 120733 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120734 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120735 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120736 | return UA_OpenSSL_AES_256_CBC_Decrypt(iv: &cc->remoteSymIv, key: &cc->remoteSymEncryptingKey, |
| 120737 | data); |
| 120738 | } |
| 120739 | |
| 120740 | static UA_StatusCode |
| 120741 | UA_SymEn_Aes256Sha256RsaPss_encrypt(void *channelContext, UA_ByteString *data) { |
| 120742 | if(channelContext == NULL || data == NULL) |
| 120743 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120744 | |
| 120745 | Channel_Context_Aes256Sha256RsaPss *cc = |
| 120746 | (Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120747 | return UA_OpenSSL_AES_256_CBC_Encrypt(iv: &cc->localSymIv, key: &cc->localSymEncryptingKey, |
| 120748 | data); |
| 120749 | } |
| 120750 | |
| 120751 | static UA_StatusCode |
| 120752 | UA_ChannelM_Aes256Sha256RsaPss_compareCertificate(const void *channelContext, |
| 120753 | const UA_ByteString *certificate) { |
| 120754 | if(channelContext == NULL || certificate == NULL) |
| 120755 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120756 | |
| 120757 | const Channel_Context_Aes256Sha256RsaPss *cc = |
| 120758 | (const Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120759 | return UA_OpenSSL_X509_compare(cert: certificate, bcert: cc->remoteCertificateX509); |
| 120760 | } |
| 120761 | |
| 120762 | static size_t |
| 120763 | UA_AsymEn_Aes256Sha256RsaPss_getLocalKeyLength(const void *channelContext) { |
| 120764 | if(channelContext == NULL) |
| 120765 | return UA_STATUSCODE_BADINTERNALERROR; |
| 120766 | |
| 120767 | const Channel_Context_Aes256Sha256RsaPss *cc = |
| 120768 | (const Channel_Context_Aes256Sha256RsaPss *)channelContext; |
| 120769 | Policy_Context_Aes256Sha256RsaPss *pc = cc->policyContext; |
| 120770 | UA_Int32 keyLen = 0; |
| 120771 | UA_Openssl_RSA_Private_GetKeyLength(privateKey: pc->localPrivateKey, keyLen: &keyLen); |
| 120772 | return (size_t)keyLen * 8; |
| 120773 | } |
| 120774 | |
| 120775 | /* the main entry of Aes256Sha256RsaPss */ |
| 120776 | |
| 120777 | UA_StatusCode |
| 120778 | UA_SecurityPolicy_Aes256Sha256RsaPss(UA_SecurityPolicy *policy, |
| 120779 | const UA_ByteString localCertificate, |
| 120780 | const UA_ByteString localPrivateKey, |
| 120781 | const UA_Logger *logger) { |
| 120782 | |
| 120783 | UA_SecurityPolicyAsymmetricModule *const asymmetricModule = &policy->asymmetricModule; |
| 120784 | UA_SecurityPolicySymmetricModule *const symmetricModule = &policy->symmetricModule; |
| 120785 | UA_SecurityPolicyChannelModule *const channelModule = &policy->channelModule; |
| 120786 | UA_StatusCode retval; |
| 120787 | |
| 120788 | UA_LOG_INFO(logger, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 120789 | msg: "The Aes256Sha256RsaPss security policy with openssl is added."); |
| 120790 | |
| 120791 | UA_Openssl_Init(); |
| 120792 | memset(s: policy, c: 0, n: sizeof(UA_SecurityPolicy)); |
| 120793 | policy->logger = logger; |
| 120794 | policy->policyUri = |
| 120795 | UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss\0"); |
| 120796 | |
| 120797 | /* set ChannelModule context */ |
| 120798 | |
| 120799 | channelModule->newContext = UA_ChannelModule_Aes256Sha256RsaPss_New_Context; |
| 120800 | channelModule->deleteContext = UA_ChannelModule_Aes256Sha256RsaPss_Delete_Context; |
| 120801 | channelModule->setLocalSymSigningKey = |
| 120802 | UA_ChannelModule_Aes256Sha256RsaPss_setLocalSymSigningKey; |
| 120803 | channelModule->setLocalSymEncryptingKey = |
| 120804 | UA_ChannelM_Aes256Sha256RsaPss_setLocalSymEncryptingKey; |
| 120805 | channelModule->setLocalSymIv = UA_ChannelM_Aes256Sha256RsaPss_setLocalSymIv; |
| 120806 | channelModule->setRemoteSymSigningKey = |
| 120807 | UA_ChannelM_Aes256Sha256RsaPss_setRemoteSymSigningKey; |
| 120808 | channelModule->setRemoteSymEncryptingKey = |
| 120809 | UA_ChannelM_Aes256Sha256RsaPss_setRemoteSymEncryptingKey; |
| 120810 | channelModule->setRemoteSymIv = UA_ChannelM_Aes256Sha256RsaPss_setRemoteSymIv; |
| 120811 | channelModule->compareCertificate = |
| 120812 | UA_ChannelM_Aes256Sha256RsaPss_compareCertificate; |
| 120813 | |
| 120814 | /* Load and convert to DER if necessary */ |
| 120815 | retval = |
| 120816 | UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate); |
| 120817 | if(retval != UA_STATUSCODE_GOOD) |
| 120818 | return retval; |
| 120819 | |
| 120820 | /* AsymmetricModule - signature algorithm */ |
| 120821 | |
| 120822 | UA_SecurityPolicySignatureAlgorithm *asySigAlgorithm = |
| 120823 | &asymmetricModule->cryptoModule.signatureAlgorithm; |
| 120824 | asySigAlgorithm->uri = |
| 120825 | UA_STRING(chars: "http://opcfoundation.org/UA/security/rsa-pss-sha2-256\0"); |
| 120826 | asySigAlgorithm->verify = UA_AsySig_Aes256Sha256RsaPss_Verify; |
| 120827 | asySigAlgorithm->getRemoteSignatureSize = |
| 120828 | UA_Asym_Aes256Sha256RsaPss_getRemoteSignatureSize; |
| 120829 | asySigAlgorithm->getLocalSignatureSize = |
| 120830 | UA_AsySig_Aes256Sha256RsaPss_getLocalSignatureSize; |
| 120831 | asySigAlgorithm->sign = UA_AsySig_Aes256Sha256RsaPss_sign; |
| 120832 | asySigAlgorithm->getLocalKeyLength = NULL; |
| 120833 | asySigAlgorithm->getRemoteKeyLength = NULL; |
| 120834 | |
| 120835 | /* AsymmetricModule encryption algorithm */ |
| 120836 | |
| 120837 | UA_SecurityPolicyEncryptionAlgorithm *asymEncryAlg = |
| 120838 | &asymmetricModule->cryptoModule.encryptionAlgorithm; |
| 120839 | asymEncryAlg->uri = UA_STRING(chars: "http://opcfoundation.org/UA/security/rsa-oaep-sha2-256\0"); |
| 120840 | asymEncryAlg->decrypt = UA_Asym_Aes256Sha256RsaPss_Decrypt; |
| 120841 | asymEncryAlg->getRemotePlainTextBlockSize = |
| 120842 | UA_AsymEn_Aes256Sha256RsaPss_getRemotePlainTextBlockSize; |
| 120843 | asymEncryAlg->getRemoteBlockSize = UA_AsymEn_Aes256Sha256RsaPss_getRemoteBlockSize; |
| 120844 | asymEncryAlg->getRemoteKeyLength = UA_AsymEn_Aes256Sha256RsaPss_getRemoteKeyLength; |
| 120845 | asymEncryAlg->encrypt = UA_AsymEn_Aes256Sha256RsaPss_encrypt; |
| 120846 | asymEncryAlg->getLocalKeyLength = UA_AsymEn_Aes256Sha256RsaPss_getLocalKeyLength; |
| 120847 | |
| 120848 | /* asymmetricModule */ |
| 120849 | |
| 120850 | asymmetricModule->compareCertificateThumbprint = |
| 120851 | UA_compareCertificateThumbprint_Aes256Sha256RsaPss; |
| 120852 | asymmetricModule->makeCertificateThumbprint = |
| 120853 | UA_makeCertificateThumbprint_Aes256Sha256RsaPss; |
| 120854 | |
| 120855 | /* SymmetricModule */ |
| 120856 | |
| 120857 | symmetricModule->secureChannelNonceLength = 32; |
| 120858 | symmetricModule->generateNonce = UA_Sym_Aes256Sha256RsaPss_generateNonce; |
| 120859 | symmetricModule->generateKey = UA_Sym_Aes256Sha256RsaPss_generateKey; |
| 120860 | |
| 120861 | /* Symmetric encryption Algorithm */ |
| 120862 | |
| 120863 | UA_SecurityPolicyEncryptionAlgorithm *symEncryptionAlgorithm = |
| 120864 | &symmetricModule->cryptoModule.encryptionAlgorithm; |
| 120865 | symEncryptionAlgorithm->uri = |
| 120866 | UA_STRING(chars: "http://www.w3.org/2001/04/xmlenc#aes256-cbc\0"); |
| 120867 | symEncryptionAlgorithm->getLocalKeyLength = UA_SymEn_Aes256Sha256RsaPss_getLocalKeyLength; |
| 120868 | symEncryptionAlgorithm->getRemoteKeyLength = UA_SymEn_Aes256Sha256RsaPss_getRemoteKeyLength; |
| 120869 | symEncryptionAlgorithm->getRemoteBlockSize = UA_SymEn_Aes256Sha256RsaPss_getBlockSize; |
| 120870 | symEncryptionAlgorithm->getRemotePlainTextBlockSize = UA_SymEn_Aes256Sha256RsaPss_getBlockSize; |
| 120871 | symEncryptionAlgorithm->decrypt = UA_SymEn_Aes256Sha256RsaPss_decrypt; |
| 120872 | symEncryptionAlgorithm->encrypt = UA_SymEn_Aes256Sha256RsaPss_encrypt; |
| 120873 | |
| 120874 | /* Symmetric signature Algorithm */ |
| 120875 | |
| 120876 | UA_SecurityPolicySignatureAlgorithm *symSignatureAlgorithm = |
| 120877 | &symmetricModule->cryptoModule.signatureAlgorithm; |
| 120878 | symSignatureAlgorithm->uri = UA_STRING(chars: "http://www.w3.org/2000/09/xmldsig#hmac-sha2-256\0"); |
| 120879 | symSignatureAlgorithm->getLocalKeyLength = UA_SymSig_Aes256Sha256RsaPss_getLocalKeyLength; |
| 120880 | symSignatureAlgorithm->getRemoteKeyLength = UA_SymSig_Aes256Sha256RsaPss_getRemoteKeyLength; |
| 120881 | symSignatureAlgorithm->getRemoteSignatureSize = UA_SymSig_Aes256Sha256RsaPss_getRemoteSignatureSize; |
| 120882 | symSignatureAlgorithm->verify = UA_SymSig_Aes256Sha256RsaPss_verify; |
| 120883 | symSignatureAlgorithm->sign = UA_SymSig_Aes256Sha256RsaPss_sign; |
| 120884 | symSignatureAlgorithm->getLocalSignatureSize = UA_SymSig_Aes256Sha256RsaPss_getLocalSignatureSize; |
| 120885 | |
| 120886 | retval = UA_Policy_Aes256Sha256RsaPss_New_Context(securityPolicy: policy, localPrivateKey, logger); |
| 120887 | if(retval != UA_STATUSCODE_GOOD) { |
| 120888 | UA_ByteString_clear(p: &policy->localCertificate); |
| 120889 | return retval; |
| 120890 | } |
| 120891 | policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_sp_aes128sha256rsapss; |
| 120892 | policy->clear = UA_Policy_Aes256Sha256RsaPss_Clear_Context; |
| 120893 | |
| 120894 | /* Certificate Signing Algorithm */ |
| 120895 | policy->certificateSigningAlgorithm.uri = |
| 120896 | UA_STRING(chars: "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\0"); |
| 120897 | policy->certificateSigningAlgorithm.verify = |
| 120898 | (UA_StatusCode (*)(void *, const UA_ByteString *, const UA_ByteString *))UA_CertSig_Aes256Sha256RsaPss_Verify; |
| 120899 | policy->certificateSigningAlgorithm.sign = |
| 120900 | (UA_StatusCode (*)(void *, const UA_ByteString *, UA_ByteString *))UA_CertSig_Aes256Sha256RsaPss_sign; |
| 120901 | policy->certificateSigningAlgorithm.getLocalSignatureSize = |
| 120902 | (size_t (*)(const void *))UA_CertSig_Aes256Sha256RsaPss_getLocalSignatureSize; |
| 120903 | policy->certificateSigningAlgorithm.getRemoteSignatureSize = |
| 120904 | (size_t (*)(const void *))UA_CertSig_Aes256Sha256RsaPss_getRemoteSignatureSize; |
| 120905 | policy->certificateSigningAlgorithm.getLocalKeyLength = NULL; // TODO: Write function |
| 120906 | policy->certificateSigningAlgorithm.getRemoteKeyLength = NULL; // TODO: Write function |
| 120907 | |
| 120908 | return UA_STATUSCODE_GOOD; |
| 120909 | } |
| 120910 | |
| 120911 | #endif |
| 120912 | |
| 120913 | /**** amalgamated original file "/plugins/crypto/openssl/ua_openssl_create_certificate.c" ****/ |
| 120914 | |
| 120915 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 120916 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 120917 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 120918 | * |
| 120919 | * Copyright 2021 (c) Christian von Arnim, ISW University of Stuttgart (for VDW and umati) |
| 120920 | * Copyright 2022 (c) Wind River Systems, Inc. |
| 120921 | * |
| 120922 | */ |
| 120923 | |
| 120924 | |
| 120925 | |
| 120926 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 120927 | |
| 120928 | |
| 120929 | #include <openssl/pem.h> |
| 120930 | #include <openssl/x509v3.h> |
| 120931 | #include <openssl/err.h> |
| 120932 | |
| 120933 | /** |
| 120934 | * Join an array of UA_String to a single NULL-Terminated UA_String |
| 120935 | * separated by character sep |
| 120936 | */ |
| 120937 | static UA_StatusCode |
| 120938 | join_string_with_sep(const UA_String *strings, size_t stringsSize, |
| 120939 | char sep, UA_String *out) { |
| 120940 | if(!out) |
| 120941 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 120942 | |
| 120943 | UA_String_clear(p: out); |
| 120944 | size_t totalSize = stringsSize; |
| 120945 | for(size_t iStr = 0; iStr < stringsSize; ++iStr) { |
| 120946 | totalSize += strings[iStr].length; |
| 120947 | } |
| 120948 | |
| 120949 | UA_ByteString_allocBuffer(bs: out, length: totalSize); |
| 120950 | if(!out->data) { |
| 120951 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 120952 | } |
| 120953 | |
| 120954 | size_t pos = 0; |
| 120955 | for(size_t iStr = 0; iStr < stringsSize; ++iStr) { |
| 120956 | memcpy(dest: &out->data[pos], src: strings[iStr].data, n: strings[iStr].length); |
| 120957 | pos += strings[iStr].length; |
| 120958 | out->data[pos] = (UA_Byte) sep; |
| 120959 | ++pos; |
| 120960 | } |
| 120961 | out->data[out->length-1] = 0; |
| 120962 | |
| 120963 | return UA_STATUSCODE_GOOD; |
| 120964 | } |
| 120965 | |
| 120966 | /** |
| 120967 | * Search for a character in a string (like strchr). |
| 120968 | * \todo Handle UTF-8 |
| 120969 | * |
| 120970 | * \return index of the character or -1 on case of an error. |
| 120971 | */ |
| 120972 | |
| 120973 | static UA_Int32 |
| 120974 | UA_String_chr(const UA_String *pUaStr, char needl) { |
| 120975 | UA_Byte byteNeedl = (UA_Byte)needl; |
| 120976 | for(size_t i = 0; (size_t)i < pUaStr->length; ++i) { |
| 120977 | if(pUaStr->data[i] == byteNeedl) { |
| 120978 | return (UA_Int32) i; |
| 120979 | } |
| 120980 | } |
| 120981 | return -1; |
| 120982 | } |
| 120983 | |
| 120984 | /* char *value cannot be const due to openssl 1.0 compatibility */ |
| 120985 | static UA_StatusCode |
| 120986 | add_x509V3ext(const UA_Logger *logger, X509 *x509, int nid, char *value) { |
| 120987 | X509_EXTENSION *ex; |
| 120988 | X509V3_CTX ctx; |
| 120989 | X509V3_set_ctx_nodb(&ctx); |
| 120990 | X509V3_set_ctx(ctx: &ctx, issuer: x509, subject: x509, NULL, NULL, flags: 0); |
| 120991 | ex = X509V3_EXT_conf_nid(NULL, ctx: &ctx, ext_nid: nid, value); |
| 120992 | if(!ex) |
| 120993 | { |
| 120994 | #if UA_LOGLEVEL <= 300 |
| 120995 | const char * file = NULL; |
| 120996 | int line = 0; |
| 120997 | const char * data = NULL; |
| 120998 | int flags = 0; |
| 120999 | get_error_line_data(&file, &line, &data, &flags); |
| 121000 | UA_LOG_INFO(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121001 | msg: "Internal SSL error file: %s:%d data: %s", file, line, data); |
| 121002 | #endif |
| 121003 | return UA_STATUSCODE_BADINTERNALERROR; |
| 121004 | } |
| 121005 | X509_add_ext(x: x509, ex, loc: -1); |
| 121006 | X509_EXTENSION_free(a: ex); |
| 121007 | return UA_STATUSCODE_GOOD; |
| 121008 | } |
| 121009 | |
| 121010 | #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) |
| 121011 | |
| 121012 | /* generate the RSA key */ |
| 121013 | |
| 121014 | static EVP_PKEY * UA_RSA_Generate_Key (size_t keySizeBits){ |
| 121015 | return EVP_RSA_gen(keySizeBits); |
| 121016 | } |
| 121017 | |
| 121018 | #endif |
| 121019 | |
| 121020 | UA_StatusCode |
| 121021 | UA_CreateCertificate(const UA_Logger *logger, const UA_String *subject, |
| 121022 | size_t subjectSize, const UA_String *subjectAltName, |
| 121023 | size_t subjectAltNameSize, UA_CertificateFormat certFormat, |
| 121024 | UA_KeyValueMap *params, UA_ByteString *outPrivateKey, |
| 121025 | UA_ByteString *outCertificate) { |
| 121026 | if(!outPrivateKey || !outCertificate || !logger || !subjectAltName || !subject || |
| 121027 | subjectAltNameSize == 0 || subjectSize == 0 || |
| 121028 | (certFormat != UA_CERTIFICATEFORMAT_DER && certFormat != UA_CERTIFICATEFORMAT_PEM)) |
| 121029 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 121030 | |
| 121031 | /* Use the maximum size */ |
| 121032 | UA_UInt16 keySizeBits = 4096; |
| 121033 | /* Default to 1 year */ |
| 121034 | UA_UInt16 expiresInDays = 365; |
| 121035 | |
| 121036 | if(params) { |
| 121037 | const UA_UInt16 *keySizeBitsValue = (const UA_UInt16 *)UA_KeyValueMap_getScalar( |
| 121038 | map: params, key: UA_QUALIFIEDNAME(nsIndex: 0, chars: "key-size-bits"), type: &UA_TYPES[UA_TYPES_UINT16]); |
| 121039 | if(keySizeBitsValue) |
| 121040 | keySizeBits = *keySizeBitsValue; |
| 121041 | |
| 121042 | const UA_UInt16 *expiresInDaysValue = (const UA_UInt16 *)UA_KeyValueMap_getScalar( |
| 121043 | map: params, key: UA_QUALIFIEDNAME(nsIndex: 0, chars: "expires-in-days"), type: &UA_TYPES[UA_TYPES_UINT16]); |
| 121044 | if(expiresInDaysValue) |
| 121045 | expiresInDays = *expiresInDaysValue; |
| 121046 | } |
| 121047 | |
| 121048 | UA_ByteString_init(p: outPrivateKey); |
| 121049 | UA_ByteString_init(p: outCertificate); |
| 121050 | |
| 121051 | UA_String fullAltSubj = UA_STRING_NULL; |
| 121052 | UA_Int32 serial = 1; |
| 121053 | |
| 121054 | /** \TODO: Seed Random generator |
| 121055 | * See: (https://www.openssl.org/docs/man1.1.0/man3/RAND_add.html) */ |
| 121056 | BIO *memCert = NULL; |
| 121057 | BIO *memPKey = NULL; |
| 121058 | |
| 121059 | UA_StatusCode errRet = UA_STATUSCODE_GOOD; |
| 121060 | |
| 121061 | X509 *x509 = X509_new(); |
| 121062 | |
| 121063 | #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) |
| 121064 | EVP_PKEY *pkey = UA_RSA_Generate_Key(keySizeBits); |
| 121065 | if((pkey == NULL) || (x509 == NULL)) { |
| 121066 | errRet = UA_STATUSCODE_BADOUTOFMEMORY; |
| 121067 | goto cleanup; |
| 121068 | } |
| 121069 | #else |
| 121070 | BIGNUM *exponent = BN_new(); |
| 121071 | EVP_PKEY *pkey = EVP_PKEY_new(); |
| 121072 | RSA *rsa = RSA_new(); |
| 121073 | if(!pkey || !x509 || !exponent || !rsa) { |
| 121074 | errRet = UA_STATUSCODE_BADOUTOFMEMORY; |
| 121075 | goto cleanup; |
| 121076 | } |
| 121077 | |
| 121078 | UA_LOG_INFO(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 121079 | "Create Certificate: Generating RSA key. This may take a while."); |
| 121080 | |
| 121081 | if(BN_set_word(exponent, RSA_F4) != 1) { |
| 121082 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 121083 | "Create Certificate: Setting RSA exponent failed."); |
| 121084 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121085 | goto cleanup; |
| 121086 | } |
| 121087 | |
| 121088 | if(RSA_generate_key_ex(rsa, (int) keySizeBits, exponent, NULL) != 1) { |
| 121089 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 121090 | "Create Certificate: Generating RSA key failed."); |
| 121091 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121092 | goto cleanup; |
| 121093 | } |
| 121094 | |
| 121095 | if(EVP_PKEY_assign_RSA(pkey, rsa) != 1) { |
| 121096 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SECURECHANNEL, |
| 121097 | "Create Certificate: Assign RSA key failed."); |
| 121098 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121099 | goto cleanup; |
| 121100 | } |
| 121101 | /* rsa will be freed by pkey */ |
| 121102 | rsa = NULL; |
| 121103 | |
| 121104 | #endif /* end of OPENSSL_VERSION_NUMBER >= 0x30000000L */ |
| 121105 | |
| 121106 | /* x509v3 has version 2 |
| 121107 | * (https://www.openssl.org/docs/man1.1.0/man3/X509_set_version.html) */ |
| 121108 | if(X509_set_version(x: x509, version: 2) != 1) { |
| 121109 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121110 | msg: "Create Certificate: Setting version failed."); |
| 121111 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121112 | goto cleanup; |
| 121113 | } |
| 121114 | |
| 121115 | if(ASN1_INTEGER_set(a: X509_get_serialNumber(x: x509), v: serial) != 1) { |
| 121116 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121117 | msg: "Create Certificate: Setting serial number failed."); |
| 121118 | /* Only memory errors are possible */ |
| 121119 | errRet = UA_STATUSCODE_BADOUTOFMEMORY; |
| 121120 | goto cleanup; |
| 121121 | } |
| 121122 | |
| 121123 | if(X509_gmtime_adj(X509_get_notBefore(x: x509), adj: 0) == NULL) { |
| 121124 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121125 | msg: "Create Certificate: Setting 'not before' failed."); |
| 121126 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121127 | goto cleanup; |
| 121128 | } |
| 121129 | |
| 121130 | if(X509_gmtime_adj(X509_get_notAfter(x: x509), adj: (UA_Int64)60 * 60 * 24 * expiresInDays) == |
| 121131 | NULL) { |
| 121132 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121133 | msg: "Create Certificate: Setting 'not before' failed."); |
| 121134 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121135 | goto cleanup; |
| 121136 | } |
| 121137 | |
| 121138 | if(X509_set_pubkey(x: x509, pkey) != 1) { |
| 121139 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121140 | msg: "Create Certificate: Setting publik key failed."); |
| 121141 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121142 | goto cleanup; |
| 121143 | } |
| 121144 | |
| 121145 | X509_NAME *name = X509_get_subject_name(a: x509); |
| 121146 | if(name == NULL) { |
| 121147 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121148 | msg: "Create Certificate: Getting name failed."); |
| 121149 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121150 | goto cleanup; |
| 121151 | } |
| 121152 | |
| 121153 | for(UA_UInt32 iSubject = 0; iSubject < subjectSize; ++iSubject) { |
| 121154 | UA_Int32 sep = UA_String_chr(pUaStr: &subject[iSubject], needl: '='); |
| 121155 | char field[16]; |
| 121156 | if(sep == -1 || sep == 0 || |
| 121157 | ((size_t) sep == (subject[iSubject].length - 1)) || sep >= 15) { |
| 121158 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121159 | msg: "Create Certificate: Subject must contain one '=' with " |
| 121160 | "content before and after."); |
| 121161 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121162 | goto cleanup; |
| 121163 | } |
| 121164 | memcpy(dest: field, src: subject[iSubject].data, n: (size_t) sep); |
| 121165 | field[sep] = 0; |
| 121166 | UA_Byte* pData = &subject[iSubject].data[sep + 1]; |
| 121167 | if(X509_NAME_add_entry_by_txt( |
| 121168 | name, field, MBSTRING_ASC, |
| 121169 | bytes: (const unsigned char *)pData, |
| 121170 | len: (int) subject[iSubject].length - (int) sep - 1, loc: -1, set: 0) != 1) { |
| 121171 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121172 | msg: "Create Certificate: Setting subject failed."); |
| 121173 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121174 | goto cleanup; |
| 121175 | } |
| 121176 | } |
| 121177 | /* Self signed, so issuer == subject */ |
| 121178 | if(X509_set_issuer_name(x: x509, name) != 1) { |
| 121179 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121180 | msg: "Create Certificate: Setting name failed."); |
| 121181 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121182 | goto cleanup; |
| 121183 | } |
| 121184 | |
| 121185 | errRet = add_x509V3ext(logger, x509, NID_basic_constraints, value: "CA:FALSE"); |
| 121186 | if(errRet != UA_STATUSCODE_GOOD) { |
| 121187 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121188 | msg: "Create Certificate: Setting 'Basic Constraints' failed."); |
| 121189 | goto cleanup; |
| 121190 | } |
| 121191 | |
| 121192 | /* See https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.3 for |
| 121193 | * possible values */ |
| 121194 | errRet = add_x509V3ext(logger, x509, NID_key_usage, |
| 121195 | value: "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyCertSign"); |
| 121196 | if(errRet != UA_STATUSCODE_GOOD) { |
| 121197 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121198 | msg: "Create Certificate: Setting 'Key Usage' failed."); |
| 121199 | goto cleanup; |
| 121200 | } |
| 121201 | |
| 121202 | errRet = add_x509V3ext(logger, x509, NID_ext_key_usage, value: "serverAuth,clientAuth"); |
| 121203 | if(errRet != UA_STATUSCODE_GOOD) { |
| 121204 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121205 | msg: "Create Certificate: Setting 'Extended Key Usage' failed."); |
| 121206 | goto cleanup; |
| 121207 | } |
| 121208 | |
| 121209 | errRet = add_x509V3ext(logger, x509, NID_subject_key_identifier, value: "hash"); |
| 121210 | if(errRet != UA_STATUSCODE_GOOD) { |
| 121211 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121212 | msg: "Create Certificate: Setting 'Subject Key Identifier' failed."); |
| 121213 | goto cleanup; |
| 121214 | } |
| 121215 | |
| 121216 | errRet = join_string_with_sep(strings: subjectAltName, stringsSize: subjectAltNameSize, sep: ',', out: &fullAltSubj); |
| 121217 | if(errRet != UA_STATUSCODE_GOOD) { |
| 121218 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121219 | msg: "Create Certificate: Joining altSubject failed."); |
| 121220 | goto cleanup; |
| 121221 | } |
| 121222 | |
| 121223 | errRet = add_x509V3ext(logger, x509, NID_subject_alt_name, value: (char*) fullAltSubj.data); |
| 121224 | if(errRet != UA_STATUSCODE_GOOD) { |
| 121225 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121226 | msg: "Create Certificate: Setting 'Subject Alternative Name' failed."); |
| 121227 | goto cleanup; |
| 121228 | } |
| 121229 | |
| 121230 | if(X509_sign(x: x509, pkey, md: EVP_sha256()) == 0) { |
| 121231 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121232 | msg: "Create Certificate: Signing failed."); |
| 121233 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121234 | goto cleanup; |
| 121235 | } |
| 121236 | |
| 121237 | switch(certFormat) { |
| 121238 | case UA_CERTIFICATEFORMAT_DER: { |
| 121239 | unsigned char *p; |
| 121240 | /* Private Key */ |
| 121241 | /* get length */ |
| 121242 | outPrivateKey->length = (size_t)i2d_PrivateKey(a: pkey, NULL); |
| 121243 | if((int)outPrivateKey->length <= 0) { |
| 121244 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121245 | msg: "Create Certificate: Create private DER key failed."); |
| 121246 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121247 | goto cleanup; |
| 121248 | } |
| 121249 | /* allocate buffer */ |
| 121250 | UA_ByteString_allocBuffer(bs: outPrivateKey, length: outPrivateKey->length); |
| 121251 | memset(s: outPrivateKey->data, c: 0, n: outPrivateKey->length); |
| 121252 | p = outPrivateKey->data; |
| 121253 | i2d_PrivateKey(a: pkey, pp: &p); |
| 121254 | |
| 121255 | /* Certificate */ |
| 121256 | /* get length */ |
| 121257 | outCertificate->length = (size_t)i2d_X509(a: x509, NULL); |
| 121258 | if((int)outCertificate->length <= 0) { |
| 121259 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121260 | msg: "Create Certificate: Create DER-certificate failed."); |
| 121261 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121262 | goto cleanup; |
| 121263 | } |
| 121264 | /* allocate buffer */ |
| 121265 | UA_ByteString_allocBuffer(bs: outCertificate, length: outCertificate->length); |
| 121266 | memset(s: outCertificate->data, c: 0, n: outCertificate->length); |
| 121267 | p = outCertificate->data; |
| 121268 | i2d_X509(a: x509, out: &p); |
| 121269 | break; |
| 121270 | } |
| 121271 | case UA_CERTIFICATEFORMAT_PEM: { |
| 121272 | /* Private Key */ |
| 121273 | memPKey = BIO_new(type: BIO_s_mem()); |
| 121274 | if(!memPKey) { |
| 121275 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121276 | msg: "Create Certificate: Allocate Membuffer for PKey failed."); |
| 121277 | errRet = UA_STATUSCODE_BADOUTOFMEMORY; |
| 121278 | goto cleanup; |
| 121279 | } |
| 121280 | |
| 121281 | if(PEM_write_bio_PrivateKey(out: memPKey, x: pkey, NULL, NULL, klen: 0, cb: 0, NULL) != 1) { |
| 121282 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121283 | msg: "Create Certificate: Generate PEM-PrivateKey failed."); |
| 121284 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121285 | goto cleanup; |
| 121286 | } |
| 121287 | |
| 121288 | UA_ByteString tmpPem = UA_BYTESTRING_NULL; |
| 121289 | tmpPem.length = (size_t) BIO_get_mem_data(memPKey, &tmpPem.data); |
| 121290 | errRet = UA_ByteString_copy(src: &tmpPem, dst: outPrivateKey); |
| 121291 | if(errRet != UA_STATUSCODE_GOOD) { |
| 121292 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121293 | msg: "Create Certificate: Copy PEM PKey failed."); |
| 121294 | goto cleanup; |
| 121295 | } |
| 121296 | |
| 121297 | /* Certificate */ |
| 121298 | memCert = BIO_new(type: BIO_s_mem()); |
| 121299 | if(!memCert) { |
| 121300 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121301 | msg: "Create Certificate: Allocate Membuffer for Cert failed."); |
| 121302 | errRet = UA_STATUSCODE_BADOUTOFMEMORY; |
| 121303 | goto cleanup; |
| 121304 | } |
| 121305 | |
| 121306 | if(PEM_write_bio_X509(out: memCert, x: x509) != 1) { |
| 121307 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121308 | msg: "Create Certificate: Generate PEM-Certifcate failed."); |
| 121309 | errRet = UA_STATUSCODE_BADINTERNALERROR; |
| 121310 | goto cleanup; |
| 121311 | } |
| 121312 | |
| 121313 | tmpPem.length = (size_t) BIO_get_mem_data(memCert, &tmpPem.data); |
| 121314 | errRet = UA_ByteString_copy(src: &tmpPem, dst: outCertificate); |
| 121315 | if(errRet != UA_STATUSCODE_GOOD) { |
| 121316 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SECURECHANNEL, |
| 121317 | msg: "Create Certificate: Copy PEM Certificate failed."); |
| 121318 | goto cleanup; |
| 121319 | } |
| 121320 | break; |
| 121321 | } |
| 121322 | } |
| 121323 | |
| 121324 | cleanup: |
| 121325 | UA_String_clear(p: &fullAltSubj); |
| 121326 | #if (OPENSSL_VERSION_NUMBER < 0x30000000L) |
| 121327 | RSA_free(rsa); |
| 121328 | BN_free(exponent); |
| 121329 | #endif |
| 121330 | X509_free(a: x509); |
| 121331 | EVP_PKEY_free(pkey); |
| 121332 | BIO_free(a: memCert); |
| 121333 | BIO_free(a: memPKey); |
| 121334 | return errRet; |
| 121335 | } |
| 121336 | |
| 121337 | #endif |
| 121338 | |
| 121339 | /**** amalgamated original file "/plugins/crypto/openssl/ua_pki_openssl.c" ****/ |
| 121340 | |
| 121341 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 121342 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 121343 | * |
| 121344 | * Copyright 2020 (c) Wind River Systems, Inc. |
| 121345 | * Copyright 2020 (c) basysKom GmbH |
| 121346 | |
| 121347 | */ |
| 121348 | |
| 121349 | |
| 121350 | |
| 121351 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 121352 | #include <openssl/x509.h> |
| 121353 | #include <openssl/x509_vfy.h> |
| 121354 | #include <openssl/x509v3.h> |
| 121355 | #include <openssl/pem.h> |
| 121356 | |
| 121357 | |
| 121358 | #include <limits.h> |
| 121359 | |
| 121360 | /* Find binary substring. Taken and adjusted from |
| 121361 | * http://tungchingkai.blogspot.com/2011/07/binary-strstr.html */ |
| 121362 | |
| 121363 | static const unsigned char * |
| 121364 | bstrchr(const unsigned char *s, const unsigned char ch, size_t l) { |
| 121365 | /* find first occurrence of c in char s[] for length l*/ |
| 121366 | for(; l > 0; ++s, --l) { |
| 121367 | if(*s == ch) |
| 121368 | return s; |
| 121369 | } |
| 121370 | return NULL; |
| 121371 | } |
| 121372 | |
| 121373 | static const unsigned char * |
| 121374 | UA_Bstrstr(const unsigned char *s1, size_t l1, const unsigned char *s2, size_t l2) { |
| 121375 | /* find first occurrence of s2[] in s1[] for length l1*/ |
| 121376 | const unsigned char *ss1 = s1; |
| 121377 | const unsigned char *ss2 = s2; |
| 121378 | /* handle special case */ |
| 121379 | if(l1 == 0) |
| 121380 | return (NULL); |
| 121381 | if(l2 == 0) |
| 121382 | return s1; |
| 121383 | |
| 121384 | /* match prefix */ |
| 121385 | for (; (s1 = bstrchr(s: s1, ch: *s2, l: (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1)) != NULL && |
| 121386 | (uintptr_t)ss1-(uintptr_t)s1+(uintptr_t)l1 != 0; ++s1) { |
| 121387 | |
| 121388 | /* match rest of prefix */ |
| 121389 | const unsigned char *sc1, *sc2; |
| 121390 | for (sc1 = s1, sc2 = s2; ;) |
| 121391 | if (++sc2 >= ss2+l2) |
| 121392 | return s1; |
| 121393 | else if (*++sc1 != *sc2) |
| 121394 | break; |
| 121395 | } |
| 121396 | return NULL; |
| 121397 | } |
| 121398 | |
| 121399 | typedef struct { |
| 121400 | /* |
| 121401 | * If the folders are defined, we use them to reload the certificates during |
| 121402 | * runtime |
| 121403 | */ |
| 121404 | |
| 121405 | UA_String trustListFolder; |
| 121406 | UA_String issuerListFolder; |
| 121407 | UA_String revocationListFolder; |
| 121408 | /* Used with mbedTLS and UA_ENABLE_CERT_REJECTED_DIR option */ |
| 121409 | UA_String rejectedListFolder; |
| 121410 | |
| 121411 | STACK_OF(X509) * skIssue; |
| 121412 | STACK_OF(X509) * skTrusted; |
| 121413 | STACK_OF(X509_CRL) * skCrls; /* Revocation list*/ |
| 121414 | |
| 121415 | UA_CertificateVerification *cv; |
| 121416 | } CertContext; |
| 121417 | |
| 121418 | static UA_StatusCode |
| 121419 | UA_CertContext_sk_Init (CertContext * context) { |
| 121420 | context->skTrusted = sk_X509_new_null(); |
| 121421 | context->skIssue = sk_X509_new_null(); |
| 121422 | context->skCrls = sk_X509_CRL_new_null(); |
| 121423 | if (context->skTrusted == NULL || context->skIssue == NULL || |
| 121424 | context->skCrls == NULL) { |
| 121425 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 121426 | } |
| 121427 | return UA_STATUSCODE_GOOD; |
| 121428 | } |
| 121429 | |
| 121430 | static void |
| 121431 | UA_CertContext_sk_free (CertContext * context) { |
| 121432 | sk_X509_pop_free (context->skTrusted, X509_free); |
| 121433 | sk_X509_pop_free (context->skIssue, X509_free); |
| 121434 | sk_X509_CRL_pop_free (context->skCrls, X509_CRL_free); |
| 121435 | } |
| 121436 | |
| 121437 | static UA_StatusCode |
| 121438 | UA_CertContext_Init (CertContext * context, UA_CertificateVerification *cv) { |
| 121439 | (void) memset (s: context, c: 0, n: sizeof (CertContext)); |
| 121440 | UA_ByteString_init (p: &context->trustListFolder); |
| 121441 | UA_ByteString_init (p: &context->issuerListFolder); |
| 121442 | UA_ByteString_init (p: &context->revocationListFolder); |
| 121443 | UA_ByteString_init (p: &context->rejectedListFolder); |
| 121444 | |
| 121445 | context->cv = cv; |
| 121446 | |
| 121447 | return UA_CertContext_sk_Init (context); |
| 121448 | } |
| 121449 | |
| 121450 | static void |
| 121451 | UA_CertificateVerification_clear (UA_CertificateVerification * cv) { |
| 121452 | if (cv == NULL) { |
| 121453 | return; |
| 121454 | } |
| 121455 | CertContext * context = (CertContext *) cv->context; |
| 121456 | if (context == NULL) { |
| 121457 | return; |
| 121458 | } |
| 121459 | UA_ByteString_clear (p: &context->trustListFolder); |
| 121460 | UA_ByteString_clear (p: &context->issuerListFolder); |
| 121461 | UA_ByteString_clear (p: &context->revocationListFolder); |
| 121462 | UA_ByteString_clear (p: &context->rejectedListFolder); |
| 121463 | |
| 121464 | UA_CertContext_sk_free (context); |
| 121465 | context->cv = NULL; |
| 121466 | UA_free (ptr: context); |
| 121467 | |
| 121468 | memset(s: cv, c: 0, n: sizeof(UA_CertificateVerification)); |
| 121469 | } |
| 121470 | |
| 121471 | static UA_StatusCode |
| 121472 | UA_skTrusted_Cert2X509 (const UA_ByteString * certificateTrustList, |
| 121473 | size_t certificateTrustListSize, |
| 121474 | CertContext * ctx) { |
| 121475 | size_t i; |
| 121476 | |
| 121477 | for (i = 0; i < certificateTrustListSize; i++) { |
| 121478 | X509 * x509 = UA_OpenSSL_LoadCertificate(certificate: &certificateTrustList[i]); |
| 121479 | |
| 121480 | if (x509 == NULL) { |
| 121481 | return UA_STATUSCODE_BADINTERNALERROR; |
| 121482 | } |
| 121483 | sk_X509_push (ctx->skTrusted, x509); |
| 121484 | } |
| 121485 | |
| 121486 | return UA_STATUSCODE_GOOD; |
| 121487 | } |
| 121488 | |
| 121489 | static UA_StatusCode |
| 121490 | UA_skIssuer_Cert2X509 (const UA_ByteString * certificateIssuerList, |
| 121491 | size_t certificateIssuerListSize, |
| 121492 | CertContext * ctx) { |
| 121493 | size_t i; |
| 121494 | |
| 121495 | for (i = 0; i < certificateIssuerListSize; i++) { |
| 121496 | X509 * x509 = UA_OpenSSL_LoadCertificate(certificate: &certificateIssuerList[i]); |
| 121497 | |
| 121498 | if (x509 == NULL) { |
| 121499 | return UA_STATUSCODE_BADINTERNALERROR; |
| 121500 | } |
| 121501 | sk_X509_push (ctx->skIssue, x509); |
| 121502 | } |
| 121503 | |
| 121504 | return UA_STATUSCODE_GOOD; |
| 121505 | } |
| 121506 | |
| 121507 | static UA_StatusCode |
| 121508 | UA_skCrls_Cert2X509 (const UA_ByteString * certificateRevocationList, |
| 121509 | size_t certificateRevocationListSize, |
| 121510 | CertContext * ctx) { |
| 121511 | size_t i; |
| 121512 | const unsigned char * pData; |
| 121513 | |
| 121514 | for (i = 0; i < certificateRevocationListSize; i++) { |
| 121515 | pData = certificateRevocationList[i].data; |
| 121516 | X509_CRL * crl = NULL; |
| 121517 | |
| 121518 | if (certificateRevocationList[i].length > 1 && pData[0] == 0x30 && pData[1] == 0x82) { // Magic number for DER encoded files |
| 121519 | crl = d2i_X509_CRL (NULL, in: &pData, len: (long) certificateRevocationList[i].length); |
| 121520 | } else { |
| 121521 | BIO* bio = NULL; |
| 121522 | bio = BIO_new_mem_buf(buf: (void *) certificateRevocationList[i].data, |
| 121523 | len: (int) certificateRevocationList[i].length); |
| 121524 | crl = PEM_read_bio_X509_CRL(out: bio, NULL, NULL, NULL); |
| 121525 | BIO_free(a: bio); |
| 121526 | } |
| 121527 | |
| 121528 | if (crl == NULL) { |
| 121529 | return UA_STATUSCODE_BADINTERNALERROR; |
| 121530 | } |
| 121531 | sk_X509_CRL_push (ctx->skCrls, crl); |
| 121532 | } |
| 121533 | |
| 121534 | return UA_STATUSCODE_GOOD; |
| 121535 | } |
| 121536 | |
| 121537 | #ifdef __linux__ |
| 121538 | #include <dirent.h> |
| 121539 | |
| 121540 | static int UA_Certificate_Filter_der_pem (const struct dirent * entry) { |
| 121541 | /* ignore hidden files */ |
| 121542 | if (entry->d_name[0] == '.') return 0; |
| 121543 | |
| 121544 | /* check file extension */ |
| 121545 | const char *pszFind = strrchr(s: entry->d_name, c: '.'); |
| 121546 | if (pszFind == 0) |
| 121547 | return 0; |
| 121548 | pszFind++; |
| 121549 | if (strcmp (s1: pszFind, s2: "der") == 0 || strcmp (s1: pszFind, s2: "pem") == 0) |
| 121550 | return 1; |
| 121551 | |
| 121552 | return 0; |
| 121553 | } |
| 121554 | |
| 121555 | static int UA_Certificate_Filter_crl (const struct dirent * entry) { |
| 121556 | |
| 121557 | /* ignore hidden files */ |
| 121558 | if (entry->d_name[0] == '.') return 0; |
| 121559 | |
| 121560 | /* check file extension */ |
| 121561 | const char *pszFind = strrchr(s: entry->d_name, c: '.'); |
| 121562 | if (pszFind == 0) |
| 121563 | return 0; |
| 121564 | pszFind++; |
| 121565 | if (strcmp (s1: pszFind, s2: "crl") == 0) |
| 121566 | return 1; |
| 121567 | |
| 121568 | return 0; |
| 121569 | } |
| 121570 | |
| 121571 | static UA_StatusCode |
| 121572 | UA_BuildFullPath (const char * path, |
| 121573 | const char * fileName, |
| 121574 | size_t fullPathBufferLength, |
| 121575 | char * fullPath) { |
| 121576 | size_t pathLen = strlen (s: path); |
| 121577 | size_t fileNameLen = strlen (s: fileName); |
| 121578 | if ((pathLen + fileNameLen + 2) > fullPathBufferLength) { |
| 121579 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 121580 | } |
| 121581 | strcpy (dest: fullPath, src: path); |
| 121582 | strcat (dest: fullPath, src: "/"); |
| 121583 | strcat (dest: fullPath, src: fileName); |
| 121584 | |
| 121585 | return UA_STATUSCODE_GOOD; |
| 121586 | } |
| 121587 | |
| 121588 | static UA_StatusCode |
| 121589 | UA_loadCertFromFile (const char * fileName, |
| 121590 | UA_ByteString * cert) { |
| 121591 | |
| 121592 | FILE * fp = fopen(filename: fileName, modes: "rb"); |
| 121593 | |
| 121594 | if (fp == NULL) |
| 121595 | return UA_STATUSCODE_BADINTERNALERROR; |
| 121596 | |
| 121597 | fseek(stream: fp, off: 0, SEEK_END); |
| 121598 | cert->length = (size_t) ftell(stream: fp); |
| 121599 | if (UA_ByteString_allocBuffer (bs: cert, length: cert->length) != UA_STATUSCODE_GOOD) { |
| 121600 | fclose (stream: fp); |
| 121601 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 121602 | } |
| 121603 | fseek(stream: fp, off: 0, SEEK_SET); |
| 121604 | size_t readLen = fread (ptr: cert->data, size: 1, n: cert->length, stream: fp); |
| 121605 | if (readLen != cert->length) { |
| 121606 | UA_ByteString_clear (p: cert); |
| 121607 | cert->length = 0; |
| 121608 | fclose (stream: fp); |
| 121609 | return UA_STATUSCODE_BADINTERNALERROR; |
| 121610 | } |
| 121611 | fclose (stream: fp); |
| 121612 | |
| 121613 | return UA_STATUSCODE_GOOD; |
| 121614 | } |
| 121615 | |
| 121616 | static UA_StatusCode |
| 121617 | UA_ReloadCertFromFolder (CertContext * ctx) { |
| 121618 | UA_StatusCode ret; |
| 121619 | struct dirent ** dirlist = NULL; |
| 121620 | int i; |
| 121621 | int numCertificates; |
| 121622 | char certFile[PATH_MAX]; |
| 121623 | UA_ByteString strCert; |
| 121624 | char folderPath[PATH_MAX]; |
| 121625 | |
| 121626 | UA_ByteString_init (p: &strCert); |
| 121627 | |
| 121628 | if (ctx->trustListFolder.length > 0) { |
| 121629 | UA_LOG_INFO(logger: ctx->cv->logging, category: UA_LOGCATEGORY_SERVER, msg: "Reloading the trust-list"); |
| 121630 | |
| 121631 | sk_X509_pop_free (ctx->skTrusted, X509_free); |
| 121632 | ctx->skTrusted = sk_X509_new_null(); |
| 121633 | if (ctx->skTrusted == NULL) { |
| 121634 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 121635 | } |
| 121636 | |
| 121637 | (void) memcpy (dest: folderPath, src: ctx->trustListFolder.data, |
| 121638 | n: ctx->trustListFolder.length); |
| 121639 | folderPath[ctx->trustListFolder.length] = 0; |
| 121640 | numCertificates = scandir(dir: folderPath, namelist: &dirlist, |
| 121641 | selector: UA_Certificate_Filter_der_pem, |
| 121642 | cmp: alphasort); |
| 121643 | for (i = 0; i < numCertificates; i++) { |
| 121644 | if (UA_BuildFullPath (path: folderPath, fileName: dirlist[i]->d_name, |
| 121645 | PATH_MAX, fullPath: certFile) != UA_STATUSCODE_GOOD) { |
| 121646 | continue; |
| 121647 | } |
| 121648 | ret = UA_loadCertFromFile (fileName: certFile, cert: &strCert); |
| 121649 | if (ret != UA_STATUSCODE_GOOD) { |
| 121650 | UA_LOG_INFO(logger: ctx->cv->logging, category: UA_LOGCATEGORY_SERVER, |
| 121651 | msg: "Failed to load the certificate file %s", certFile); |
| 121652 | continue; /* continue or return ? */ |
| 121653 | } |
| 121654 | if (UA_skTrusted_Cert2X509 (certificateTrustList: &strCert, certificateTrustListSize: 1, ctx) != UA_STATUSCODE_GOOD) { |
| 121655 | UA_LOG_INFO (logger: ctx->cv->logging, category: UA_LOGCATEGORY_SERVER, |
| 121656 | msg: "Failed to decode the certificate file %s", certFile); |
| 121657 | UA_ByteString_clear (p: &strCert); |
| 121658 | continue; /* continue or return ? */ |
| 121659 | } |
| 121660 | UA_ByteString_clear (p: &strCert); |
| 121661 | } |
| 121662 | for (i = 0; i < numCertificates; i++) { |
| 121663 | free(ptr: dirlist[i]); |
| 121664 | } |
| 121665 | free(ptr: dirlist); |
| 121666 | } |
| 121667 | |
| 121668 | if (ctx->issuerListFolder.length > 0) { |
| 121669 | UA_LOG_INFO(logger: ctx->cv->logging, category: UA_LOGCATEGORY_SERVER, msg: "Reloading the issuer-list"); |
| 121670 | |
| 121671 | sk_X509_pop_free (ctx->skIssue, X509_free); |
| 121672 | ctx->skIssue = sk_X509_new_null(); |
| 121673 | if (ctx->skIssue == NULL) { |
| 121674 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 121675 | } |
| 121676 | |
| 121677 | memcpy (dest: folderPath, src: ctx->issuerListFolder.data, n: ctx->issuerListFolder.length); |
| 121678 | folderPath[ctx->issuerListFolder.length] = 0; |
| 121679 | numCertificates = scandir(dir: folderPath, namelist: &dirlist, |
| 121680 | selector: UA_Certificate_Filter_der_pem, |
| 121681 | cmp: alphasort); |
| 121682 | for (i = 0; i < numCertificates; i++) { |
| 121683 | if (UA_BuildFullPath (path: folderPath, fileName: dirlist[i]->d_name, |
| 121684 | PATH_MAX, fullPath: certFile) != UA_STATUSCODE_GOOD) { |
| 121685 | continue; |
| 121686 | } |
| 121687 | ret = UA_loadCertFromFile (fileName: certFile, cert: &strCert); |
| 121688 | if (ret != UA_STATUSCODE_GOOD) { |
| 121689 | UA_LOG_INFO (logger: ctx->cv->logging, category: UA_LOGCATEGORY_SERVER, |
| 121690 | msg: "Failed to load the certificate file %s", certFile); |
| 121691 | continue; /* continue or return ? */ |
| 121692 | } |
| 121693 | if (UA_skIssuer_Cert2X509 (certificateIssuerList: &strCert, certificateIssuerListSize: 1, ctx) != UA_STATUSCODE_GOOD) { |
| 121694 | UA_LOG_INFO (logger: ctx->cv->logging, category: UA_LOGCATEGORY_SERVER, |
| 121695 | msg: "Failed to decode the certificate file %s", certFile); |
| 121696 | UA_ByteString_clear (p: &strCert); |
| 121697 | continue; /* continue or return ? */ |
| 121698 | } |
| 121699 | UA_ByteString_clear (p: &strCert); |
| 121700 | } |
| 121701 | for (i = 0; i < numCertificates; i++) { |
| 121702 | free(ptr: dirlist[i]); |
| 121703 | } |
| 121704 | free(ptr: dirlist); |
| 121705 | } |
| 121706 | |
| 121707 | if (ctx->revocationListFolder.length > 0) { |
| 121708 | UA_LOG_INFO(logger: ctx->cv->logging, category: UA_LOGCATEGORY_SERVER, msg: "Reloading the revocation-list"); |
| 121709 | |
| 121710 | sk_X509_CRL_pop_free (ctx->skCrls, X509_CRL_free); |
| 121711 | ctx->skCrls = sk_X509_CRL_new_null(); |
| 121712 | if (ctx->skCrls == NULL) { |
| 121713 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 121714 | } |
| 121715 | |
| 121716 | memcpy (dest: folderPath, src: ctx->revocationListFolder.data, n: ctx->revocationListFolder.length); |
| 121717 | folderPath[ctx->revocationListFolder.length] = 0; |
| 121718 | numCertificates = scandir(dir: folderPath, namelist: &dirlist, |
| 121719 | selector: UA_Certificate_Filter_crl, |
| 121720 | cmp: alphasort); |
| 121721 | for (i = 0; i < numCertificates; i++) { |
| 121722 | if (UA_BuildFullPath (path: folderPath, fileName: dirlist[i]->d_name, |
| 121723 | PATH_MAX, fullPath: certFile) != UA_STATUSCODE_GOOD) { |
| 121724 | continue; |
| 121725 | } |
| 121726 | ret = UA_loadCertFromFile (fileName: certFile, cert: &strCert); |
| 121727 | if (ret != UA_STATUSCODE_GOOD) { |
| 121728 | UA_LOG_INFO (logger: ctx->cv->logging, category: UA_LOGCATEGORY_SERVER, |
| 121729 | msg: "Failed to load the revocation file %s", certFile); |
| 121730 | continue; /* continue or return ? */ |
| 121731 | } |
| 121732 | if (UA_skCrls_Cert2X509 (certificateRevocationList: &strCert, certificateRevocationListSize: 1, ctx) != UA_STATUSCODE_GOOD) { |
| 121733 | UA_LOG_INFO (logger: ctx->cv->logging, category: UA_LOGCATEGORY_SERVER, |
| 121734 | msg: "Failed to decode the revocation file %s", certFile); |
| 121735 | UA_ByteString_clear (p: &strCert); |
| 121736 | continue; /* continue or return ? */ |
| 121737 | } |
| 121738 | UA_ByteString_clear (p: &strCert); |
| 121739 | } |
| 121740 | for (i = 0; i < numCertificates; i++) { |
| 121741 | free(ptr: dirlist[i]); |
| 121742 | } |
| 121743 | free(ptr: dirlist); |
| 121744 | } |
| 121745 | |
| 121746 | ret = UA_STATUSCODE_GOOD; |
| 121747 | return ret; |
| 121748 | } |
| 121749 | |
| 121750 | #endif /* end of __linux__ */ |
| 121751 | |
| 121752 | static const unsigned char openssl_PEM_PRE[28] = "-----BEGIN CERTIFICATE-----"; |
| 121753 | |
| 121754 | /* Extract the leaf certificate from a bytestring that may contain an entire chain */ |
| 121755 | static X509 * |
| 121756 | openSSLLoadLeafCertificate(UA_ByteString cert, size_t *offset) { |
| 121757 | if(cert.length <= *offset) |
| 121758 | return NULL; |
| 121759 | cert.length -= *offset; |
| 121760 | cert.data += *offset; |
| 121761 | |
| 121762 | /* Detect DER encoding. Extract the encoding length and cut. */ |
| 121763 | if(cert.length >= 4 && cert.data[0] == 0x30 && cert.data[1] == 0x82) { |
| 121764 | /* The certificate length is encoded after the magic bytes */ |
| 121765 | size_t certLen = 4; /* Magic numbers + length bytes */ |
| 121766 | certLen += (size_t)(((uint16_t)cert.data[2]) << 8); |
| 121767 | certLen += cert.data[3]; |
| 121768 | if(certLen > cert.length) |
| 121769 | return NULL; |
| 121770 | cert.length = certLen; |
| 121771 | *offset += certLen; |
| 121772 | const UA_Byte *dataPtr = cert.data; |
| 121773 | return d2i_X509(NULL, in: &dataPtr, len: (long)cert.length); |
| 121774 | } |
| 121775 | |
| 121776 | /* Assume PEM encoding. Detect multiple certificates and cut. */ |
| 121777 | if(cert.length > 27 * 4) { |
| 121778 | const unsigned char *match = |
| 121779 | UA_Bstrstr(s1: openssl_PEM_PRE, l1: 27, s2: &cert.data[27*2], l2: cert.length - (27*2)); |
| 121780 | if(match) |
| 121781 | cert.length = (uintptr_t)(match - cert.data); |
| 121782 | } |
| 121783 | *offset += cert.length; |
| 121784 | |
| 121785 | BIO *bio = BIO_new_mem_buf(buf: (void *) cert.data, len: (int)cert.length); |
| 121786 | X509 *result = PEM_read_bio_X509(out: bio, NULL, NULL, NULL); |
| 121787 | BIO_free(a: bio); |
| 121788 | return result; |
| 121789 | } |
| 121790 | |
| 121791 | /* The bytestring might contain an entire certificate chain. The first |
| 121792 | * stack-element is the leaf certificate itself. The remaining ones are |
| 121793 | * potential issuer certificates. */ |
| 121794 | static STACK_OF(X509) * |
| 121795 | openSSLLoadCertificateStack(const UA_ByteString cert) { |
| 121796 | size_t offset = 0; |
| 121797 | X509 *x509 = NULL; |
| 121798 | STACK_OF(X509) *result = sk_X509_new_null(); |
| 121799 | if(!result) |
| 121800 | return NULL; |
| 121801 | while((x509 = openSSLLoadLeafCertificate(cert, offset: &offset))) { |
| 121802 | sk_X509_push(result, x509); |
| 121803 | } |
| 121804 | return result; |
| 121805 | } |
| 121806 | |
| 121807 | /* Return the first matching issuer candidate AFTER prev */ |
| 121808 | static X509 * |
| 121809 | openSSLFindNextIssuer(CertContext *ctx, STACK_OF(X509) *stack, X509 *x509, X509 *prev) { |
| 121810 | /* First check issuers from the stack - provided in the same bytestring as |
| 121811 | * the certificate. This can also return x509 itself. */ |
| 121812 | X509_NAME *in = X509_get_issuer_name(a: x509); |
| 121813 | do { |
| 121814 | int size = sk_X509_num(stack); |
| 121815 | for(int i = 0; i < size; i++) { |
| 121816 | X509 *candidate = sk_X509_value(stack, i); |
| 121817 | if(prev) { |
| 121818 | if(prev == candidate) |
| 121819 | prev = NULL; /* This was the last issuer we tried to verify */ |
| 121820 | continue; |
| 121821 | } |
| 121822 | /* This checks subject/issuer name and the key usage of the issuer. |
| 121823 | * It does not verify the validity period and if the issuer key was |
| 121824 | * used for the signature. We check that afterwards. */ |
| 121825 | if(X509_NAME_cmp(a: in, b: X509_get_subject_name(a: candidate)) == 0) |
| 121826 | return candidate; |
| 121827 | } |
| 121828 | /* Switch from the stack that came with the cert to the issuer list and |
| 121829 | * then to the trust list. */ |
| 121830 | if(stack == ctx->skTrusted) |
| 121831 | stack = NULL; |
| 121832 | else if(stack == ctx->skIssue) |
| 121833 | stack = ctx->skTrusted; |
| 121834 | else |
| 121835 | stack = ctx->skIssue; |
| 121836 | } while(stack); |
| 121837 | return NULL; |
| 121838 | } |
| 121839 | |
| 121840 | /* Is the certificate a CA? */ |
| 121841 | static UA_Boolean |
| 121842 | openSSLCheckCA(X509 *cert) { |
| 121843 | uint32_t flags = X509_get_extension_flags(x: cert); |
| 121844 | /* The basic constraints must be set with the CA flag true */ |
| 121845 | if(!(flags & EXFLAG_CA)) |
| 121846 | return false; |
| 121847 | |
| 121848 | /* The Key Usage extension must be set */ |
| 121849 | if(!(flags & EXFLAG_KUSAGE)) |
| 121850 | return false; |
| 121851 | |
| 121852 | /* The Key Usage must include cert signing and CRL issuing */ |
| 121853 | uint32_t usage = X509_get_key_usage(x: cert); |
| 121854 | if(!(usage & KU_KEY_CERT_SIGN) || !(usage & KU_CRL_SIGN)) |
| 121855 | return false; |
| 121856 | |
| 121857 | return true; |
| 121858 | } |
| 121859 | |
| 121860 | static UA_StatusCode |
| 121861 | openSSLCheckRevoked(CertContext *ctx, X509 *cert) { |
| 121862 | const ASN1_INTEGER *sn = X509_get0_serialNumber(x: cert); |
| 121863 | const X509_NAME *in = X509_get_issuer_name(a: cert); |
| 121864 | int size = sk_X509_CRL_num(ctx->skCrls); |
| 121865 | |
| 121866 | if(size == 0) { |
| 121867 | UA_LOG_WARNING(logger: ctx->cv->logging, category: UA_LOGCATEGORY_SECURITYPOLICY, |
| 121868 | msg: "Zero revocation lists have been loaded. " |
| 121869 | "This seems intentional - omitting the check."); |
| 121870 | return UA_STATUSCODE_GOOD; |
| 121871 | } |
| 121872 | |
| 121873 | /* Loop over the crl and match the Issuer Name */ |
| 121874 | UA_StatusCode res = UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN; |
| 121875 | for(int i = 0; i < size; i++) { |
| 121876 | /* The crl contains a list of serial numbers from the same issuer */ |
| 121877 | X509_CRL *crl = sk_X509_CRL_value(ctx->skCrls, i); |
| 121878 | if(X509_NAME_cmp(a: in, b: X509_CRL_get_issuer(crl)) != 0) |
| 121879 | continue; |
| 121880 | STACK_OF(X509_REVOKED) *rs = X509_CRL_get_REVOKED(crl); |
| 121881 | int rsize = sk_X509_REVOKED_num(rs); |
| 121882 | for(int j = 0; j < rsize; j++) { |
| 121883 | X509_REVOKED *r = sk_X509_REVOKED_value(rs, j); |
| 121884 | if(ASN1_INTEGER_cmp(x: sn, y: X509_REVOKED_get0_serialNumber(x: r)) == 0) |
| 121885 | return UA_STATUSCODE_BADCERTIFICATEREVOKED; |
| 121886 | } |
| 121887 | res = UA_STATUSCODE_GOOD; /* There was at least one crl that did not revoke (so far) */ |
| 121888 | } |
| 121889 | return res; |
| 121890 | } |
| 121891 | |
| 121892 | #define UA_OPENSSL_MAX_CHAIN_LENGTH 10 |
| 121893 | |
| 121894 | static UA_StatusCode |
| 121895 | openSSL_verifyChain(CertContext *ctx, STACK_OF(X509) *stack, X509 **old_issuers, |
| 121896 | X509 *cert, int depth) { |
| 121897 | /* Maxiumum chain length */ |
| 121898 | if(depth == UA_OPENSSL_MAX_CHAIN_LENGTH) |
| 121899 | return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; |
| 121900 | |
| 121901 | /* Verification Step: Validity Period */ |
| 121902 | ASN1_TIME *notBefore = X509_get_notBefore(x: cert); |
| 121903 | ASN1_TIME *notAfter = X509_get_notAfter(x: cert); |
| 121904 | if(X509_cmp_current_time(s: notBefore) != -1 || X509_cmp_current_time(s: notAfter) != 1) |
| 121905 | return (depth == 0) ? UA_STATUSCODE_BADCERTIFICATETIMEINVALID : |
| 121906 | UA_STATUSCODE_BADCERTIFICATEISSUERTIMEINVALID; |
| 121907 | |
| 121908 | /* Return the most specific error code. BADCERTIFICATECHAININCOMPLETE is |
| 121909 | * returned only if all possible chains are incomplete. */ |
| 121910 | X509 *issuer = NULL; |
| 121911 | UA_StatusCode ret = UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; |
| 121912 | while(ret != UA_STATUSCODE_GOOD) { |
| 121913 | /* Find the issuer. We jump back here to find a different path if a |
| 121914 | * subsequent check fails. */ |
| 121915 | issuer = openSSLFindNextIssuer(ctx, stack, x509: cert, prev: issuer); |
| 121916 | if(!issuer) |
| 121917 | break; |
| 121918 | |
| 121919 | /* Verification Step: Certificate Usage |
| 121920 | * Can the issuer act as CA? Omit for self-signed leaf certificates. */ |
| 121921 | if((depth > 0 || issuer != cert) && !openSSLCheckCA(cert: issuer)) { |
| 121922 | ret = UA_STATUSCODE_BADCERTIFICATEISSUERUSENOTALLOWED; |
| 121923 | continue; |
| 121924 | } |
| 121925 | |
| 121926 | /* Verification Step: Signature */ |
| 121927 | int opensslRet = X509_verify(a: cert, r: X509_get0_pubkey(x: issuer)); |
| 121928 | if(opensslRet == -1) { |
| 121929 | return UA_STATUSCODE_BADCERTIFICATEINVALID; /* Ill-formed signature */ |
| 121930 | } else if(opensslRet == 0) { |
| 121931 | ret = UA_STATUSCODE_BADCERTIFICATEINVALID; /* Wrong issuer, try again */ |
| 121932 | continue; |
| 121933 | } |
| 121934 | |
| 121935 | /* The certificate is self-signed. We have arrived at the top of the |
| 121936 | * chain. We check whether the certificate is trusted below. This is the |
| 121937 | * only place where we return UA_STATUSCODE_BADCERTIFICATEUNTRUSTED. |
| 121938 | * This signals that the chain is complete (but can be still |
| 121939 | * untrusted). |
| 121940 | * |
| 121941 | * Break here as we have reached the end of the chain. Omit the |
| 121942 | * Revocation Check for self-signed certificates. */ |
| 121943 | if(cert == issuer || X509_cmp(a: cert, b: issuer) == 0) { |
| 121944 | ret = UA_STATUSCODE_BADCERTIFICATEUNTRUSTED; |
| 121945 | break; |
| 121946 | } |
| 121947 | |
| 121948 | /* Verification Step: Revocation Check */ |
| 121949 | ret = openSSLCheckRevoked(ctx, cert); |
| 121950 | if(depth > 0) { |
| 121951 | if(ret == UA_STATUSCODE_BADCERTIFICATEREVOKED) |
| 121952 | ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOKED; |
| 121953 | if(ret == UA_STATUSCODE_BADCERTIFICATEREVOCATIONUNKNOWN) |
| 121954 | ret = UA_STATUSCODE_BADCERTIFICATEISSUERREVOCATIONUNKNOWN; |
| 121955 | } |
| 121956 | if(ret != UA_STATUSCODE_GOOD) |
| 121957 | continue; |
| 121958 | |
| 121959 | /* Detect (endless) loops of issuers. The last one can be skipped by the |
| 121960 | * check for self-signed just before. */ |
| 121961 | for(int i = 0; i < depth; i++) { |
| 121962 | if(old_issuers[i] == issuer) |
| 121963 | return UA_STATUSCODE_BADCERTIFICATECHAININCOMPLETE; |
| 121964 | } |
| 121965 | old_issuers[depth] = issuer; |
| 121966 | |
| 121967 | /* We have found the issuer certificate used for the signature. Recurse |
| 121968 | * to the next certificate in the chain (verify the current issuer). */ |
| 121969 | ret = openSSL_verifyChain(ctx, stack, old_issuers, cert: issuer, depth: depth + 1); |
| 121970 | } |
| 121971 | |
| 121972 | /* Is the certificate in the trust list? If yes, then we are done. */ |
| 121973 | if(ret == UA_STATUSCODE_BADCERTIFICATEUNTRUSTED) { |
| 121974 | for(int i = 0; i < sk_X509_num(ctx->skTrusted); i++) { |
| 121975 | if(X509_cmp(a: cert, sk_X509_value(ctx->skTrusted, i)) == 0) |
| 121976 | return UA_STATUSCODE_GOOD; |
| 121977 | } |
| 121978 | } |
| 121979 | |
| 121980 | return ret; |
| 121981 | } |
| 121982 | |
| 121983 | /* This follows Part 6, 6.1.3 Determining if a Certificate is trusted. |
| 121984 | * It defines a sequence of steps for certificate verification. */ |
| 121985 | static UA_StatusCode |
| 121986 | UA_CertificateVerification_Verify(const UA_CertificateVerification *cv, |
| 121987 | const UA_ByteString *certificate) { |
| 121988 | if(!cv || !certificate) |
| 121989 | return UA_STATUSCODE_BADINTERNALERROR; |
| 121990 | |
| 121991 | UA_StatusCode ret = UA_STATUSCODE_GOOD; |
| 121992 | CertContext *ctx = (CertContext *)cv->context; |
| 121993 | X509 *old_issuers[UA_OPENSSL_MAX_CHAIN_LENGTH]; |
| 121994 | |
| 121995 | #ifdef __linux__ |
| 121996 | ret = UA_ReloadCertFromFolder(ctx); |
| 121997 | if(ret != UA_STATUSCODE_GOOD) |
| 121998 | return ret; |
| 121999 | #endif |
| 122000 | |
| 122001 | /* Verification Step: Certificate Structure */ |
| 122002 | STACK_OF(X509) *stack = openSSLLoadCertificateStack(cert: *certificate); |
| 122003 | if(!stack || sk_X509_num(stack) < 1) { |
| 122004 | ret = UA_STATUSCODE_BADCERTIFICATEINVALID; |
| 122005 | goto errout; |
| 122006 | } |
| 122007 | |
| 122008 | /* Verification Step: Certificate Usage |
| 122009 | * Check whether the certificate is a User certificate or a CA certificate. |
| 122010 | * Refer the test case CTT/Security/Security Certificate Validation/029.js |
| 122011 | * for more details. */ |
| 122012 | X509 *leaf = sk_X509_value(stack, 0); |
| 122013 | if(openSSLCheckCA(cert: leaf)) { |
| 122014 | ret = UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED; |
| 122015 | goto errout; |
| 122016 | } |
| 122017 | |
| 122018 | /* These steps are performed outside of this method. |
| 122019 | * Because we need the server or client context. |
| 122020 | * - Security Policy |
| 122021 | * - Host Name |
| 122022 | * - URI */ |
| 122023 | |
| 122024 | /* Verification Step: Build Certificate Chain |
| 122025 | * We perform the checks for each certificate inside. */ |
| 122026 | ret = openSSL_verifyChain(ctx, stack, old_issuers, cert: leaf, depth: 0); |
| 122027 | |
| 122028 | errout: |
| 122029 | if(stack) |
| 122030 | sk_X509_pop_free(stack, X509_free); |
| 122031 | |
| 122032 | #ifdef UA_ENABLE_CERT_REJECTED_DIR |
| 122033 | if(ret != UA_STATUSCODE_GOOD && |
| 122034 | ctx->rejectedListFolder.length > 0) { |
| 122035 | char rejectedFileName[256] = {0}; |
| 122036 | UA_ByteString thumbprint; |
| 122037 | UA_ByteString_allocBuffer(&thumbprint, UA_SHA1_LENGTH); |
| 122038 | if(UA_Openssl_X509_GetCertificateThumbprint(certificate, &thumbprint, true) == UA_STATUSCODE_GOOD) { |
| 122039 | static const char hex2char[] = "0123456789ABCDEF"; |
| 122040 | for(size_t pos = 0, namePos = 0; pos < thumbprint.length; pos++) { |
| 122041 | rejectedFileName[namePos++] = hex2char[(thumbprint.data[pos] & 0xf0) >> 4]; |
| 122042 | rejectedFileName[namePos++] = hex2char[thumbprint.data[pos] & 0x0f]; |
| 122043 | } |
| 122044 | strcat(rejectedFileName, ".der"); |
| 122045 | } else { |
| 122046 | UA_UInt64 dt = (UA_UInt64) UA_DateTime_now(); |
| 122047 | sprintf(rejectedFileName, "cert_%"PRIu64 ".der", dt); |
| 122048 | } |
| 122049 | UA_ByteString_clear(&thumbprint); |
| 122050 | char *rejectedFullFileName = (char *) |
| 122051 | calloc(ctx->rejectedListFolder.length + 1 /* '/' */ + strlen(rejectedFileName) + 1, sizeof(char)); |
| 122052 | if(!rejectedFullFileName) |
| 122053 | return ret; |
| 122054 | memcpy(rejectedFullFileName, ctx->rejectedListFolder.data, ctx->rejectedListFolder.length); |
| 122055 | rejectedFullFileName[ctx->rejectedListFolder.length] = '/'; |
| 122056 | memcpy(&rejectedFullFileName[ctx->rejectedListFolder.length + 1], rejectedFileName, strlen(rejectedFileName)); |
| 122057 | FILE * fp_rejectedFile = fopen(rejectedFullFileName, "wb"); |
| 122058 | if(fp_rejectedFile) { |
| 122059 | fwrite(certificate->data, sizeof(certificate->data[0]), certificate->length, fp_rejectedFile); |
| 122060 | fclose(fp_rejectedFile); |
| 122061 | } |
| 122062 | free(rejectedFullFileName); |
| 122063 | } |
| 122064 | #endif |
| 122065 | |
| 122066 | return ret; |
| 122067 | } |
| 122068 | |
| 122069 | static UA_StatusCode |
| 122070 | UA_CertificateVerification_VerifyApplicationURI (const UA_CertificateVerification *cv, |
| 122071 | const UA_ByteString * certificate, |
| 122072 | const UA_String * applicationURI) { |
| 122073 | const unsigned char * pData; |
| 122074 | X509 * certificateX509; |
| 122075 | UA_String subjectURI = UA_STRING_NULL; |
| 122076 | GENERAL_NAMES * pNames; |
| 122077 | int i; |
| 122078 | UA_StatusCode ret; |
| 122079 | CertContext * ctx; |
| 122080 | |
| 122081 | if (cv == NULL) { |
| 122082 | return UA_STATUSCODE_BADINTERNALERROR; |
| 122083 | } |
| 122084 | ctx = (CertContext *)cv->context; |
| 122085 | if (ctx == NULL) { |
| 122086 | return UA_STATUSCODE_BADINTERNALERROR; |
| 122087 | } |
| 122088 | |
| 122089 | pData = certificate->data; |
| 122090 | if (pData == NULL) { |
| 122091 | UA_LOG_ERROR(logger: cv->logging, category: UA_LOGCATEGORY_USERLAND, msg: "Error Empty Certificate"); |
| 122092 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 122093 | } |
| 122094 | |
| 122095 | certificateX509 = UA_OpenSSL_LoadCertificate(certificate); |
| 122096 | if (certificateX509 == NULL) { |
| 122097 | UA_LOG_ERROR(logger: cv->logging, category: UA_LOGCATEGORY_USERLAND, msg: "Error loading X509 Certificate"); |
| 122098 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 122099 | } |
| 122100 | |
| 122101 | pNames = (GENERAL_NAMES *) X509_get_ext_d2i(x: certificateX509, NID_subject_alt_name, |
| 122102 | NULL, NULL); |
| 122103 | if (pNames == NULL) { |
| 122104 | X509_free (a: certificateX509); |
| 122105 | UA_LOG_ERROR(logger: cv->logging, category: UA_LOGCATEGORY_USERLAND, msg: "Error processing X509 Certificate"); |
| 122106 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 122107 | } |
| 122108 | |
| 122109 | UA_String_init(p: &subjectURI); |
| 122110 | |
| 122111 | for (i = 0; i < sk_GENERAL_NAME_num (pNames); i++) { |
| 122112 | GENERAL_NAME * value = sk_GENERAL_NAME_value (pNames, i); |
| 122113 | if (value->type == GEN_URI) { |
| 122114 | subjectURI.length = (size_t) (value->d.ia5->length); |
| 122115 | subjectURI.data = (UA_Byte *) UA_malloc (size: subjectURI.length); |
| 122116 | if (subjectURI.data == NULL) { |
| 122117 | UA_LOG_ERROR(logger: cv->logging, category: UA_LOGCATEGORY_USERLAND, msg: "Error Empty subjectURI"); |
| 122118 | X509_free (a: certificateX509); |
| 122119 | sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free); |
| 122120 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 122121 | } |
| 122122 | (void) memcpy (dest: subjectURI.data, src: value->d.ia5->data, n: subjectURI.length); |
| 122123 | break; |
| 122124 | } |
| 122125 | |
| 122126 | } |
| 122127 | |
| 122128 | ret = UA_STATUSCODE_GOOD; |
| 122129 | if (UA_Bstrstr (s1: subjectURI.data, l1: subjectURI.length, |
| 122130 | s2: applicationURI->data, l2: applicationURI->length) == NULL) { |
| 122131 | UA_LOG_ERROR(logger: cv->logging, category: UA_LOGCATEGORY_USERLAND, msg: "Empty comparing subjectURI and applicationURI"); |
| 122132 | ret = UA_STATUSCODE_BADCERTIFICATEURIINVALID; |
| 122133 | } |
| 122134 | |
| 122135 | X509_free (a: certificateX509); |
| 122136 | sk_GENERAL_NAME_pop_free(pNames, GENERAL_NAME_free); |
| 122137 | UA_String_clear (p: &subjectURI); |
| 122138 | return ret; |
| 122139 | } |
| 122140 | |
| 122141 | #ifdef UA_ENABLE_ENCRYPTION_OPENSSL |
| 122142 | static UA_StatusCode |
| 122143 | UA_GetCertificate_ExpirationDate(UA_DateTime *expiryDateTime, |
| 122144 | UA_ByteString *certificate) { |
| 122145 | const unsigned char *pData = certificate->data; |
| 122146 | X509 * x509 = d2i_X509 (NULL, in: &pData, len: (long)certificate->length); |
| 122147 | if (x509 == NULL) { |
| 122148 | return UA_STATUSCODE_BADINTERNALERROR; |
| 122149 | } |
| 122150 | |
| 122151 | /* Get the certificate Expiry date */ |
| 122152 | ASN1_TIME *not_after = X509_get_notAfter(x: x509); |
| 122153 | |
| 122154 | struct tm dtTime; |
| 122155 | ASN1_TIME_to_tm(s: not_after, tm: &dtTime); |
| 122156 | X509_free(a: x509); |
| 122157 | |
| 122158 | struct musl_tm dateTime; |
| 122159 | memset(s: &dateTime, c: 0, n: sizeof(struct musl_tm)); |
| 122160 | dateTime.tm_year = dtTime.tm_year; |
| 122161 | dateTime.tm_mon = dtTime.tm_mon; |
| 122162 | dateTime.tm_mday = dtTime.tm_mday; |
| 122163 | dateTime.tm_hour = dtTime.tm_hour; |
| 122164 | dateTime.tm_min = dtTime.tm_min; |
| 122165 | dateTime.tm_sec = dtTime.tm_sec; |
| 122166 | |
| 122167 | long long sec_epoch = musl_tm_to_secs(tm: &dateTime); |
| 122168 | *expiryDateTime = UA_DATETIME_UNIX_EPOCH; |
| 122169 | *expiryDateTime += sec_epoch * UA_DATETIME_SEC; |
| 122170 | return UA_STATUSCODE_GOOD; |
| 122171 | } |
| 122172 | #endif |
| 122173 | |
| 122174 | static UA_StatusCode |
| 122175 | UA_GetCertificate_SubjectName(UA_String *subjectName, |
| 122176 | UA_ByteString *certificate) { |
| 122177 | const unsigned char *pData = certificate->data; |
| 122178 | X509 *x509 = d2i_X509 (NULL, in: &pData, len: (long)certificate->length); |
| 122179 | if(!x509) |
| 122180 | return UA_STATUSCODE_BADINTERNALERROR; |
| 122181 | X509_NAME *sn = X509_get_subject_name(a: x509); |
| 122182 | char buf[1024]; |
| 122183 | *subjectName = UA_STRING_ALLOC(X509_NAME_oneline(sn, buf, 1024)); |
| 122184 | X509_free(a: x509); |
| 122185 | return UA_STATUSCODE_GOOD; |
| 122186 | } |
| 122187 | |
| 122188 | /* main entry */ |
| 122189 | |
| 122190 | UA_StatusCode |
| 122191 | UA_CertificateVerification_Trustlist(UA_CertificateVerification * cv, |
| 122192 | const UA_ByteString * certificateTrustList, |
| 122193 | size_t certificateTrustListSize, |
| 122194 | const UA_ByteString * certificateIssuerList, |
| 122195 | size_t certificateIssuerListSize, |
| 122196 | const UA_ByteString * certificateRevocationList, |
| 122197 | size_t certificateRevocationListSize) { |
| 122198 | UA_StatusCode ret; |
| 122199 | |
| 122200 | if (cv == NULL) { |
| 122201 | return UA_STATUSCODE_BADINTERNALERROR; |
| 122202 | } |
| 122203 | if (cv->logging == NULL) { |
| 122204 | return UA_STATUSCODE_BADINTERNALERROR; |
| 122205 | } |
| 122206 | |
| 122207 | /* Clear if the plugin is already initialized */ |
| 122208 | if(cv->clear) |
| 122209 | cv->clear(cv); |
| 122210 | |
| 122211 | CertContext * context = (CertContext *) UA_malloc (size: sizeof (CertContext)); |
| 122212 | if (context == NULL) { |
| 122213 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 122214 | } |
| 122215 | |
| 122216 | cv->verifyApplicationURI = UA_CertificateVerification_VerifyApplicationURI; |
| 122217 | cv->clear = UA_CertificateVerification_clear; |
| 122218 | cv->context = context; |
| 122219 | cv->verifyCertificate = UA_CertificateVerification_Verify; |
| 122220 | #ifdef UA_ENABLE_ENCRYPTION_OPENSSL |
| 122221 | cv->getExpirationDate = UA_GetCertificate_ExpirationDate; |
| 122222 | #endif |
| 122223 | cv->getSubjectName = UA_GetCertificate_SubjectName; |
| 122224 | |
| 122225 | ret = UA_CertContext_Init (context, cv); |
| 122226 | if (ret != UA_STATUSCODE_GOOD) { |
| 122227 | return ret; |
| 122228 | } |
| 122229 | |
| 122230 | if (certificateTrustListSize > 0) { |
| 122231 | if (UA_skTrusted_Cert2X509 (certificateTrustList, certificateTrustListSize, |
| 122232 | ctx: context) != UA_STATUSCODE_GOOD) { |
| 122233 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 122234 | goto errout; |
| 122235 | } |
| 122236 | } |
| 122237 | |
| 122238 | if (certificateIssuerListSize > 0) { |
| 122239 | if (UA_skIssuer_Cert2X509 (certificateIssuerList, certificateIssuerListSize, |
| 122240 | ctx: context) != UA_STATUSCODE_GOOD) { |
| 122241 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 122242 | goto errout; |
| 122243 | } |
| 122244 | } |
| 122245 | |
| 122246 | if (certificateRevocationListSize > 0) { |
| 122247 | if (UA_skCrls_Cert2X509 (certificateRevocationList, certificateRevocationListSize, |
| 122248 | ctx: context) != UA_STATUSCODE_GOOD) { |
| 122249 | ret = UA_STATUSCODE_BADINTERNALERROR; |
| 122250 | goto errout; |
| 122251 | } |
| 122252 | } |
| 122253 | |
| 122254 | return UA_STATUSCODE_GOOD; |
| 122255 | |
| 122256 | errout: |
| 122257 | UA_CertificateVerification_clear (cv); |
| 122258 | return ret; |
| 122259 | } |
| 122260 | |
| 122261 | #ifdef __linux__ /* Linux only so far */ |
| 122262 | UA_StatusCode |
| 122263 | UA_CertificateVerification_CertFolders(UA_CertificateVerification *cv, |
| 122264 | const char *trustListFolder, |
| 122265 | const char *issuerListFolder, |
| 122266 | const char *revocationListFolder |
| 122267 | #ifdef UA_ENABLE_CERT_REJECTED_DIR |
| 122268 | , const char *rejectedListFolder |
| 122269 | #endif |
| 122270 | ) { |
| 122271 | UA_StatusCode ret; |
| 122272 | if (cv == NULL) { |
| 122273 | return UA_STATUSCODE_BADINTERNALERROR; |
| 122274 | } |
| 122275 | if (cv->logging == NULL) { |
| 122276 | return UA_STATUSCODE_BADINTERNALERROR; |
| 122277 | } |
| 122278 | |
| 122279 | /* Clear if the plugin is already initialized */ |
| 122280 | if(cv->clear) |
| 122281 | cv->clear(cv); |
| 122282 | |
| 122283 | CertContext * context = (CertContext *) UA_malloc (size: sizeof (CertContext)); |
| 122284 | if (context == NULL) { |
| 122285 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 122286 | } |
| 122287 | |
| 122288 | cv->verifyApplicationURI = UA_CertificateVerification_VerifyApplicationURI; |
| 122289 | cv->clear = UA_CertificateVerification_clear; |
| 122290 | cv->context = context; |
| 122291 | cv->verifyCertificate = UA_CertificateVerification_Verify; |
| 122292 | |
| 122293 | ret = UA_CertContext_Init (context, cv); |
| 122294 | if (ret != UA_STATUSCODE_GOOD) { |
| 122295 | return ret; |
| 122296 | } |
| 122297 | |
| 122298 | /* Only set the folder paths. They will be reloaded during runtime. */ |
| 122299 | |
| 122300 | context->trustListFolder = UA_STRING_ALLOC(trustListFolder); |
| 122301 | context->issuerListFolder = UA_STRING_ALLOC(issuerListFolder); |
| 122302 | context->revocationListFolder = UA_STRING_ALLOC(revocationListFolder); |
| 122303 | #ifdef UA_ENABLE_CERT_REJECTED_DIR |
| 122304 | context->rejectedListFolder = UA_STRING_ALLOC(rejectedListFolder); |
| 122305 | #endif |
| 122306 | |
| 122307 | return UA_STATUSCODE_GOOD; |
| 122308 | } |
| 122309 | #endif |
| 122310 | |
| 122311 | static int |
| 122312 | privateKeyPasswordCallback(char *buf, int size, int rwflag, void *userdata) { |
| 122313 | (void) rwflag; |
| 122314 | UA_ByteString *pw = (UA_ByteString*)userdata; |
| 122315 | if(pw->length <= (size_t)size) |
| 122316 | memcpy(dest: buf, src: pw->data, n: pw->length); |
| 122317 | return (int)pw->length; |
| 122318 | } |
| 122319 | |
| 122320 | UA_StatusCode |
| 122321 | UA_PKI_decryptPrivateKey(const UA_ByteString privateKey, |
| 122322 | const UA_ByteString password, |
| 122323 | UA_ByteString *outDerKey) { |
| 122324 | if(!outDerKey) |
| 122325 | return UA_STATUSCODE_BADINTERNALERROR; |
| 122326 | |
| 122327 | if (privateKey.length == 0) { |
| 122328 | *outDerKey = UA_BYTESTRING_NULL; |
| 122329 | return UA_STATUSCODE_BADINVALIDARGUMENT; |
| 122330 | } |
| 122331 | |
| 122332 | /* Already in DER format -> return verbatim */ |
| 122333 | if(privateKey.length > 1 && privateKey.data[0] == 0x30 && privateKey.data[1] == 0x82) |
| 122334 | return UA_ByteString_copy(src: &privateKey, dst: outDerKey); |
| 122335 | |
| 122336 | /* Decrypt */ |
| 122337 | BIO *bio = BIO_new_mem_buf(buf: (void*)privateKey.data, len: (int)privateKey.length); |
| 122338 | EVP_PKEY *pkey = PEM_read_bio_PrivateKey(out: bio, NULL, |
| 122339 | cb: privateKeyPasswordCallback, |
| 122340 | u: (void*)(uintptr_t)&password); |
| 122341 | BIO_free(a: bio); |
| 122342 | if(!pkey) |
| 122343 | return UA_STATUSCODE_BADSECURITYCHECKSFAILED; |
| 122344 | |
| 122345 | /* Write DER encoded, allocates the new memory */ |
| 122346 | unsigned char *data = NULL; |
| 122347 | const int numBytes = i2d_PrivateKey(a: pkey, pp: &data); |
| 122348 | EVP_PKEY_free(pkey); |
| 122349 | if(!data) |
| 122350 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 122351 | |
| 122352 | /* Copy to the data to outDerKey |
| 122353 | * Passing the data pointer directly causes a heap corruption on Windows |
| 122354 | * when outDerKey is cleared. |
| 122355 | */ |
| 122356 | UA_ByteString temp = UA_BYTESTRING_NULL; |
| 122357 | temp.data = data; |
| 122358 | temp.length = (size_t)numBytes; |
| 122359 | const UA_StatusCode success = UA_ByteString_copy(src: &temp, dst: outDerKey); |
| 122360 | /* OPENSSL_clear_free() is not supported by the LibreSSL version in the CI */ |
| 122361 | OPENSSL_cleanse(ptr: data, len: numBytes); |
| 122362 | OPENSSL_free(data); |
| 122363 | return success; |
| 122364 | } |
| 122365 | |
| 122366 | #endif /* end of defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) */ |
| 122367 | |
| 122368 | /**** amalgamated original file "/plugins/crypto/ua_pki_none.c" ****/ |
| 122369 | |
| 122370 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 122371 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 122372 | * |
| 122373 | * Copyright 2020 (c) Julius Pfrommer, Fraunhofer IOSB |
| 122374 | */ |
| 122375 | |
| 122376 | |
| 122377 | static UA_StatusCode |
| 122378 | verifyCertificateAllowAll(const UA_CertificateVerification *cv, |
| 122379 | const UA_ByteString *certificate) { |
| 122380 | UA_LOG_WARNING(logger: cv->logging, category: UA_LOGCATEGORY_USERLAND, |
| 122381 | msg: "No certificate store configured. Accepting the certificate."); |
| 122382 | return UA_STATUSCODE_GOOD; |
| 122383 | } |
| 122384 | |
| 122385 | static UA_StatusCode |
| 122386 | verifyApplicationURIAllowAll(const UA_CertificateVerification *cv, |
| 122387 | const UA_ByteString *certificate, |
| 122388 | const UA_String *applicationURI) { |
| 122389 | return UA_STATUSCODE_GOOD; |
| 122390 | } |
| 122391 | |
| 122392 | static void |
| 122393 | clearVerifyAllowAll(UA_CertificateVerification *cv) { |
| 122394 | |
| 122395 | } |
| 122396 | |
| 122397 | void UA_CertificateVerification_AcceptAll(UA_CertificateVerification *cv) { |
| 122398 | /* Clear the structure, as it may have already been initialized. */ |
| 122399 | if(cv->clear) |
| 122400 | cv->clear(cv); |
| 122401 | cv->verifyCertificate = verifyCertificateAllowAll; |
| 122402 | cv->verifyApplicationURI = verifyApplicationURIAllowAll; |
| 122403 | cv->clear = clearVerifyAllowAll; |
| 122404 | } |
| 122405 | |
| 122406 | /**** amalgamated original file "/plugins/crypto/ua_securitypolicy_none.c" ****/ |
| 122407 | |
| 122408 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 122409 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 122410 | * |
| 122411 | * Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB |
| 122412 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 122413 | */ |
| 122414 | |
| 122415 | |
| 122416 | #ifdef UA_ENABLE_ENCRYPTION_MBEDTLS |
| 122417 | #endif |
| 122418 | |
| 122419 | #if defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 122420 | #endif |
| 122421 | |
| 122422 | static UA_StatusCode |
| 122423 | verify_none(void *channelContext, |
| 122424 | const UA_ByteString *message, |
| 122425 | const UA_ByteString *signature) { |
| 122426 | return UA_STATUSCODE_GOOD; |
| 122427 | } |
| 122428 | |
| 122429 | static UA_StatusCode |
| 122430 | sign_none(void *channelContext, const UA_ByteString *message, |
| 122431 | UA_ByteString *signature) { |
| 122432 | return UA_STATUSCODE_GOOD; |
| 122433 | } |
| 122434 | |
| 122435 | static size_t |
| 122436 | length_none(const void *channelContext) { |
| 122437 | return 0; |
| 122438 | } |
| 122439 | |
| 122440 | static UA_StatusCode |
| 122441 | encrypt_none(void *channelContext, UA_ByteString *data) { |
| 122442 | return UA_STATUSCODE_GOOD; |
| 122443 | } |
| 122444 | |
| 122445 | static UA_StatusCode |
| 122446 | decrypt_none(void *channelContext, UA_ByteString *data) { |
| 122447 | return UA_STATUSCODE_GOOD; |
| 122448 | } |
| 122449 | |
| 122450 | static UA_StatusCode |
| 122451 | makeThumbprint_none(const UA_SecurityPolicy *securityPolicy, |
| 122452 | const UA_ByteString *certificate, |
| 122453 | UA_ByteString *thumbprint) { |
| 122454 | return UA_STATUSCODE_GOOD; |
| 122455 | } |
| 122456 | |
| 122457 | static UA_StatusCode |
| 122458 | compareThumbprint_none(const UA_SecurityPolicy *securityPolicy, |
| 122459 | const UA_ByteString *certificateThumbprint) { |
| 122460 | return UA_STATUSCODE_GOOD; |
| 122461 | } |
| 122462 | |
| 122463 | static UA_StatusCode |
| 122464 | generateKey_none(void *policyContext, const UA_ByteString *secret, |
| 122465 | const UA_ByteString *seed, UA_ByteString *out) { |
| 122466 | return UA_STATUSCODE_GOOD; |
| 122467 | } |
| 122468 | |
| 122469 | /* Use the non-cryptographic RNG to set the nonce */ |
| 122470 | static UA_StatusCode |
| 122471 | generateNonce_none(void *policyContext, UA_ByteString *out) { |
| 122472 | if(out == NULL) |
| 122473 | return UA_STATUSCODE_BADINTERNALERROR; |
| 122474 | |
| 122475 | if(out->length == 0) |
| 122476 | return UA_STATUSCODE_GOOD; |
| 122477 | |
| 122478 | /* Fill blocks of four byte */ |
| 122479 | size_t i = 0; |
| 122480 | while(i + 3 < out->length) { |
| 122481 | UA_UInt32 randNumber = UA_UInt32_random(); |
| 122482 | memcpy(dest: &out->data[i], src: &randNumber, n: 4); |
| 122483 | i = i+4; |
| 122484 | } |
| 122485 | |
| 122486 | /* Fill the remaining byte */ |
| 122487 | UA_UInt32 randNumber = UA_UInt32_random(); |
| 122488 | memcpy(dest: &out->data[i], src: &randNumber, n: out->length % 4); |
| 122489 | |
| 122490 | return UA_STATUSCODE_GOOD; |
| 122491 | } |
| 122492 | |
| 122493 | static UA_StatusCode |
| 122494 | newContext_none(const UA_SecurityPolicy *securityPolicy, |
| 122495 | const UA_ByteString *remoteCertificate, |
| 122496 | void **channelContext) { |
| 122497 | return UA_STATUSCODE_GOOD; |
| 122498 | } |
| 122499 | |
| 122500 | static void |
| 122501 | deleteContext_none(void *channelContext) { |
| 122502 | } |
| 122503 | |
| 122504 | static UA_StatusCode |
| 122505 | setContextValue_none(void *channelContext, |
| 122506 | const UA_ByteString *key) { |
| 122507 | return UA_STATUSCODE_GOOD; |
| 122508 | } |
| 122509 | |
| 122510 | static UA_StatusCode |
| 122511 | compareCertificate_none(const void *channelContext, |
| 122512 | const UA_ByteString *certificate) { |
| 122513 | return UA_STATUSCODE_GOOD; |
| 122514 | } |
| 122515 | |
| 122516 | static UA_StatusCode |
| 122517 | updateCertificateAndPrivateKey_none(UA_SecurityPolicy *policy, |
| 122518 | const UA_ByteString newCertificate, |
| 122519 | const UA_ByteString newPrivateKey) { |
| 122520 | UA_ByteString_clear(p: &policy->localCertificate); |
| 122521 | UA_ByteString_copy(src: &newCertificate, dst: &policy->localCertificate); |
| 122522 | return UA_STATUSCODE_GOOD; |
| 122523 | } |
| 122524 | |
| 122525 | |
| 122526 | static void |
| 122527 | policy_clear_none(UA_SecurityPolicy *policy) { |
| 122528 | UA_ByteString_clear(p: &policy->localCertificate); |
| 122529 | } |
| 122530 | |
| 122531 | UA_StatusCode |
| 122532 | UA_SecurityPolicy_None(UA_SecurityPolicy *policy, const UA_ByteString localCertificate, |
| 122533 | const UA_Logger *logger) { |
| 122534 | policy->policyContext = (void *)(uintptr_t)logger; |
| 122535 | policy->policyUri = UA_STRING(chars: "http://opcfoundation.org/UA/SecurityPolicy#None"); |
| 122536 | policy->logger = logger; |
| 122537 | |
| 122538 | #ifdef UA_ENABLE_ENCRYPTION_MBEDTLS |
| 122539 | UA_mbedTLS_LoadLocalCertificate(&localCertificate, &policy->localCertificate); |
| 122540 | #elif defined(UA_ENABLE_ENCRYPTION_OPENSSL) || defined(UA_ENABLE_ENCRYPTION_LIBRESSL) |
| 122541 | UA_OpenSSL_LoadLocalCertificate(certificate: &localCertificate, target: &policy->localCertificate); |
| 122542 | #else |
| 122543 | UA_ByteString_copy(&localCertificate, &policy->localCertificate); |
| 122544 | #endif |
| 122545 | |
| 122546 | policy->symmetricModule.generateKey = generateKey_none; |
| 122547 | policy->symmetricModule.generateNonce = generateNonce_none; |
| 122548 | |
| 122549 | UA_SecurityPolicySignatureAlgorithm *sym_signatureAlgorithm = |
| 122550 | &policy->symmetricModule.cryptoModule.signatureAlgorithm; |
| 122551 | sym_signatureAlgorithm->uri = UA_STRING_NULL; |
| 122552 | sym_signatureAlgorithm->verify = verify_none; |
| 122553 | sym_signatureAlgorithm->sign = sign_none; |
| 122554 | sym_signatureAlgorithm->getLocalSignatureSize = length_none; |
| 122555 | sym_signatureAlgorithm->getRemoteSignatureSize = length_none; |
| 122556 | sym_signatureAlgorithm->getLocalKeyLength = length_none; |
| 122557 | sym_signatureAlgorithm->getRemoteKeyLength = length_none; |
| 122558 | |
| 122559 | UA_SecurityPolicyEncryptionAlgorithm *sym_encryptionAlgorithm = |
| 122560 | &policy->symmetricModule.cryptoModule.encryptionAlgorithm; |
| 122561 | sym_encryptionAlgorithm->uri = UA_STRING_NULL; |
| 122562 | sym_encryptionAlgorithm->encrypt = encrypt_none; |
| 122563 | sym_encryptionAlgorithm->decrypt = decrypt_none; |
| 122564 | sym_encryptionAlgorithm->getLocalKeyLength = length_none; |
| 122565 | sym_encryptionAlgorithm->getRemoteKeyLength = length_none; |
| 122566 | sym_encryptionAlgorithm->getRemoteBlockSize = length_none; |
| 122567 | sym_encryptionAlgorithm->getRemotePlainTextBlockSize = length_none; |
| 122568 | policy->symmetricModule.secureChannelNonceLength = 0; |
| 122569 | |
| 122570 | policy->asymmetricModule.makeCertificateThumbprint = makeThumbprint_none; |
| 122571 | policy->asymmetricModule.compareCertificateThumbprint = compareThumbprint_none; |
| 122572 | |
| 122573 | // This only works for none since symmetric and asymmetric crypto modules do the same i.e. nothing |
| 122574 | policy->asymmetricModule.cryptoModule = policy->symmetricModule.cryptoModule; |
| 122575 | |
| 122576 | // Use the same signing algorithm as for asymmetric signing |
| 122577 | policy->certificateSigningAlgorithm = policy->asymmetricModule.cryptoModule.signatureAlgorithm; |
| 122578 | |
| 122579 | policy->channelModule.newContext = newContext_none; |
| 122580 | policy->channelModule.deleteContext = deleteContext_none; |
| 122581 | policy->channelModule.setLocalSymEncryptingKey = setContextValue_none; |
| 122582 | policy->channelModule.setLocalSymSigningKey = setContextValue_none; |
| 122583 | policy->channelModule.setLocalSymIv = setContextValue_none; |
| 122584 | policy->channelModule.setRemoteSymEncryptingKey = setContextValue_none; |
| 122585 | policy->channelModule.setRemoteSymSigningKey = setContextValue_none; |
| 122586 | policy->channelModule.setRemoteSymIv = setContextValue_none; |
| 122587 | policy->channelModule.compareCertificate = compareCertificate_none; |
| 122588 | policy->updateCertificateAndPrivateKey = updateCertificateAndPrivateKey_none; |
| 122589 | policy->clear = policy_clear_none; |
| 122590 | |
| 122591 | return UA_STATUSCODE_GOOD; |
| 122592 | } |
| 122593 | |
| 122594 | /**** amalgamated original file "/arch/common/ua_timer.h" ****/ |
| 122595 | |
| 122596 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 122597 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 122598 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 122599 | * |
| 122600 | * Copyright 2017, 2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 122601 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 122602 | */ |
| 122603 | |
| 122604 | |
| 122605 | |
| 122606 | _UA_BEGIN_DECLS |
| 122607 | |
| 122608 | /* The timer is protected by its own mutex. The mutex is released before calling |
| 122609 | * into the callbacks. So the timer can be modified from the callbacks it is |
| 122610 | * executing. Also, the timer mutex can never lead to locking. Because the timer |
| 122611 | * mutex will be left without acquiring another mutex. |
| 122612 | * |
| 122613 | * Obviously, the timer must not be deleted from within one of its |
| 122614 | * callbacks. */ |
| 122615 | |
| 122616 | /* Callback where the application is either a client or a server */ |
| 122617 | typedef void (*UA_ApplicationCallback)(void *application, void *data); |
| 122618 | |
| 122619 | typedef struct UA_TimerEntry { |
| 122620 | ZIP_ENTRY(UA_TimerEntry) treeEntry; |
| 122621 | UA_TimerPolicy timerPolicy; /* Timer policy to handle cycle misses */ |
| 122622 | UA_DateTime nextTime; /* The next time when the callback is to be |
| 122623 | * executed */ |
| 122624 | UA_UInt64 interval; /* Interval in 100ns resolution. If the |
| 122625 | * interval is zero, the callback is not |
| 122626 | * repeated and removed after execution. */ |
| 122627 | UA_ApplicationCallback callback; /* This is also a sentinel value. If the |
| 122628 | * callback is NULL, then the entry is |
| 122629 | * marked for deletion. */ |
| 122630 | void *application; |
| 122631 | void *data; |
| 122632 | |
| 122633 | ZIP_ENTRY(UA_TimerEntry) idTreeEntry; |
| 122634 | UA_UInt64 id; /* Id of the entry */ |
| 122635 | } UA_TimerEntry; |
| 122636 | |
| 122637 | typedef ZIP_HEAD(UA_TimerTree, UA_TimerEntry) UA_TimerTree; |
| 122638 | typedef ZIP_HEAD(UA_TimerIdTree, UA_TimerEntry) UA_TimerIdTree; |
| 122639 | |
| 122640 | typedef struct { |
| 122641 | UA_TimerTree tree; /* The root of the time-sorted tree */ |
| 122642 | UA_TimerIdTree idTree; /* The root of the id-sorted tree */ |
| 122643 | UA_UInt64 idCounter; /* Generate unique identifiers. Identifiers are |
| 122644 | * always above zero. */ |
| 122645 | #if UA_MULTITHREADING >= 100 |
| 122646 | UA_Lock timerMutex; |
| 122647 | #endif |
| 122648 | |
| 122649 | UA_TimerTree processTree; /* When the timer is processed, all entries that |
| 122650 | * need processing now are moved to processTree. |
| 122651 | * Then we iterate over that tree. */ |
| 122652 | } UA_Timer; |
| 122653 | |
| 122654 | void |
| 122655 | UA_Timer_init(UA_Timer *t); |
| 122656 | |
| 122657 | UA_DateTime |
| 122658 | UA_Timer_nextRepeatedTime(UA_Timer *t); |
| 122659 | |
| 122660 | UA_StatusCode |
| 122661 | UA_Timer_addTimedCallback(UA_Timer *t, UA_ApplicationCallback callback, |
| 122662 | void *application, void *data, UA_DateTime date, |
| 122663 | UA_UInt64 *callbackId); |
| 122664 | |
| 122665 | UA_StatusCode |
| 122666 | UA_Timer_addRepeatedCallback(UA_Timer *t, UA_ApplicationCallback callback, |
| 122667 | void *application, void *data, UA_Double interval_ms, |
| 122668 | UA_DateTime *baseTime, UA_TimerPolicy timerPolicy, |
| 122669 | UA_UInt64 *callbackId); |
| 122670 | |
| 122671 | UA_StatusCode |
| 122672 | UA_Timer_changeRepeatedCallback(UA_Timer *t, UA_UInt64 callbackId, |
| 122673 | UA_Double interval_ms, UA_DateTime *baseTime, |
| 122674 | UA_TimerPolicy timerPolicy); |
| 122675 | |
| 122676 | void |
| 122677 | UA_Timer_removeCallback(UA_Timer *t, UA_UInt64 callbackId); |
| 122678 | |
| 122679 | UA_DateTime |
| 122680 | UA_Timer_process(UA_Timer *t, UA_DateTime nowMonotonic); |
| 122681 | |
| 122682 | void |
| 122683 | UA_Timer_clear(UA_Timer *t); |
| 122684 | |
| 122685 | _UA_END_DECLS |
| 122686 | |
| 122687 | |
| 122688 | /**** amalgamated original file "/arch/eventloop_common.h" ****/ |
| 122689 | |
| 122690 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 122691 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 122692 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 122693 | * |
| 122694 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 122695 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes) |
| 122696 | */ |
| 122697 | |
| 122698 | |
| 122699 | |
| 122700 | /* Utility definitions to be used in EventLoop implementations. |
| 122701 | * Not part of the public API. */ |
| 122702 | |
| 122703 | _UA_BEGIN_DECLS |
| 122704 | |
| 122705 | /* Typing restrictions for key-value parameters */ |
| 122706 | typedef struct { |
| 122707 | UA_QualifiedName name; |
| 122708 | const UA_DataType *type; |
| 122709 | UA_Boolean required; |
| 122710 | UA_Boolean scalar; |
| 122711 | UA_Boolean array; |
| 122712 | } UA_KeyValueRestriction; |
| 122713 | |
| 122714 | UA_StatusCode |
| 122715 | UA_KeyValueRestriction_validate(const UA_Logger *logger, |
| 122716 | const char *logprefix, |
| 122717 | const UA_KeyValueRestriction *restrictions, |
| 122718 | size_t restrictionsSiz, |
| 122719 | const UA_KeyValueMap *map); |
| 122720 | |
| 122721 | _UA_END_DECLS |
| 122722 | |
| 122723 | |
| 122724 | /**** amalgamated original file "/arch/eventloop_posix.h" ****/ |
| 122725 | |
| 122726 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 122727 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 122728 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 122729 | * |
| 122730 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 122731 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes) |
| 122732 | */ |
| 122733 | |
| 122734 | |
| 122735 | |
| 122736 | #if defined(UA_ARCHITECTURE_POSIX) || defined(UA_ARCHITECTURE_WIN32) |
| 122737 | |
| 122738 | /* Include architecture-specific definitions */ |
| 122739 | #if defined(UA_ARCHITECTURE_WIN32) |
| 122740 | #elif defined(UA_ARCHITECTURE_POSIX) |
| 122741 | #endif |
| 122742 | |
| 122743 | |
| 122744 | #if !defined(__QNX__) |
| 122745 | #endif |
| 122746 | |
| 122747 | /* epoll_pwait returns bogus data with the tc compiler */ |
| 122748 | #if defined(__linux__) && !defined(__TINYC__) |
| 122749 | # define UA_HAVE_EPOLL |
| 122750 | # include <sys/epoll.h> |
| 122751 | #endif |
| 122752 | |
| 122753 | #define UA_MAXBACKLOG 100 |
| 122754 | #define UA_MAXHOSTNAME_LENGTH 256 |
| 122755 | #define UA_MAXPORTSTR_LENGTH 6 |
| 122756 | |
| 122757 | #ifndef MSG_NOSIGNAL |
| 122758 | #define MSG_NOSIGNAL 0 |
| 122759 | #endif |
| 122760 | |
| 122761 | #ifndef MSG_DONTWAIT |
| 122762 | #define MSG_DONTWAIT 0 |
| 122763 | #endif |
| 122764 | |
| 122765 | _UA_BEGIN_DECLS |
| 122766 | |
| 122767 | /* POSIX events are based on sockets / file descriptors. The EventSources can |
| 122768 | * register their fd in the EventLoop so that they are considered by the |
| 122769 | * EventLoop dropping into "poll" to wait for events. */ |
| 122770 | |
| 122771 | /* TODO: Move the macro-forest from /arch/<arch>/ua_architecture.h */ |
| 122772 | |
| 122773 | #define UA_FD UA_SOCKET |
| 122774 | #define UA_INVALID_FD UA_INVALID_SOCKET |
| 122775 | |
| 122776 | struct UA_RegisteredFD; |
| 122777 | typedef struct UA_RegisteredFD UA_RegisteredFD; |
| 122778 | |
| 122779 | /* Bitmask to be used for the UA_FDCallback event argument */ |
| 122780 | #define UA_FDEVENT_IN 1 |
| 122781 | #define UA_FDEVENT_OUT 2 |
| 122782 | #define UA_FDEVENT_ERR 4 |
| 122783 | |
| 122784 | typedef void (*UA_FDCallback)(UA_EventSource *es, UA_RegisteredFD *rfd, short event); |
| 122785 | |
| 122786 | struct UA_RegisteredFD { |
| 122787 | UA_DelayedCallback dc; /* Used for async closing. Must be the first member |
| 122788 | * because the rfd is freed by the delayed callback |
| 122789 | * mechanism. */ |
| 122790 | |
| 122791 | ZIP_ENTRY(UA_RegisteredFD) zipPointers; /* Register FD in the EventSource */ |
| 122792 | UA_FD fd; |
| 122793 | short listenEvents; /* UA_FDEVENT_IN | UA_FDEVENT_OUT*/ |
| 122794 | |
| 122795 | UA_EventSource *es; /* Backpointer to the EventSource */ |
| 122796 | UA_FDCallback eventSourceCB; |
| 122797 | }; |
| 122798 | |
| 122799 | enum ZIP_CMP cmpFD(const UA_FD *a, const UA_FD *b); |
| 122800 | typedef ZIP_HEAD(UA_FDTree, UA_RegisteredFD) UA_FDTree; |
| 122801 | ZIP_FUNCTIONS(UA_FDTree, UA_RegisteredFD, zipPointers, UA_FD, fd, cmpFD) |
| 122802 | |
| 122803 | /* All ConnectionManager in the POSIX EventLoop can be cast to |
| 122804 | * UA_ConnectionManagerPOSIX. They carry a sorted tree of their open |
| 122805 | * sockets/file-descriptors. */ |
| 122806 | typedef struct { |
| 122807 | UA_ConnectionManager cm; |
| 122808 | |
| 122809 | /* Reused receive buffer. The size is configured via |
| 122810 | * the recv-bufsize parameter.*/ |
| 122811 | UA_ByteString rxBuffer; |
| 122812 | |
| 122813 | /* Sorted tree of the FDs */ |
| 122814 | size_t fdsSize; |
| 122815 | UA_FDTree fds; |
| 122816 | } UA_POSIXConnectionManager; |
| 122817 | |
| 122818 | typedef struct { |
| 122819 | UA_EventLoop eventLoop; |
| 122820 | |
| 122821 | /* Timer */ |
| 122822 | UA_Timer timer; |
| 122823 | |
| 122824 | /* Linked List of Delayed Callbacks */ |
| 122825 | UA_DelayedCallback *delayedCallbacks; |
| 122826 | |
| 122827 | /* Flag determining whether the eventloop is currently within the |
| 122828 | * "run" method */ |
| 122829 | UA_Boolean executing; |
| 122830 | |
| 122831 | #if defined(UA_HAVE_EPOLL) |
| 122832 | UA_FD epollfd; |
| 122833 | #else |
| 122834 | UA_RegisteredFD **fds; |
| 122835 | size_t fdsSize; |
| 122836 | #endif |
| 122837 | |
| 122838 | #if UA_MULTITHREADING >= 100 |
| 122839 | UA_Lock elMutex; |
| 122840 | #endif |
| 122841 | } UA_EventLoopPOSIX; |
| 122842 | |
| 122843 | /* |
| 122844 | * The following functions differ between epoll and normal select |
| 122845 | */ |
| 122846 | |
| 122847 | /* Register to start receiving events */ |
| 122848 | UA_StatusCode |
| 122849 | UA_EventLoopPOSIX_registerFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd); |
| 122850 | |
| 122851 | /* Modify the events that the fd listens on */ |
| 122852 | UA_StatusCode |
| 122853 | UA_EventLoopPOSIX_modifyFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd); |
| 122854 | |
| 122855 | /* Deregister but do not close the fd. No further events are received. */ |
| 122856 | void |
| 122857 | UA_EventLoopPOSIX_deregisterFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd); |
| 122858 | |
| 122859 | UA_StatusCode |
| 122860 | UA_EventLoopPOSIX_pollFDs(UA_EventLoopPOSIX *el, UA_DateTime listenTimeout); |
| 122861 | |
| 122862 | /* Helper functions between EventSources */ |
| 122863 | |
| 122864 | UA_StatusCode |
| 122865 | UA_EventLoopPOSIX_allocateRXBuffer(UA_POSIXConnectionManager *pcm); |
| 122866 | |
| 122867 | UA_StatusCode |
| 122868 | UA_EventLoopPOSIX_allocNetworkBuffer(UA_ConnectionManager *cm, |
| 122869 | uintptr_t connectionId, |
| 122870 | UA_ByteString *buf, |
| 122871 | size_t bufSize); |
| 122872 | |
| 122873 | void |
| 122874 | UA_EventLoopPOSIX_freeNetworkBuffer(UA_ConnectionManager *cm, |
| 122875 | uintptr_t connectionId, |
| 122876 | UA_ByteString *buf); |
| 122877 | |
| 122878 | /* |
| 122879 | * Helper functions to be used across protocols |
| 122880 | */ |
| 122881 | |
| 122882 | /* Set the socket non-blocking. If the listen-socket is nonblocking, incoming |
| 122883 | * connections inherit this state. */ |
| 122884 | UA_StatusCode |
| 122885 | UA_EventLoopPOSIX_setNonBlocking(UA_FD sockfd); |
| 122886 | |
| 122887 | /* Don't have the socket create interrupt signals */ |
| 122888 | UA_StatusCode |
| 122889 | UA_EventLoopPOSIX_setNoSigPipe(UA_FD sockfd); |
| 122890 | |
| 122891 | /* Enables sharing of the same listening address on different sockets */ |
| 122892 | UA_StatusCode |
| 122893 | UA_EventLoopPOSIX_setReusable(UA_FD sockfd); |
| 122894 | |
| 122895 | _UA_END_DECLS |
| 122896 | |
| 122897 | #endif /* defined(UA_ARCHITECTURE_POSIX) || defined(UA_ARCHITECTURE_WIN32) */ |
| 122898 | |
| 122899 | |
| 122900 | /**** amalgamated original file "/arch/posix/ua_clock.c" ****/ |
| 122901 | |
| 122902 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 122903 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 122904 | * |
| 122905 | * Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 122906 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 122907 | * Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA |
| 122908 | */ |
| 122909 | |
| 122910 | |
| 122911 | #ifdef UA_ARCHITECTURE_POSIX |
| 122912 | |
| 122913 | #include <time.h> |
| 122914 | #include <sys/time.h> |
| 122915 | |
| 122916 | #if defined(__APPLE__) || defined(__MACH__) |
| 122917 | # include <mach/clock.h> |
| 122918 | # include <mach/mach.h> |
| 122919 | #endif |
| 122920 | |
| 122921 | UA_DateTime UA_DateTime_now(void) { |
| 122922 | struct timeval tv; |
| 122923 | gettimeofday(tv: &tv, NULL); |
| 122924 | return (tv.tv_sec * UA_DATETIME_SEC) + (tv.tv_usec * UA_DATETIME_USEC) + UA_DATETIME_UNIX_EPOCH; |
| 122925 | } |
| 122926 | |
| 122927 | /* Credit to https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c */ |
| 122928 | UA_Int64 UA_DateTime_localTimeUtcOffset(void) { |
| 122929 | time_t gmt, rawtime = time(NULL); |
| 122930 | struct tm *ptm; |
| 122931 | struct tm gbuf; |
| 122932 | ptm = gmtime_r(timer: &rawtime, tp: &gbuf); |
| 122933 | // Request that mktime() looksup dst in timezone database |
| 122934 | ptm->tm_isdst = -1; |
| 122935 | gmt = mktime(tp: ptm); |
| 122936 | return (UA_Int64) (difftime(time1: rawtime, time0: gmt) * UA_DATETIME_SEC); |
| 122937 | } |
| 122938 | |
| 122939 | UA_DateTime UA_DateTime_nowMonotonic(void) { |
| 122940 | #if defined(__APPLE__) || defined(__MACH__) |
| 122941 | /* OS X does not have clock_gettime, use clock_get_time */ |
| 122942 | clock_serv_t cclock; |
| 122943 | mach_timespec_t mts; |
| 122944 | host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); |
| 122945 | clock_get_time(cclock, &mts); |
| 122946 | mach_port_deallocate(mach_task_self(), cclock); |
| 122947 | return (mts.tv_sec * UA_DATETIME_SEC) + (mts.tv_nsec / 100); |
| 122948 | #elif !defined(CLOCK_MONOTONIC_RAW) |
| 122949 | struct timespec ts; |
| 122950 | clock_gettime(CLOCK_MONOTONIC, &ts); |
| 122951 | return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100); |
| 122952 | #else |
| 122953 | struct timespec ts; |
| 122954 | clock_gettime(CLOCK_MONOTONIC_RAW, tp: &ts); |
| 122955 | return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100); |
| 122956 | #endif |
| 122957 | } |
| 122958 | |
| 122959 | #endif /* UA_ARCHITECTURE_POSIX */ |
| 122960 | |
| 122961 | /**** amalgamated original file "/arch/win32/ua_clock.c" ****/ |
| 122962 | |
| 122963 | /* This work is licensed under a Creative Commons CCZero 1.0 Universal License. |
| 122964 | * See http://creativecommons.org/publicdomain/zero/1.0/ for more information. |
| 122965 | * |
| 122966 | * Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB |
| 122967 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 122968 | * Copyright 2017 (c) Thomas Stalder |
| 122969 | */ |
| 122970 | |
| 122971 | |
| 122972 | #ifdef UA_ARCHITECTURE_WIN32 |
| 122973 | |
| 122974 | #include <time.h> |
| 122975 | /* Backup definition of SLIST_ENTRY on mingw winnt.h */ |
| 122976 | # ifdef SLIST_ENTRY |
| 122977 | # pragma push_macro("SLIST_ENTRY") |
| 122978 | # undef SLIST_ENTRY |
| 122979 | # define POP_SLIST_ENTRY |
| 122980 | # endif |
| 122981 | # include <windows.h> |
| 122982 | /* restore definition */ |
| 122983 | # ifdef POP_SLIST_ENTRY |
| 122984 | # undef SLIST_ENTRY |
| 122985 | # undef POP_SLIST_ENTRY |
| 122986 | # pragma pop_macro("SLIST_ENTRY") |
| 122987 | # endif |
| 122988 | |
| 122989 | UA_DateTime UA_DateTime_now(void) { |
| 122990 | /* Windows filetime has the same definition as UA_DateTime */ |
| 122991 | FILETIME ft; |
| 122992 | SYSTEMTIME st; |
| 122993 | GetSystemTime(&st); |
| 122994 | SystemTimeToFileTime(&st, &ft); |
| 122995 | ULARGE_INTEGER ul; |
| 122996 | ul.LowPart = ft.dwLowDateTime; |
| 122997 | ul.HighPart = ft.dwHighDateTime; |
| 122998 | return (UA_DateTime)ul.QuadPart; |
| 122999 | } |
| 123000 | |
| 123001 | /* Credit to https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c */ |
| 123002 | UA_Int64 UA_DateTime_localTimeUtcOffset(void) { |
| 123003 | time_t gmt, rawtime = time(NULL); |
| 123004 | |
| 123005 | struct tm ptm; |
| 123006 | #ifdef __CODEGEARC__ |
| 123007 | gmtime_s(&rawtime, &ptm); |
| 123008 | #else |
| 123009 | gmtime_s(&ptm, &rawtime); |
| 123010 | #endif |
| 123011 | // Request that mktime() looksup dst in timezone database |
| 123012 | ptm.tm_isdst = -1; |
| 123013 | gmt = mktime(&ptm); |
| 123014 | |
| 123015 | return (UA_Int64) (difftime(rawtime, gmt) * UA_DATETIME_SEC); |
| 123016 | } |
| 123017 | |
| 123018 | UA_DateTime UA_DateTime_nowMonotonic(void) { |
| 123019 | LARGE_INTEGER freq, ticks; |
| 123020 | QueryPerformanceFrequency(&freq); |
| 123021 | QueryPerformanceCounter(&ticks); |
| 123022 | UA_Double ticks2dt = UA_DATETIME_SEC / (UA_Double)freq.QuadPart; |
| 123023 | return (UA_DateTime)(ticks.QuadPart * ticks2dt); |
| 123024 | } |
| 123025 | |
| 123026 | #endif /* UA_ARCHITECTURE_WIN32 */ |
| 123027 | |
| 123028 | /**** amalgamated original file "/arch/common/ua_timer.c" ****/ |
| 123029 | |
| 123030 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 123031 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 123032 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 123033 | * |
| 123034 | * Copyright 2017, 2018, 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 123035 | * Copyright 2017 (c) Stefan Profanter, fortiss GmbH |
| 123036 | */ |
| 123037 | |
| 123038 | |
| 123039 | static enum ZIP_CMP |
| 123040 | cmpDateTime(const UA_DateTime *a, const UA_DateTime *b) { |
| 123041 | if(*a == *b) |
| 123042 | return ZIP_CMP_EQ; |
| 123043 | return (*a < *b) ? ZIP_CMP_LESS : ZIP_CMP_MORE; |
| 123044 | } |
| 123045 | |
| 123046 | static enum ZIP_CMP |
| 123047 | cmpId(const UA_UInt64 *a, const UA_UInt64 *b) { |
| 123048 | if(*a == *b) |
| 123049 | return ZIP_CMP_EQ; |
| 123050 | return (*a < *b) ? ZIP_CMP_LESS : ZIP_CMP_MORE; |
| 123051 | } |
| 123052 | |
| 123053 | ZIP_FUNCTIONS(UA_TimerTree, UA_TimerEntry, treeEntry, UA_DateTime, nextTime, cmpDateTime) |
| 123054 | ZIP_FUNCTIONS(UA_TimerIdTree, UA_TimerEntry, idTreeEntry, UA_UInt64, id, cmpId) |
| 123055 | |
| 123056 | static UA_DateTime |
| 123057 | calculateNextTime(UA_DateTime currentTime, UA_DateTime baseTime, |
| 123058 | UA_DateTime interval) { |
| 123059 | /* Take the difference between current and base time */ |
| 123060 | UA_DateTime diffCurrentTimeBaseTime = currentTime - baseTime; |
| 123061 | |
| 123062 | /* Take modulo of the diff time with the interval. This is the duration we |
| 123063 | * are already "into" the current interval. Subtract it from (current + |
| 123064 | * interval) to get the next execution time. */ |
| 123065 | UA_DateTime cycleDelay = diffCurrentTimeBaseTime % interval; |
| 123066 | |
| 123067 | /* Handle the special case where the baseTime is in the future */ |
| 123068 | if(UA_UNLIKELY(cycleDelay < 0)) |
| 123069 | cycleDelay += interval; |
| 123070 | |
| 123071 | return currentTime + interval - cycleDelay; |
| 123072 | } |
| 123073 | |
| 123074 | void |
| 123075 | UA_Timer_init(UA_Timer *t) { |
| 123076 | memset(s: t, c: 0, n: sizeof(UA_Timer)); |
| 123077 | UA_LOCK_INIT(&t->timerMutex); |
| 123078 | } |
| 123079 | |
| 123080 | /* Global variables, only used behind the mutex */ |
| 123081 | static UA_DateTime earliest, latest, adjustedNextTime; |
| 123082 | |
| 123083 | static void * |
| 123084 | findTimer2Batch(void *context, UA_TimerEntry *compare) { |
| 123085 | UA_TimerEntry *te = (UA_TimerEntry*)context; |
| 123086 | |
| 123087 | /* NextTime deviation within interval? */ |
| 123088 | if(compare->nextTime < earliest || compare->nextTime > latest) |
| 123089 | return NULL; |
| 123090 | |
| 123091 | /* Check if one interval is a multiple of the other */ |
| 123092 | if(te->interval < compare->interval && compare->interval % te->interval != 0) |
| 123093 | return NULL; |
| 123094 | if(te->interval > compare->interval && te->interval % compare->interval != 0) |
| 123095 | return NULL; |
| 123096 | |
| 123097 | adjustedNextTime = compare->nextTime; /* Candidate found */ |
| 123098 | |
| 123099 | /* Abort when a perfect match is found */ |
| 123100 | return (te->interval == compare->interval) ? te : NULL; |
| 123101 | } |
| 123102 | |
| 123103 | static UA_StatusCode |
| 123104 | addCallback(UA_Timer *t, UA_ApplicationCallback callback, void *application, |
| 123105 | void *data, UA_DateTime nextTime, UA_UInt64 interval, |
| 123106 | UA_TimerPolicy timerPolicy, UA_UInt64 *callbackId) { |
| 123107 | /* A callback method needs to be present */ |
| 123108 | if(!callback) |
| 123109 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123110 | |
| 123111 | /* Allocate the repeated callback structure */ |
| 123112 | UA_TimerEntry *te = (UA_TimerEntry*)UA_malloc(size: sizeof(UA_TimerEntry)); |
| 123113 | if(!te) |
| 123114 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 123115 | |
| 123116 | /* Set the repeated callback */ |
| 123117 | te->interval = interval; |
| 123118 | te->id = ++t->idCounter; |
| 123119 | te->callback = callback; |
| 123120 | te->application = application; |
| 123121 | te->data = data; |
| 123122 | te->nextTime = nextTime; |
| 123123 | te->timerPolicy = timerPolicy; |
| 123124 | |
| 123125 | /* Adjust the nextTime to batch cyclic callbacks. Look in an interval around |
| 123126 | * the original nextTime. Deviate from the original nextTime by at most 1/4 |
| 123127 | * of the interval and at most by 1s. */ |
| 123128 | if(timerPolicy == UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME && interval != 0) { |
| 123129 | UA_UInt64 deviate = te->interval / 4; |
| 123130 | if(deviate > UA_DATETIME_SEC) |
| 123131 | deviate = UA_DATETIME_SEC; |
| 123132 | earliest = te->nextTime - deviate; |
| 123133 | latest = te->nextTime + deviate; |
| 123134 | adjustedNextTime = te->nextTime; |
| 123135 | ZIP_ITER(UA_TimerIdTree, &t->idTree, findTimer2Batch, te); |
| 123136 | te->nextTime = adjustedNextTime; |
| 123137 | } |
| 123138 | |
| 123139 | /* Set the output identifier */ |
| 123140 | if(callbackId) |
| 123141 | *callbackId = te->id; |
| 123142 | |
| 123143 | ZIP_INSERT(UA_TimerTree, &t->tree, te); |
| 123144 | ZIP_INSERT(UA_TimerIdTree, &t->idTree, te); |
| 123145 | return UA_STATUSCODE_GOOD; |
| 123146 | } |
| 123147 | |
| 123148 | UA_StatusCode |
| 123149 | UA_Timer_addTimedCallback(UA_Timer *t, UA_ApplicationCallback callback, |
| 123150 | void *application, void *data, UA_DateTime date, |
| 123151 | UA_UInt64 *callbackId) { |
| 123152 | UA_LOCK(&t->timerMutex); |
| 123153 | UA_StatusCode res = addCallback(t, callback, application, data, nextTime: date, |
| 123154 | interval: 0, timerPolicy: UA_TIMER_HANDLE_CYCLEMISS_WITH_CURRENTTIME, |
| 123155 | callbackId); |
| 123156 | UA_UNLOCK(&t->timerMutex); |
| 123157 | return res; |
| 123158 | } |
| 123159 | |
| 123160 | /* Adding repeated callbacks: Add an entry with the "nextTime" timestamp in the |
| 123161 | * future. This will be picked up in the next iteration and inserted at the |
| 123162 | * correct place. So that the next execution takes place ät "nextTime". */ |
| 123163 | UA_StatusCode |
| 123164 | UA_Timer_addRepeatedCallback(UA_Timer *t, UA_ApplicationCallback callback, |
| 123165 | void *application, void *data, UA_Double interval_ms, |
| 123166 | UA_DateTime *baseTime, UA_TimerPolicy timerPolicy, |
| 123167 | UA_UInt64 *callbackId) { |
| 123168 | /* The interval needs to be positive */ |
| 123169 | if(interval_ms <= 0.0) |
| 123170 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123171 | UA_UInt64 interval = (UA_UInt64)(interval_ms * UA_DATETIME_MSEC); |
| 123172 | if(interval == 0) |
| 123173 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123174 | |
| 123175 | /* Compute the first time for execution */ |
| 123176 | UA_DateTime currentTime = UA_DateTime_nowMonotonic(); |
| 123177 | UA_DateTime nextTime; |
| 123178 | if(baseTime == NULL) { |
| 123179 | /* Use "now" as the basetime */ |
| 123180 | nextTime = currentTime + (UA_DateTime)interval; |
| 123181 | } else { |
| 123182 | nextTime = calculateNextTime(currentTime, baseTime: *baseTime, interval: (UA_DateTime)interval); |
| 123183 | } |
| 123184 | |
| 123185 | UA_LOCK(&t->timerMutex); |
| 123186 | UA_StatusCode res = addCallback(t, callback, application, data, nextTime, |
| 123187 | interval, timerPolicy, callbackId); |
| 123188 | UA_UNLOCK(&t->timerMutex); |
| 123189 | return res; |
| 123190 | } |
| 123191 | |
| 123192 | UA_StatusCode |
| 123193 | UA_Timer_changeRepeatedCallback(UA_Timer *t, UA_UInt64 callbackId, |
| 123194 | UA_Double interval_ms, UA_DateTime *baseTime, |
| 123195 | UA_TimerPolicy timerPolicy) { |
| 123196 | /* The interval needs to be positive */ |
| 123197 | if(interval_ms <= 0.0) |
| 123198 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123199 | UA_UInt64 interval = (UA_UInt64)(interval_ms * UA_DATETIME_MSEC); |
| 123200 | if(interval == 0) |
| 123201 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123202 | |
| 123203 | UA_LOCK(&t->timerMutex); |
| 123204 | |
| 123205 | /* Find according to the id */ |
| 123206 | UA_TimerEntry *te = ZIP_FIND(UA_TimerIdTree, &t->idTree, &callbackId); |
| 123207 | if(!te) { |
| 123208 | UA_UNLOCK(&t->timerMutex); |
| 123209 | return UA_STATUSCODE_BADNOTFOUND; |
| 123210 | } |
| 123211 | |
| 123212 | /* Try to remove from the time-sorted tree. If not found, then the entry is |
| 123213 | * in the processTree. If that is the case, leave it there and only adjust |
| 123214 | * the interval and nextTime (if the TimerPolicy uses a basetime). */ |
| 123215 | UA_Boolean normalTree = (ZIP_REMOVE(UA_TimerTree, &t->tree, te) != NULL); |
| 123216 | |
| 123217 | /* Compute the next time for execution. The logic is identical to the |
| 123218 | * creation of a new repeated callback. */ |
| 123219 | UA_DateTime currentTime = UA_DateTime_nowMonotonic(); |
| 123220 | if(baseTime == NULL) { |
| 123221 | /* Use "now" as the basetime */ |
| 123222 | te->nextTime = currentTime + (UA_DateTime)interval; |
| 123223 | } else { |
| 123224 | te->nextTime = calculateNextTime(currentTime, baseTime: *baseTime, interval: (UA_DateTime)interval); |
| 123225 | } |
| 123226 | |
| 123227 | /* Update the remaining parameters and re-insert */ |
| 123228 | te->interval = interval; |
| 123229 | te->timerPolicy = timerPolicy; |
| 123230 | |
| 123231 | if(normalTree) |
| 123232 | ZIP_INSERT(UA_TimerTree, &t->tree, te); |
| 123233 | |
| 123234 | UA_UNLOCK(&t->timerMutex); |
| 123235 | return UA_STATUSCODE_GOOD; |
| 123236 | } |
| 123237 | |
| 123238 | void |
| 123239 | UA_Timer_removeCallback(UA_Timer *t, UA_UInt64 callbackId) { |
| 123240 | UA_LOCK(&t->timerMutex); |
| 123241 | UA_TimerEntry *te = ZIP_FIND(UA_TimerIdTree, &t->idTree, &callbackId); |
| 123242 | if(UA_LIKELY(te != NULL)) { |
| 123243 | if(t->processTree.root == NULL) { |
| 123244 | /* Remove/free the entry */ |
| 123245 | ZIP_REMOVE(UA_TimerTree, &t->tree, te); |
| 123246 | ZIP_REMOVE(UA_TimerIdTree, &t->idTree, te); |
| 123247 | UA_free(ptr: te); |
| 123248 | } else { |
| 123249 | /* We are currently processing. Only mark the entry to be deleted. |
| 123250 | * Will be removed/freed the next time we reach it in the processing |
| 123251 | * callback. */ |
| 123252 | te->callback = NULL; |
| 123253 | } |
| 123254 | } |
| 123255 | UA_UNLOCK(&t->timerMutex); |
| 123256 | } |
| 123257 | |
| 123258 | struct TimerProcessContext { |
| 123259 | UA_Timer *t; |
| 123260 | UA_DateTime nowMonotonic; |
| 123261 | }; |
| 123262 | |
| 123263 | static void * |
| 123264 | processEntryCallback(void *context, UA_TimerEntry *te) { |
| 123265 | struct TimerProcessContext *tpc = (struct TimerProcessContext*)context; |
| 123266 | UA_Timer *t = tpc->t; |
| 123267 | |
| 123268 | /* Execute the callback. The memory is not freed during the callback. |
| 123269 | * Instead, whenever t->processTree != NULL, the entries are only marked for |
| 123270 | * deletion by setting elm->callback to NULL. */ |
| 123271 | if(te->callback) { |
| 123272 | te->callback(te->application, te->data); |
| 123273 | } |
| 123274 | |
| 123275 | /* Remove and free the entry if marked for deletion or a one-time timed |
| 123276 | * callback */ |
| 123277 | if(!te->callback || te->interval == 0) { |
| 123278 | ZIP_REMOVE(UA_TimerIdTree, &t->idTree, te); |
| 123279 | UA_free(ptr: te); |
| 123280 | return NULL; |
| 123281 | } |
| 123282 | |
| 123283 | /* Set the time for the next regular execution */ |
| 123284 | te->nextTime += (UA_DateTime)te->interval; |
| 123285 | |
| 123286 | /* Handle the case where the "window" was missed. E.g. due to congestion of |
| 123287 | * the application or if the clock was shifted. |
| 123288 | * |
| 123289 | * If the timer policy is "CurrentTime", then there is at least the |
| 123290 | * interval between executions. This is used for Monitoreditems, for |
| 123291 | * which the spec says: The sampling interval indicates the fastest rate |
| 123292 | * at which the Server should sample its underlying source for data |
| 123293 | * changes. (Part 4, 5.12.1.2) */ |
| 123294 | if(te->nextTime < tpc->nowMonotonic) { |
| 123295 | if(te->timerPolicy == UA_TIMER_HANDLE_CYCLEMISS_WITH_BASETIME) |
| 123296 | te->nextTime = calculateNextTime(currentTime: tpc->nowMonotonic, baseTime: te->nextTime, |
| 123297 | interval: (UA_DateTime)te->interval); |
| 123298 | else |
| 123299 | te->nextTime = tpc->nowMonotonic + (UA_DateTime)te->interval; |
| 123300 | } |
| 123301 | |
| 123302 | /* Insert back into the time-sorted tree */ |
| 123303 | ZIP_INSERT(UA_TimerTree, &t->tree, te); |
| 123304 | return NULL; |
| 123305 | } |
| 123306 | |
| 123307 | UA_DateTime |
| 123308 | UA_Timer_process(UA_Timer *t, UA_DateTime nowMonotonic) { |
| 123309 | UA_LOCK(&t->timerMutex); |
| 123310 | |
| 123311 | /* Not reentrant. Don't call _process from within _process. */ |
| 123312 | if(!t->processTree.root) { |
| 123313 | /* Move all entries <= nowMonotonic to processTree */ |
| 123314 | ZIP_UNZIP(UA_TimerTree, &t->tree, &nowMonotonic, |
| 123315 | &t->processTree, &t->tree); |
| 123316 | |
| 123317 | /* Consistency check. The smallest not-processed entry isn't ready. */ |
| 123318 | UA_assert(!ZIP_MIN(UA_TimerTree, &t->tree) || |
| 123319 | ZIP_MIN(UA_TimerTree, &t->tree)->nextTime > nowMonotonic); |
| 123320 | |
| 123321 | /* Iterate over the entries that need processing in-order. This also |
| 123322 | * moves them back to the regular time-ordered tree. */ |
| 123323 | struct TimerProcessContext ctx; |
| 123324 | ctx.t = t; |
| 123325 | ctx.nowMonotonic = nowMonotonic; |
| 123326 | ZIP_ITER(UA_TimerTree, &t->processTree, processEntryCallback, &ctx); |
| 123327 | |
| 123328 | /* Reset processTree. All entries are already moved to the normal tree. */ |
| 123329 | t->processTree.root = NULL; |
| 123330 | } |
| 123331 | |
| 123332 | /* Compute the timestamp of the earliest next callback */ |
| 123333 | UA_TimerEntry *first = ZIP_MIN(UA_TimerTree, &t->tree); |
| 123334 | UA_DateTime next = (first) ? first->nextTime : UA_INT64_MAX; |
| 123335 | if(next < nowMonotonic) |
| 123336 | next = nowMonotonic; |
| 123337 | |
| 123338 | UA_UNLOCK(&t->timerMutex); |
| 123339 | return next; |
| 123340 | } |
| 123341 | |
| 123342 | UA_DateTime |
| 123343 | UA_Timer_nextRepeatedTime(UA_Timer *t) { |
| 123344 | UA_LOCK(&t->timerMutex); |
| 123345 | UA_TimerEntry *first = ZIP_MIN(UA_TimerTree, &t->tree); |
| 123346 | UA_DateTime next = (first) ? first->nextTime : UA_INT64_MAX; |
| 123347 | UA_UNLOCK(&t->timerMutex); |
| 123348 | return next; |
| 123349 | } |
| 123350 | |
| 123351 | static void * |
| 123352 | freeEntryCallback(void *context, UA_TimerEntry *entry) { |
| 123353 | UA_free(ptr: entry); |
| 123354 | return NULL; |
| 123355 | } |
| 123356 | |
| 123357 | void |
| 123358 | UA_Timer_clear(UA_Timer *t) { |
| 123359 | UA_LOCK(&t->timerMutex); |
| 123360 | |
| 123361 | ZIP_ITER(UA_TimerIdTree, &t->idTree, freeEntryCallback, NULL); |
| 123362 | t->tree.root = NULL; |
| 123363 | t->idTree.root = NULL; |
| 123364 | t->idCounter = 0; |
| 123365 | |
| 123366 | UA_UNLOCK(&t->timerMutex); |
| 123367 | |
| 123368 | #if UA_MULTITHREADING >= 100 |
| 123369 | UA_LOCK_DESTROY(&t->timerMutex); |
| 123370 | #endif |
| 123371 | } |
| 123372 | |
| 123373 | /**** amalgamated original file "/arch/eventloop_common.c" ****/ |
| 123374 | |
| 123375 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 123376 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 123377 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 123378 | * |
| 123379 | * Copyright 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 123380 | */ |
| 123381 | |
| 123382 | |
| 123383 | UA_StatusCode |
| 123384 | UA_KeyValueRestriction_validate(const UA_Logger *logger, const char *logprefix, |
| 123385 | const UA_KeyValueRestriction *restrictions, size_t restrictionsSize, |
| 123386 | const UA_KeyValueMap *map) { |
| 123387 | for(size_t i = 0; i < restrictionsSize; i++) { |
| 123388 | const UA_KeyValueRestriction *r = &restrictions[i]; |
| 123389 | const UA_Variant *val = UA_KeyValueMap_get(map, key: r->name); |
| 123390 | |
| 123391 | /* Value not present but required? */ |
| 123392 | if(!val) { |
| 123393 | if(r->required) { |
| 123394 | UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_USERLAND, |
| 123395 | msg: "%s\t| Parameter %.*s required but not defined", |
| 123396 | logprefix, (int)r->name.name.length, (char*)r->name.name.data); |
| 123397 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123398 | } |
| 123399 | continue; |
| 123400 | } |
| 123401 | |
| 123402 | /* Type matches */ |
| 123403 | if(val->type != r->type) { |
| 123404 | UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_USERLAND, |
| 123405 | msg: "%s\t| Parameter %.*s has the wrong type", |
| 123406 | logprefix, (int)r->name.name.length, (char*)r->name.name.data); |
| 123407 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123408 | } |
| 123409 | |
| 123410 | /* Scalar / array is allowed */ |
| 123411 | UA_Boolean scalar = UA_Variant_isScalar(v: val); |
| 123412 | if(scalar && !r->scalar) { |
| 123413 | UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_USERLAND, |
| 123414 | msg: "%s\t| Parameter %.*s must not be scalar", |
| 123415 | logprefix, (int)r->name.name.length, (char*)r->name.name.data); |
| 123416 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123417 | } |
| 123418 | if(!scalar && !r->array) { |
| 123419 | UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_USERLAND, |
| 123420 | msg: "%s\t| Parameter %.*s must not be an array", |
| 123421 | logprefix, (int)r->name.name.length, (char*)r->name.name.data); |
| 123422 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 123423 | } |
| 123424 | } |
| 123425 | |
| 123426 | return UA_STATUSCODE_GOOD; |
| 123427 | } |
| 123428 | |
| 123429 | /**** amalgamated original file "/arch/eventloop_posix.c" ****/ |
| 123430 | |
| 123431 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 123432 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 123433 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 123434 | * |
| 123435 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 123436 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes) |
| 123437 | */ |
| 123438 | |
| 123439 | |
| 123440 | /*********/ |
| 123441 | /* Timer */ |
| 123442 | /*********/ |
| 123443 | |
| 123444 | /* Process delayed callbacks immediately */ |
| 123445 | static UA_DateTime |
| 123446 | UA_EventLoopPOSIX_nextCyclicTime(UA_EventLoop *public_el) { |
| 123447 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)public_el; |
| 123448 | if(el->delayedCallbacks) |
| 123449 | el->eventLoop.dateTime_nowMonotonic(&el->eventLoop); |
| 123450 | return UA_Timer_nextRepeatedTime(t: &el->timer); |
| 123451 | } |
| 123452 | |
| 123453 | static UA_StatusCode |
| 123454 | UA_EventLoopPOSIX_addTimedCallback(UA_EventLoop *public_el, |
| 123455 | UA_Callback callback, |
| 123456 | void *application, void *data, |
| 123457 | UA_DateTime date, |
| 123458 | UA_UInt64 *callbackId) { |
| 123459 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)public_el; |
| 123460 | return UA_Timer_addTimedCallback(t: &el->timer, callback, application, |
| 123461 | data, date, callbackId); |
| 123462 | } |
| 123463 | |
| 123464 | static UA_StatusCode |
| 123465 | UA_EventLoopPOSIX_addCyclicCallback(UA_EventLoop *public_el, |
| 123466 | UA_Callback cb, |
| 123467 | void *application, void *data, |
| 123468 | UA_Double interval_ms, |
| 123469 | UA_DateTime *baseTime, |
| 123470 | UA_TimerPolicy timerPolicy, |
| 123471 | UA_UInt64 *callbackId) { |
| 123472 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)public_el; |
| 123473 | return UA_Timer_addRepeatedCallback(t: &el->timer, callback: cb, application, |
| 123474 | data, interval_ms, baseTime, |
| 123475 | timerPolicy, callbackId); |
| 123476 | } |
| 123477 | |
| 123478 | static UA_StatusCode |
| 123479 | UA_EventLoopPOSIX_modifyCyclicCallback(UA_EventLoop *public_el, |
| 123480 | UA_UInt64 callbackId, |
| 123481 | UA_Double interval_ms, |
| 123482 | UA_DateTime *baseTime, |
| 123483 | UA_TimerPolicy timerPolicy) { |
| 123484 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)public_el; |
| 123485 | return UA_Timer_changeRepeatedCallback(t: &el->timer, callbackId, |
| 123486 | interval_ms, baseTime, |
| 123487 | timerPolicy); |
| 123488 | } |
| 123489 | |
| 123490 | static void |
| 123491 | UA_EventLoopPOSIX_removeCyclicCallback(UA_EventLoop *public_el, |
| 123492 | UA_UInt64 callbackId) { |
| 123493 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)public_el; |
| 123494 | UA_Timer_removeCallback(t: &el->timer, callbackId); |
| 123495 | } |
| 123496 | |
| 123497 | static void |
| 123498 | UA_EventLoopPOSIX_addDelayedCallback(UA_EventLoop *public_el, |
| 123499 | UA_DelayedCallback *dc) { |
| 123500 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)public_el; |
| 123501 | UA_LOCK(&el->elMutex); |
| 123502 | dc->next = el->delayedCallbacks; |
| 123503 | el->delayedCallbacks = dc; |
| 123504 | UA_UNLOCK(&el->elMutex); |
| 123505 | } |
| 123506 | |
| 123507 | static void |
| 123508 | UA_EventLoopPOSIX_removeDelayedCallback(UA_EventLoop *public_el, |
| 123509 | UA_DelayedCallback *dc) { |
| 123510 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)public_el; |
| 123511 | UA_LOCK(&el->elMutex); |
| 123512 | UA_DelayedCallback **prev = &el->delayedCallbacks; |
| 123513 | while(*prev) { |
| 123514 | if(*prev == dc) { |
| 123515 | *prev = (*prev)->next; |
| 123516 | UA_UNLOCK(&el->elMutex); |
| 123517 | return; |
| 123518 | } |
| 123519 | prev = &(*prev)->next; |
| 123520 | } |
| 123521 | UA_UNLOCK(&el->elMutex); |
| 123522 | } |
| 123523 | |
| 123524 | /* Process and then free registered delayed callbacks */ |
| 123525 | static void |
| 123526 | processDelayed(UA_EventLoopPOSIX *el) { |
| 123527 | UA_LOG_TRACE(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 123528 | msg: "Process delayed callbacks"); |
| 123529 | |
| 123530 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 123531 | |
| 123532 | /* First empty the linked list in the el. So a delayed callback can add |
| 123533 | * (itself) to the list. New entries are then processed during the next |
| 123534 | * iteration. */ |
| 123535 | UA_DelayedCallback *dc = el->delayedCallbacks, *next = NULL; |
| 123536 | el->delayedCallbacks = NULL; |
| 123537 | |
| 123538 | for(; dc; dc = next) { |
| 123539 | next = dc->next; |
| 123540 | /* Delayed Callbacks might have no callback set. We don't return a |
| 123541 | * StatusCode during "add" and don't validate. So test here. */ |
| 123542 | if(!dc->callback) |
| 123543 | continue; |
| 123544 | dc->callback(dc->application, dc->context); |
| 123545 | } |
| 123546 | } |
| 123547 | |
| 123548 | /***********************/ |
| 123549 | /* EventLoop Lifecycle */ |
| 123550 | /***********************/ |
| 123551 | |
| 123552 | static UA_StatusCode |
| 123553 | UA_EventLoopPOSIX_start(UA_EventLoopPOSIX *el) { |
| 123554 | UA_LOCK(&el->elMutex); |
| 123555 | |
| 123556 | if(el->eventLoop.state != UA_EVENTLOOPSTATE_FRESH && |
| 123557 | el->eventLoop.state != UA_EVENTLOOPSTATE_STOPPED) { |
| 123558 | UA_UNLOCK(&el->elMutex); |
| 123559 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123560 | } |
| 123561 | |
| 123562 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 123563 | msg: "Starting the EventLoop"); |
| 123564 | |
| 123565 | #ifdef UA_HAVE_EPOLL |
| 123566 | el->epollfd = epoll_create1(flags: 0); |
| 123567 | if(el->epollfd == -1) { |
| 123568 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 123569 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 123570 | "Eventloop\t| Could not create the epoll socket (%s)", |
| 123571 | errno_str)); |
| 123572 | UA_UNLOCK(&el->elMutex); |
| 123573 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123574 | } |
| 123575 | #endif |
| 123576 | |
| 123577 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 123578 | UA_EventSource *es = el->eventLoop.eventSources; |
| 123579 | while(es) { |
| 123580 | res |= es->start(es); |
| 123581 | es = es->next; |
| 123582 | } |
| 123583 | |
| 123584 | /* Dirty-write the state that is const "from the outside" */ |
| 123585 | *(UA_EventLoopState*)(uintptr_t)&el->eventLoop.state = |
| 123586 | UA_EVENTLOOPSTATE_STARTED; |
| 123587 | |
| 123588 | UA_UNLOCK(&el->elMutex); |
| 123589 | return res; |
| 123590 | } |
| 123591 | |
| 123592 | static void |
| 123593 | checkClosed(UA_EventLoopPOSIX *el) { |
| 123594 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 123595 | |
| 123596 | UA_EventSource *es = el->eventLoop.eventSources; |
| 123597 | while(es) { |
| 123598 | if(es->state != UA_EVENTSOURCESTATE_STOPPED) |
| 123599 | return; |
| 123600 | es = es->next; |
| 123601 | } |
| 123602 | |
| 123603 | /* Not closed until all delayed callbacks are processed */ |
| 123604 | if(el->delayedCallbacks != NULL) |
| 123605 | return; |
| 123606 | |
| 123607 | /* Dirty-write the state that is const "from the outside" */ |
| 123608 | *(UA_EventLoopState*)(uintptr_t)&el->eventLoop.state = |
| 123609 | UA_EVENTLOOPSTATE_STOPPED; |
| 123610 | |
| 123611 | /* Close the epoll/IOCP socket once all EventSources have shut down */ |
| 123612 | #ifdef UA_HAVE_EPOLL |
| 123613 | close(fd: el->epollfd); |
| 123614 | #endif |
| 123615 | |
| 123616 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 123617 | msg: "The EventLoop has stopped"); |
| 123618 | } |
| 123619 | |
| 123620 | static void |
| 123621 | UA_EventLoopPOSIX_stop(UA_EventLoopPOSIX *el) { |
| 123622 | UA_LOCK(&el->elMutex); |
| 123623 | |
| 123624 | if(el->eventLoop.state != UA_EVENTLOOPSTATE_STARTED) { |
| 123625 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 123626 | msg: "The EventLoop is not running, cannot be stopped"); |
| 123627 | UA_UNLOCK(&el->elMutex); |
| 123628 | return; |
| 123629 | } |
| 123630 | |
| 123631 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 123632 | msg: "Stopping the EventLoop"); |
| 123633 | |
| 123634 | /* Set to STOPPING to prevent "normal use" */ |
| 123635 | *(UA_EventLoopState*)(uintptr_t)&el->eventLoop.state = |
| 123636 | UA_EVENTLOOPSTATE_STOPPING; |
| 123637 | |
| 123638 | /* Stop all event sources (asynchronous) */ |
| 123639 | UA_EventSource *es = el->eventLoop.eventSources; |
| 123640 | for(; es; es = es->next) { |
| 123641 | if(es->state == UA_EVENTSOURCESTATE_STARTING || |
| 123642 | es->state == UA_EVENTSOURCESTATE_STARTED) { |
| 123643 | es->stop(es); |
| 123644 | } |
| 123645 | } |
| 123646 | |
| 123647 | /* Set to STOPPED if all EventSources are STOPPED */ |
| 123648 | checkClosed(el); |
| 123649 | |
| 123650 | UA_UNLOCK(&el->elMutex); |
| 123651 | } |
| 123652 | |
| 123653 | static UA_StatusCode |
| 123654 | UA_EventLoopPOSIX_run(UA_EventLoopPOSIX *el, UA_UInt32 timeout) { |
| 123655 | UA_LOCK(&el->elMutex); |
| 123656 | |
| 123657 | if(el->executing) { |
| 123658 | UA_LOG_ERROR(logger: el->eventLoop.logger, |
| 123659 | category: UA_LOGCATEGORY_EVENTLOOP, |
| 123660 | msg: "Cannot run EventLoop from the run method itself"); |
| 123661 | UA_UNLOCK(&el->elMutex); |
| 123662 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123663 | } |
| 123664 | |
| 123665 | el->executing = true; |
| 123666 | |
| 123667 | if(el->eventLoop.state == UA_EVENTLOOPSTATE_FRESH || |
| 123668 | el->eventLoop.state == UA_EVENTLOOPSTATE_STOPPED) { |
| 123669 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 123670 | msg: "Cannot iterate a stopped EventLoop"); |
| 123671 | el->executing = false; |
| 123672 | UA_UNLOCK(&el->elMutex); |
| 123673 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123674 | } |
| 123675 | |
| 123676 | UA_LOG_TRACE(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 123677 | msg: "Iterate the EventLoop"); |
| 123678 | |
| 123679 | /* Process cyclic callbacks */ |
| 123680 | UA_DateTime dateBefore = |
| 123681 | el->eventLoop.dateTime_nowMonotonic(&el->eventLoop); |
| 123682 | |
| 123683 | UA_DateTime dateNext = UA_Timer_process(t: &el->timer, nowMonotonic: dateBefore); |
| 123684 | |
| 123685 | /* Process delayed callbacks here: |
| 123686 | * - Removes closed sockets already here instead of polling them again. |
| 123687 | * - The timeout for polling is selected to be ready in time for the next |
| 123688 | * cyclic callback. So we want to do little work between the timeout |
| 123689 | * running out and executing the due cyclic callbacks. */ |
| 123690 | processDelayed(el); |
| 123691 | |
| 123692 | /* A delayed callback could create another delayed callback (or re-add |
| 123693 | * itself). In that case we don't want to wait (indefinitely) for an event |
| 123694 | * to happen. Process queued events but don't sleep. Then process the |
| 123695 | * delayed callbacks in the next iteration. */ |
| 123696 | if(el->delayedCallbacks != NULL) |
| 123697 | timeout = 0; |
| 123698 | |
| 123699 | /* Compute the remaining time */ |
| 123700 | UA_DateTime maxDate = dateBefore + (timeout * UA_DATETIME_MSEC); |
| 123701 | if(dateNext > maxDate) |
| 123702 | dateNext = maxDate; |
| 123703 | UA_DateTime listenTimeout = |
| 123704 | dateNext - el->eventLoop.dateTime_nowMonotonic(&el->eventLoop); |
| 123705 | if(listenTimeout < 0) |
| 123706 | listenTimeout = 0; |
| 123707 | |
| 123708 | /* Listen on the active file-descriptors (sockets) from the |
| 123709 | * ConnectionManagers */ |
| 123710 | UA_StatusCode rv = UA_EventLoopPOSIX_pollFDs(el, listenTimeout); |
| 123711 | |
| 123712 | /* Check if the last EventSource was successfully stopped */ |
| 123713 | if(el->eventLoop.state == UA_EVENTLOOPSTATE_STOPPING) |
| 123714 | checkClosed(el); |
| 123715 | |
| 123716 | el->executing = false; |
| 123717 | UA_UNLOCK(&el->elMutex); |
| 123718 | return rv; |
| 123719 | } |
| 123720 | |
| 123721 | /*****************************/ |
| 123722 | /* Registering Event Sources */ |
| 123723 | /*****************************/ |
| 123724 | |
| 123725 | static UA_StatusCode |
| 123726 | UA_EventLoopPOSIX_registerEventSource(UA_EventLoopPOSIX *el, |
| 123727 | UA_EventSource *es) { |
| 123728 | UA_LOCK(&el->elMutex); |
| 123729 | |
| 123730 | /* Already registered? */ |
| 123731 | if(es->state != UA_EVENTSOURCESTATE_FRESH) { |
| 123732 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 123733 | msg: "Cannot register the EventSource \"%.*s\": " |
| 123734 | "already registered", |
| 123735 | (int)es->name.length, (char*)es->name.data); |
| 123736 | UA_UNLOCK(&el->elMutex); |
| 123737 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123738 | } |
| 123739 | |
| 123740 | /* Add to linked list */ |
| 123741 | es->next = el->eventLoop.eventSources; |
| 123742 | el->eventLoop.eventSources = es; |
| 123743 | |
| 123744 | es->eventLoop = &el->eventLoop; |
| 123745 | es->state = UA_EVENTSOURCESTATE_STOPPED; |
| 123746 | |
| 123747 | /* Start if the entire EventLoop is started */ |
| 123748 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 123749 | if(el->eventLoop.state == UA_EVENTLOOPSTATE_STARTED) |
| 123750 | res = es->start(es); |
| 123751 | |
| 123752 | UA_UNLOCK(&el->elMutex); |
| 123753 | return res; |
| 123754 | } |
| 123755 | |
| 123756 | static UA_StatusCode |
| 123757 | UA_EventLoopPOSIX_deregisterEventSource(UA_EventLoopPOSIX *el, |
| 123758 | UA_EventSource *es) { |
| 123759 | UA_LOCK(&el->elMutex); |
| 123760 | |
| 123761 | if(es->state != UA_EVENTSOURCESTATE_STOPPED) { |
| 123762 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 123763 | msg: "Cannot deregister the EventSource %.*s: " |
| 123764 | "Has to be stopped first", |
| 123765 | (int)es->name.length, es->name.data); |
| 123766 | UA_UNLOCK(&el->elMutex); |
| 123767 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123768 | } |
| 123769 | |
| 123770 | /* Remove from the linked list */ |
| 123771 | UA_EventSource **s = &el->eventLoop.eventSources; |
| 123772 | while(*s) { |
| 123773 | if(*s == es) { |
| 123774 | *s = es->next; |
| 123775 | break; |
| 123776 | } |
| 123777 | s = &(*s)->next; |
| 123778 | } |
| 123779 | |
| 123780 | /* Set the state to non-registered */ |
| 123781 | es->state = UA_EVENTSOURCESTATE_FRESH; |
| 123782 | |
| 123783 | UA_UNLOCK(&el->elMutex); |
| 123784 | return UA_STATUSCODE_GOOD; |
| 123785 | } |
| 123786 | |
| 123787 | /***************/ |
| 123788 | /* Time Domain */ |
| 123789 | /***************/ |
| 123790 | |
| 123791 | /* No special synchronization with an external source, just use the globally |
| 123792 | * defined functions. */ |
| 123793 | |
| 123794 | static UA_DateTime |
| 123795 | UA_EventLoopPOSIX_DateTime_now(UA_EventLoop *el) { |
| 123796 | return UA_DateTime_now(); |
| 123797 | } |
| 123798 | |
| 123799 | static UA_DateTime |
| 123800 | UA_EventLoopPOSIX_DateTime_nowMonotonic(UA_EventLoop *el) { |
| 123801 | return UA_DateTime_nowMonotonic(); |
| 123802 | } |
| 123803 | |
| 123804 | static UA_Int64 |
| 123805 | UA_EventLoopPOSIX_DateTime_localTimeUtcOffset(UA_EventLoop *el) { |
| 123806 | return UA_DateTime_localTimeUtcOffset(); |
| 123807 | } |
| 123808 | |
| 123809 | /*************************/ |
| 123810 | /* Initialize and Delete */ |
| 123811 | /*************************/ |
| 123812 | |
| 123813 | static UA_StatusCode |
| 123814 | UA_EventLoopPOSIX_free(UA_EventLoopPOSIX *el) { |
| 123815 | UA_LOCK(&el->elMutex); |
| 123816 | |
| 123817 | /* Check if the EventLoop can be deleted */ |
| 123818 | if(el->eventLoop.state != UA_EVENTLOOPSTATE_STOPPED && |
| 123819 | el->eventLoop.state != UA_EVENTLOOPSTATE_FRESH) { |
| 123820 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 123821 | msg: "Cannot delete a running EventLoop"); |
| 123822 | UA_UNLOCK(&el->elMutex); |
| 123823 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123824 | } |
| 123825 | |
| 123826 | /* Deregister and delete all the EventSources */ |
| 123827 | while(el->eventLoop.eventSources) { |
| 123828 | UA_EventSource *es = el->eventLoop.eventSources; |
| 123829 | UA_EventLoopPOSIX_deregisterEventSource(el, es); |
| 123830 | es->free(es); |
| 123831 | } |
| 123832 | |
| 123833 | /* Remove the repeated timed callbacks */ |
| 123834 | UA_Timer_clear(t: &el->timer); |
| 123835 | |
| 123836 | /* Process remaining delayed callbacks */ |
| 123837 | processDelayed(el); |
| 123838 | |
| 123839 | #ifdef UA_ARCHITECTURE_WIN32 |
| 123840 | /* Stop the Windows networking subsystem */ |
| 123841 | WSACleanup(); |
| 123842 | #endif |
| 123843 | |
| 123844 | /* Clean up */ |
| 123845 | UA_UNLOCK(&el->elMutex); |
| 123846 | UA_LOCK_DESTROY(&el->elMutex); |
| 123847 | UA_free(ptr: el); |
| 123848 | return UA_STATUSCODE_GOOD; |
| 123849 | } |
| 123850 | |
| 123851 | static void |
| 123852 | UA_EventLoopPOSIX_lock(UA_EventLoop *public_el) { |
| 123853 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)public_el; |
| 123854 | UA_LOCK(&el->elMutex); |
| 123855 | } |
| 123856 | |
| 123857 | static void |
| 123858 | UA_EventLoopPOSIX_unlock(UA_EventLoop *public_el) { |
| 123859 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)public_el; |
| 123860 | UA_UNLOCK(&el->elMutex); |
| 123861 | } |
| 123862 | |
| 123863 | UA_EventLoop * |
| 123864 | UA_EventLoop_new_POSIX(const UA_Logger *logger) { |
| 123865 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*) |
| 123866 | UA_calloc(nmemb: 1, size: sizeof(UA_EventLoopPOSIX)); |
| 123867 | if(!el) |
| 123868 | return NULL; |
| 123869 | |
| 123870 | UA_LOCK_INIT(&el->elMutex); |
| 123871 | UA_Timer_init(t: &el->timer); |
| 123872 | |
| 123873 | #ifdef UA_ARCHITECTURE_WIN32 |
| 123874 | /* Start the WSA networking subsystem on Windows */ |
| 123875 | WSADATA wsaData; |
| 123876 | WSAStartup(MAKEWORD(2, 2), &wsaData); |
| 123877 | #endif |
| 123878 | |
| 123879 | /* Set the public EventLoop content */ |
| 123880 | el->eventLoop.logger = logger; |
| 123881 | |
| 123882 | el->eventLoop.start = (UA_StatusCode (*)(UA_EventLoop*))UA_EventLoopPOSIX_start; |
| 123883 | el->eventLoop.stop = (void (*)(UA_EventLoop*))UA_EventLoopPOSIX_stop; |
| 123884 | el->eventLoop.run = (UA_StatusCode (*)(UA_EventLoop*, UA_UInt32))UA_EventLoopPOSIX_run; |
| 123885 | el->eventLoop.free = (UA_StatusCode (*)(UA_EventLoop*))UA_EventLoopPOSIX_free; |
| 123886 | |
| 123887 | el->eventLoop.dateTime_now = UA_EventLoopPOSIX_DateTime_now; |
| 123888 | el->eventLoop.dateTime_nowMonotonic = |
| 123889 | UA_EventLoopPOSIX_DateTime_nowMonotonic; |
| 123890 | el->eventLoop.dateTime_localTimeUtcOffset = |
| 123891 | UA_EventLoopPOSIX_DateTime_localTimeUtcOffset; |
| 123892 | |
| 123893 | el->eventLoop.nextCyclicTime = UA_EventLoopPOSIX_nextCyclicTime; |
| 123894 | el->eventLoop.addCyclicCallback = UA_EventLoopPOSIX_addCyclicCallback; |
| 123895 | el->eventLoop.modifyCyclicCallback = UA_EventLoopPOSIX_modifyCyclicCallback; |
| 123896 | el->eventLoop.removeCyclicCallback = UA_EventLoopPOSIX_removeCyclicCallback; |
| 123897 | el->eventLoop.addTimedCallback = UA_EventLoopPOSIX_addTimedCallback; |
| 123898 | el->eventLoop.addDelayedCallback = UA_EventLoopPOSIX_addDelayedCallback; |
| 123899 | el->eventLoop.removeDelayedCallback = UA_EventLoopPOSIX_removeDelayedCallback; |
| 123900 | |
| 123901 | el->eventLoop.registerEventSource = |
| 123902 | (UA_StatusCode (*)(UA_EventLoop*, UA_EventSource*)) |
| 123903 | UA_EventLoopPOSIX_registerEventSource; |
| 123904 | el->eventLoop.deregisterEventSource = |
| 123905 | (UA_StatusCode (*)(UA_EventLoop*, UA_EventSource*)) |
| 123906 | UA_EventLoopPOSIX_deregisterEventSource; |
| 123907 | |
| 123908 | el->eventLoop.lock = UA_EventLoopPOSIX_lock; |
| 123909 | el->eventLoop.unlock = UA_EventLoopPOSIX_unlock; |
| 123910 | |
| 123911 | return &el->eventLoop; |
| 123912 | } |
| 123913 | |
| 123914 | /* Reusable EventSource functionality */ |
| 123915 | |
| 123916 | UA_StatusCode |
| 123917 | UA_EventLoopPOSIX_allocNetworkBuffer(UA_ConnectionManager *cm, |
| 123918 | uintptr_t connectionId, |
| 123919 | UA_ByteString *buf, |
| 123920 | size_t bufSize) { |
| 123921 | return UA_ByteString_allocBuffer(bs: buf, length: bufSize); |
| 123922 | } |
| 123923 | |
| 123924 | void |
| 123925 | UA_EventLoopPOSIX_freeNetworkBuffer(UA_ConnectionManager *cm, |
| 123926 | uintptr_t connectionId, |
| 123927 | UA_ByteString *buf) { |
| 123928 | UA_ByteString_clear(p: buf); |
| 123929 | } |
| 123930 | |
| 123931 | UA_StatusCode |
| 123932 | UA_EventLoopPOSIX_allocateRXBuffer(UA_POSIXConnectionManager *pcm) { |
| 123933 | UA_UInt32 rxBufSize = 2u << 16; /* The default is 64kb */ |
| 123934 | const UA_UInt32 *configRxBufSize = (const UA_UInt32 *) |
| 123935 | UA_KeyValueMap_getScalar(map: &pcm->cm.eventSource.params, |
| 123936 | key: UA_QUALIFIEDNAME(nsIndex: 0, chars: "recv-bufsize"), |
| 123937 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 123938 | if(configRxBufSize) |
| 123939 | rxBufSize = *configRxBufSize; |
| 123940 | if(pcm->rxBuffer.length != rxBufSize) { |
| 123941 | UA_ByteString_clear(p: &pcm->rxBuffer); |
| 123942 | return UA_ByteString_allocBuffer(bs: &pcm->rxBuffer, length: rxBufSize); |
| 123943 | } |
| 123944 | return UA_STATUSCODE_GOOD; |
| 123945 | } |
| 123946 | |
| 123947 | /* Socket Handling */ |
| 123948 | |
| 123949 | enum ZIP_CMP |
| 123950 | cmpFD(const UA_FD *a, const UA_FD *b) { |
| 123951 | if(*a == *b) |
| 123952 | return ZIP_CMP_EQ; |
| 123953 | return (*a < *b) ? ZIP_CMP_LESS : ZIP_CMP_MORE; |
| 123954 | } |
| 123955 | |
| 123956 | UA_StatusCode |
| 123957 | UA_EventLoopPOSIX_setNonBlocking(UA_FD sockfd) { |
| 123958 | #ifndef UA_ARCHITECTURE_WIN32 |
| 123959 | int opts = fcntl(fd: sockfd, F_GETFL); |
| 123960 | if(opts < 0 || fcntl(fd: sockfd, F_SETFL, opts | O_NONBLOCK) < 0) |
| 123961 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123962 | #else |
| 123963 | u_long iMode = 1; |
| 123964 | if(ioctlsocket(sockfd, FIONBIO, &iMode) != NO_ERROR) |
| 123965 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123966 | #endif |
| 123967 | return UA_STATUSCODE_GOOD; |
| 123968 | } |
| 123969 | |
| 123970 | UA_StatusCode |
| 123971 | UA_EventLoopPOSIX_setNoSigPipe(UA_FD sockfd) { |
| 123972 | #ifdef SO_NOSIGPIPE |
| 123973 | int val = 1; |
| 123974 | int res = UA_setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof(val)); |
| 123975 | if(res < 0) |
| 123976 | return UA_STATUSCODE_BADINTERNALERROR; |
| 123977 | #endif |
| 123978 | return UA_STATUSCODE_GOOD; |
| 123979 | } |
| 123980 | |
| 123981 | UA_StatusCode |
| 123982 | UA_EventLoopPOSIX_setReusable(UA_FD sockfd) { |
| 123983 | int enableReuseVal = 1; |
| 123984 | #ifndef UA_ARCHITECTURE_WIN32 |
| 123985 | int res = UA_setsockopt(fd: sockfd, SOL_SOCKET, SO_REUSEADDR, |
| 123986 | optval: (const char*)&enableReuseVal, optlen: sizeof(enableReuseVal)); |
| 123987 | res |= UA_setsockopt(fd: sockfd, SOL_SOCKET, SO_REUSEPORT, |
| 123988 | optval: (const char*)&enableReuseVal, optlen: sizeof(enableReuseVal)); |
| 123989 | return (res == 0) ? UA_STATUSCODE_GOOD : UA_STATUSCODE_BADINTERNALERROR; |
| 123990 | #else |
| 123991 | int res = UA_setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, |
| 123992 | (const char*)&enableReuseVal, sizeof(enableReuseVal)); |
| 123993 | return (res == 0) ? UA_STATUSCODE_GOOD : UA_STATUSCODE_BADINTERNALERROR; |
| 123994 | #endif |
| 123995 | } |
| 123996 | |
| 123997 | /**** amalgamated original file "/arch/eventloop_posix_select.c" ****/ |
| 123998 | |
| 123999 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 124000 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 124001 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 124002 | * |
| 124003 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 124004 | */ |
| 124005 | |
| 124006 | |
| 124007 | #if !defined(UA_HAVE_EPOLL) |
| 124008 | |
| 124009 | UA_StatusCode |
| 124010 | UA_EventLoopPOSIX_registerFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd) { |
| 124011 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 124012 | UA_LOG_DEBUG(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP, |
| 124013 | "Registering fd: %u", (unsigned)rfd->fd); |
| 124014 | |
| 124015 | /* Realloc */ |
| 124016 | UA_RegisteredFD **fds_tmp = (UA_RegisteredFD**) |
| 124017 | UA_realloc(el->fds, sizeof(UA_RegisteredFD*) * (el->fdsSize + 1)); |
| 124018 | if(!fds_tmp) { |
| 124019 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 124020 | } |
| 124021 | el->fds = fds_tmp; |
| 124022 | |
| 124023 | /* Add to the last entry */ |
| 124024 | el->fds[el->fdsSize] = rfd; |
| 124025 | el->fdsSize++; |
| 124026 | return UA_STATUSCODE_GOOD; |
| 124027 | } |
| 124028 | |
| 124029 | UA_StatusCode |
| 124030 | UA_EventLoopPOSIX_modifyFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd) { |
| 124031 | /* Do nothing, it is enough if the data was changed in the rfd */ |
| 124032 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 124033 | return UA_STATUSCODE_GOOD; |
| 124034 | } |
| 124035 | |
| 124036 | void |
| 124037 | UA_EventLoopPOSIX_deregisterFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd) { |
| 124038 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 124039 | UA_LOG_DEBUG(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP, |
| 124040 | "Unregistering fd: %u", (unsigned)rfd->fd); |
| 124041 | |
| 124042 | /* Find the entry */ |
| 124043 | size_t i = 0; |
| 124044 | for(; i < el->fdsSize; i++) { |
| 124045 | if(el->fds[i] == rfd) |
| 124046 | break; |
| 124047 | } |
| 124048 | |
| 124049 | /* Not found? */ |
| 124050 | if(i == el->fdsSize) |
| 124051 | return; |
| 124052 | |
| 124053 | if(el->fdsSize > 1) { |
| 124054 | /* Move the last entry in the ith slot and realloc. */ |
| 124055 | el->fdsSize--; |
| 124056 | el->fds[i] = el->fds[el->fdsSize]; |
| 124057 | UA_RegisteredFD **fds_tmp = (UA_RegisteredFD**) |
| 124058 | UA_realloc(el->fds, sizeof(UA_RegisteredFD*) * el->fdsSize); |
| 124059 | /* if realloc fails the fds are still in a correct state with |
| 124060 | * possibly lost memory, so failing silently here is ok */ |
| 124061 | if(fds_tmp) |
| 124062 | el->fds = fds_tmp; |
| 124063 | } else { |
| 124064 | /* Remove the last entry */ |
| 124065 | UA_free(el->fds); |
| 124066 | el->fds = NULL; |
| 124067 | el->fdsSize = 0; |
| 124068 | } |
| 124069 | } |
| 124070 | |
| 124071 | static UA_FD |
| 124072 | setFDSets(UA_EventLoopPOSIX *el, fd_set *readset, fd_set *writeset, fd_set *errset) { |
| 124073 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 124074 | |
| 124075 | FD_ZERO(readset); |
| 124076 | FD_ZERO(writeset); |
| 124077 | FD_ZERO(errset); |
| 124078 | UA_FD highestfd = UA_INVALID_FD; |
| 124079 | for(size_t i = 0; i < el->fdsSize; i++) { |
| 124080 | UA_FD currentFD = el->fds[i]->fd; |
| 124081 | |
| 124082 | /* Add to the fd_sets */ |
| 124083 | if(el->fds[i]->listenEvents & UA_FDEVENT_IN) |
| 124084 | FD_SET(currentFD, readset); |
| 124085 | if(el->fds[i]->listenEvents & UA_FDEVENT_OUT) |
| 124086 | FD_SET(currentFD, writeset); |
| 124087 | |
| 124088 | /* Always return errors */ |
| 124089 | FD_SET(currentFD, errset); |
| 124090 | |
| 124091 | /* Highest fd? */ |
| 124092 | if(currentFD > highestfd || highestfd == UA_INVALID_FD) |
| 124093 | highestfd = currentFD; |
| 124094 | } |
| 124095 | return highestfd; |
| 124096 | } |
| 124097 | |
| 124098 | UA_StatusCode |
| 124099 | UA_EventLoopPOSIX_pollFDs(UA_EventLoopPOSIX *el, UA_DateTime listenTimeout) { |
| 124100 | UA_assert(listenTimeout >= 0); |
| 124101 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 124102 | |
| 124103 | fd_set readset, writeset, errset; |
| 124104 | UA_FD highestfd = setFDSets(el, &readset, &writeset, &errset); |
| 124105 | |
| 124106 | /* Nothing to do? */ |
| 124107 | if(highestfd == UA_INVALID_FD) { |
| 124108 | UA_LOG_TRACE(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP, |
| 124109 | "No valid FDs for processing"); |
| 124110 | return UA_STATUSCODE_GOOD; |
| 124111 | } |
| 124112 | |
| 124113 | struct timeval tmptv = { |
| 124114 | #ifndef UA_ARCHITECTURE_WIN32 |
| 124115 | (time_t)(listenTimeout / UA_DATETIME_SEC), |
| 124116 | (suseconds_t)((listenTimeout % UA_DATETIME_SEC) / UA_DATETIME_USEC) |
| 124117 | #else |
| 124118 | (long)(listenTimeout / UA_DATETIME_SEC), |
| 124119 | (long)((listenTimeout % UA_DATETIME_SEC) / UA_DATETIME_USEC) |
| 124120 | #endif |
| 124121 | }; |
| 124122 | |
| 124123 | UA_UNLOCK(&el->elMutex); |
| 124124 | int selectStatus = UA_select(highestfd+1, &readset, &writeset, &errset, &tmptv); |
| 124125 | UA_LOCK(&el->elMutex); |
| 124126 | if(selectStatus < 0) { |
| 124127 | /* We will retry, only log the error */ |
| 124128 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124129 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP, |
| 124130 | "Error during select: %s", errno_str)); |
| 124131 | return UA_STATUSCODE_GOOD; |
| 124132 | } |
| 124133 | |
| 124134 | /* Loop over all registered FD to see if an event arrived. Yes, this is why |
| 124135 | * select is slow for many open sockets. */ |
| 124136 | for(size_t i = 0; i < el->fdsSize; i++) { |
| 124137 | UA_RegisteredFD *rfd = el->fds[i]; |
| 124138 | |
| 124139 | /* The rfd is already registered for removal. Don't process incoming |
| 124140 | * events any longer. */ |
| 124141 | if(rfd->dc.callback) |
| 124142 | continue; |
| 124143 | |
| 124144 | /* Event signaled for the fd? */ |
| 124145 | short event = 0; |
| 124146 | if(FD_ISSET(rfd->fd, &readset)) { |
| 124147 | event = UA_FDEVENT_IN; |
| 124148 | } else if(FD_ISSET(rfd->fd, &writeset)) { |
| 124149 | event = UA_FDEVENT_OUT; |
| 124150 | } else if(FD_ISSET(rfd->fd, &errset)) { |
| 124151 | event = UA_FDEVENT_ERR; |
| 124152 | } else { |
| 124153 | continue; |
| 124154 | } |
| 124155 | |
| 124156 | UA_LOG_DEBUG(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP, |
| 124157 | "Processing event %u on fd %u", (unsigned)event, |
| 124158 | (unsigned)rfd->fd); |
| 124159 | |
| 124160 | /* Call the EventSource callback */ |
| 124161 | rfd->eventSourceCB(rfd->es, rfd, event); |
| 124162 | |
| 124163 | /* The fd has removed itself */ |
| 124164 | if(i == el->fdsSize || rfd != el->fds[i]) |
| 124165 | i--; |
| 124166 | } |
| 124167 | return UA_STATUSCODE_GOOD; |
| 124168 | } |
| 124169 | |
| 124170 | #endif /* !defined(UA_HAVE_EPOLL) */ |
| 124171 | |
| 124172 | /**** amalgamated original file "/arch/eventloop_posix_epoll.c" ****/ |
| 124173 | |
| 124174 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 124175 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 124176 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 124177 | * |
| 124178 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 124179 | */ |
| 124180 | |
| 124181 | |
| 124182 | #if defined(UA_HAVE_EPOLL) |
| 124183 | |
| 124184 | UA_StatusCode |
| 124185 | UA_EventLoopPOSIX_registerFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd) { |
| 124186 | struct epoll_event event; |
| 124187 | memset(s: &event, c: 0, n: sizeof(struct epoll_event)); |
| 124188 | event.data.ptr = rfd; |
| 124189 | event.events = 0; |
| 124190 | if(rfd->listenEvents & UA_FDEVENT_IN) |
| 124191 | event.events |= EPOLLIN; |
| 124192 | if(rfd->listenEvents & UA_FDEVENT_OUT) |
| 124193 | event.events |= EPOLLOUT; |
| 124194 | |
| 124195 | int err = epoll_ctl(epfd: el->epollfd, EPOLL_CTL_ADD, fd: rfd->fd, event: &event); |
| 124196 | if(err != 0) { |
| 124197 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124198 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124199 | "TCP %u\t| Could not register for epoll (%s)", |
| 124200 | rfd->fd, errno_str)); |
| 124201 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124202 | } |
| 124203 | return UA_STATUSCODE_GOOD; |
| 124204 | } |
| 124205 | |
| 124206 | UA_StatusCode |
| 124207 | UA_EventLoopPOSIX_modifyFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd) { |
| 124208 | struct epoll_event event; |
| 124209 | memset(s: &event, c: 0, n: sizeof(struct epoll_event)); |
| 124210 | event.data.ptr = rfd; |
| 124211 | event.events = 0; |
| 124212 | if(rfd->listenEvents & UA_FDEVENT_IN) |
| 124213 | event.events |= EPOLLIN; |
| 124214 | if(rfd->listenEvents & UA_FDEVENT_OUT) |
| 124215 | event.events |= EPOLLOUT; |
| 124216 | |
| 124217 | int err = epoll_ctl(epfd: el->epollfd, EPOLL_CTL_MOD, fd: rfd->fd, event: &event); |
| 124218 | if(err != 0) { |
| 124219 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124220 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124221 | "TCP %u\t| Could not modify for epoll (%s)", |
| 124222 | rfd->fd, errno_str)); |
| 124223 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124224 | } |
| 124225 | return UA_STATUSCODE_GOOD; |
| 124226 | } |
| 124227 | |
| 124228 | void |
| 124229 | UA_EventLoopPOSIX_deregisterFD(UA_EventLoopPOSIX *el, UA_RegisteredFD *rfd) { |
| 124230 | int res = epoll_ctl(epfd: el->epollfd, EPOLL_CTL_DEL, fd: rfd->fd, NULL); |
| 124231 | if(res != 0) { |
| 124232 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124233 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124234 | "TCP %u\t| Could not deregister from epoll (%s)", |
| 124235 | rfd->fd, errno_str)); |
| 124236 | } |
| 124237 | } |
| 124238 | |
| 124239 | UA_StatusCode |
| 124240 | UA_EventLoopPOSIX_pollFDs(UA_EventLoopPOSIX *el, UA_DateTime listenTimeout) { |
| 124241 | UA_assert(listenTimeout >= 0); |
| 124242 | |
| 124243 | /* If there is a positive timeout, wait at least one millisecond, the |
| 124244 | * minimum for blocking epoll_wait. This prevents a busy-loop, as the |
| 124245 | * open62541 library allows even smaller timeouts, which can result in a |
| 124246 | * zero timeout due to rounding to an integer here. */ |
| 124247 | int timeout = (int)(listenTimeout / UA_DATETIME_MSEC); |
| 124248 | if(timeout == 0 && listenTimeout > 0) |
| 124249 | timeout = 1; |
| 124250 | |
| 124251 | /* Poll the registered sockets */ |
| 124252 | struct epoll_event epoll_events[64]; |
| 124253 | UA_UNLOCK(&el->elMutex); |
| 124254 | int events = epoll_wait(epfd: el->epollfd, events: epoll_events, maxevents: 64, timeout: timeout); |
| 124255 | UA_LOCK(&el->elMutex); |
| 124256 | |
| 124257 | /* TODO: Replace with pwait2 for higher-precision timeouts once this is |
| 124258 | * available in the standard library. |
| 124259 | * |
| 124260 | * struct timespec precisionTimeout = { |
| 124261 | * (long)(listenTimeout / UA_DATETIME_SEC), |
| 124262 | * (long)((listenTimeout % UA_DATETIME_SEC) * 100) |
| 124263 | * }; |
| 124264 | * int events = epoll_pwait2(epollfd, epoll_events, 64, |
| 124265 | * precisionTimeout, NULL); */ |
| 124266 | |
| 124267 | /* Handle error conditions */ |
| 124268 | if(events == -1) { |
| 124269 | if(errno == EINTR) { |
| 124270 | /* We will retry, only log the error */ |
| 124271 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 124272 | msg: "Timeout during poll"); |
| 124273 | return UA_STATUSCODE_GOOD; |
| 124274 | } |
| 124275 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124276 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124277 | "TCP\t| Error %s, closing the server socket", |
| 124278 | errno_str)); |
| 124279 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124280 | } |
| 124281 | |
| 124282 | /* Process all received events */ |
| 124283 | for(int i = 0; i < events; i++) { |
| 124284 | UA_RegisteredFD *rfd = (UA_RegisteredFD*)epoll_events[i].data.ptr; |
| 124285 | |
| 124286 | /* The rfd is already registered for removal. Don't process incoming |
| 124287 | * events any longer. */ |
| 124288 | if(rfd->dc.callback) |
| 124289 | continue; |
| 124290 | |
| 124291 | /* Get the event */ |
| 124292 | short revent = 0; |
| 124293 | if((epoll_events[i].events & EPOLLIN) == EPOLLIN) { |
| 124294 | revent = UA_FDEVENT_IN; |
| 124295 | } else if((epoll_events[i].events & EPOLLOUT) == EPOLLOUT) { |
| 124296 | revent = UA_FDEVENT_OUT; |
| 124297 | } else { |
| 124298 | revent = UA_FDEVENT_ERR; |
| 124299 | } |
| 124300 | |
| 124301 | /* Call the EventSource callback */ |
| 124302 | rfd->eventSourceCB(rfd->es, rfd, revent); |
| 124303 | } |
| 124304 | return UA_STATUSCODE_GOOD; |
| 124305 | } |
| 124306 | |
| 124307 | #endif /* defined(UA_HAVE_EPOLL) */ |
| 124308 | |
| 124309 | /**** amalgamated original file "/arch/eventloop_posix_tcp.c" ****/ |
| 124310 | |
| 124311 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 124312 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 124313 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 124314 | * |
| 124315 | * Copyright 2021-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 124316 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes) |
| 124317 | */ |
| 124318 | |
| 124319 | |
| 124320 | /* Configuration parameters */ |
| 124321 | #define TCP_PARAMETERSSIZE 6 |
| 124322 | #define TCP_PARAMINDEX_RECVBUF 0 |
| 124323 | #define TCP_PARAMINDEX_ADDR 1 |
| 124324 | #define TCP_PARAMINDEX_PORT 2 |
| 124325 | #define TCP_PARAMINDEX_LISTEN 3 |
| 124326 | #define TCP_PARAMINDEX_VALIDATE 4 |
| 124327 | #define TCP_PARAMINDEX_REUSE 5 |
| 124328 | |
| 124329 | static UA_KeyValueRestriction TCPConfigParameters[TCP_PARAMETERSSIZE] = { |
| 124330 | {{0, UA_STRING_STATIC("recv-bufsize")}, &UA_TYPES[UA_TYPES_UINT32], false, true, false}, |
| 124331 | {{0, UA_STRING_STATIC("address")}, &UA_TYPES[UA_TYPES_STRING], false, true, true}, |
| 124332 | {{0, UA_STRING_STATIC("port")}, &UA_TYPES[UA_TYPES_UINT16], true, true, false}, |
| 124333 | {{0, UA_STRING_STATIC("listen")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false}, |
| 124334 | {{0, UA_STRING_STATIC("validate")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false}, |
| 124335 | {{0, UA_STRING_STATIC("reuse")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false} |
| 124336 | }; |
| 124337 | |
| 124338 | typedef struct { |
| 124339 | UA_RegisteredFD rfd; |
| 124340 | |
| 124341 | UA_ConnectionManager_connectionCallback applicationCB; |
| 124342 | void *application; |
| 124343 | void *context; |
| 124344 | } TCP_FD; |
| 124345 | |
| 124346 | static void |
| 124347 | TCP_shutdown(UA_ConnectionManager *cm, TCP_FD *conn); |
| 124348 | |
| 124349 | /* Do not merge packets on the socket (disable Nagle's algorithm) */ |
| 124350 | static UA_StatusCode |
| 124351 | TCP_setNoNagle(UA_FD sockfd) { |
| 124352 | int val = 1; |
| 124353 | int res = UA_setsockopt(fd: sockfd, IPPROTO_TCP, TCP_NODELAY, optval: &val, optlen: sizeof(val)); |
| 124354 | if(res < 0) |
| 124355 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124356 | return UA_STATUSCODE_GOOD; |
| 124357 | } |
| 124358 | |
| 124359 | /* Test if the ConnectionManager can be stopped */ |
| 124360 | static void |
| 124361 | TCP_checkStopped(UA_POSIXConnectionManager *pcm) { |
| 124362 | UA_LOCK_ASSERT(&((UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop)->elMutex, 1); |
| 124363 | |
| 124364 | if(pcm->fdsSize == 0 && |
| 124365 | pcm->cm.eventSource.state == UA_EVENTSOURCESTATE_STOPPING) { |
| 124366 | UA_LOG_DEBUG(logger: pcm->cm.eventSource.eventLoop->logger, category: UA_LOGCATEGORY_NETWORK, |
| 124367 | msg: "TCP\t| All sockets closed, the EventLoop has stopped"); |
| 124368 | pcm->cm.eventSource.state = UA_EVENTSOURCESTATE_STOPPED; |
| 124369 | } |
| 124370 | } |
| 124371 | |
| 124372 | static void |
| 124373 | TCP_delayedClose(void *application, void *context) { |
| 124374 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)application; |
| 124375 | UA_ConnectionManager *cm = &pcm->cm; |
| 124376 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 124377 | TCP_FD *conn = (TCP_FD*)context; |
| 124378 | |
| 124379 | UA_LOCK(&el->elMutex); |
| 124380 | |
| 124381 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 124382 | msg: "TCP %u\t| Delayed closing of the connection", |
| 124383 | (unsigned)conn->rfd.fd); |
| 124384 | |
| 124385 | /* Ensure reuse is possible right away. Port-stealing is no longer an issue |
| 124386 | * as the socket gets closed anyway. And we do not want to wait for the |
| 124387 | * timeout to open a new socket for the same address and port. */ |
| 124388 | UA_EventLoopPOSIX_setReusable(sockfd: conn->rfd.fd); |
| 124389 | |
| 124390 | /* Deregister from the EventLoop */ |
| 124391 | UA_EventLoopPOSIX_deregisterFD(el, rfd: &conn->rfd); |
| 124392 | |
| 124393 | /* Deregister internally */ |
| 124394 | ZIP_REMOVE(UA_FDTree, &pcm->fds, &conn->rfd); |
| 124395 | UA_assert(pcm->fdsSize > 0); |
| 124396 | pcm->fdsSize--; |
| 124397 | |
| 124398 | /* Signal closing to the application */ |
| 124399 | conn->applicationCB(cm, (uintptr_t)conn->rfd.fd, |
| 124400 | conn->application, &conn->context, |
| 124401 | UA_CONNECTIONSTATE_CLOSING, |
| 124402 | &UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL); |
| 124403 | |
| 124404 | /* Close the socket */ |
| 124405 | int ret = UA_close(fd: conn->rfd.fd); |
| 124406 | if(ret == 0) { |
| 124407 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124408 | msg: "TCP %u\t| Socket closed", (unsigned)conn->rfd.fd); |
| 124409 | } else { |
| 124410 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124411 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124412 | "TCP %u\t| Could not close the socket (%s)", |
| 124413 | (unsigned)conn->rfd.fd, errno_str)); |
| 124414 | } |
| 124415 | |
| 124416 | UA_free(ptr: conn); |
| 124417 | |
| 124418 | /* Check if this was the last connection for a closing ConnectionManager */ |
| 124419 | TCP_checkStopped(pcm); |
| 124420 | |
| 124421 | UA_UNLOCK(&el->elMutex); |
| 124422 | } |
| 124423 | |
| 124424 | static int |
| 124425 | getSockError(TCP_FD *conn) { |
| 124426 | int error = 0; |
| 124427 | #ifndef UA_ARCHITECTURE_WIN32 |
| 124428 | socklen_t errlen = sizeof(int); |
| 124429 | int err = getsockopt(fd: conn->rfd.fd, SOL_SOCKET, SO_ERROR, optval: &error, optlen: &errlen); |
| 124430 | #else |
| 124431 | int errlen = (int)sizeof(int); |
| 124432 | int err = getsockopt((SOCKET)conn->rfd.fd, SOL_SOCKET, SO_ERROR, |
| 124433 | (char*)&error, &errlen); |
| 124434 | #endif |
| 124435 | return (err == 0) ? error : err; |
| 124436 | } |
| 124437 | |
| 124438 | /* Gets called when a connection socket opens, receives data or closes */ |
| 124439 | static void |
| 124440 | TCP_connectionSocketCallback(UA_ConnectionManager *cm, TCP_FD *conn, |
| 124441 | short event) { |
| 124442 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 124443 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 124444 | |
| 124445 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124446 | msg: "TCP %u\t| Activity on the socket", |
| 124447 | (unsigned)conn->rfd.fd); |
| 124448 | |
| 124449 | /* Error. The connection has closed. */ |
| 124450 | if(event == UA_FDEVENT_ERR) { |
| 124451 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124452 | msg: "TCP %u\t| The connection closes with error %i", |
| 124453 | (unsigned)conn->rfd.fd, getSockError(conn)); |
| 124454 | TCP_shutdown(cm, conn); |
| 124455 | return; |
| 124456 | } |
| 124457 | |
| 124458 | /* Write-Event, a new connection has opened. But some errors come as an |
| 124459 | * out-event. For example if the remote side could not be reached to |
| 124460 | * initiate the connection. So we check manually for error conditions on |
| 124461 | * the socket. */ |
| 124462 | if(event == UA_FDEVENT_OUT) { |
| 124463 | int error = getSockError(conn); |
| 124464 | if(error != 0) { |
| 124465 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124466 | msg: "TCP %u\t| The connection closes with error %i", |
| 124467 | (unsigned)conn->rfd.fd, error); |
| 124468 | TCP_shutdown(cm, conn); |
| 124469 | return; |
| 124470 | } |
| 124471 | |
| 124472 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124473 | msg: "TCP %u\t| Opening a new connection", |
| 124474 | (unsigned)conn->rfd.fd); |
| 124475 | |
| 124476 | /* Now we are interested in read-events. */ |
| 124477 | conn->rfd.listenEvents = UA_FDEVENT_IN; |
| 124478 | UA_EventLoopPOSIX_modifyFD(el, rfd: &conn->rfd); |
| 124479 | |
| 124480 | /* A new socket has opened. Signal it to the application. */ |
| 124481 | conn->applicationCB(cm, (uintptr_t)conn->rfd.fd, |
| 124482 | conn->application, &conn->context, |
| 124483 | UA_CONNECTIONSTATE_ESTABLISHED, |
| 124484 | &UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL); |
| 124485 | return; |
| 124486 | } |
| 124487 | |
| 124488 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124489 | msg: "TCP %u\t| Allocate receive buffer", |
| 124490 | (unsigned)conn->rfd.fd); |
| 124491 | |
| 124492 | /* Use the already allocated receive-buffer */ |
| 124493 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 124494 | UA_ByteString response = pcm->rxBuffer; |
| 124495 | |
| 124496 | /* Receive */ |
| 124497 | #ifndef UA_ARCHITECTURE_WIN32 |
| 124498 | ssize_t ret = UA_recv(fd: conn->rfd.fd, buf: (char*)response.data, |
| 124499 | n: response.length, MSG_DONTWAIT); |
| 124500 | #else |
| 124501 | int ret = UA_recv(conn->rfd.fd, (char*)response.data, |
| 124502 | response.length, MSG_DONTWAIT); |
| 124503 | #endif |
| 124504 | |
| 124505 | /* Receive has failed */ |
| 124506 | if(ret <= 0) { |
| 124507 | if(UA_ERRNO == UA_INTERRUPTED || |
| 124508 | UA_ERRNO == UA_WOULDBLOCK || |
| 124509 | UA_ERRNO == UA_AGAIN) |
| 124510 | return; /* Temporary error on an non-blocking socket */ |
| 124511 | |
| 124512 | /* Orderly shutdown of the socket */ |
| 124513 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124514 | UA_LOG_DEBUG(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124515 | "TCP %u\t| recv signaled the socket was shutdown (%s)", |
| 124516 | (unsigned)conn->rfd.fd, errno_str)); |
| 124517 | TCP_shutdown(cm, conn); |
| 124518 | return; |
| 124519 | } |
| 124520 | |
| 124521 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124522 | msg: "TCP %u\t| Received message of size %u", |
| 124523 | (unsigned)conn->rfd.fd, (unsigned)ret); |
| 124524 | |
| 124525 | /* Callback to the application layer */ |
| 124526 | response.length = (size_t)ret; /* Set the length of the received buffer */ |
| 124527 | conn->applicationCB(cm, (uintptr_t)conn->rfd.fd, |
| 124528 | conn->application, &conn->context, |
| 124529 | UA_CONNECTIONSTATE_ESTABLISHED, |
| 124530 | &UA_KEYVALUEMAP_NULL, response); |
| 124531 | } |
| 124532 | |
| 124533 | /* Gets called when a new connection opens or if the listenSocket is closed */ |
| 124534 | static void |
| 124535 | TCP_listenSocketCallback(UA_ConnectionManager *cm, TCP_FD *conn, short event) { |
| 124536 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 124537 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 124538 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 124539 | |
| 124540 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124541 | msg: "TCP %u\t| Callback on server socket", |
| 124542 | (unsigned)conn->rfd.fd); |
| 124543 | |
| 124544 | /* Try to accept a new connection */ |
| 124545 | struct sockaddr_storage remote; |
| 124546 | socklen_t remote_size = sizeof(remote); |
| 124547 | UA_FD newsockfd = accept(fd: conn->rfd.fd, addr: (struct sockaddr*)&remote, addr_len: &remote_size); |
| 124548 | if(newsockfd == UA_INVALID_FD) { |
| 124549 | /* Temporary error -- retry */ |
| 124550 | if(UA_ERRNO == UA_INTERRUPTED) |
| 124551 | return; |
| 124552 | |
| 124553 | /* Close the listen socket */ |
| 124554 | if(cm->eventSource.state != UA_EVENTSOURCESTATE_STOPPING) { |
| 124555 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124556 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124557 | "TCP %u\t| Error %s, closing the server socket", |
| 124558 | (unsigned)conn->rfd.fd, errno_str)); |
| 124559 | } |
| 124560 | |
| 124561 | TCP_shutdown(cm, conn); |
| 124562 | return; |
| 124563 | } |
| 124564 | |
| 124565 | /* Log the name of the remote host */ |
| 124566 | char hoststr[UA_MAXHOSTNAME_LENGTH]; |
| 124567 | int get_res = UA_getnameinfo((struct sockaddr *)&remote, sizeof(remote), |
| 124568 | hoststr, sizeof(hoststr), |
| 124569 | NULL, 0, NI_NUMERICHOST); |
| 124570 | if(get_res != 0) { |
| 124571 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124572 | UA_LOG_WARNING(cm->eventSource.eventLoop->logger, UA_LOGCATEGORY_NETWORK, |
| 124573 | "TCP %u\t| getnameinfo(...) could not resolve the " |
| 124574 | "hostname (%s)", (unsigned)conn->rfd.fd, errno_str)); |
| 124575 | } |
| 124576 | UA_LOG_INFO(logger: cm->eventSource.eventLoop->logger, category: UA_LOGCATEGORY_NETWORK, |
| 124577 | msg: "TCP %u\t| Connection opened from \"%s\" via the server socket %u", |
| 124578 | (unsigned)newsockfd, hoststr, (unsigned)conn->rfd.fd); |
| 124579 | |
| 124580 | /* Configure the new socket */ |
| 124581 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 124582 | /* res |= UA_EventLoopPOSIX_setNonBlocking(newsockfd); Inherited from the listen-socket */ |
| 124583 | res |= UA_EventLoopPOSIX_setNoSigPipe(sockfd: newsockfd); /* Supress interrupts from the socket */ |
| 124584 | res |= TCP_setNoNagle(sockfd: newsockfd); /* Disable Nagle's algorithm */ |
| 124585 | if(res != UA_STATUSCODE_GOOD) { |
| 124586 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124587 | UA_LOG_WARNING(cm->eventSource.eventLoop->logger, UA_LOGCATEGORY_NETWORK, |
| 124588 | "TCP %u\t| Error seeting the TCP options (%s)", |
| 124589 | (unsigned)newsockfd, errno_str)); |
| 124590 | /* Close the new socket */ |
| 124591 | UA_close(fd: newsockfd); |
| 124592 | return; |
| 124593 | } |
| 124594 | |
| 124595 | /* Allocate the UA_RegisteredFD */ |
| 124596 | TCP_FD *newConn = (TCP_FD*)UA_calloc(nmemb: 1, size: sizeof(TCP_FD)); |
| 124597 | if(!newConn) { |
| 124598 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124599 | msg: "TCP %u\t| Error allocating memory for the socket", |
| 124600 | (unsigned)newsockfd); |
| 124601 | UA_close(fd: newsockfd); |
| 124602 | return; |
| 124603 | } |
| 124604 | |
| 124605 | newConn->rfd.fd = newsockfd; |
| 124606 | newConn->rfd.listenEvents = UA_FDEVENT_IN; |
| 124607 | newConn->rfd.es = &cm->eventSource; |
| 124608 | newConn->rfd.eventSourceCB = (UA_FDCallback)TCP_connectionSocketCallback; |
| 124609 | newConn->applicationCB = conn->applicationCB; |
| 124610 | newConn->application = conn->application; |
| 124611 | newConn->context = conn->context; |
| 124612 | |
| 124613 | /* Register in the EventLoop. Signal to the user if registering failed. */ |
| 124614 | res = UA_EventLoopPOSIX_registerFD(el, rfd: &newConn->rfd); |
| 124615 | if(res != UA_STATUSCODE_GOOD) { |
| 124616 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124617 | msg: "TCP %u\t| Error registering the socket", |
| 124618 | (unsigned)newsockfd); |
| 124619 | UA_free(ptr: newConn); |
| 124620 | UA_close(fd: newsockfd); |
| 124621 | return; |
| 124622 | } |
| 124623 | |
| 124624 | /* Register internally in the EventSource */ |
| 124625 | ZIP_INSERT(UA_FDTree, &pcm->fds, &newConn->rfd); |
| 124626 | pcm->fdsSize++; |
| 124627 | |
| 124628 | /* Forward the remote hostname to the application */ |
| 124629 | UA_KeyValuePair kvp; |
| 124630 | kvp.key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "remote-address"); |
| 124631 | UA_String hostName = UA_STRING(chars: hoststr); |
| 124632 | UA_Variant_setScalar(v: &kvp.value, p: &hostName, type: &UA_TYPES[UA_TYPES_STRING]); |
| 124633 | |
| 124634 | UA_KeyValueMap kvm; |
| 124635 | kvm.mapSize = 1; |
| 124636 | kvm.map = &kvp; |
| 124637 | |
| 124638 | /* The socket has opened. Signal it to the application. */ |
| 124639 | newConn->applicationCB(cm, (uintptr_t)newsockfd, |
| 124640 | newConn->application, &newConn->context, |
| 124641 | UA_CONNECTIONSTATE_ESTABLISHED, |
| 124642 | &kvm, UA_BYTESTRING_NULL); |
| 124643 | } |
| 124644 | |
| 124645 | static UA_StatusCode |
| 124646 | TCP_registerListenSocket(UA_POSIXConnectionManager *pcm, struct addrinfo *ai, |
| 124647 | const char *hostname, UA_UInt16 port, |
| 124648 | void *application, void *context, |
| 124649 | UA_ConnectionManager_connectionCallback connectionCallback, |
| 124650 | UA_Boolean validate, UA_Boolean reuseaddr) { |
| 124651 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 124652 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 124653 | |
| 124654 | /* Translate INADDR_ANY to IPv4/IPv6 address */ |
| 124655 | char addrstr[UA_MAXHOSTNAME_LENGTH]; |
| 124656 | int get_res = UA_getnameinfo(ai->ai_addr, ai->ai_addrlen, |
| 124657 | addrstr, sizeof(addrstr), NULL, 0, 0); |
| 124658 | if(get_res != 0) { |
| 124659 | get_res = UA_getnameinfo(ai->ai_addr, ai->ai_addrlen, |
| 124660 | addrstr, sizeof(addrstr), |
| 124661 | NULL, 0, NI_NUMERICHOST); |
| 124662 | if(get_res != 0) { |
| 124663 | addrstr[0] = 0; |
| 124664 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124665 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124666 | "TCP\t| getnameinfo(...) could not resolve the " |
| 124667 | "hostname (%s)", errno_str)); |
| 124668 | } |
| 124669 | } |
| 124670 | |
| 124671 | /* Create the server socket */ |
| 124672 | UA_FD listenSocket = socket(domain: ai->ai_family, type: ai->ai_socktype, protocol: ai->ai_protocol); |
| 124673 | if(listenSocket == UA_INVALID_FD) { |
| 124674 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124675 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124676 | "TCP %u\t| Error opening the listen socket for " |
| 124677 | "\"%s\" on port %u (%s)", |
| 124678 | (unsigned)listenSocket, addrstr, port, errno_str)); |
| 124679 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124680 | } |
| 124681 | |
| 124682 | /* Some Linux distributions have net.ipv6.bindv6only not activated. So |
| 124683 | * sockets can double-bind to IPv4 and IPv6. This leads to problems. Use |
| 124684 | * AF_INET6 sockets only for IPv6. */ |
| 124685 | #if UA_IPV6 |
| 124686 | int optval = 1; |
| 124687 | if(ai->ai_family == AF_INET6 && |
| 124688 | UA_setsockopt(fd: listenSocket, IPPROTO_IPV6, IPV6_V6ONLY, |
| 124689 | optval: (const char*)&optval, optlen: sizeof(optval)) == -1) { |
| 124690 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124691 | msg: "TCP %u\t| Could not set an IPv6 socket to IPv6 only", |
| 124692 | (unsigned)listenSocket); |
| 124693 | UA_close(fd: listenSocket); |
| 124694 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124695 | } |
| 124696 | #endif |
| 124697 | |
| 124698 | /* Allow rebinding to the IP/port combination. Eg. to restart the server. */ |
| 124699 | if(reuseaddr && |
| 124700 | UA_EventLoopPOSIX_setReusable(sockfd: listenSocket) != UA_STATUSCODE_GOOD) { |
| 124701 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124702 | msg: "TCP %u\t| Could not make the socket addr reusable", |
| 124703 | (unsigned)listenSocket); |
| 124704 | UA_close(fd: listenSocket); |
| 124705 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124706 | } |
| 124707 | |
| 124708 | /* Set the socket non-blocking */ |
| 124709 | if(UA_EventLoopPOSIX_setNonBlocking(sockfd: listenSocket) != UA_STATUSCODE_GOOD) { |
| 124710 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124711 | msg: "TCP %u\t| Could not set the socket non-blocking", |
| 124712 | (unsigned)listenSocket); |
| 124713 | UA_close(fd: listenSocket); |
| 124714 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124715 | } |
| 124716 | |
| 124717 | /* Supress interrupts from the socket */ |
| 124718 | if(UA_EventLoopPOSIX_setNoSigPipe(sockfd: listenSocket) != UA_STATUSCODE_GOOD) { |
| 124719 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124720 | msg: "TCP %u\t| Could not disable SIGPIPE", |
| 124721 | (unsigned)listenSocket); |
| 124722 | UA_close(fd: listenSocket); |
| 124723 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124724 | } |
| 124725 | |
| 124726 | /* Bind socket to address */ |
| 124727 | int ret = bind(fd: listenSocket, addr: ai->ai_addr, len: (socklen_t)ai->ai_addrlen); |
| 124728 | |
| 124729 | /* Get the port being used if dynamic porting was used */ |
| 124730 | if(port == 0) { |
| 124731 | struct sockaddr_in sin; |
| 124732 | memset(s: &sin, c: 0, n: sizeof(sin)); |
| 124733 | socklen_t len = sizeof(sin); |
| 124734 | getsockname(fd: listenSocket, addr: (struct sockaddr *)&sin, len: &len); |
| 124735 | port = ntohs(netshort: sin.sin_port); |
| 124736 | } |
| 124737 | |
| 124738 | /* If the INADDR_ANY is used, use the local hostname */ |
| 124739 | char hoststr[UA_MAXHOSTNAME_LENGTH]; |
| 124740 | if(hostname) { |
| 124741 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124742 | msg: "TCP %u\t| Creating listen socket for \"%s\" on port %u", |
| 124743 | (unsigned)listenSocket, hostname, port); |
| 124744 | } else { |
| 124745 | gethostname(name: hoststr, UA_MAXHOSTNAME_LENGTH); |
| 124746 | hostname = hoststr; |
| 124747 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124748 | msg: "TCP %u\t| Creating listen socket for \"%s\" " |
| 124749 | "(with local hostname \"%s\") on port %u", |
| 124750 | (unsigned)listenSocket, addrstr, hostname, port); |
| 124751 | } |
| 124752 | |
| 124753 | if(ret < 0) { |
| 124754 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124755 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124756 | "TCP %u\t| Error binding the socket to the address %s (%s)", |
| 124757 | (unsigned)listenSocket, hostname, errno_str)); |
| 124758 | UA_close(fd: listenSocket); |
| 124759 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124760 | } |
| 124761 | |
| 124762 | /* Only validate, don't actually start listening */ |
| 124763 | if(validate) { |
| 124764 | UA_EventLoopPOSIX_setReusable(sockfd: listenSocket); /* Ensure reuse is possible */ |
| 124765 | UA_close(fd: listenSocket); |
| 124766 | return UA_STATUSCODE_GOOD; |
| 124767 | } |
| 124768 | |
| 124769 | /* Start listening */ |
| 124770 | if(listen(fd: listenSocket, UA_MAXBACKLOG) < 0) { |
| 124771 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124772 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 124773 | "TCP %u\t| Error listening on the socket (%s)", |
| 124774 | (unsigned)listenSocket, errno_str)); |
| 124775 | UA_EventLoopPOSIX_setReusable(sockfd: listenSocket); /* Ensure reuse is possible */ |
| 124776 | UA_close(fd: listenSocket); |
| 124777 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124778 | } |
| 124779 | |
| 124780 | /* Allocate the connection */ |
| 124781 | TCP_FD *newConn = (TCP_FD*)UA_calloc(nmemb: 1, size: sizeof(TCP_FD)); |
| 124782 | if(!newConn) { |
| 124783 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124784 | msg: "TCP %u\t| Error allocating memory for the socket", |
| 124785 | (unsigned)listenSocket); |
| 124786 | UA_EventLoopPOSIX_setReusable(sockfd: listenSocket); /* Ensure reuse is possible */ |
| 124787 | UA_close(fd: listenSocket); |
| 124788 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124789 | } |
| 124790 | |
| 124791 | newConn->rfd.fd = listenSocket; |
| 124792 | newConn->rfd.listenEvents = UA_FDEVENT_IN; |
| 124793 | newConn->rfd.es = &pcm->cm.eventSource; |
| 124794 | newConn->rfd.eventSourceCB = (UA_FDCallback)TCP_listenSocketCallback; |
| 124795 | newConn->applicationCB = connectionCallback; |
| 124796 | newConn->application = application; |
| 124797 | newConn->context = context; |
| 124798 | |
| 124799 | /* Register in the EventLoop */ |
| 124800 | UA_StatusCode res = UA_EventLoopPOSIX_registerFD(el, rfd: &newConn->rfd); |
| 124801 | if(res != UA_STATUSCODE_GOOD) { |
| 124802 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124803 | msg: "TCP %u\t| Error registering the socket", |
| 124804 | (unsigned)listenSocket); |
| 124805 | UA_free(ptr: newConn); |
| 124806 | UA_EventLoopPOSIX_setReusable(sockfd: listenSocket); /* Ensure reuse is possible */ |
| 124807 | UA_close(fd: listenSocket); |
| 124808 | return res; |
| 124809 | } |
| 124810 | |
| 124811 | /* Register internally */ |
| 124812 | ZIP_INSERT(UA_FDTree, &pcm->fds, &newConn->rfd); |
| 124813 | pcm->fdsSize++; |
| 124814 | |
| 124815 | /* Set up the callback parameters */ |
| 124816 | UA_String listenAddress = UA_STRING(chars: (char*)(uintptr_t)hostname); |
| 124817 | UA_KeyValuePair params[2]; |
| 124818 | params[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "listen-address"); |
| 124819 | UA_Variant_setScalar(v: ¶ms[0].value, p: &listenAddress, type: &UA_TYPES[UA_TYPES_STRING]); |
| 124820 | params[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "listen-port"); |
| 124821 | UA_Variant_setScalar(v: ¶ms[1].value, p: &port, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 124822 | UA_KeyValueMap paramMap = {2, params}; |
| 124823 | |
| 124824 | /* Announce the listen-socket in the application */ |
| 124825 | connectionCallback(&pcm->cm, (uintptr_t)listenSocket, |
| 124826 | application, &newConn->context, |
| 124827 | UA_CONNECTIONSTATE_ESTABLISHED, |
| 124828 | ¶mMap, UA_BYTESTRING_NULL); |
| 124829 | |
| 124830 | return UA_STATUSCODE_GOOD; |
| 124831 | } |
| 124832 | |
| 124833 | static UA_StatusCode |
| 124834 | TCP_registerListenSockets(UA_POSIXConnectionManager *pcm, const char *hostname, |
| 124835 | UA_UInt16 port, void *application, void *context, |
| 124836 | UA_ConnectionManager_connectionCallback connectionCallback, |
| 124837 | UA_Boolean validate, UA_Boolean reuseaddr) { |
| 124838 | UA_LOCK_ASSERT(&((UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop)->elMutex, 1); |
| 124839 | |
| 124840 | /* Create a string for the port */ |
| 124841 | char portstr[6]; |
| 124842 | mp_snprintf(s: portstr, n: sizeof(portstr), format: "%d", port); |
| 124843 | |
| 124844 | /* Get all the interface and IPv4/6 combinations for the configured hostname */ |
| 124845 | struct addrinfo hints, *res; |
| 124846 | memset(s: &hints, c: 0, n: sizeof hints); |
| 124847 | #if UA_IPV6 |
| 124848 | hints.ai_family = AF_UNSPEC; /* Allow IPv4 and IPv6 */ |
| 124849 | #else |
| 124850 | hints.ai_family = AF_INET; /* IPv4 only */ |
| 124851 | #endif |
| 124852 | hints.ai_socktype = SOCK_STREAM; |
| 124853 | hints.ai_protocol = IPPROTO_TCP; |
| 124854 | hints.ai_flags = AI_PASSIVE; |
| 124855 | |
| 124856 | int retcode = getaddrinfo(name: hostname, service: portstr, req: &hints, pai: &res); |
| 124857 | if(retcode != 0) { |
| 124858 | #ifdef UA_ARCHITECTURE_WIN32 |
| 124859 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124860 | UA_LOG_WARNING(pcm->cm.eventSource.eventLoop->logger, UA_LOGCATEGORY_NETWORK, |
| 124861 | "TCP\t| Lookup for \"%s\" on port %u failed (%s)", |
| 124862 | hostname, port, errno_str)); |
| 124863 | #else |
| 124864 | UA_LOG_WARNING(logger: pcm->cm.eventSource.eventLoop->logger, category: UA_LOGCATEGORY_NETWORK, |
| 124865 | msg: "TCP\t| Lookup for \"%s\" on port %u failed (%s)", |
| 124866 | hostname, port, gai_strerror(ecode: retcode)); |
| 124867 | #endif |
| 124868 | return UA_STATUSCODE_BADINTERNALERROR; |
| 124869 | } |
| 124870 | |
| 124871 | /* Add listen sockets. Aggregate the results to see if at least one |
| 124872 | * listen-socket was established. */ |
| 124873 | UA_StatusCode total_result = UA_INT32_MAX; |
| 124874 | struct addrinfo *ai = res; |
| 124875 | while(ai) { |
| 124876 | total_result &= TCP_registerListenSocket(pcm, ai, hostname, port, application, context, |
| 124877 | connectionCallback, validate, reuseaddr); |
| 124878 | ai = ai->ai_next; |
| 124879 | } |
| 124880 | freeaddrinfo(ai: res); |
| 124881 | |
| 124882 | return total_result; |
| 124883 | } |
| 124884 | |
| 124885 | /* Close the connection via a delayed callback */ |
| 124886 | static void |
| 124887 | TCP_shutdown(UA_ConnectionManager *cm, TCP_FD *conn) { |
| 124888 | /* Already closing - nothing to do */ |
| 124889 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 124890 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 124891 | |
| 124892 | if(conn->rfd.dc.callback) { |
| 124893 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124894 | msg: "TCP %u\t| Cannot shutdown - already triggered", |
| 124895 | (unsigned)conn->rfd.fd); |
| 124896 | return; |
| 124897 | } |
| 124898 | |
| 124899 | /* Shutdown the socket to cancel the current select/epoll */ |
| 124900 | shutdown(fd: conn->rfd.fd, UA_SHUT_RDWR); |
| 124901 | |
| 124902 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124903 | msg: "TCP %u\t| Shutdown triggered", |
| 124904 | (unsigned)conn->rfd.fd); |
| 124905 | |
| 124906 | /* Add to the delayed callback list. Will be cleaned up in the next |
| 124907 | * iteration. */ |
| 124908 | UA_DelayedCallback *dc = &conn->rfd.dc; |
| 124909 | dc->callback = TCP_delayedClose; |
| 124910 | dc->application = cm; |
| 124911 | dc->context = conn; |
| 124912 | |
| 124913 | /* Don't use the "public" el->addDelayedCallback. It takes a lock. */ |
| 124914 | dc->next = el->delayedCallbacks; |
| 124915 | el->delayedCallbacks = dc; |
| 124916 | } |
| 124917 | |
| 124918 | static UA_StatusCode |
| 124919 | TCP_shutdownConnection(UA_ConnectionManager *cm, uintptr_t connectionId) { |
| 124920 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 124921 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)cm->eventSource.eventLoop; |
| 124922 | UA_LOCK(&el->elMutex); |
| 124923 | |
| 124924 | UA_FD fd = (UA_FD)connectionId; |
| 124925 | TCP_FD *conn = (TCP_FD*)ZIP_FIND(UA_FDTree, &pcm->fds, &fd); |
| 124926 | if(!conn) { |
| 124927 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 124928 | msg: "TCP\t| Cannot close TCP connection %u - not found", |
| 124929 | (unsigned)connectionId); |
| 124930 | UA_UNLOCK(&el->elMutex); |
| 124931 | return UA_STATUSCODE_BADNOTFOUND; |
| 124932 | } |
| 124933 | |
| 124934 | TCP_shutdown(cm, conn); |
| 124935 | |
| 124936 | UA_UNLOCK(&el->elMutex); |
| 124937 | return UA_STATUSCODE_GOOD; |
| 124938 | } |
| 124939 | |
| 124940 | static UA_StatusCode |
| 124941 | TCP_sendWithConnection(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 124942 | const UA_KeyValueMap *params, UA_ByteString *buf) { |
| 124943 | /* We may not have a lock. But we need not take it. As the connectionId is |
| 124944 | * the fd, no need to do a lookup and access internal data strucures. */ |
| 124945 | |
| 124946 | /* Prevent OS signals when sending to a closed socket */ |
| 124947 | int flags = MSG_NOSIGNAL; |
| 124948 | |
| 124949 | struct pollfd tmp_poll_fd; |
| 124950 | tmp_poll_fd.fd = (UA_FD)connectionId; |
| 124951 | tmp_poll_fd.events = UA_POLLOUT; |
| 124952 | |
| 124953 | /* Send the full buffer. This may require several calls to send */ |
| 124954 | size_t nWritten = 0; |
| 124955 | do { |
| 124956 | ssize_t n = 0; |
| 124957 | do { |
| 124958 | UA_LOG_DEBUG(logger: cm->eventSource.eventLoop->logger, category: UA_LOGCATEGORY_NETWORK, |
| 124959 | msg: "TCP %u\t| Attempting to send", (unsigned)connectionId); |
| 124960 | size_t bytes_to_send = buf->length - nWritten; |
| 124961 | n = UA_send(fd: (UA_FD)connectionId, |
| 124962 | buf: (const char*)buf->data + nWritten, |
| 124963 | n: bytes_to_send, flags: flags); |
| 124964 | if(n < 0) { |
| 124965 | /* An error we cannot recover from? */ |
| 124966 | if(UA_ERRNO != UA_INTERRUPTED && UA_ERRNO != UA_WOULDBLOCK && |
| 124967 | UA_ERRNO != UA_AGAIN) |
| 124968 | goto shutdown; |
| 124969 | |
| 124970 | /* Poll for the socket resources to become available and retry |
| 124971 | * (blocking) */ |
| 124972 | int poll_ret; |
| 124973 | do { |
| 124974 | poll_ret = UA_poll(fds: &tmp_poll_fd, nfds: 1, timeout: 100); |
| 124975 | if(poll_ret < 0 && UA_ERRNO != UA_INTERRUPTED) |
| 124976 | goto shutdown; |
| 124977 | } while(poll_ret <= 0); |
| 124978 | } |
| 124979 | } while(n < 0); |
| 124980 | nWritten += (size_t)n; |
| 124981 | } while(nWritten < buf->length); |
| 124982 | |
| 124983 | /* Free the buffer */ |
| 124984 | UA_ByteString_clear(p: buf); |
| 124985 | return UA_STATUSCODE_GOOD; |
| 124986 | |
| 124987 | shutdown: |
| 124988 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 124989 | UA_LOG_ERROR(cm->eventSource.eventLoop->logger, UA_LOGCATEGORY_NETWORK, |
| 124990 | "TCP %u\t| Send failed with error %s", |
| 124991 | (unsigned)connectionId, errno_str)); |
| 124992 | TCP_shutdownConnection(cm, connectionId); |
| 124993 | UA_ByteString_clear(p: buf); |
| 124994 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 124995 | } |
| 124996 | |
| 124997 | /* Create a listen-socket that waits for incoming connections */ |
| 124998 | static UA_StatusCode |
| 124999 | TCP_openPassiveConnection(UA_POSIXConnectionManager *pcm, const UA_KeyValueMap *params, |
| 125000 | void *application, void *context, |
| 125001 | UA_ConnectionManager_connectionCallback connectionCallback, |
| 125002 | UA_Boolean validate) { |
| 125003 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 125004 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 125005 | |
| 125006 | /* Get the port parameter */ |
| 125007 | const UA_UInt16 *port = (const UA_UInt16*) |
| 125008 | UA_KeyValueMap_getScalar(map: params, key: TCPConfigParameters[TCP_PARAMINDEX_PORT].name, |
| 125009 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 125010 | UA_assert(port); /* existence is checked before */ |
| 125011 | |
| 125012 | /* Get the address parameter */ |
| 125013 | const UA_Variant *addrs = |
| 125014 | UA_KeyValueMap_get(map: params, key: TCPConfigParameters[TCP_PARAMINDEX_ADDR].name); |
| 125015 | size_t addrsSize = 0; |
| 125016 | if(addrs) { |
| 125017 | UA_assert(addrs->type == &UA_TYPES[UA_TYPES_STRING]); |
| 125018 | if(UA_Variant_isScalar(v: addrs)) |
| 125019 | addrsSize = 1; |
| 125020 | else |
| 125021 | addrsSize = addrs->arrayLength; |
| 125022 | } |
| 125023 | |
| 125024 | /* Get the reuseaddr parameter */ |
| 125025 | UA_Boolean reuseaddr = false; |
| 125026 | const UA_Boolean *reuseaddrTmp = (const UA_Boolean*) |
| 125027 | UA_KeyValueMap_getScalar(map: params, key: TCPConfigParameters[TCP_PARAMINDEX_REUSE].name, |
| 125028 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 125029 | if(reuseaddrTmp) |
| 125030 | reuseaddr = *reuseaddrTmp; |
| 125031 | |
| 125032 | #ifdef UA_ENABLE_ALLOW_REUSEADDR |
| 125033 | reuseaddr = true; |
| 125034 | #endif |
| 125035 | |
| 125036 | /* Undefined or empty addresses array -> listen on all interfaces */ |
| 125037 | if(addrsSize == 0) { |
| 125038 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125039 | msg: "TCP\t| Listening on all interfaces"); |
| 125040 | return TCP_registerListenSockets(pcm, NULL, port: *port, application, |
| 125041 | context, connectionCallback, validate, reuseaddr); |
| 125042 | } |
| 125043 | |
| 125044 | /* Iterate over the configured hostnames */ |
| 125045 | UA_String *hostStrings = (UA_String*)addrs->data; |
| 125046 | UA_StatusCode retval = UA_STATUSCODE_BADINTERNALERROR; |
| 125047 | for(size_t i = 0; i < addrsSize; i++) { |
| 125048 | char hostname[512]; |
| 125049 | if(hostStrings[i].length >= sizeof(hostname)) |
| 125050 | continue; |
| 125051 | memcpy(dest: hostname, src: hostStrings[i].data, n: hostStrings->length); |
| 125052 | hostname[hostStrings->length] = '\0'; |
| 125053 | if(TCP_registerListenSockets(pcm, hostname, port: *port, application, |
| 125054 | context, connectionCallback, validate, reuseaddr) == UA_STATUSCODE_GOOD) |
| 125055 | retval = UA_STATUSCODE_GOOD; |
| 125056 | } |
| 125057 | return retval; |
| 125058 | } |
| 125059 | |
| 125060 | /* Open a TCP connection to a remote host */ |
| 125061 | static UA_StatusCode |
| 125062 | TCP_openActiveConnection(UA_POSIXConnectionManager *pcm, const UA_KeyValueMap *params, |
| 125063 | void *application, void *context, |
| 125064 | UA_ConnectionManager_connectionCallback connectionCallback, |
| 125065 | UA_Boolean validate) { |
| 125066 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 125067 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 125068 | |
| 125069 | /* Get the connection parameters */ |
| 125070 | char hostname[UA_MAXHOSTNAME_LENGTH]; |
| 125071 | char portStr[UA_MAXPORTSTR_LENGTH]; |
| 125072 | |
| 125073 | /* Prepare the port parameter as a string */ |
| 125074 | const UA_UInt16 *port = (const UA_UInt16*) |
| 125075 | UA_KeyValueMap_getScalar(map: params, key: TCPConfigParameters[TCP_PARAMINDEX_PORT].name, |
| 125076 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 125077 | UA_assert(port); /* existence is checked before */ |
| 125078 | mp_snprintf(s: portStr, UA_MAXPORTSTR_LENGTH, format: "%d", *port); |
| 125079 | |
| 125080 | /* Prepare the hostname string */ |
| 125081 | const UA_String *addr = (const UA_String*) |
| 125082 | UA_KeyValueMap_getScalar(map: params, key: TCPConfigParameters[TCP_PARAMINDEX_ADDR].name, |
| 125083 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 125084 | if(!addr) { |
| 125085 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125086 | msg: "TCP\t| Open TCP Connection: No hostname defined, aborting"); |
| 125087 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125088 | } |
| 125089 | if(addr->length >= UA_MAXHOSTNAME_LENGTH) { |
| 125090 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 125091 | msg: "TCP\t| Open TCP Connection: Hostname too long, aborting"); |
| 125092 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125093 | } |
| 125094 | strncpy(dest: hostname, src: (const char*)addr->data, n: addr->length); |
| 125095 | hostname[addr->length] = 0; |
| 125096 | |
| 125097 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125098 | msg: "TCP\t| Open a connection to \"%s\" on port %s", hostname, portStr); |
| 125099 | |
| 125100 | /* Create the socket description from the connectString |
| 125101 | * TODO: Make this non-blocking */ |
| 125102 | struct addrinfo hints, *info; |
| 125103 | memset(s: &hints, c: 0, n: sizeof(struct addrinfo)); |
| 125104 | hints.ai_family = AF_UNSPEC; |
| 125105 | hints.ai_socktype = SOCK_STREAM; |
| 125106 | int error = getaddrinfo(name: hostname, service: portStr, req: &hints, pai: &info); |
| 125107 | if(error != 0) { |
| 125108 | #ifdef UA_ARCHITECTURE_WIN32 |
| 125109 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125110 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 125111 | "TCP\t| Lookup of %s failed (%s)", |
| 125112 | hostname, errno_str)); |
| 125113 | #else |
| 125114 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125115 | msg: "TCP\t| Lookup of %s failed (%s)", |
| 125116 | hostname, gai_strerror(ecode: error)); |
| 125117 | #endif |
| 125118 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125119 | } |
| 125120 | |
| 125121 | /* Create a socket */ |
| 125122 | UA_FD newSock = socket(domain: info->ai_family, type: info->ai_socktype, protocol: info->ai_protocol); |
| 125123 | if(newSock == UA_INVALID_FD) { |
| 125124 | freeaddrinfo(ai: info); |
| 125125 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125126 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 125127 | "TCP\t| Could not create socket to connect to %s (%s)", |
| 125128 | hostname, errno_str)); |
| 125129 | return UA_STATUSCODE_BADDISCONNECT; |
| 125130 | } |
| 125131 | |
| 125132 | /* Set the socket options */ |
| 125133 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 125134 | res |= UA_EventLoopPOSIX_setNonBlocking(sockfd: newSock); |
| 125135 | res |= UA_EventLoopPOSIX_setNoSigPipe(sockfd: newSock); |
| 125136 | res |= TCP_setNoNagle(sockfd: newSock); |
| 125137 | if(res != UA_STATUSCODE_GOOD) { |
| 125138 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125139 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 125140 | "TCP\t| Could not set socket options: %s", errno_str)); |
| 125141 | freeaddrinfo(ai: info); |
| 125142 | UA_close(fd: newSock); |
| 125143 | return res; |
| 125144 | } |
| 125145 | |
| 125146 | /* Only validate, don't actually open the connection */ |
| 125147 | if(validate) { |
| 125148 | freeaddrinfo(ai: info); |
| 125149 | UA_close(fd: newSock); |
| 125150 | return UA_STATUSCODE_GOOD; |
| 125151 | } |
| 125152 | |
| 125153 | /* Non-blocking connect */ |
| 125154 | error = UA_connect(fd: newSock, addr: info->ai_addr, len: info->ai_addrlen); |
| 125155 | freeaddrinfo(ai: info); |
| 125156 | if(error != 0 && |
| 125157 | UA_ERRNO != UA_INPROGRESS && |
| 125158 | UA_ERRNO != UA_WOULDBLOCK) { |
| 125159 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125160 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 125161 | "TCP\t| Connecting the socket to %s failed (%s)", |
| 125162 | hostname, errno_str)); |
| 125163 | UA_close(fd: newSock); |
| 125164 | return UA_STATUSCODE_BADDISCONNECT; |
| 125165 | } |
| 125166 | |
| 125167 | /* Allocate the UA_RegisteredFD */ |
| 125168 | TCP_FD *newConn = (TCP_FD*)UA_calloc(nmemb: 1, size: sizeof(TCP_FD)); |
| 125169 | if(!newConn) { |
| 125170 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125171 | msg: "TCP %u\t| Error allocating memory for the socket", |
| 125172 | (unsigned)newSock); |
| 125173 | UA_close(fd: newSock); |
| 125174 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 125175 | } |
| 125176 | |
| 125177 | newConn->rfd.fd = newSock; |
| 125178 | newConn->rfd.es = &pcm->cm.eventSource; |
| 125179 | newConn->rfd.eventSourceCB = (UA_FDCallback)TCP_connectionSocketCallback; |
| 125180 | newConn->rfd.listenEvents = UA_FDEVENT_OUT; /* Switched to _IN once the |
| 125181 | * connection is open */ |
| 125182 | newConn->applicationCB = connectionCallback; |
| 125183 | newConn->application = application; |
| 125184 | newConn->context = context; |
| 125185 | |
| 125186 | /* Register the fd to trigger when output is possible (the connection is open) */ |
| 125187 | res = UA_EventLoopPOSIX_registerFD(el, rfd: &newConn->rfd); |
| 125188 | if(res != UA_STATUSCODE_GOOD) { |
| 125189 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125190 | msg: "TCP\t| Registering the socket to connect to %s failed", hostname); |
| 125191 | UA_close(fd: newSock); |
| 125192 | UA_free(ptr: newConn); |
| 125193 | return res; |
| 125194 | } |
| 125195 | |
| 125196 | /* Register internally in the EventSource */ |
| 125197 | ZIP_INSERT(UA_FDTree, &pcm->fds, &newConn->rfd); |
| 125198 | pcm->fdsSize++; |
| 125199 | |
| 125200 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125201 | msg: "TCP %u\t| Opening a connection to \"%s\" on port %s", |
| 125202 | (unsigned)newSock, hostname, portStr); |
| 125203 | |
| 125204 | /* Signal the new connection to the application as asynchonously opening */ |
| 125205 | connectionCallback(&pcm->cm, (uintptr_t)newSock, |
| 125206 | application, &newConn->context, |
| 125207 | UA_CONNECTIONSTATE_OPENING, &UA_KEYVALUEMAP_NULL, |
| 125208 | UA_BYTESTRING_NULL); |
| 125209 | |
| 125210 | return UA_STATUSCODE_GOOD; |
| 125211 | } |
| 125212 | |
| 125213 | static UA_StatusCode |
| 125214 | TCP_openConnection(UA_ConnectionManager *cm, const UA_KeyValueMap *params, |
| 125215 | void *application, void *context, |
| 125216 | UA_ConnectionManager_connectionCallback connectionCallback) { |
| 125217 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 125218 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 125219 | UA_LOCK(&el->elMutex); |
| 125220 | |
| 125221 | if(cm->eventSource.state != UA_EVENTSOURCESTATE_STARTED) { |
| 125222 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125223 | msg: "TCP\t| Cannot open a connection for a " |
| 125224 | "ConnectionManager that is not started"); |
| 125225 | UA_UNLOCK(&el->elMutex); |
| 125226 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125227 | } |
| 125228 | |
| 125229 | /* Check the parameters */ |
| 125230 | UA_StatusCode res = |
| 125231 | UA_KeyValueRestriction_validate(logger: el->eventLoop.logger, logprefix: "TCP", |
| 125232 | restrictions: &TCPConfigParameters[1], |
| 125233 | TCP_PARAMETERSSIZE-1, map: params); |
| 125234 | if(res != UA_STATUSCODE_GOOD) { |
| 125235 | UA_UNLOCK(&el->elMutex); |
| 125236 | return res; |
| 125237 | } |
| 125238 | |
| 125239 | /* Only validate the parameters? */ |
| 125240 | UA_Boolean validate = false; |
| 125241 | const UA_Boolean *validateParam = (const UA_Boolean*) |
| 125242 | UA_KeyValueMap_getScalar(map: params, |
| 125243 | key: TCPConfigParameters[TCP_PARAMINDEX_VALIDATE].name, |
| 125244 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 125245 | if(validateParam) |
| 125246 | validate = *validateParam; |
| 125247 | |
| 125248 | /* Listen or active connection? */ |
| 125249 | UA_Boolean listen = false; |
| 125250 | const UA_Boolean *listenParam = (const UA_Boolean*) |
| 125251 | UA_KeyValueMap_getScalar(map: params, |
| 125252 | key: TCPConfigParameters[TCP_PARAMINDEX_LISTEN].name, |
| 125253 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 125254 | if(listenParam) |
| 125255 | listen = *listenParam; |
| 125256 | |
| 125257 | if(listen) { |
| 125258 | res = TCP_openPassiveConnection(pcm, params, application, context, |
| 125259 | connectionCallback, validate); |
| 125260 | } else { |
| 125261 | res = TCP_openActiveConnection(pcm, params, application, context, |
| 125262 | connectionCallback, validate); |
| 125263 | } |
| 125264 | |
| 125265 | UA_UNLOCK(&el->elMutex); |
| 125266 | return res; |
| 125267 | } |
| 125268 | |
| 125269 | static UA_StatusCode |
| 125270 | TCP_eventSourceStart(UA_ConnectionManager *cm) { |
| 125271 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 125272 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 125273 | if(!el) |
| 125274 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125275 | |
| 125276 | UA_LOCK(&el->elMutex); |
| 125277 | |
| 125278 | /* Check the state */ |
| 125279 | if(cm->eventSource.state != UA_EVENTSOURCESTATE_STOPPED) { |
| 125280 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125281 | msg: "TCP\t| To start the ConnectionManager, it has to be " |
| 125282 | "registered in an EventLoop and not started yet"); |
| 125283 | UA_UNLOCK(&el->elMutex); |
| 125284 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125285 | } |
| 125286 | |
| 125287 | /* Check the parameters */ |
| 125288 | UA_StatusCode res = |
| 125289 | UA_KeyValueRestriction_validate(logger: el->eventLoop.logger, logprefix: "TCP", |
| 125290 | restrictions: TCPConfigParameters, restrictionsSize: 1, |
| 125291 | map: &cm->eventSource.params); |
| 125292 | if(res != UA_STATUSCODE_GOOD) |
| 125293 | goto finish; |
| 125294 | |
| 125295 | /* Allocate the rx buffer */ |
| 125296 | res = UA_EventLoopPOSIX_allocateRXBuffer(pcm); |
| 125297 | if(res != UA_STATUSCODE_GOOD) |
| 125298 | goto finish; |
| 125299 | |
| 125300 | /* Set the EventSource to the started state */ |
| 125301 | cm->eventSource.state = UA_EVENTSOURCESTATE_STARTED; |
| 125302 | |
| 125303 | finish: |
| 125304 | UA_UNLOCK(&el->elMutex); |
| 125305 | return res; |
| 125306 | } |
| 125307 | |
| 125308 | static void * |
| 125309 | TCP_shutdownCB(void *application, UA_RegisteredFD *rfd) { |
| 125310 | UA_ConnectionManager *cm = (UA_ConnectionManager*)application; |
| 125311 | TCP_shutdown(cm, conn: (TCP_FD*)rfd); |
| 125312 | return NULL; |
| 125313 | } |
| 125314 | |
| 125315 | static void |
| 125316 | TCP_eventSourceStop(UA_ConnectionManager *cm) { |
| 125317 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 125318 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 125319 | (void)el; |
| 125320 | |
| 125321 | UA_LOCK(&el->elMutex); |
| 125322 | |
| 125323 | UA_LOG_INFO(logger: cm->eventSource.eventLoop->logger, category: UA_LOGCATEGORY_NETWORK, |
| 125324 | msg: "TCP\t| Shutting down the ConnectionManager"); |
| 125325 | |
| 125326 | /* Prevent new connections to open */ |
| 125327 | cm->eventSource.state = UA_EVENTSOURCESTATE_STOPPING; |
| 125328 | |
| 125329 | /* Shutdown all existing connection */ |
| 125330 | ZIP_ITER(UA_FDTree, &pcm->fds, TCP_shutdownCB, cm); |
| 125331 | |
| 125332 | /* All sockets closed? Otherwise iterate some more. */ |
| 125333 | TCP_checkStopped(pcm); |
| 125334 | |
| 125335 | UA_UNLOCK(&el->elMutex); |
| 125336 | } |
| 125337 | |
| 125338 | static UA_StatusCode |
| 125339 | TCP_eventSourceDelete(UA_ConnectionManager *cm) { |
| 125340 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 125341 | if(cm->eventSource.state >= UA_EVENTSOURCESTATE_STARTING) { |
| 125342 | UA_LOG_ERROR(logger: cm->eventSource.eventLoop->logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 125343 | msg: "TCP\t| The EventSource must be stopped before it can be deleted"); |
| 125344 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125345 | } |
| 125346 | |
| 125347 | UA_ByteString_clear(p: &pcm->rxBuffer); |
| 125348 | UA_KeyValueMap_clear(map: &cm->eventSource.params); |
| 125349 | UA_String_clear(p: &cm->eventSource.name); |
| 125350 | UA_free(ptr: cm); |
| 125351 | |
| 125352 | return UA_STATUSCODE_GOOD; |
| 125353 | } |
| 125354 | |
| 125355 | static const char *tcpName = "tcp"; |
| 125356 | |
| 125357 | UA_ConnectionManager * |
| 125358 | UA_ConnectionManager_new_POSIX_TCP(const UA_String eventSourceName) { |
| 125359 | UA_POSIXConnectionManager *cm = (UA_POSIXConnectionManager*) |
| 125360 | UA_calloc(nmemb: 1, size: sizeof(UA_POSIXConnectionManager)); |
| 125361 | if(!cm) |
| 125362 | return NULL; |
| 125363 | |
| 125364 | cm->cm.eventSource.eventSourceType = UA_EVENTSOURCETYPE_CONNECTIONMANAGER; |
| 125365 | UA_String_copy(src: &eventSourceName, dst: &cm->cm.eventSource.name); |
| 125366 | cm->cm.eventSource.start = (UA_StatusCode (*)(UA_EventSource *))TCP_eventSourceStart; |
| 125367 | cm->cm.eventSource.stop = (void (*)(UA_EventSource *))TCP_eventSourceStop; |
| 125368 | cm->cm.eventSource.free = (UA_StatusCode (*)(UA_EventSource *))TCP_eventSourceDelete; |
| 125369 | cm->cm.protocol = UA_STRING(chars: (char*)(uintptr_t)tcpName); |
| 125370 | cm->cm.openConnection = TCP_openConnection; |
| 125371 | cm->cm.allocNetworkBuffer = UA_EventLoopPOSIX_allocNetworkBuffer; |
| 125372 | cm->cm.freeNetworkBuffer = UA_EventLoopPOSIX_freeNetworkBuffer; |
| 125373 | cm->cm.sendWithConnection = TCP_sendWithConnection; |
| 125374 | cm->cm.closeConnection = TCP_shutdownConnection; |
| 125375 | return &cm->cm; |
| 125376 | } |
| 125377 | |
| 125378 | /**** amalgamated original file "/arch/eventloop_posix_udp.c" ****/ |
| 125379 | |
| 125380 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 125381 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 125382 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 125383 | * |
| 125384 | * Copyright 2021-2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 125385 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Jan Hermes) |
| 125386 | */ |
| 125387 | |
| 125388 | |
| 125389 | #define IPV4_PREFIX_MASK 0xF0 |
| 125390 | #define IPV4_MULTICAST_PREFIX 0xE0 |
| 125391 | #if UA_IPV6 |
| 125392 | # define IPV6_PREFIX_MASK 0xFF |
| 125393 | # define IPV6_MULTICAST_PREFIX 0xFF |
| 125394 | #endif |
| 125395 | |
| 125396 | /* Configuration parameters */ |
| 125397 | #define UDP_PARAMETERSSIZE 10 |
| 125398 | #define UDP_PARAMINDEX_RECVBUF 0 |
| 125399 | #define UDP_PARAMINDEX_LISTEN 1 |
| 125400 | #define UDP_PARAMINDEX_ADDR 2 |
| 125401 | #define UDP_PARAMINDEX_PORT 3 |
| 125402 | #define UDP_PARAMINDEX_INTERFACE 4 |
| 125403 | #define UDP_PARAMINDEX_TTL 5 |
| 125404 | #define UDP_PARAMINDEX_LOOPBACK 6 |
| 125405 | #define UDP_PARAMINDEX_REUSE 7 |
| 125406 | #define UDP_PARAMINDEX_SOCKPRIO 8 |
| 125407 | #define UDP_PARAMINDEX_VALIDATE 9 |
| 125408 | |
| 125409 | static UA_KeyValueRestriction UDPConfigParameters[UDP_PARAMETERSSIZE] = { |
| 125410 | {{0, UA_STRING_STATIC("recv-bufsize")}, &UA_TYPES[UA_TYPES_UINT32], false, true, false}, |
| 125411 | {{0, UA_STRING_STATIC("listen")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false}, |
| 125412 | {{0, UA_STRING_STATIC("address")}, &UA_TYPES[UA_TYPES_STRING], false, true, true}, |
| 125413 | {{0, UA_STRING_STATIC("port")}, &UA_TYPES[UA_TYPES_UINT16], true, true, false}, |
| 125414 | {{0, UA_STRING_STATIC("interface")}, &UA_TYPES[UA_TYPES_STRING], false, true, false}, |
| 125415 | {{0, UA_STRING_STATIC("ttl")}, &UA_TYPES[UA_TYPES_UINT32], false, true, false}, |
| 125416 | {{0, UA_STRING_STATIC("loopback")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false}, |
| 125417 | {{0, UA_STRING_STATIC("reuse")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false}, |
| 125418 | {{0, UA_STRING_STATIC("sockpriority")}, &UA_TYPES[UA_TYPES_UINT32], false, true, false}, |
| 125419 | {{0, UA_STRING_STATIC("validate")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false} |
| 125420 | }; |
| 125421 | |
| 125422 | /* A registered file descriptor with an additional method pointer */ |
| 125423 | typedef struct { |
| 125424 | UA_RegisteredFD rfd; |
| 125425 | |
| 125426 | UA_ConnectionManager_connectionCallback applicationCB; |
| 125427 | void *application; |
| 125428 | void *context; |
| 125429 | |
| 125430 | struct sockaddr_storage sendAddr; |
| 125431 | #ifdef UA_ARCHITECTURE_WIN32 |
| 125432 | size_t sendAddrLength; |
| 125433 | #else |
| 125434 | socklen_t sendAddrLength; |
| 125435 | #endif |
| 125436 | } UDP_FD; |
| 125437 | |
| 125438 | typedef enum { |
| 125439 | MULTICASTTYPE_NONE = 0, |
| 125440 | MULTICASTTYPE_IPV4, |
| 125441 | MULTICASTTYPE_IPV6 |
| 125442 | } MultiCastType; |
| 125443 | |
| 125444 | typedef union { |
| 125445 | #if !defined(ip_mreqn) |
| 125446 | struct ip_mreq ipv4; |
| 125447 | #else |
| 125448 | struct ip_mreqn ipv4; |
| 125449 | #endif |
| 125450 | #if UA_IPV6 |
| 125451 | struct ipv6_mreq ipv6; |
| 125452 | #endif |
| 125453 | } MulticastRequest; |
| 125454 | |
| 125455 | static UA_Boolean |
| 125456 | isMulticastAddress(const UA_Byte *address, UA_Byte mask, UA_Byte prefix) { |
| 125457 | return (address[0] & mask) == prefix; |
| 125458 | } |
| 125459 | |
| 125460 | static MultiCastType |
| 125461 | multiCastType(struct addrinfo *info) { |
| 125462 | const UA_Byte *address; |
| 125463 | if(info->ai_family == AF_INET) { |
| 125464 | address = (UA_Byte *)&((struct sockaddr_in *)info->ai_addr)->sin_addr; |
| 125465 | if(isMulticastAddress(address, IPV4_PREFIX_MASK, IPV4_MULTICAST_PREFIX)) |
| 125466 | return MULTICASTTYPE_IPV4; |
| 125467 | #if UA_IPV6 |
| 125468 | } else if(info->ai_family == AF_INET6) { |
| 125469 | address = (UA_Byte *)&((struct sockaddr_in6 *)info->ai_addr)->sin6_addr; |
| 125470 | if(isMulticastAddress(address, IPV6_PREFIX_MASK, IPV6_MULTICAST_PREFIX)) |
| 125471 | return MULTICASTTYPE_IPV6; |
| 125472 | #endif |
| 125473 | } |
| 125474 | return MULTICASTTYPE_NONE; |
| 125475 | } |
| 125476 | |
| 125477 | #ifdef UA_ARCHITECTURE_WIN32 |
| 125478 | |
| 125479 | #define ADDR_BUFFER_SIZE 15000 /* recommended size in the MSVC docs */ |
| 125480 | |
| 125481 | static UA_StatusCode |
| 125482 | setMulticastInterface(const char *netif, struct addrinfo *info, |
| 125483 | MulticastRequest *req, const UA_Logger *logger) { |
| 125484 | ULONG outBufLen = ADDR_BUFFER_SIZE; |
| 125485 | UA_STACKARRAY(char, addrBuf, ADDR_BUFFER_SIZE); |
| 125486 | |
| 125487 | /* Get the network interface descriptions */ |
| 125488 | ULONG flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | |
| 125489 | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_FRIENDLY_NAME; |
| 125490 | PIP_ADAPTER_ADDRESSES ifaddr = (IP_ADAPTER_ADDRESSES *)addrBuf; |
| 125491 | DWORD ret = GetAdaptersAddresses(info->ai_family, flags, NULL, ifaddr, &outBufLen); |
| 125492 | if(ret != NO_ERROR) { |
| 125493 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, |
| 125494 | "UDP\t| Interface configuration preparation failed"); |
| 125495 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125496 | } |
| 125497 | |
| 125498 | /* Iterate through linked list of network interfaces */ |
| 125499 | char sourceAddr[64]; |
| 125500 | unsigned int idx = 0; |
| 125501 | for(PIP_ADAPTER_ADDRESSES ifa = ifaddr; ifa != NULL; ifa = ifa->Next) { |
| 125502 | idx = (info->ai_family == AF_INET) ? ifa->IfIndex : ifa->Ipv6IfIndex; |
| 125503 | |
| 125504 | /* Check if network interface name matches */ |
| 125505 | if(strcmp(ifa->AdapterName, netif) == 0) |
| 125506 | goto done; |
| 125507 | |
| 125508 | /* Check if ip address matches */ |
| 125509 | for(PIP_ADAPTER_UNICAST_ADDRESS u = ifa->FirstUnicastAddress; u; u = u->Next) { |
| 125510 | LPSOCKADDR addr = u->Address.lpSockaddr; |
| 125511 | if(addr->sa_family == AF_INET) { |
| 125512 | inet_ntop(AF_INET, &((struct sockaddr_in*)addr)->sin_addr, |
| 125513 | sourceAddr, sizeof(sourceAddr)); |
| 125514 | } else if(addr->sa_family == AF_INET6) { |
| 125515 | inet_ntop(AF_INET6, &((struct sockaddr_in6*)addr)->sin6_addr, |
| 125516 | sourceAddr, sizeof(sourceAddr)); |
| 125517 | } else { |
| 125518 | continue; |
| 125519 | } |
| 125520 | if(strcmp(sourceAddr, netif) == 0) |
| 125521 | goto done; |
| 125522 | } |
| 125523 | } |
| 125524 | |
| 125525 | /* Not matching interface found */ |
| 125526 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, |
| 125527 | "UDP\t| Interface configuration preparation failed " |
| 125528 | "(interface %s not found)", netif); |
| 125529 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125530 | |
| 125531 | done: |
| 125532 | /* Write the interface index */ |
| 125533 | if(info->ai_family == AF_INET) |
| 125534 | /* MSVC documentation of struct ip_mreq: To use an interface index of 1 |
| 125535 | * would be the same as an IP address of 0.0.0.1. */ |
| 125536 | req->ipv4.imr_interface.s_addr = htonl(idx); |
| 125537 | #if UA_IPV6 |
| 125538 | else /* if(info->ai_family == AF_INET6) */ |
| 125539 | req->ipv6.ipv6mr_interface = idx; |
| 125540 | #endif |
| 125541 | return UA_STATUSCODE_GOOD; |
| 125542 | } |
| 125543 | |
| 125544 | #else |
| 125545 | |
| 125546 | static UA_StatusCode |
| 125547 | setMulticastInterface(const char *netif, struct addrinfo *info, |
| 125548 | MulticastRequest *req, const UA_Logger *logger) { |
| 125549 | struct ifaddrs *ifaddr; |
| 125550 | int ret = getifaddrs(ifap: &ifaddr); |
| 125551 | if(ret == -1) { |
| 125552 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125553 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, |
| 125554 | "UDP\t| Interface configuration preparation failed " |
| 125555 | "(getifaddrs error: %s)", errno_str)); |
| 125556 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125557 | } |
| 125558 | |
| 125559 | /* Iterate over the interfaces */ |
| 125560 | unsigned int idx = 0; |
| 125561 | struct ifaddrs *ifa = NULL; |
| 125562 | for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { |
| 125563 | if(!ifa->ifa_addr) |
| 125564 | continue; |
| 125565 | |
| 125566 | /* Does the protocol family match? */ |
| 125567 | if(ifa->ifa_addr->sa_family != info->ai_family) |
| 125568 | continue; |
| 125569 | |
| 125570 | idx = UA_if_nametoindex(ifname: ifa->ifa_name); |
| 125571 | if(idx == 0) |
| 125572 | continue; |
| 125573 | |
| 125574 | /* Found network interface by name */ |
| 125575 | if(strcmp(s1: ifa->ifa_name, s2: netif) == 0) |
| 125576 | break; |
| 125577 | |
| 125578 | /* Check if the interface name is an IP address that matches */ |
| 125579 | char host[NI_MAXHOST]; |
| 125580 | ret = getnameinfo(sa: ifa->ifa_addr, |
| 125581 | salen: (info->ai_family == AF_INET) ? |
| 125582 | sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), |
| 125583 | host: host, NI_MAXHOST, NULL, servlen: 0, NI_NUMERICHOST); |
| 125584 | if(ret != 0) { |
| 125585 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125586 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_SERVER, |
| 125587 | "UDP\t| Interface configuration preparation " |
| 125588 | "ifailed (getnameinfo error: %s).", errno_str)); |
| 125589 | freeifaddrs(ifa: ifaddr); |
| 125590 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125591 | } |
| 125592 | if(strcmp(s1: host, s2: netif) == 0) |
| 125593 | break; |
| 125594 | } |
| 125595 | |
| 125596 | freeifaddrs(ifa: ifaddr); |
| 125597 | if(!ifa) |
| 125598 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125599 | |
| 125600 | /* Write the interface index */ |
| 125601 | if(info->ai_family == AF_INET) { |
| 125602 | #if defined(ip_mreqn) |
| 125603 | req->ipv4.imr_ifindex = idx; |
| 125604 | #endif |
| 125605 | #if UA_IPV6 |
| 125606 | } else { /* if(info->ai_family == AF_INET6) */ |
| 125607 | req->ipv6.ipv6mr_interface = idx; |
| 125608 | #endif |
| 125609 | } |
| 125610 | return UA_STATUSCODE_GOOD; |
| 125611 | } |
| 125612 | |
| 125613 | #endif /* UA_ARCHITECTURE_WIN32 */ |
| 125614 | |
| 125615 | static UA_StatusCode |
| 125616 | setupMulticastRequest(UA_FD socket, MulticastRequest *req, const UA_KeyValueMap *params, |
| 125617 | struct addrinfo *info, const UA_Logger *logger) { |
| 125618 | /* Initialize the address information */ |
| 125619 | if(info->ai_family == AF_INET) { |
| 125620 | struct sockaddr_in *sin = (struct sockaddr_in *)info->ai_addr; |
| 125621 | req->ipv4.imr_multiaddr = sin->sin_addr; |
| 125622 | #if !defined(ip_mreqn) |
| 125623 | req->ipv4.imr_interface.s_addr = htonl(INADDR_ANY); /* default ANY */ |
| 125624 | #else |
| 125625 | req->ipv4.imr_address.s_addr = htonl(INADDR_ANY); /* default ANY */ |
| 125626 | req->ipv4.imr_ifindex = 0; |
| 125627 | #endif |
| 125628 | #if UA_IPV6 |
| 125629 | } else if(info->ai_family == AF_INET6) { |
| 125630 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)info->ai_addr; |
| 125631 | req->ipv6.ipv6mr_multiaddr = sin6->sin6_addr; |
| 125632 | req->ipv6.ipv6mr_interface = 0; /* default ANY interface */ |
| 125633 | #endif |
| 125634 | } else { |
| 125635 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_SERVER, |
| 125636 | msg: "UDP\t| Multicast configuration failed: Unknown protocol family"); |
| 125637 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125638 | } |
| 125639 | |
| 125640 | /* Was an interface (or local IP address) defined? */ |
| 125641 | const UA_String *netif = (const UA_String*) |
| 125642 | UA_KeyValueMap_getScalar(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_INTERFACE].name, |
| 125643 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 125644 | if(!netif) { |
| 125645 | UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK, |
| 125646 | msg: "UDP %u\t| No network interface defined for multicast. " |
| 125647 | "The first suitable network interface is used.", |
| 125648 | (unsigned)socket); |
| 125649 | return UA_STATUSCODE_GOOD; |
| 125650 | } |
| 125651 | |
| 125652 | /* Set the interface index */ |
| 125653 | UA_STACKARRAY(char, interfaceAsChar, sizeof(char) * netif->length + 1); |
| 125654 | memcpy(dest: interfaceAsChar, src: netif->data, n: netif->length); |
| 125655 | interfaceAsChar[netif->length] = 0; |
| 125656 | return setMulticastInterface(netif: interfaceAsChar, info, req, logger); |
| 125657 | } |
| 125658 | |
| 125659 | /* Retrieves hostname and port from given key value parameters. |
| 125660 | * |
| 125661 | * @param[in] params the parameter map to retrieve from |
| 125662 | * @param[out] hostname the retrieved hostname when present, NULL otherwise |
| 125663 | * @param[out] portStr the retrieved port when present, NULL otherwise |
| 125664 | * @param[in] logger the logger to log information |
| 125665 | * @return -1 upon error, 0 if there was no host or port parameter, 1 if |
| 125666 | * host and port are present */ |
| 125667 | static int |
| 125668 | getHostAndPortFromParams(const UA_KeyValueMap *params, char *hostname, |
| 125669 | char *portStr, const UA_Logger *logger) { |
| 125670 | /* Prepare the port parameter as a string */ |
| 125671 | const UA_UInt16 *port = (const UA_UInt16*) |
| 125672 | UA_KeyValueMap_getScalar(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_PORT].name, |
| 125673 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 125674 | UA_assert(port); /* checked before */ |
| 125675 | mp_snprintf(s: portStr, UA_MAXPORTSTR_LENGTH, format: "%d", *port); |
| 125676 | |
| 125677 | /* Prepare the hostname string */ |
| 125678 | const UA_String *host = (const UA_String*) |
| 125679 | UA_KeyValueMap_getScalar(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_ADDR].name, |
| 125680 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 125681 | if(!host) { |
| 125682 | UA_LOG_DEBUG(logger, category: UA_LOGCATEGORY_NETWORK, |
| 125683 | msg: "UDP\t| No address configured"); |
| 125684 | return -1; |
| 125685 | } |
| 125686 | if(host->length >= UA_MAXHOSTNAME_LENGTH) { |
| 125687 | UA_LOG_ERROR(logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 125688 | msg: "UDP\t| Open UDP Connection: Hostname too long, aborting"); |
| 125689 | return -1; |
| 125690 | } |
| 125691 | strncpy(dest: hostname, src: (const char*)host->data, n: host->length); |
| 125692 | hostname[host->length] = 0; |
| 125693 | return 1; |
| 125694 | } |
| 125695 | |
| 125696 | static int |
| 125697 | getConnectionInfoFromParams(const UA_KeyValueMap *params, |
| 125698 | char *hostname, char *portStr, |
| 125699 | struct addrinfo **info, const UA_Logger *logger) { |
| 125700 | int foundParams = getHostAndPortFromParams(params, hostname, portStr, logger); |
| 125701 | if(foundParams < 0) |
| 125702 | return -1; |
| 125703 | |
| 125704 | /* Create the socket description from the connectString |
| 125705 | * TODO: Make this non-blocking */ |
| 125706 | struct addrinfo hints; |
| 125707 | memset(s: &hints, c: 0, n: sizeof(struct addrinfo)); |
| 125708 | hints.ai_family = AF_UNSPEC; |
| 125709 | hints.ai_socktype = SOCK_DGRAM; |
| 125710 | int error = getaddrinfo(name: hostname, service: portStr, req: &hints, pai: info); |
| 125711 | if(error != 0) { |
| 125712 | UA_LOG_SOCKET_ERRNO_GAI_WRAP( |
| 125713 | UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK, |
| 125714 | "UDP\t| Lookup of %s failed with error %d - %s", |
| 125715 | hostname, error, errno_str)); |
| 125716 | return -1; |
| 125717 | } |
| 125718 | return 1; |
| 125719 | } |
| 125720 | |
| 125721 | /* Set loop back data to your host */ |
| 125722 | static UA_StatusCode |
| 125723 | setLoopBackData(UA_SOCKET sockfd, UA_Boolean enableLoopback, |
| 125724 | int ai_family, const UA_Logger *logger) { |
| 125725 | /* The Linux Kernel IPv6 socket code checks for optlen to be at least the |
| 125726 | * size of an integer. However, channelDataUDPMC->enableLoopback is a |
| 125727 | * boolean. In order for the code to work for IPv4 and IPv6 propagate it to |
| 125728 | * a temporary integer here. */ |
| 125729 | UA_Int32 enable = enableLoopback; |
| 125730 | #if UA_IPV6 |
| 125731 | if(UA_setsockopt(fd: sockfd, |
| 125732 | level: ai_family == AF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, |
| 125733 | optname: ai_family == AF_INET6 ? IPV6_MULTICAST_LOOP : IP_MULTICAST_LOOP, |
| 125734 | optval: (const char *)&enable, |
| 125735 | optlen: sizeof (enable)) < 0) |
| 125736 | #else |
| 125737 | if(UA_setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, |
| 125738 | (const char *)&enable, |
| 125739 | sizeof (enable)) < 0) |
| 125740 | #endif |
| 125741 | { |
| 125742 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125743 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_NETWORK, |
| 125744 | "UDP %u\t| Loopback setup failed: " |
| 125745 | "Cannot set socket option IP_MULTICAST_LOOP. Error: %s", |
| 125746 | (unsigned)sockfd, errno_str)); |
| 125747 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125748 | } |
| 125749 | return UA_STATUSCODE_GOOD; |
| 125750 | } |
| 125751 | |
| 125752 | static UA_StatusCode |
| 125753 | setTimeToLive(UA_SOCKET sockfd, UA_UInt32 messageTTL, |
| 125754 | int ai_family, const UA_Logger *logger) { |
| 125755 | /* Set Time to live (TTL). Value of 1 prevent forward beyond the local network. */ |
| 125756 | #if UA_IPV6 |
| 125757 | if(UA_setsockopt(fd: sockfd, |
| 125758 | level: ai_family == PF_INET6 ? IPPROTO_IPV6 : IPPROTO_IP, |
| 125759 | optname: ai_family == PF_INET6 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL, |
| 125760 | optval: (const char *)&messageTTL, |
| 125761 | optlen: sizeof(messageTTL)) < 0) |
| 125762 | #else |
| 125763 | if(UA_setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, |
| 125764 | (const char *)&messageTTL, |
| 125765 | sizeof(messageTTL)) < 0) |
| 125766 | #endif |
| 125767 | { |
| 125768 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125769 | UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK, |
| 125770 | "UDP %u\t| Time to live setup failed: " |
| 125771 | "Cannot set socket option IP_MULTICAST_TTL. Error: %s", |
| 125772 | (unsigned)sockfd, errno_str)); |
| 125773 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125774 | } |
| 125775 | return UA_STATUSCODE_GOOD; |
| 125776 | } |
| 125777 | |
| 125778 | static UA_StatusCode |
| 125779 | setReuseAddress(UA_SOCKET sockfd, UA_Boolean enableReuse, const UA_Logger *logger) { |
| 125780 | /* Set reuse address -> enables sharing of the same listening address on |
| 125781 | * different sockets */ |
| 125782 | int enableReuseVal = (enableReuse) ? 1 : 0; |
| 125783 | if(UA_setsockopt(fd: sockfd, SOL_SOCKET, SO_REUSEADDR, |
| 125784 | optval: (const char*)&enableReuseVal, optlen: sizeof(enableReuseVal)) < 0) { |
| 125785 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125786 | UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK, |
| 125787 | "UDP %u\t| Reuse address setup failed: " |
| 125788 | "Cannot set socket option SO_REUSEADDR. Error: %s", |
| 125789 | (unsigned)sockfd, errno_str)); |
| 125790 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125791 | } |
| 125792 | return UA_STATUSCODE_GOOD; |
| 125793 | } |
| 125794 | |
| 125795 | #ifdef __linux__ |
| 125796 | static UA_StatusCode |
| 125797 | setSocketPriority(UA_SOCKET sockfd, UA_UInt32 socketPriority, |
| 125798 | const UA_Logger *logger) { |
| 125799 | int prio = (int)socketPriority; |
| 125800 | if(UA_setsockopt(fd: sockfd, SOL_SOCKET, SO_PRIORITY, optval: &prio, optlen: sizeof(int)) < 0) { |
| 125801 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125802 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_NETWORK, |
| 125803 | "UDP %u\t| Socket priority setup failed: " |
| 125804 | "Cannot set socket option SO_PRIORITY. Error: %s", |
| 125805 | (unsigned)sockfd, errno_str)); |
| 125806 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125807 | } |
| 125808 | return UA_STATUSCODE_GOOD; |
| 125809 | } |
| 125810 | #endif |
| 125811 | |
| 125812 | static UA_StatusCode |
| 125813 | setConnectionConfig(UA_FD socket, const UA_KeyValueMap *params, |
| 125814 | int ai_family, const UA_Logger *logger) { |
| 125815 | /* Set socket config that is always set */ |
| 125816 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 125817 | res |= UA_EventLoopPOSIX_setNonBlocking(sockfd: socket); |
| 125818 | res |= UA_EventLoopPOSIX_setNoSigPipe(sockfd: socket); |
| 125819 | if(res != UA_STATUSCODE_GOOD) |
| 125820 | return res; |
| 125821 | |
| 125822 | /* Some Linux distributions have net.ipv6.bindv6only not activated. So |
| 125823 | * sockets can double-bind to IPv4 and IPv6. This leads to problems. Use |
| 125824 | * AF_INET6 sockets only for IPv6. */ |
| 125825 | #if UA_IPV6 |
| 125826 | int optval = 1; |
| 125827 | if(ai_family == AF_INET6 && |
| 125828 | UA_setsockopt(fd: socket, IPPROTO_IPV6, IPV6_V6ONLY, |
| 125829 | optval: (const char*)&optval, optlen: sizeof(optval)) == -1) { |
| 125830 | UA_LOG_WARNING(logger, category: UA_LOGCATEGORY_NETWORK, |
| 125831 | msg: "UDP %u\t| Could not set an IPv6 socket to IPv6 only, closing", |
| 125832 | (unsigned)socket); |
| 125833 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 125834 | } |
| 125835 | #endif |
| 125836 | |
| 125837 | /* Set socket settings from the parameters */ |
| 125838 | const UA_UInt32 *messageTTL = (const UA_UInt32*) |
| 125839 | UA_KeyValueMap_getScalar(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_TTL].name, |
| 125840 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 125841 | if(messageTTL) |
| 125842 | res |= setTimeToLive(sockfd: socket, messageTTL: *messageTTL, ai_family, logger); |
| 125843 | |
| 125844 | const UA_Boolean *enableLoopback = (const UA_Boolean*) |
| 125845 | UA_KeyValueMap_getScalar(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_LOOPBACK].name, |
| 125846 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 125847 | if(enableLoopback) |
| 125848 | res |= setLoopBackData(sockfd: socket, enableLoopback: *enableLoopback, ai_family, logger); |
| 125849 | |
| 125850 | const UA_Boolean *enableReuse = (const UA_Boolean*) |
| 125851 | UA_KeyValueMap_getScalar(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_REUSE].name, |
| 125852 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 125853 | if(enableReuse) |
| 125854 | res |= setReuseAddress(sockfd: socket, enableReuse: *enableReuse, logger); |
| 125855 | |
| 125856 | #ifdef __linux__ |
| 125857 | const UA_UInt32 *socketPriority = (const UA_UInt32*) |
| 125858 | UA_KeyValueMap_getScalar(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_SOCKPRIO].name, |
| 125859 | type: &UA_TYPES[UA_TYPES_UINT32]); |
| 125860 | if(socketPriority) |
| 125861 | res |= setSocketPriority(sockfd: socket, socketPriority: *socketPriority, logger); |
| 125862 | #endif |
| 125863 | |
| 125864 | if(res != UA_STATUSCODE_GOOD) { |
| 125865 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125866 | UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK, |
| 125867 | "UDP\t| Could not set socket options: %s", errno_str)); |
| 125868 | } |
| 125869 | return res; |
| 125870 | } |
| 125871 | |
| 125872 | static UA_StatusCode |
| 125873 | setupListenMultiCast(UA_FD fd, struct addrinfo *info, const UA_KeyValueMap *params, |
| 125874 | MultiCastType multiCastType, const UA_Logger *logger) { |
| 125875 | MulticastRequest req; |
| 125876 | UA_StatusCode res = setupMulticastRequest(socket: fd, req: &req, params, info, logger); |
| 125877 | if(res != UA_STATUSCODE_GOOD) |
| 125878 | return res; |
| 125879 | |
| 125880 | int result = -1; |
| 125881 | if(info->ai_family == AF_INET && multiCastType == MULTICASTTYPE_IPV4) { |
| 125882 | result = UA_setsockopt(fd: fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, |
| 125883 | optval: &req.ipv4, optlen: sizeof(req.ipv4)); |
| 125884 | #if UA_IPV6 |
| 125885 | } else if(info->ai_family == AF_INET6 && multiCastType == MULTICASTTYPE_IPV6) { |
| 125886 | result = UA_setsockopt(fd: fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, |
| 125887 | optval: &req.ipv6, optlen: sizeof(req.ipv6)); |
| 125888 | #endif |
| 125889 | } |
| 125890 | |
| 125891 | if(result < 0) { |
| 125892 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125893 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_NETWORK, |
| 125894 | "UDP %u\t| Cannot set socket for multicast receiving. Error: %s", |
| 125895 | (unsigned)fd, errno_str)); |
| 125896 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125897 | } |
| 125898 | return UA_STATUSCODE_GOOD; |
| 125899 | } |
| 125900 | |
| 125901 | static UA_StatusCode |
| 125902 | setupSendMultiCast(UA_FD fd, struct addrinfo *info, const UA_KeyValueMap *params, |
| 125903 | MultiCastType multiCastType, const UA_Logger *logger) { |
| 125904 | MulticastRequest req; |
| 125905 | UA_StatusCode res = setupMulticastRequest(socket: fd, req: &req, params, info, logger); |
| 125906 | if(res != UA_STATUSCODE_GOOD) |
| 125907 | return res; |
| 125908 | |
| 125909 | int result = -1; |
| 125910 | if(info->ai_family == AF_INET && multiCastType == MULTICASTTYPE_IPV4) { |
| 125911 | result = setsockopt(fd: fd, IPPROTO_IP, IP_MULTICAST_IF, |
| 125912 | #ifdef UA_ARCHITECTURE_WIN32 |
| 125913 | (const char *)&req.ipv4.imr_interface, |
| 125914 | sizeof(struct in_addr)); |
| 125915 | #else |
| 125916 | optval: &req.ipv4, optlen: sizeof(req.ipv4)); |
| 125917 | #endif |
| 125918 | #if UA_IPV6 |
| 125919 | } else if(info->ai_family == AF_INET6 && multiCastType == MULTICASTTYPE_IPV6) { |
| 125920 | result = setsockopt(fd: fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, |
| 125921 | #ifdef UA_ARCHITECTURE_WIN32 |
| 125922 | (const char *)&req.ipv6.ipv6mr_interface, |
| 125923 | #else |
| 125924 | optval: &req.ipv6.ipv6mr_interface, |
| 125925 | #endif |
| 125926 | optlen: sizeof(req.ipv6.ipv6mr_interface)); |
| 125927 | #endif |
| 125928 | } |
| 125929 | |
| 125930 | if(result < 0) { |
| 125931 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125932 | UA_LOG_ERROR(logger, UA_LOGCATEGORY_NETWORK, |
| 125933 | "UDP %u\t| Cannot set socket for multicast sending. Error: %s", |
| 125934 | (unsigned)fd, errno_str)); |
| 125935 | return UA_STATUSCODE_BADINTERNALERROR; |
| 125936 | } |
| 125937 | return UA_STATUSCODE_GOOD; |
| 125938 | } |
| 125939 | |
| 125940 | /* Test if the ConnectionManager can be stopped */ |
| 125941 | static void |
| 125942 | UDP_checkStopped(UA_POSIXConnectionManager *pcm) { |
| 125943 | UA_LOCK_ASSERT(&((UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop)->elMutex, 1); |
| 125944 | |
| 125945 | if(pcm->fdsSize == 0 && |
| 125946 | pcm->cm.eventSource.state == UA_EVENTSOURCESTATE_STOPPING) { |
| 125947 | UA_LOG_DEBUG(logger: pcm->cm.eventSource.eventLoop->logger, category: UA_LOGCATEGORY_NETWORK, |
| 125948 | msg: "UDP\t| All sockets closed, the EventLoop has stopped"); |
| 125949 | pcm->cm.eventSource.state = UA_EVENTSOURCESTATE_STOPPED; |
| 125950 | } |
| 125951 | } |
| 125952 | |
| 125953 | /* This method must not be called from the application directly, but from within |
| 125954 | * the EventLoop. Otherwise we cannot be sure whether the file descriptor is |
| 125955 | * still used after calling close. */ |
| 125956 | static void |
| 125957 | UDP_close(UA_POSIXConnectionManager *pcm, UDP_FD *conn) { |
| 125958 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 125959 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 125960 | |
| 125961 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125962 | msg: "UDP %u\t| Closing connection", |
| 125963 | (unsigned)conn->rfd.fd); |
| 125964 | |
| 125965 | /* Deregister from the EventLoop */ |
| 125966 | UA_EventLoopPOSIX_deregisterFD(el, rfd: &conn->rfd); |
| 125967 | |
| 125968 | /* Deregister internally */ |
| 125969 | ZIP_REMOVE(UA_FDTree, &pcm->fds, &conn->rfd); |
| 125970 | UA_assert(pcm->fdsSize > 0); |
| 125971 | pcm->fdsSize--; |
| 125972 | |
| 125973 | /* Signal closing to the application */ |
| 125974 | conn->applicationCB(&pcm->cm, (uintptr_t)conn->rfd.fd, |
| 125975 | conn->application, &conn->context, |
| 125976 | UA_CONNECTIONSTATE_CLOSING, |
| 125977 | &UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL); |
| 125978 | |
| 125979 | /* Close the socket */ |
| 125980 | int ret = UA_close(fd: conn->rfd.fd); |
| 125981 | if(ret == 0) { |
| 125982 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 125983 | msg: "UDP %u\t| Socket closed", (unsigned)conn->rfd.fd); |
| 125984 | } else { |
| 125985 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 125986 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 125987 | "UDP %u\t| Could not close the socket (%s)", |
| 125988 | (unsigned)conn->rfd.fd, errno_str)); |
| 125989 | } |
| 125990 | |
| 125991 | UA_free(ptr: conn); |
| 125992 | |
| 125993 | /* Stop if the ucm is stopping and this was the last open socket */ |
| 125994 | UDP_checkStopped(pcm); |
| 125995 | } |
| 125996 | |
| 125997 | static void |
| 125998 | UDP_delayedClose(void *application, void *context) { |
| 125999 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)application; |
| 126000 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 126001 | UDP_FD *conn = (UDP_FD*)context; |
| 126002 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 126003 | msg: "UDP %u\t| Delayed closing of the connection", |
| 126004 | (unsigned)conn->rfd.fd); |
| 126005 | UA_LOCK(&el->elMutex); |
| 126006 | UDP_close(pcm, conn); |
| 126007 | UA_UNLOCK(&el->elMutex); |
| 126008 | } |
| 126009 | |
| 126010 | /* Gets called when a socket receives data or closes */ |
| 126011 | static void |
| 126012 | UDP_connectionSocketCallback(UA_POSIXConnectionManager *pcm, UDP_FD *conn, |
| 126013 | short event) { |
| 126014 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 126015 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 126016 | |
| 126017 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126018 | msg: "UDP %u\t| Activity on the socket", |
| 126019 | (unsigned)conn->rfd.fd); |
| 126020 | |
| 126021 | if(event == UA_FDEVENT_ERR) { |
| 126022 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126023 | UA_LOG_DEBUG(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 126024 | "UDP %u\t| recv signaled the socket was shutdown (%s)", |
| 126025 | (unsigned)conn->rfd.fd, errno_str)); |
| 126026 | UDP_close(pcm, conn); |
| 126027 | return; |
| 126028 | } |
| 126029 | |
| 126030 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126031 | msg: "UDP %u\t| Allocate receive buffer", (unsigned)conn->rfd.fd); |
| 126032 | |
| 126033 | /* Use the already allocated receive-buffer */ |
| 126034 | UA_ByteString response = pcm->rxBuffer; |
| 126035 | |
| 126036 | /* Receive */ |
| 126037 | struct sockaddr_storage source; |
| 126038 | #ifndef UA_ARCHITECTURE_WIN32 |
| 126039 | socklen_t sourceSize = (socklen_t)sizeof(struct sockaddr_storage); |
| 126040 | ssize_t ret = recvfrom(fd: conn->rfd.fd, buf: (char*)response.data, n: response.length, |
| 126041 | MSG_DONTWAIT, addr: (struct sockaddr*)&source, addr_len: &sourceSize); |
| 126042 | #else |
| 126043 | int sourceSize = (int)sizeof(struct sockaddr_storage); |
| 126044 | int ret = recvfrom(conn->rfd.fd, (char*)response.data, (int)response.length, |
| 126045 | MSG_DONTWAIT, (struct sockaddr*)&source, &sourceSize); |
| 126046 | #endif |
| 126047 | |
| 126048 | /* Receive has failed */ |
| 126049 | if(ret <= 0) { |
| 126050 | if(UA_ERRNO == UA_INTERRUPTED) |
| 126051 | return; |
| 126052 | |
| 126053 | /* Orderly shutdown of the socket. We can immediately close as no method |
| 126054 | * "below" in the call stack will use the socket in this iteration of |
| 126055 | * the EventLoop. */ |
| 126056 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126057 | UA_LOG_DEBUG(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 126058 | "UDP %u\t| recv signaled the socket was shutdown (%s)", |
| 126059 | (unsigned)conn->rfd.fd, errno_str)); |
| 126060 | UDP_close(pcm, conn); |
| 126061 | return; |
| 126062 | } |
| 126063 | |
| 126064 | response.length = (size_t)ret; /* Set the length of the received buffer */ |
| 126065 | |
| 126066 | /* Extract message source and port */ |
| 126067 | char sourceAddr[64]; |
| 126068 | UA_UInt16 sourcePort; |
| 126069 | switch(source.ss_family) { |
| 126070 | case AF_INET: |
| 126071 | inet_ntop(AF_INET, cp: &((struct sockaddr_in *)&source)->sin_addr, |
| 126072 | buf: sourceAddr, len: 64); |
| 126073 | sourcePort = htons(hostshort: ((struct sockaddr_in *)&source)->sin_port); |
| 126074 | break; |
| 126075 | case AF_INET6: |
| 126076 | inet_ntop(AF_INET6, cp: &(((struct sockaddr_in6 *)&source)->sin6_addr), |
| 126077 | buf: sourceAddr, len: 64); |
| 126078 | sourcePort = htons(hostshort: ((struct sockaddr_in6 *)&source)->sin6_port); |
| 126079 | break; |
| 126080 | default: |
| 126081 | sourceAddr[0] = 0; |
| 126082 | sourcePort = 0; |
| 126083 | } |
| 126084 | |
| 126085 | UA_String sourceAddrStr = UA_STRING(chars: sourceAddr); |
| 126086 | UA_KeyValuePair kvp[2]; |
| 126087 | kvp[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "remote-address"); |
| 126088 | UA_Variant_setScalar(v: &kvp[0].value, p: &sourceAddrStr, type: &UA_TYPES[UA_TYPES_STRING]); |
| 126089 | kvp[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "remote-port"); |
| 126090 | UA_Variant_setScalar(v: &kvp[1].value, p: &sourcePort, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 126091 | UA_KeyValueMap kvm = {2, kvp}; |
| 126092 | |
| 126093 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126094 | msg: "UDP %u\t| Received message of size %u from %s on port %u", |
| 126095 | (unsigned)conn->rfd.fd, (unsigned)ret, |
| 126096 | sourceAddr, sourcePort); |
| 126097 | |
| 126098 | /* Callback to the application layer */ |
| 126099 | conn->applicationCB(&pcm->cm, (uintptr_t)conn->rfd.fd, |
| 126100 | conn->application, &conn->context, |
| 126101 | UA_CONNECTIONSTATE_ESTABLISHED, |
| 126102 | &kvm, response); |
| 126103 | } |
| 126104 | |
| 126105 | static UA_StatusCode |
| 126106 | UDP_registerListenSocket(UA_POSIXConnectionManager *pcm, UA_UInt16 port, |
| 126107 | struct addrinfo *info, const UA_KeyValueMap *params, |
| 126108 | void *application, void *context, |
| 126109 | UA_ConnectionManager_connectionCallback connectionCallback, |
| 126110 | UA_Boolean validate) { |
| 126111 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 126112 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 126113 | |
| 126114 | /* Get logging information */ |
| 126115 | char hoststr[UA_MAXHOSTNAME_LENGTH]; |
| 126116 | int get_res = UA_getnameinfo(info->ai_addr, info->ai_addrlen, |
| 126117 | hoststr, sizeof(hoststr), |
| 126118 | NULL, 0, NI_NUMERICHOST); |
| 126119 | if(get_res != 0) { |
| 126120 | hoststr[0] = 0; |
| 126121 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126122 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 126123 | "UDP\t| getnameinfo(...) could not resolve the hostname (%s)", |
| 126124 | errno_str)); |
| 126125 | if(validate) { |
| 126126 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 126127 | } |
| 126128 | } |
| 126129 | |
| 126130 | /* Create the listen socket */ |
| 126131 | UA_FD listenSocket = socket(domain: info->ai_family, type: info->ai_socktype, protocol: info->ai_protocol); |
| 126132 | if(listenSocket == UA_INVALID_FD) { |
| 126133 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126134 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 126135 | "UDP %u\t| Error opening the listen socket for " |
| 126136 | "\"%s\" on port %u (%s)", |
| 126137 | (unsigned)listenSocket, hoststr, port, errno_str)); |
| 126138 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 126139 | } |
| 126140 | |
| 126141 | /* Set the socket configuration per the parameters */ |
| 126142 | UA_StatusCode res = |
| 126143 | setConnectionConfig(socket: listenSocket, params, |
| 126144 | ai_family: info->ai_family, logger: el->eventLoop.logger); |
| 126145 | if(res != UA_STATUSCODE_GOOD) { |
| 126146 | UA_close(fd: listenSocket); |
| 126147 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 126148 | } |
| 126149 | |
| 126150 | /* Are we going to prepare a socket for multicast? */ |
| 126151 | MultiCastType mc = multiCastType(info); |
| 126152 | |
| 126153 | /* Bind socket to the address */ |
| 126154 | #ifdef UA_ARCHITECTURE_WIN32 |
| 126155 | /* On windows we need to bind the socket to INADDR_ANY before registering |
| 126156 | * for the multicast group */ |
| 126157 | int ret = -1; |
| 126158 | if(mc != MULTICASTTYPE_NONE) { |
| 126159 | if(info->ai_family == AF_INET) { |
| 126160 | struct sockaddr_in *orig = (struct sockaddr_in *)info->ai_addr; |
| 126161 | struct sockaddr_in sin; |
| 126162 | memset(&sin, 0, sizeof(sin)); |
| 126163 | sin.sin_family = AF_INET; |
| 126164 | sin.sin_addr.s_addr = htonl(INADDR_ANY); |
| 126165 | sin.sin_port = orig->sin_port; |
| 126166 | ret = bind(listenSocket, (struct sockaddr*)&sin, sizeof(sin)); |
| 126167 | } else if(info->ai_family == AF_INET6) { |
| 126168 | struct sockaddr_in6 *orig = (struct sockaddr_in6 *)info->ai_addr; |
| 126169 | struct sockaddr_in6 sin6; |
| 126170 | memset(&sin6, 0, sizeof(sin6)); |
| 126171 | sin6.sin6_family = AF_INET6; |
| 126172 | sin6.sin6_addr = in6addr_any; |
| 126173 | sin6.sin6_port = orig->sin6_port; |
| 126174 | ret = bind(listenSocket, (struct sockaddr*)&sin6, sizeof(sin6)); |
| 126175 | } |
| 126176 | } else { |
| 126177 | ret = bind(listenSocket, info->ai_addr, (socklen_t)info->ai_addrlen); |
| 126178 | } |
| 126179 | #else |
| 126180 | int ret = bind(fd: listenSocket, addr: info->ai_addr, len: (socklen_t)info->ai_addrlen); |
| 126181 | #endif |
| 126182 | |
| 126183 | /* Get the port being used if dynamic porting was used */ |
| 126184 | if(port == 0) { |
| 126185 | struct sockaddr_in sin; |
| 126186 | memset(s: &sin, c: 0, n: sizeof(sin)); |
| 126187 | socklen_t len = sizeof(sin); |
| 126188 | getsockname(fd: listenSocket, addr: (struct sockaddr *)&sin, len: &len); |
| 126189 | port = ntohs(netshort: sin.sin_port); |
| 126190 | } |
| 126191 | |
| 126192 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126193 | msg: "UDP %u\t| New listen socket for \"%s\" on port %u", |
| 126194 | (unsigned)listenSocket, hoststr, port); |
| 126195 | |
| 126196 | if(ret < 0) { |
| 126197 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126198 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 126199 | "UDP %u\t| Error binding the socket to the address (%s), closing", |
| 126200 | (unsigned)listenSocket, errno_str)); |
| 126201 | UA_close(fd: listenSocket); |
| 126202 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 126203 | } |
| 126204 | |
| 126205 | /* Enable multicast if this is a multicast address */ |
| 126206 | if(mc != MULTICASTTYPE_NONE) { |
| 126207 | res = setupListenMultiCast(fd: listenSocket, info, params, |
| 126208 | multiCastType: mc, logger: el->eventLoop.logger); |
| 126209 | if(res != UA_STATUSCODE_GOOD) { |
| 126210 | UA_close(fd: listenSocket); |
| 126211 | return res; |
| 126212 | } |
| 126213 | } |
| 126214 | |
| 126215 | /* Validation is complete - close and return */ |
| 126216 | if(validate) { |
| 126217 | UA_close(fd: listenSocket); |
| 126218 | return UA_STATUSCODE_GOOD; |
| 126219 | } |
| 126220 | |
| 126221 | /* Allocate the UA_RegisteredFD */ |
| 126222 | UDP_FD *newudpfd = (UDP_FD*)UA_calloc(nmemb: 1, size: sizeof(UDP_FD)); |
| 126223 | if(!newudpfd) { |
| 126224 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126225 | msg: "UDP %u\t| Error allocating memory for the socket, closing", |
| 126226 | (unsigned)listenSocket); |
| 126227 | UA_close(fd: listenSocket); |
| 126228 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 126229 | } |
| 126230 | |
| 126231 | newudpfd->rfd.fd = listenSocket; |
| 126232 | newudpfd->rfd.es = &pcm->cm.eventSource; |
| 126233 | newudpfd->rfd.listenEvents = UA_FDEVENT_IN; |
| 126234 | newudpfd->rfd.eventSourceCB = (UA_FDCallback)UDP_connectionSocketCallback; |
| 126235 | newudpfd->applicationCB = connectionCallback; |
| 126236 | newudpfd->application = application; |
| 126237 | newudpfd->context = context; |
| 126238 | |
| 126239 | /* Register in the EventLoop */ |
| 126240 | res = UA_EventLoopPOSIX_registerFD(el, rfd: &newudpfd->rfd); |
| 126241 | if(res != UA_STATUSCODE_GOOD) { |
| 126242 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126243 | msg: "UDP %u\t| Error registering the socket, closing", |
| 126244 | (unsigned)listenSocket); |
| 126245 | UA_free(ptr: newudpfd); |
| 126246 | UA_close(fd: listenSocket); |
| 126247 | return res; |
| 126248 | } |
| 126249 | |
| 126250 | /* Register internally in the EventSource */ |
| 126251 | ZIP_INSERT(UA_FDTree, &pcm->fds, &newudpfd->rfd); |
| 126252 | pcm->fdsSize++; |
| 126253 | |
| 126254 | /* Register the listen socket in the application */ |
| 126255 | connectionCallback(&pcm->cm, (uintptr_t)newudpfd->rfd.fd, |
| 126256 | application, &newudpfd->context, |
| 126257 | UA_CONNECTIONSTATE_ESTABLISHED, |
| 126258 | &UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL); |
| 126259 | return UA_STATUSCODE_GOOD; |
| 126260 | } |
| 126261 | |
| 126262 | static UA_StatusCode |
| 126263 | UDP_registerListenSockets(UA_POSIXConnectionManager *pcm, const char *hostname, |
| 126264 | UA_UInt16 port, const UA_KeyValueMap *params, |
| 126265 | void *application, void *context, |
| 126266 | UA_ConnectionManager_connectionCallback connectionCallback, |
| 126267 | UA_Boolean validate) { |
| 126268 | UA_LOCK_ASSERT(&((UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop)->elMutex, 1); |
| 126269 | |
| 126270 | /* Get all the interface and IPv4/6 combinations for the configured hostname */ |
| 126271 | struct addrinfo hints, *res; |
| 126272 | memset(s: &hints, c: 0, n: sizeof hints); |
| 126273 | #if UA_IPV6 |
| 126274 | hints.ai_family = AF_UNSPEC; /* Allow IPv4 and IPv6 */ |
| 126275 | #else |
| 126276 | hints.ai_family = AF_INET; /* IPv4 only */ |
| 126277 | #endif |
| 126278 | hints.ai_socktype = SOCK_DGRAM; |
| 126279 | hints.ai_protocol = IPPROTO_UDP; |
| 126280 | hints.ai_flags = AI_PASSIVE; |
| 126281 | |
| 126282 | /* Set up the port string */ |
| 126283 | char portstr[6]; |
| 126284 | mp_snprintf(s: portstr, n: 6, format: "%d", port); |
| 126285 | |
| 126286 | int retcode = getaddrinfo(name: hostname, service: portstr, req: &hints, pai: &res); |
| 126287 | if(retcode != 0) { |
| 126288 | UA_LOG_SOCKET_ERRNO_GAI_WRAP( |
| 126289 | UA_LOG_WARNING(pcm->cm.eventSource.eventLoop->logger, |
| 126290 | UA_LOGCATEGORY_NETWORK, |
| 126291 | "UDP\t| getaddrinfo lookup for \"%s\" on port %u failed (%s)", |
| 126292 | hostname, port, errno_str)); |
| 126293 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 126294 | } |
| 126295 | |
| 126296 | /* Add listen sockets */ |
| 126297 | struct addrinfo *ai = res; |
| 126298 | UA_StatusCode rv = UA_STATUSCODE_GOOD; |
| 126299 | while(ai) { |
| 126300 | rv = UDP_registerListenSocket(pcm, port, info: ai, params, application, |
| 126301 | context, connectionCallback, validate); |
| 126302 | if(rv != UA_STATUSCODE_GOOD) |
| 126303 | break; |
| 126304 | ai = ai->ai_next; |
| 126305 | } |
| 126306 | freeaddrinfo(ai: res); |
| 126307 | return rv; |
| 126308 | } |
| 126309 | |
| 126310 | /* Close the connection via a delayed callback */ |
| 126311 | static void |
| 126312 | UDP_shutdown(UA_ConnectionManager *cm, UA_RegisteredFD *rfd) { |
| 126313 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)cm->eventSource.eventLoop; |
| 126314 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 126315 | |
| 126316 | if(rfd->dc.callback) { |
| 126317 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126318 | msg: "UDP %u\t| Cannot close - already closing", |
| 126319 | (unsigned)rfd->fd); |
| 126320 | return; |
| 126321 | } |
| 126322 | |
| 126323 | /* Shutdown the socket to cancel the current select/epoll */ |
| 126324 | shutdown(fd: rfd->fd, UA_SHUT_RDWR); |
| 126325 | |
| 126326 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126327 | msg: "UDP %u\t| Shutdown called", (unsigned)rfd->fd); |
| 126328 | |
| 126329 | UA_DelayedCallback *dc = &rfd->dc; |
| 126330 | dc->callback = UDP_delayedClose; |
| 126331 | dc->application = cm; |
| 126332 | dc->context = rfd; |
| 126333 | |
| 126334 | /* Don't use the "public" el->addDelayedCallback. It takes a lock. */ |
| 126335 | dc->next = el->delayedCallbacks; |
| 126336 | el->delayedCallbacks = dc; |
| 126337 | } |
| 126338 | |
| 126339 | static UA_StatusCode |
| 126340 | UDP_shutdownConnection(UA_ConnectionManager *cm, uintptr_t connectionId) { |
| 126341 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 126342 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)cm->eventSource.eventLoop; |
| 126343 | UA_FD fd = (UA_FD)connectionId; |
| 126344 | |
| 126345 | UA_LOCK(&el->elMutex); |
| 126346 | UA_RegisteredFD *rfd = ZIP_FIND(UA_FDTree, &pcm->fds, &fd); |
| 126347 | if(!rfd) { |
| 126348 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126349 | msg: "UDP\t| Cannot close UDP connection %u - not found", |
| 126350 | (unsigned)connectionId); |
| 126351 | UA_UNLOCK(&el->elMutex); |
| 126352 | return UA_STATUSCODE_BADNOTFOUND; |
| 126353 | } |
| 126354 | UDP_shutdown(cm, rfd); |
| 126355 | UA_UNLOCK(&el->elMutex); |
| 126356 | return UA_STATUSCODE_GOOD; |
| 126357 | } |
| 126358 | |
| 126359 | static UA_StatusCode |
| 126360 | UDP_sendWithConnection(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 126361 | const UA_KeyValueMap *params, |
| 126362 | UA_ByteString *buf) { |
| 126363 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 126364 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 126365 | |
| 126366 | UA_LOCK(&el->elMutex); |
| 126367 | |
| 126368 | /* Look up the registered UDP socket */ |
| 126369 | UA_FD fd = (UA_FD)connectionId; |
| 126370 | UDP_FD *conn = (UDP_FD*)ZIP_FIND(UA_FDTree, &pcm->fds, &fd); |
| 126371 | if(!conn) { |
| 126372 | UA_UNLOCK(&el->elMutex); |
| 126373 | UA_ByteString_clear(p: buf); |
| 126374 | return UA_STATUSCODE_BADINTERNALERROR; |
| 126375 | } |
| 126376 | |
| 126377 | /* Send the full buffer. This may require several calls to send */ |
| 126378 | size_t nWritten = 0; |
| 126379 | do { |
| 126380 | ssize_t n = 0; |
| 126381 | do { |
| 126382 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126383 | msg: "UDP %u\t| Attempting to send", (unsigned)connectionId); |
| 126384 | |
| 126385 | /* Prevent OS signals when sending to a closed socket */ |
| 126386 | int flags = MSG_NOSIGNAL; |
| 126387 | size_t bytes_to_send = buf->length - nWritten; |
| 126388 | n = UA_sendto(fd: (UA_FD)connectionId, buf: (const char*)buf->data + nWritten, |
| 126389 | n: bytes_to_send, flags: flags, addr: (struct sockaddr*)&conn->sendAddr, |
| 126390 | addr_len: conn->sendAddrLength); |
| 126391 | if(n < 0) { |
| 126392 | /* An error we cannot recover from? */ |
| 126393 | if(UA_ERRNO != UA_INTERRUPTED && |
| 126394 | UA_ERRNO != UA_WOULDBLOCK && |
| 126395 | UA_ERRNO != UA_AGAIN) { |
| 126396 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126397 | UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 126398 | "UDP %u\t| Send failed with error %s", |
| 126399 | (unsigned)connectionId, errno_str)); |
| 126400 | UA_UNLOCK(&el->elMutex); |
| 126401 | UDP_shutdownConnection(cm, connectionId); |
| 126402 | UA_ByteString_clear(p: buf); |
| 126403 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 126404 | } |
| 126405 | |
| 126406 | /* Poll for the socket resources to become available and retry |
| 126407 | * (blocking) */ |
| 126408 | int poll_ret; |
| 126409 | struct pollfd tmp_poll_fd; |
| 126410 | tmp_poll_fd.fd = (UA_FD)connectionId; |
| 126411 | tmp_poll_fd.events = UA_POLLOUT; |
| 126412 | do { |
| 126413 | poll_ret = UA_poll(fds: &tmp_poll_fd, nfds: 1, timeout: 100); |
| 126414 | if(poll_ret < 0 && UA_ERRNO != UA_INTERRUPTED) { |
| 126415 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126416 | UA_LOG_ERROR(el->eventLoop.logger, |
| 126417 | UA_LOGCATEGORY_NETWORK, |
| 126418 | "UDP %u\t| Send failed with error %s", |
| 126419 | (unsigned)connectionId, errno_str)); |
| 126420 | UA_UNLOCK(&el->elMutex); |
| 126421 | UDP_shutdownConnection(cm, connectionId); |
| 126422 | UA_ByteString_clear(p: buf); |
| 126423 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 126424 | } |
| 126425 | } while(poll_ret <= 0); |
| 126426 | } |
| 126427 | } while(n < 0); |
| 126428 | nWritten += (size_t)n; |
| 126429 | } while(nWritten < buf->length); |
| 126430 | |
| 126431 | /* Free the buffer */ |
| 126432 | UA_UNLOCK(&el->elMutex); |
| 126433 | UA_ByteString_clear(p: buf); |
| 126434 | return UA_STATUSCODE_GOOD; |
| 126435 | } |
| 126436 | |
| 126437 | static UA_StatusCode |
| 126438 | registerSocketAndDestinationForSend(const UA_KeyValueMap *params, |
| 126439 | const char *hostname, struct addrinfo *info, |
| 126440 | int error, UDP_FD *ufd, UA_FD *sock, |
| 126441 | const UA_Logger *logger) { |
| 126442 | UA_FD newSock = socket(domain: info->ai_family, type: info->ai_socktype, protocol: info->ai_protocol); |
| 126443 | *sock = newSock; |
| 126444 | if(newSock == UA_INVALID_FD) { |
| 126445 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126446 | UA_LOG_WARNING(logger, UA_LOGCATEGORY_NETWORK, |
| 126447 | "UDP\t| Could not create socket to connect to %s (%s)", |
| 126448 | hostname, errno_str)); |
| 126449 | return UA_STATUSCODE_BADDISCONNECT; |
| 126450 | } |
| 126451 | UA_StatusCode res = setConnectionConfig(socket: newSock, params, ai_family: info->ai_family, logger); |
| 126452 | if(res != UA_STATUSCODE_GOOD) { |
| 126453 | UA_close(fd: newSock); |
| 126454 | return res; |
| 126455 | } |
| 126456 | |
| 126457 | /* Prepare socket for multicast */ |
| 126458 | MultiCastType mc = multiCastType(info); |
| 126459 | if(mc != MULTICASTTYPE_NONE) { |
| 126460 | res = setupSendMultiCast(fd: newSock, info, params, multiCastType: mc, logger); |
| 126461 | if(res != UA_STATUSCODE_GOOD) { |
| 126462 | UA_close(fd: newSock); |
| 126463 | return res; |
| 126464 | } |
| 126465 | } |
| 126466 | |
| 126467 | memcpy(dest: &ufd->sendAddr, src: info->ai_addr, n: info->ai_addrlen); |
| 126468 | ufd->sendAddrLength = info->ai_addrlen; |
| 126469 | return UA_STATUSCODE_GOOD; |
| 126470 | } |
| 126471 | |
| 126472 | static UA_StatusCode |
| 126473 | UDP_openSendConnection(UA_POSIXConnectionManager *pcm, const UA_KeyValueMap *params, |
| 126474 | void *application, void *context, |
| 126475 | UA_ConnectionManager_connectionCallback connectionCallback, |
| 126476 | UA_Boolean validate) { |
| 126477 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)pcm->cm.eventSource.eventLoop; |
| 126478 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 126479 | |
| 126480 | /* Get the connection parameters */ |
| 126481 | char hostname[UA_MAXHOSTNAME_LENGTH]; |
| 126482 | char portStr[UA_MAXPORTSTR_LENGTH]; |
| 126483 | struct addrinfo *info = NULL; |
| 126484 | |
| 126485 | int error = getConnectionInfoFromParams(params, hostname, |
| 126486 | portStr, info: &info, logger: el->eventLoop.logger); |
| 126487 | if(error < 0 || info == NULL) { |
| 126488 | if(info != NULL) { |
| 126489 | freeaddrinfo(ai: info); |
| 126490 | } |
| 126491 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126492 | msg: "UDP\t| Opening a connection failed"); |
| 126493 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 126494 | } |
| 126495 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126496 | msg: "UDP\t| Open a connection to \"%s\" on port %s", hostname, portStr); |
| 126497 | |
| 126498 | /* Allocate the UA_RegisteredFD */ |
| 126499 | UDP_FD *conn = (UDP_FD*)UA_calloc(nmemb: 1, size: sizeof(UDP_FD)); |
| 126500 | if(!conn) { |
| 126501 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126502 | msg: "UDP\t| Error allocating memory for the socket, closing"); |
| 126503 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 126504 | } |
| 126505 | |
| 126506 | /* Create a socket and register the destination address from the provided parameters */ |
| 126507 | UA_FD newSock = UA_INVALID_FD; |
| 126508 | UA_StatusCode res = |
| 126509 | registerSocketAndDestinationForSend(params, hostname, info, |
| 126510 | error, ufd: conn, sock: &newSock, |
| 126511 | logger: el->eventLoop.logger); |
| 126512 | freeaddrinfo(ai: info); |
| 126513 | if(validate && res == UA_STATUSCODE_GOOD) { |
| 126514 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126515 | msg: "UDP %u\t| Connection validated to \"%s\" on port %s", |
| 126516 | (unsigned)newSock, hostname, portStr); |
| 126517 | UA_close(fd: newSock); |
| 126518 | UA_free(ptr: conn); |
| 126519 | return UA_STATUSCODE_GOOD; |
| 126520 | } |
| 126521 | if(res != UA_STATUSCODE_GOOD) { |
| 126522 | UA_free(ptr: conn); |
| 126523 | return res; |
| 126524 | } |
| 126525 | |
| 126526 | conn->rfd.fd = newSock; |
| 126527 | conn->rfd.listenEvents = 0; |
| 126528 | conn->rfd.es = &pcm->cm.eventSource; |
| 126529 | conn->rfd.eventSourceCB = (UA_FDCallback)UDP_connectionSocketCallback; |
| 126530 | conn->applicationCB = connectionCallback; |
| 126531 | conn->application = application; |
| 126532 | conn->context = context; |
| 126533 | |
| 126534 | /* Register the fd to trigger when output is possible (the connection is open) */ |
| 126535 | res = UA_EventLoopPOSIX_registerFD(el, rfd: &conn->rfd); |
| 126536 | if(res != UA_STATUSCODE_GOOD) { |
| 126537 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126538 | msg: "UDP\t| Registering the socket for %s failed", hostname); |
| 126539 | UA_close(fd: newSock); |
| 126540 | UA_free(ptr: conn); |
| 126541 | return res; |
| 126542 | } |
| 126543 | |
| 126544 | /* Register internally in the EventSource */ |
| 126545 | ZIP_INSERT(UA_FDTree, &pcm->fds, &conn->rfd); |
| 126546 | pcm->fdsSize++; |
| 126547 | |
| 126548 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126549 | msg: "UDP %u\t| New connection to \"%s\" on port %s", |
| 126550 | (unsigned)newSock, hostname, portStr); |
| 126551 | |
| 126552 | /* Signal the connection as opening. The connection fully opens in the next |
| 126553 | * iteration of the EventLoop */ |
| 126554 | connectionCallback(&pcm->cm, (uintptr_t)newSock, application, |
| 126555 | &conn->context, UA_CONNECTIONSTATE_ESTABLISHED, |
| 126556 | &UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL); |
| 126557 | |
| 126558 | return UA_STATUSCODE_GOOD; |
| 126559 | } |
| 126560 | |
| 126561 | static UA_StatusCode |
| 126562 | UDP_openReceiveConnection(UA_POSIXConnectionManager *pcm, const UA_KeyValueMap *params, |
| 126563 | void *application, void *context, |
| 126564 | UA_ConnectionManager_connectionCallback connectionCallback, |
| 126565 | UA_Boolean validate) { |
| 126566 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 126567 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 126568 | |
| 126569 | /* Get the port */ |
| 126570 | const UA_UInt16 *port = (const UA_UInt16*) |
| 126571 | UA_KeyValueMap_getScalar(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_PORT].name, |
| 126572 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 126573 | UA_assert(port); /* checked before */ |
| 126574 | |
| 126575 | /* Get the hostname configuration */ |
| 126576 | const UA_Variant *addrs = |
| 126577 | UA_KeyValueMap_get(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_ADDR].name); |
| 126578 | size_t addrsSize = 0; |
| 126579 | if(addrs) { |
| 126580 | UA_assert(addrs->type == &UA_TYPES[UA_TYPES_STRING]); |
| 126581 | if(UA_Variant_isScalar(v: addrs)) |
| 126582 | addrsSize = 1; |
| 126583 | else |
| 126584 | addrsSize = addrs->arrayLength; |
| 126585 | } |
| 126586 | |
| 126587 | /* No hostname configured -> listen on all interfaces */ |
| 126588 | if(addrsSize == 0) { |
| 126589 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126590 | msg: "UDP\t| Listening on all interfaces"); |
| 126591 | return UDP_registerListenSockets(pcm, NULL, port: *port, params, application, |
| 126592 | context, connectionCallback, validate); |
| 126593 | } |
| 126594 | |
| 126595 | /* Iterate over the configured hostnames */ |
| 126596 | UA_String *hostStrings = (UA_String*)addrs->data; |
| 126597 | for(size_t i = 0; i < addrsSize; i++) { |
| 126598 | char hn[UA_MAXHOSTNAME_LENGTH]; |
| 126599 | if(hostStrings[i].length >= sizeof(hn)) |
| 126600 | continue; |
| 126601 | memcpy(dest: hn, src: hostStrings[i].data, n: hostStrings->length); |
| 126602 | hn[hostStrings->length] = '\0'; |
| 126603 | UA_StatusCode rv = |
| 126604 | UDP_registerListenSockets(pcm, hostname: hn, port: *port, params, application, |
| 126605 | context, connectionCallback, validate); |
| 126606 | if(rv != UA_STATUSCODE_GOOD) |
| 126607 | return rv; |
| 126608 | } |
| 126609 | |
| 126610 | return UA_STATUSCODE_GOOD; |
| 126611 | } |
| 126612 | |
| 126613 | static UA_StatusCode |
| 126614 | UDP_openConnection(UA_ConnectionManager *cm, const UA_KeyValueMap *params, |
| 126615 | void *application, void *context, |
| 126616 | UA_ConnectionManager_connectionCallback connectionCallback) { |
| 126617 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 126618 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 126619 | UA_LOCK(&el->elMutex); |
| 126620 | |
| 126621 | if(cm->eventSource.state != UA_EVENTSOURCESTATE_STARTED) { |
| 126622 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126623 | msg: "UDP\t| Cannot open a connection for a " |
| 126624 | "ConnectionManager that is not started"); |
| 126625 | UA_UNLOCK(&el->elMutex); |
| 126626 | return UA_STATUSCODE_BADINTERNALERROR; |
| 126627 | } |
| 126628 | |
| 126629 | /* Check the parameters */ |
| 126630 | UA_StatusCode res = |
| 126631 | UA_KeyValueRestriction_validate(logger: el->eventLoop.logger, logprefix: "UDP", |
| 126632 | restrictions: &UDPConfigParameters[1], |
| 126633 | UDP_PARAMETERSSIZE-1, map: params); |
| 126634 | if(res != UA_STATUSCODE_GOOD) { |
| 126635 | UA_UNLOCK(&el->elMutex); |
| 126636 | return res; |
| 126637 | } |
| 126638 | |
| 126639 | UA_Boolean validate = false; |
| 126640 | const UA_Boolean *validationValue = (const UA_Boolean*) |
| 126641 | UA_KeyValueMap_getScalar(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_VALIDATE].name, |
| 126642 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 126643 | if(validationValue) |
| 126644 | validate = *validationValue; |
| 126645 | |
| 126646 | UA_Boolean listen = false; |
| 126647 | const UA_Boolean *listenValue = (const UA_Boolean*) |
| 126648 | UA_KeyValueMap_getScalar(map: params, key: UDPConfigParameters[UDP_PARAMINDEX_LISTEN].name, |
| 126649 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 126650 | if(listenValue) |
| 126651 | listen = *listenValue; |
| 126652 | |
| 126653 | if(listen) { |
| 126654 | res = UDP_openReceiveConnection(pcm, params, application, context, |
| 126655 | connectionCallback, validate); |
| 126656 | } else { |
| 126657 | res = UDP_openSendConnection(pcm, params, application, context, |
| 126658 | connectionCallback, validate); |
| 126659 | } |
| 126660 | UA_UNLOCK(&el->elMutex); |
| 126661 | return res; |
| 126662 | } |
| 126663 | |
| 126664 | static UA_StatusCode |
| 126665 | UDP_eventSourceStart(UA_ConnectionManager *cm) { |
| 126666 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 126667 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 126668 | if(!el) |
| 126669 | return UA_STATUSCODE_BADINTERNALERROR; |
| 126670 | |
| 126671 | UA_LOCK(&el->elMutex); |
| 126672 | |
| 126673 | /* Check the state */ |
| 126674 | if(cm->eventSource.state != UA_EVENTSOURCESTATE_STOPPED) { |
| 126675 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 126676 | msg: "UDP\t| To start the ConnectionManager, " |
| 126677 | "it has to be registered in an EventLoop and not started"); |
| 126678 | UA_UNLOCK(&el->elMutex); |
| 126679 | return UA_STATUSCODE_BADINTERNALERROR; |
| 126680 | } |
| 126681 | |
| 126682 | /* Check the parameters */ |
| 126683 | UA_StatusCode res = |
| 126684 | UA_KeyValueRestriction_validate(logger: el->eventLoop.logger, logprefix: "UDP", |
| 126685 | restrictions: UDPConfigParameters, restrictionsSize: 1, |
| 126686 | map: &cm->eventSource.params); |
| 126687 | if(res != UA_STATUSCODE_GOOD) |
| 126688 | goto finish; |
| 126689 | |
| 126690 | /* Allocate the rx buffer */ |
| 126691 | res = UA_EventLoopPOSIX_allocateRXBuffer(pcm); |
| 126692 | if(res != UA_STATUSCODE_GOOD) |
| 126693 | goto finish; |
| 126694 | |
| 126695 | /* Set the EventSource to the started state */ |
| 126696 | cm->eventSource.state = UA_EVENTSOURCESTATE_STARTED; |
| 126697 | |
| 126698 | finish: |
| 126699 | UA_UNLOCK(&el->elMutex); |
| 126700 | return res; |
| 126701 | } |
| 126702 | |
| 126703 | static void * |
| 126704 | UDP_shutdownCB(void *application, UA_RegisteredFD *rfd) { |
| 126705 | UA_ConnectionManager *cm = (UA_ConnectionManager*)application; |
| 126706 | UDP_shutdown(cm, rfd); |
| 126707 | return NULL; |
| 126708 | } |
| 126709 | |
| 126710 | static void |
| 126711 | UDP_eventSourceStop(UA_ConnectionManager *cm) { |
| 126712 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 126713 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 126714 | (void)el; |
| 126715 | UA_LOCK(&el->elMutex); |
| 126716 | |
| 126717 | UA_LOG_INFO(logger: cm->eventSource.eventLoop->logger, category: UA_LOGCATEGORY_NETWORK, |
| 126718 | msg: "UDP\t| Shutting down the ConnectionManager"); |
| 126719 | |
| 126720 | /* Prevent new connections to open */ |
| 126721 | cm->eventSource.state = UA_EVENTSOURCESTATE_STOPPING; |
| 126722 | |
| 126723 | /* Shutdown all existing connection */ |
| 126724 | ZIP_ITER(UA_FDTree, &pcm->fds, UDP_shutdownCB, cm); |
| 126725 | |
| 126726 | /* Check if stopped once more (also checking inside UDP_close, but there we |
| 126727 | * don't check if there is no rfd at all) */ |
| 126728 | UDP_checkStopped(pcm); |
| 126729 | |
| 126730 | UA_UNLOCK(&el->elMutex); |
| 126731 | } |
| 126732 | |
| 126733 | static UA_StatusCode |
| 126734 | UDP_eventSourceDelete(UA_ConnectionManager *cm) { |
| 126735 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 126736 | if(cm->eventSource.state >= UA_EVENTSOURCESTATE_STARTING) { |
| 126737 | UA_LOG_ERROR(logger: cm->eventSource.eventLoop->logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 126738 | msg: "UDP\t| The EventSource must be stopped before it can be deleted"); |
| 126739 | return UA_STATUSCODE_BADINTERNALERROR; |
| 126740 | } |
| 126741 | |
| 126742 | UA_ByteString_clear(p: &pcm->rxBuffer); |
| 126743 | UA_KeyValueMap_clear(map: &cm->eventSource.params); |
| 126744 | UA_String_clear(p: &cm->eventSource.name); |
| 126745 | UA_free(ptr: cm); |
| 126746 | |
| 126747 | return UA_STATUSCODE_GOOD; |
| 126748 | } |
| 126749 | |
| 126750 | static const char *udpName = "udp"; |
| 126751 | |
| 126752 | UA_ConnectionManager * |
| 126753 | UA_ConnectionManager_new_POSIX_UDP(const UA_String eventSourceName) { |
| 126754 | UA_POSIXConnectionManager *cm = (UA_POSIXConnectionManager*) |
| 126755 | UA_calloc(nmemb: 1, size: sizeof(UA_POSIXConnectionManager)); |
| 126756 | if(!cm) |
| 126757 | return NULL; |
| 126758 | |
| 126759 | cm->cm.eventSource.eventSourceType = UA_EVENTSOURCETYPE_CONNECTIONMANAGER; |
| 126760 | UA_String_copy(src: &eventSourceName, dst: &cm->cm.eventSource.name); |
| 126761 | cm->cm.eventSource.start = (UA_StatusCode (*)(UA_EventSource *))UDP_eventSourceStart; |
| 126762 | cm->cm.eventSource.stop = (void (*)(UA_EventSource *))UDP_eventSourceStop; |
| 126763 | cm->cm.eventSource.free = (UA_StatusCode (*)(UA_EventSource *))UDP_eventSourceDelete; |
| 126764 | cm->cm.protocol = UA_STRING(chars: (char*)(uintptr_t)udpName); |
| 126765 | cm->cm.openConnection = UDP_openConnection; |
| 126766 | cm->cm.allocNetworkBuffer = UA_EventLoopPOSIX_allocNetworkBuffer; |
| 126767 | cm->cm.freeNetworkBuffer = UA_EventLoopPOSIX_freeNetworkBuffer; |
| 126768 | cm->cm.sendWithConnection = UDP_sendWithConnection; |
| 126769 | cm->cm.closeConnection = UDP_shutdownConnection; |
| 126770 | return &cm->cm; |
| 126771 | } |
| 126772 | |
| 126773 | /**** amalgamated original file "/arch/eventloop_posix_interrupt.c" ****/ |
| 126774 | |
| 126775 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 126776 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 126777 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 126778 | * |
| 126779 | * Copyright 2021 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 126780 | */ |
| 126781 | |
| 126782 | #include <signal.h> |
| 126783 | |
| 126784 | /* Different implementation approaches: |
| 126785 | * - Linux: Use signalfd |
| 126786 | * - Other: Use the self-pipe trick (http://cr.yp.to/docs/selfpipe.html) */ |
| 126787 | |
| 126788 | typedef struct UA_RegisteredSignal { |
| 126789 | #ifdef UA_HAVE_EPOLL |
| 126790 | /* With epoll, register each signal with a socket. |
| 126791 | * This has to be the first element of the struct to allow casting. */ |
| 126792 | UA_RegisteredFD rfd; |
| 126793 | #else |
| 126794 | /* Without epoll, we add the rfd to a tailq and self-pipe to trigger the |
| 126795 | * traversal of the tailq */ |
| 126796 | TAILQ_ENTRY(UA_RegisteredSignal) triggeredEntry; |
| 126797 | #endif |
| 126798 | |
| 126799 | LIST_ENTRY(UA_RegisteredSignal) listPointers; |
| 126800 | |
| 126801 | UA_InterruptCallback signalCallback; |
| 126802 | void *context; |
| 126803 | int signal; /* POSIX identifier of the interrupt signal */ |
| 126804 | |
| 126805 | UA_Boolean active; /* Signals are only active when the EventLoop is started */ |
| 126806 | UA_Boolean triggered; |
| 126807 | } UA_RegisteredSignal; |
| 126808 | |
| 126809 | typedef struct { |
| 126810 | UA_InterruptManager im; |
| 126811 | |
| 126812 | /* Registered signals */ |
| 126813 | size_t signalsSize; |
| 126814 | LIST_HEAD(, UA_RegisteredSignal) signals; |
| 126815 | |
| 126816 | #ifndef UA_HAVE_EPOLL |
| 126817 | UA_RegisteredFD readFD; |
| 126818 | UA_FD writeFD; |
| 126819 | TAILQ_HEAD(, UA_RegisteredSignal) triggered; |
| 126820 | #endif |
| 126821 | } UA_POSIXInterruptManager; |
| 126822 | |
| 126823 | #ifndef UA_HAVE_EPOLL |
| 126824 | /* On non-linux systems we can have at most one interrupt manager */ |
| 126825 | static UA_POSIXInterruptManager *singletonIM = NULL; |
| 126826 | #endif |
| 126827 | |
| 126828 | /* The following methods have to be implemented for epoll/self-pipe each. */ |
| 126829 | static void activateSignal(UA_RegisteredSignal *rs); |
| 126830 | static void deactivateSignal(UA_RegisteredSignal *rs); |
| 126831 | |
| 126832 | #ifdef UA_HAVE_EPOLL |
| 126833 | #include <sys/signalfd.h> |
| 126834 | |
| 126835 | static void |
| 126836 | handlePOSIXInterruptEvent(UA_EventSource *es, UA_RegisteredFD *rfd, short event) { |
| 126837 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)es->eventLoop; |
| 126838 | (void)el; |
| 126839 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 126840 | |
| 126841 | UA_RegisteredSignal *rs = (UA_RegisteredSignal*)rfd; |
| 126842 | struct signalfd_siginfo fdsi; |
| 126843 | ssize_t s = read(fd: rfd->fd, buf: &fdsi, nbytes: sizeof(fdsi)); |
| 126844 | if(s < (ssize_t)sizeof(fdsi)) { |
| 126845 | /* A problem occured */ |
| 126846 | deactivateSignal(rs); |
| 126847 | return; |
| 126848 | } |
| 126849 | |
| 126850 | /* Signal received */ |
| 126851 | UA_LOG_DEBUG(logger: es->eventLoop->logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 126852 | msg: "Interrupt %u\t| Received a signal %u", |
| 126853 | (unsigned)rfd->fd, fdsi.ssi_signo); |
| 126854 | |
| 126855 | UA_UNLOCK(&el->elMutex); |
| 126856 | rs->signalCallback((UA_InterruptManager *)es, (uintptr_t)rfd->fd, |
| 126857 | rs->context, &UA_KEYVALUEMAP_NULL); |
| 126858 | UA_LOCK(&el->elMutex); |
| 126859 | } |
| 126860 | |
| 126861 | static void |
| 126862 | activateSignal(UA_RegisteredSignal *rs) { |
| 126863 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)rs->rfd.es->eventLoop; |
| 126864 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 126865 | |
| 126866 | if(rs->active) |
| 126867 | return; |
| 126868 | |
| 126869 | /* Block the normal signal handling */ |
| 126870 | sigset_t mask; |
| 126871 | sigemptyset(set: &mask); |
| 126872 | sigaddset(set: &mask, signo: rs->signal); |
| 126873 | int res2 = sigprocmask(SIG_BLOCK, set: &mask, NULL); |
| 126874 | if(res2 == -1) { |
| 126875 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126876 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP, |
| 126877 | "Interrupt\t| Could not block the default " |
| 126878 | "signal handling with an error: %s", |
| 126879 | errno_str)); |
| 126880 | return; |
| 126881 | } |
| 126882 | |
| 126883 | /* Create the fd */ |
| 126884 | UA_FD newfd = signalfd(fd: -1, mask: &mask, flags: 0); |
| 126885 | if(newfd < 0) { |
| 126886 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126887 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_EVENTLOOP, |
| 126888 | "Interrupt\t|Could not create a signal file " |
| 126889 | "description with error: %s", |
| 126890 | errno_str)); |
| 126891 | sigprocmask(SIG_UNBLOCK, set: &mask, NULL); /* restore signal */ |
| 126892 | return; |
| 126893 | } |
| 126894 | |
| 126895 | rs->rfd.fd = newfd; |
| 126896 | rs->rfd.eventSourceCB = handlePOSIXInterruptEvent; |
| 126897 | rs->rfd.listenEvents = UA_FDEVENT_IN; |
| 126898 | |
| 126899 | /* Register the fd in the EventLoop */ |
| 126900 | UA_StatusCode res = UA_EventLoopPOSIX_registerFD(el, rfd: &rs->rfd); |
| 126901 | if(res != UA_STATUSCODE_GOOD) { |
| 126902 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 126903 | msg: "Interrupt\t|Could not register the a signal file " |
| 126904 | "description in the EventLoop"); |
| 126905 | UA_close(fd: newfd); |
| 126906 | sigprocmask(SIG_UNBLOCK, set: &mask, NULL); /* restore signal */ |
| 126907 | return; |
| 126908 | } |
| 126909 | |
| 126910 | rs->active = true; |
| 126911 | } |
| 126912 | |
| 126913 | static void |
| 126914 | deactivateSignal(UA_RegisteredSignal *rs) { |
| 126915 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)rs->rfd.es->eventLoop; |
| 126916 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 126917 | |
| 126918 | /* Only dectivate if active */ |
| 126919 | if(!rs->active) |
| 126920 | return; |
| 126921 | rs->active = false; |
| 126922 | |
| 126923 | /* Stop receiving the signal on the FD */ |
| 126924 | UA_EventLoopPOSIX_deregisterFD(el, rfd: &rs->rfd); |
| 126925 | |
| 126926 | /* Unblock the signal */ |
| 126927 | sigset_t mask; |
| 126928 | sigemptyset(set: &mask); |
| 126929 | sigaddset(set: &mask, signo: (int)rs->signal); |
| 126930 | sigprocmask(SIG_UNBLOCK, set: &mask, NULL); |
| 126931 | |
| 126932 | /* Clean up locally */ |
| 126933 | UA_close(fd: rs->rfd.fd); |
| 126934 | } |
| 126935 | |
| 126936 | #else /* !UA_HAVE_EPOLL */ |
| 126937 | |
| 126938 | static void |
| 126939 | triggerPOSIXInterruptEvent(int sig) { |
| 126940 | UA_assert(singletonIM != NULL); |
| 126941 | |
| 126942 | /* Don't take a lock. All we are doing here can be done from within a |
| 126943 | * (reentrant) interrupt. */ |
| 126944 | |
| 126945 | /* Get the rs. Only use it if not already triggered. */ |
| 126946 | UA_RegisteredSignal *rs; |
| 126947 | LIST_FOREACH(rs, &singletonIM->signals, listPointers) { |
| 126948 | if(rs->signal == sig) |
| 126949 | break; |
| 126950 | } |
| 126951 | if(!rs || rs->triggered || !rs->active) |
| 126952 | return; |
| 126953 | |
| 126954 | /* Add to the triggered list */ |
| 126955 | TAILQ_INSERT_TAIL(&singletonIM->triggered, rs, triggeredEntry); |
| 126956 | rs->triggered = true; |
| 126957 | |
| 126958 | #ifdef UA_ARCHITECTURE_WIN32 |
| 126959 | /* On WIN32 we have to re-arm the signal or it will go back to SIG_DFL */ |
| 126960 | signal(sig, triggerPOSIXInterruptEvent); |
| 126961 | #endif |
| 126962 | |
| 126963 | /* Trigger the FD in the EventLoop for the self-pipe trick */ |
| 126964 | #ifdef UA_ARCHITECTURE_WIN32 |
| 126965 | int err = send(singletonIM->writeFD, ".", 1, 0); |
| 126966 | #else |
| 126967 | ssize_t err = write(singletonIM->writeFD, ".", 1); |
| 126968 | #endif |
| 126969 | if(err <= 0) { |
| 126970 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126971 | UA_LOG_WARNING(singletonIM->im.eventSource.eventLoop->logger, |
| 126972 | UA_LOGCATEGORY_EVENTLOOP, |
| 126973 | "Error signaling the interrupt on FD %u to the EventLoop (%s)", |
| 126974 | (unsigned)singletonIM->writeFD, errno_str)); |
| 126975 | } |
| 126976 | } |
| 126977 | |
| 126978 | static void |
| 126979 | activateSignal(UA_RegisteredSignal *rs) { |
| 126980 | UA_assert(singletonIM != NULL); |
| 126981 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)singletonIM->im.eventSource.eventLoop; |
| 126982 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 126983 | |
| 126984 | /* Register the signal on the OS level */ |
| 126985 | if(rs->active) |
| 126986 | return; |
| 126987 | |
| 126988 | void (*prev)(int); |
| 126989 | prev = signal(rs->signal, triggerPOSIXInterruptEvent); |
| 126990 | if(prev == SIG_ERR) { |
| 126991 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 126992 | UA_LOG_WARNING(singletonIM->im.eventSource.eventLoop->logger, |
| 126993 | UA_LOGCATEGORY_EVENTLOOP, |
| 126994 | "Error registering the signal: %s", errno_str)); |
| 126995 | return; |
| 126996 | } |
| 126997 | |
| 126998 | rs->active = true; |
| 126999 | } |
| 127000 | |
| 127001 | static void |
| 127002 | deactivateSignal(UA_RegisteredSignal *rs) { |
| 127003 | UA_assert(singletonIM != NULL); |
| 127004 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)singletonIM->im.eventSource.eventLoop; |
| 127005 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 127006 | |
| 127007 | /* Only dectivate if active */ |
| 127008 | if(!rs->active) |
| 127009 | return; |
| 127010 | |
| 127011 | /* Stop receiving the signal */ |
| 127012 | signal(rs->signal, SIG_DFL); |
| 127013 | |
| 127014 | /* Clean up locally */ |
| 127015 | if(rs->triggered) { |
| 127016 | TAILQ_REMOVE(&singletonIM->triggered, rs, triggeredEntry); |
| 127017 | rs->triggered = false; |
| 127018 | } |
| 127019 | |
| 127020 | rs->active = false; |
| 127021 | } |
| 127022 | |
| 127023 | /* Execute all triggered interrupts via the self-pipe trick from within the EventLoop */ |
| 127024 | static void |
| 127025 | executeTriggeredPOSIXInterrupts(UA_EventSource *es, UA_RegisteredFD *rfd, short event) { |
| 127026 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)es->eventLoop; |
| 127027 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 127028 | |
| 127029 | /* Re-arm the socket for the next signal by reading from it */ |
| 127030 | char buf[128]; |
| 127031 | #ifdef UA_ARCHITECTURE_WIN32 |
| 127032 | recv(rfd->fd, buf, 128, 0); /* ignore the result */ |
| 127033 | #else |
| 127034 | ssize_t i; |
| 127035 | do { |
| 127036 | i = read(rfd->fd, buf, 128); |
| 127037 | } while(i > 0); |
| 127038 | #endif |
| 127039 | |
| 127040 | UA_RegisteredSignal *rs, *rs_tmp; |
| 127041 | TAILQ_FOREACH_SAFE(rs, &singletonIM->triggered, triggeredEntry, rs_tmp) { |
| 127042 | TAILQ_REMOVE(&singletonIM->triggered, rs, triggeredEntry); |
| 127043 | rs->triggered = false; |
| 127044 | UA_UNLOCK(&el->elMutex); |
| 127045 | rs->signalCallback(&singletonIM->im, (uintptr_t)rs->signal, |
| 127046 | rs->context, &UA_KEYVALUEMAP_NULL); |
| 127047 | UA_LOCK(&el->elMutex); |
| 127048 | } |
| 127049 | } |
| 127050 | |
| 127051 | #endif /* !UA_HAVE_EPOLL */ |
| 127052 | |
| 127053 | static UA_StatusCode |
| 127054 | registerPOSIXInterrupt(UA_InterruptManager *im, uintptr_t interruptHandle, |
| 127055 | const UA_KeyValueMap *params, |
| 127056 | UA_InterruptCallback callback, void *interruptContext) { |
| 127057 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)im->eventSource.eventLoop; |
| 127058 | if(!UA_KeyValueMap_isEmpty(map: params)) { |
| 127059 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 127060 | msg: "Interrupt\t| Supplied parameters invalid for the " |
| 127061 | "POSIX InterruptManager"); |
| 127062 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127063 | } |
| 127064 | |
| 127065 | UA_LOCK(&el->elMutex); |
| 127066 | |
| 127067 | /* Was the signal already registered? */ |
| 127068 | int signal = (int)interruptHandle; |
| 127069 | UA_POSIXInterruptManager *pim = (UA_POSIXInterruptManager *)im; |
| 127070 | UA_RegisteredSignal *rs; |
| 127071 | LIST_FOREACH(rs, &pim->signals, listPointers) { |
| 127072 | if(rs->signal == signal) |
| 127073 | break; |
| 127074 | } |
| 127075 | if(rs) { |
| 127076 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 127077 | msg: "Interrupt\t| Signal %u already registered", |
| 127078 | (unsigned)interruptHandle); |
| 127079 | UA_UNLOCK(&el->elMutex); |
| 127080 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127081 | } |
| 127082 | |
| 127083 | /* Create and populate the new context object */ |
| 127084 | rs = (UA_RegisteredSignal *)UA_calloc(nmemb: 1, size: sizeof(UA_RegisteredSignal)); |
| 127085 | if(!rs) { |
| 127086 | UA_UNLOCK(&el->elMutex); |
| 127087 | return UA_STATUSCODE_BADOUTOFMEMORY; |
| 127088 | } |
| 127089 | |
| 127090 | #ifdef UA_HAVE_EPOLL |
| 127091 | rs->rfd.es = &im->eventSource; |
| 127092 | #endif |
| 127093 | rs->signal = (int)interruptHandle; |
| 127094 | rs->signalCallback = callback; |
| 127095 | rs->context = interruptContext; |
| 127096 | |
| 127097 | /* Add to the InterruptManager */ |
| 127098 | LIST_INSERT_HEAD(&pim->signals, rs, listPointers); |
| 127099 | pim->signalsSize++; |
| 127100 | |
| 127101 | /* Activate if we are already running */ |
| 127102 | if(pim->im.eventSource.state == UA_EVENTSOURCESTATE_STARTED) |
| 127103 | activateSignal(rs); |
| 127104 | |
| 127105 | UA_UNLOCK(&el->elMutex); |
| 127106 | return UA_STATUSCODE_GOOD; |
| 127107 | } |
| 127108 | |
| 127109 | static void |
| 127110 | deregisterPOSIXInterrupt(UA_InterruptManager *im, uintptr_t interruptHandle) { |
| 127111 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)im->eventSource.eventLoop; |
| 127112 | (void)el; |
| 127113 | UA_POSIXInterruptManager *pim = (UA_POSIXInterruptManager *)im; |
| 127114 | UA_LOCK(&el->elMutex); |
| 127115 | |
| 127116 | int signal = (int)interruptHandle; |
| 127117 | UA_RegisteredSignal *rs; |
| 127118 | LIST_FOREACH(rs, &pim->signals, listPointers) { |
| 127119 | if(rs->signal == signal) |
| 127120 | break; |
| 127121 | } |
| 127122 | if(rs) { |
| 127123 | deactivateSignal(rs); |
| 127124 | LIST_REMOVE(rs, listPointers); |
| 127125 | UA_free(ptr: rs); |
| 127126 | } |
| 127127 | |
| 127128 | UA_UNLOCK(&el->elMutex); |
| 127129 | } |
| 127130 | |
| 127131 | #ifdef UA_ARCHITECTURE_WIN32 |
| 127132 | /* Windows has no pipes. Use a local TCP connection for the self-pipe trick. |
| 127133 | * https://stackoverflow.com/a/3333565 */ |
| 127134 | static int |
| 127135 | pair(SOCKET fds[2]) { |
| 127136 | struct sockaddr_in inaddr; |
| 127137 | struct sockaddr addr; |
| 127138 | SOCKET lst = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); |
| 127139 | memset(&inaddr, 0, sizeof(inaddr)); |
| 127140 | memset(&addr, 0, sizeof(addr)); |
| 127141 | inaddr.sin_family = AF_INET; |
| 127142 | inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
| 127143 | inaddr.sin_port = 0; |
| 127144 | int yes = 1; |
| 127145 | setsockopt(lst, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)); |
| 127146 | bind(lst, (struct sockaddr *)&inaddr, sizeof(inaddr)); |
| 127147 | listen(lst, 1); |
| 127148 | int len = sizeof(inaddr); |
| 127149 | getsockname(lst, &addr, &len); |
| 127150 | fds[0] = socket(AF_INET, SOCK_STREAM, 0); |
| 127151 | int err = connect(fds[0], &addr, len); |
| 127152 | fds[1] = accept(lst, 0, 0); |
| 127153 | closesocket(lst); |
| 127154 | return err; |
| 127155 | } |
| 127156 | #endif |
| 127157 | |
| 127158 | static UA_StatusCode |
| 127159 | startPOSIXInterruptManager(UA_EventSource *es) { |
| 127160 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)es->eventLoop; |
| 127161 | (void)el; |
| 127162 | UA_LOCK(&el->elMutex); |
| 127163 | |
| 127164 | /* Check the state */ |
| 127165 | if(es->state != UA_EVENTSOURCESTATE_STOPPED) { |
| 127166 | UA_LOG_ERROR(logger: es->eventLoop->logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 127167 | msg: "Interrupt\t| To start the InterruptManager, " |
| 127168 | "it has to be registered in an EventLoop and not started"); |
| 127169 | UA_UNLOCK(&el->elMutex); |
| 127170 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127171 | } |
| 127172 | |
| 127173 | UA_POSIXInterruptManager *pim = (UA_POSIXInterruptManager *)es; |
| 127174 | UA_LOG_DEBUG(logger: es->eventLoop->logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 127175 | msg: "Interrupt\t| Starting the InterruptManager"); |
| 127176 | |
| 127177 | #ifndef UA_HAVE_EPOLL |
| 127178 | /* Create pipe for self-signaling */ |
| 127179 | UA_FD pipefd[2]; |
| 127180 | #ifdef UA_ARCHITECTURE_WIN32 |
| 127181 | int err = pair(pipefd); |
| 127182 | #else |
| 127183 | int err = pipe(pipefd); |
| 127184 | #endif |
| 127185 | if(err != 0) { |
| 127186 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 127187 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 127188 | "Interrupt\t| Could not open the pipe for " |
| 127189 | "self-signaling (%s)", errno_str)); |
| 127190 | UA_UNLOCK(&el->elMutex); |
| 127191 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127192 | } |
| 127193 | |
| 127194 | UA_StatusCode res = UA_STATUSCODE_GOOD; |
| 127195 | #ifndef UA_ARCHITECTURE_WIN32 |
| 127196 | /* Mark pipes as non-blocking */ |
| 127197 | for(size_t i = 0; i < (sizeof(pipefd) / sizeof(*pipefd)); ++i) { |
| 127198 | res = UA_EventLoopPOSIX_setNonBlocking(pipefd[i]); |
| 127199 | if(res != UA_STATUSCODE_GOOD) { |
| 127200 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 127201 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 127202 | "Interrupt\t| Could mark pipe for " |
| 127203 | "self-signaling as non-blocking(%s)", |
| 127204 | errno_str)); |
| 127205 | UA_UNLOCK(&el->elMutex); |
| 127206 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127207 | } |
| 127208 | } |
| 127209 | #endif |
| 127210 | |
| 127211 | UA_LOG_DEBUG(es->eventLoop->logger, UA_LOGCATEGORY_EVENTLOOP, |
| 127212 | "Interrupt\t| Socket pair for the self-pipe: %u,%u", |
| 127213 | (unsigned)pipefd[0], (unsigned)pipefd[1]); |
| 127214 | |
| 127215 | pim->writeFD = pipefd[1]; |
| 127216 | pim->readFD.fd = pipefd[0]; |
| 127217 | pim->readFD.es = &pim->im.eventSource; |
| 127218 | pim->readFD.listenEvents = UA_FDEVENT_IN; |
| 127219 | pim->readFD.eventSourceCB = executeTriggeredPOSIXInterrupts; |
| 127220 | res = UA_EventLoopPOSIX_registerFD(el, &pim->readFD); |
| 127221 | if(res != UA_STATUSCODE_GOOD) { |
| 127222 | UA_LOG_ERROR(es->eventLoop->logger, UA_LOGCATEGORY_EVENTLOOP, |
| 127223 | "Interrupt\t| Could not register the InterruptManager socket"); |
| 127224 | UA_close(pipefd[0]); |
| 127225 | UA_close(pipefd[1]); |
| 127226 | UA_UNLOCK(&el->elMutex); |
| 127227 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127228 | } |
| 127229 | #endif |
| 127230 | |
| 127231 | /* Activate the registered signal handlers */ |
| 127232 | UA_RegisteredSignal*rs; |
| 127233 | LIST_FOREACH(rs, &pim->signals, listPointers) { |
| 127234 | activateSignal(rs); |
| 127235 | } |
| 127236 | |
| 127237 | /* Set the EventSource to the started state */ |
| 127238 | es->state = UA_EVENTSOURCESTATE_STARTED; |
| 127239 | |
| 127240 | UA_UNLOCK(&el->elMutex); |
| 127241 | return UA_STATUSCODE_GOOD; |
| 127242 | } |
| 127243 | |
| 127244 | static void |
| 127245 | stopPOSIXInterruptManager(UA_EventSource *es) { |
| 127246 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)es->eventLoop; |
| 127247 | (void)el; |
| 127248 | UA_LOCK(&el->elMutex); |
| 127249 | |
| 127250 | if(es->state != UA_EVENTSOURCESTATE_STARTED) { |
| 127251 | UA_UNLOCK(&el->elMutex); |
| 127252 | return; |
| 127253 | } |
| 127254 | |
| 127255 | UA_LOG_DEBUG(logger: es->eventLoop->logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 127256 | msg: "Interrupt\t| Stopping the InterruptManager"); |
| 127257 | |
| 127258 | /* Close all registered signals */ |
| 127259 | UA_POSIXInterruptManager *pim = (UA_POSIXInterruptManager *)es; |
| 127260 | UA_RegisteredSignal*rs; |
| 127261 | LIST_FOREACH(rs, &pim->signals, listPointers) { |
| 127262 | deactivateSignal(rs); |
| 127263 | } |
| 127264 | |
| 127265 | #ifndef UA_HAVE_EPOLL |
| 127266 | /* Close the FD for the self-pipe trick */ |
| 127267 | UA_EventLoopPOSIX_deregisterFD(el, &pim->readFD); |
| 127268 | UA_close(pim->readFD.fd); |
| 127269 | UA_close(pim->writeFD); |
| 127270 | #endif |
| 127271 | |
| 127272 | /* Immediately set to stopped */ |
| 127273 | es->state = UA_EVENTSOURCESTATE_STOPPED; |
| 127274 | |
| 127275 | UA_UNLOCK(&el->elMutex); |
| 127276 | } |
| 127277 | |
| 127278 | static UA_StatusCode |
| 127279 | freePOSIXInterruptmanager(UA_EventSource *es) { |
| 127280 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)es->eventLoop; |
| 127281 | (void)el; |
| 127282 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 127283 | |
| 127284 | if(es->state >= UA_EVENTSOURCESTATE_STARTING) { |
| 127285 | UA_LOG_ERROR(logger: es->eventLoop->logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 127286 | msg: "Interrupt\t| The EventSource must be stopped " |
| 127287 | "before it can be deleted"); |
| 127288 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127289 | } |
| 127290 | |
| 127291 | /* Deactivate and remove all registered signals */ |
| 127292 | UA_POSIXInterruptManager *pim = (UA_POSIXInterruptManager *)es; |
| 127293 | UA_RegisteredSignal *rs, *rs_tmp; |
| 127294 | LIST_FOREACH_SAFE(rs, &pim->signals, listPointers, rs_tmp) { |
| 127295 | deactivateSignal(rs); |
| 127296 | LIST_REMOVE(rs, listPointers); |
| 127297 | UA_free(ptr: rs); |
| 127298 | } |
| 127299 | |
| 127300 | UA_String_clear(p: &es->name); |
| 127301 | UA_free(ptr: es); |
| 127302 | |
| 127303 | #ifndef UA_HAVE_EPOLL |
| 127304 | singletonIM = NULL; /* Reset the global singleton pointer */ |
| 127305 | #endif |
| 127306 | |
| 127307 | return UA_STATUSCODE_GOOD; |
| 127308 | } |
| 127309 | |
| 127310 | UA_InterruptManager * |
| 127311 | UA_InterruptManager_new_POSIX(const UA_String eventSourceName) { |
| 127312 | #ifndef UA_HAVE_EPOLL |
| 127313 | /* There can be only one InterruptManager if epoll is not present */ |
| 127314 | if(singletonIM) |
| 127315 | return NULL; |
| 127316 | #endif |
| 127317 | |
| 127318 | UA_POSIXInterruptManager *pim = (UA_POSIXInterruptManager *) |
| 127319 | UA_calloc(nmemb: 1, size: sizeof(UA_POSIXInterruptManager)); |
| 127320 | if(!pim) |
| 127321 | return NULL; |
| 127322 | |
| 127323 | LIST_INIT(&pim->signals); |
| 127324 | |
| 127325 | #ifndef UA_HAVE_EPOLL |
| 127326 | TAILQ_INIT(&pim->triggered); |
| 127327 | singletonIM = pim; /* Register the singleton singleton pointer */ |
| 127328 | #endif |
| 127329 | |
| 127330 | UA_InterruptManager *im = &pim->im; |
| 127331 | im->eventSource.eventSourceType = UA_EVENTSOURCETYPE_INTERRUPTMANAGER; |
| 127332 | UA_String_copy(src: &eventSourceName, dst: &im->eventSource.name); |
| 127333 | im->eventSource.start = startPOSIXInterruptManager; |
| 127334 | im->eventSource.stop = stopPOSIXInterruptManager; |
| 127335 | im->eventSource.free = freePOSIXInterruptmanager; |
| 127336 | im->registerInterrupt = registerPOSIXInterrupt; |
| 127337 | im->deregisterInterrupt = deregisterPOSIXInterrupt; |
| 127338 | return im; |
| 127339 | } |
| 127340 | |
| 127341 | /**** amalgamated original file "/arch/eventloop_posix_eth.c" ****/ |
| 127342 | |
| 127343 | /* This Source Code Form is subject to the terms of the Mozilla Public |
| 127344 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 127345 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| 127346 | * |
| 127347 | * Copyright 2018 (c) Kontron Europe GmbH (Author: Rudolf Hoyler) |
| 127348 | * Copyright 2019-2020 (c) Kalycito Infotech Private Limited |
| 127349 | * Copyright 2019-2020 (c) Wind River Systems, Inc. |
| 127350 | * Copyright 2022 (c) Fraunhofer IOSB (Author: Julius Pfrommer) |
| 127351 | */ |
| 127352 | |
| 127353 | |
| 127354 | #if defined(UA_ARCHITECTURE_POSIX) && defined(__linux__) |
| 127355 | |
| 127356 | #include <arpa/inet.h> /* htons */ |
| 127357 | #include <net/ethernet.h> /* ETH_P_*/ |
| 127358 | #include <linux/if_packet.h> |
| 127359 | |
| 127360 | /* Configuration parameters */ |
| 127361 | #define ETH_PARAMETERSSIZE 9 |
| 127362 | #define ETH_PARAMINDEX_ADDR 0 |
| 127363 | #define ETH_PARAMINDEX_LISTEN 1 |
| 127364 | #define ETH_PARAMINDEX_IFACE 2 |
| 127365 | #define ETH_PARAMINDEX_ETHERTYPE 3 |
| 127366 | #define ETH_PARAMINDEX_VID 4 |
| 127367 | #define ETH_PARAMINDEX_PCP 5 |
| 127368 | #define ETH_PARAMINDEX_DEI 6 |
| 127369 | #define ETH_PARAMINDEX_PROMISCUOUS 7 |
| 127370 | #define ETH_PARAMINDEX_VALIDATE 8 |
| 127371 | |
| 127372 | static UA_KeyValueRestriction ETHConfigParameters[ETH_PARAMETERSSIZE+1] = { |
| 127373 | {{0, UA_STRING_STATIC("address")}, &UA_TYPES[UA_TYPES_STRING], false, true, false}, |
| 127374 | {{0, UA_STRING_STATIC("listen")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false}, |
| 127375 | {{0, UA_STRING_STATIC("interface")}, &UA_TYPES[UA_TYPES_STRING], true, true, false}, |
| 127376 | {{0, UA_STRING_STATIC("ethertype")}, &UA_TYPES[UA_TYPES_UINT16], false, true, false}, |
| 127377 | {{0, UA_STRING_STATIC("vid")}, &UA_TYPES[UA_TYPES_UINT16], false, true, false}, |
| 127378 | {{0, UA_STRING_STATIC("pcp")}, &UA_TYPES[UA_TYPES_BYTE], false, true, false}, |
| 127379 | {{0, UA_STRING_STATIC("dei")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false}, |
| 127380 | {{0, UA_STRING_STATIC("promiscuous")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false}, |
| 127381 | {{0, UA_STRING_STATIC("validate")}, &UA_TYPES[UA_TYPES_BOOLEAN], false, true, false}, |
| 127382 | /* Duplicated address parameter with a scalar value required. For the send-socket case. */ |
| 127383 | {{0, UA_STRING_STATIC("address")}, &UA_TYPES[UA_TYPES_STRING], true, true, false}, |
| 127384 | }; |
| 127385 | |
| 127386 | #define UA_ETH_MAXHEADERLENGTH (2*ETHER_ADDR_LEN)+4+2+2 |
| 127387 | |
| 127388 | typedef struct { |
| 127389 | UA_RegisteredFD rfd; |
| 127390 | |
| 127391 | UA_ConnectionManager_connectionCallback applicationCB; |
| 127392 | void *application; |
| 127393 | void *context; |
| 127394 | |
| 127395 | struct sockaddr_ll sll; |
| 127396 | /* The Ethernet header to prepend for sending frames is precomputed and reused. |
| 127397 | * The length field (the last 2 byte) is adjusted. |
| 127398 | * - 2 * ETHER_ADDR_LEN: destination and source |
| 127399 | * - 4 byte: VLAN tagging (optional) |
| 127400 | * - 2 byte: EtherType (optional) |
| 127401 | * - 2 byte: length */ |
| 127402 | unsigned char header[UA_ETH_MAXHEADERLENGTH]; |
| 127403 | unsigned char headerSize; |
| 127404 | unsigned char lengthOffset; /* No length field if zero */ |
| 127405 | } ETH_FD; |
| 127406 | |
| 127407 | /* The format of a Ethernet address is six groups of hexadecimal digits, |
| 127408 | * separated by hyphens (e.g. 01-23-45-67-89-ab). */ |
| 127409 | static UA_StatusCode |
| 127410 | parseEthAddress(const UA_String *buf, UA_Byte *addr) { |
| 127411 | size_t curr = 0, idx = 0; |
| 127412 | for(; idx < ETHER_ADDR_LEN; idx++) { |
| 127413 | UA_UInt32 value; |
| 127414 | size_t progress = UA_readNumberWithBase(buf: &buf->data[curr], |
| 127415 | buflen: buf->length - curr, number: &value, base: 16); |
| 127416 | if(progress == 0 || value > (long)0xff) |
| 127417 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127418 | |
| 127419 | addr[idx] = (UA_Byte) value; |
| 127420 | |
| 127421 | curr += progress; |
| 127422 | if(curr == buf->length) |
| 127423 | break; |
| 127424 | |
| 127425 | if(buf->data[curr] != '-') |
| 127426 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127427 | |
| 127428 | curr++; /* skip '-' */ |
| 127429 | } |
| 127430 | |
| 127431 | if(idx != (ETH_ALEN-1)) |
| 127432 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127433 | |
| 127434 | return UA_STATUSCODE_GOOD; |
| 127435 | } |
| 127436 | |
| 127437 | static UA_Boolean |
| 127438 | isMulticastEthAddress(const UA_Byte *address) { |
| 127439 | if((address[0] & 1) == 0) |
| 127440 | return false; /* Unicast address */ |
| 127441 | for(size_t i = 0; i < ETHER_ADDR_LEN; i++) { |
| 127442 | if(address[i] != 0xff) |
| 127443 | return true; /* Not broadcast address ff-ff-ff-ff-ff-ff */ |
| 127444 | } |
| 127445 | return false; |
| 127446 | } |
| 127447 | |
| 127448 | static void |
| 127449 | setAddrString(unsigned char addrStr[18], unsigned char addr[ETHER_ADDR_LEN]) { |
| 127450 | mp_snprintf(s: (char*)addrStr, n: 18, format: "%02x-%02x-%02x-%02x-%02x-%02x", |
| 127451 | addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); |
| 127452 | } |
| 127453 | |
| 127454 | /* Return zero if parsing failed */ |
| 127455 | static size_t |
| 127456 | parseETHHeader(const UA_ByteString *buf, |
| 127457 | unsigned char destAddr[ETHER_ADDR_LEN], |
| 127458 | unsigned char sourceAddr[ETHER_ADDR_LEN], |
| 127459 | UA_UInt16 *etherType, UA_UInt16 *vid, |
| 127460 | UA_Byte *pcp, UA_Boolean *dei) { |
| 127461 | if(buf->length < (2 * ETHER_ADDR_LEN)+2) |
| 127462 | return 0; |
| 127463 | |
| 127464 | /* Parse "normal" Ethernet header */ |
| 127465 | memcpy(dest: destAddr, src: buf->data, ETHER_ADDR_LEN); |
| 127466 | memcpy(dest: sourceAddr, src: &buf->data[ETHER_ADDR_LEN], ETHER_ADDR_LEN); |
| 127467 | size_t pos = 2 * ETHER_ADDR_LEN; |
| 127468 | UA_UInt16 length = ntohs(netshort: *(UA_UInt16*)&buf->data[pos]); |
| 127469 | pos += 2; |
| 127470 | |
| 127471 | /* No EtherType and no VLAN */ |
| 127472 | if(length <= 1500) |
| 127473 | return pos; |
| 127474 | |
| 127475 | /* Parse 802.1Q VLAN header */ |
| 127476 | if(length == 0x8100) { |
| 127477 | if(buf->length < (2 * ETHER_ADDR_LEN)+2+4) |
| 127478 | return 0; |
| 127479 | pos += 2; |
| 127480 | UA_UInt16 vlan = ntohs(netshort: *(UA_UInt16*)&buf->data[pos]); |
| 127481 | *pcp = 0x07 & vlan; |
| 127482 | *dei = 0x01 & (vlan >> 3); |
| 127483 | *vid = vlan >> 4; |
| 127484 | pos += 2; |
| 127485 | length = ntohs(netshort: *(UA_UInt16*)&buf->data[pos]); |
| 127486 | } |
| 127487 | |
| 127488 | /* Set the EtherType if it is set */ |
| 127489 | if(length > 1500) |
| 127490 | *etherType = length; |
| 127491 | |
| 127492 | return pos; |
| 127493 | } |
| 127494 | |
| 127495 | static unsigned char |
| 127496 | setETHHeader(unsigned char *buf, |
| 127497 | unsigned char destAddr[ETHER_ADDR_LEN], |
| 127498 | unsigned char sourceAddr[ETHER_ADDR_LEN], |
| 127499 | UA_UInt16 etherType, UA_UInt16 vid, |
| 127500 | UA_Byte pcp, UA_Boolean dei, unsigned char *lengthOffset) { |
| 127501 | /* Set dest and source address */ |
| 127502 | size_t pos = 0; |
| 127503 | memcpy(dest: buf, src: destAddr, ETHER_ADDR_LEN); |
| 127504 | pos += ETHER_ADDR_LEN; |
| 127505 | memcpy(dest: &buf[pos], src: sourceAddr, ETHER_ADDR_LEN); |
| 127506 | pos += ETHER_ADDR_LEN; |
| 127507 | |
| 127508 | /* Set the 802.1Q VLAN header */ |
| 127509 | if(vid > 0 && vid != ETH_P_ALL) { |
| 127510 | *(UA_UInt16*)&buf[pos] = htons(hostshort: 0x8100); |
| 127511 | pos += 2; |
| 127512 | UA_UInt16 vlan = (UA_UInt16)((UA_UInt16)pcp + (((UA_UInt16)dei) << 3) + (vid << 4)); |
| 127513 | *(UA_UInt16*)&buf[pos] = htons(hostshort: vlan); |
| 127514 | pos += 2; |
| 127515 | } |
| 127516 | |
| 127517 | /* Set the Ethertype or store the offset for the length field */ |
| 127518 | if(etherType == 0 || etherType == ETH_P_ALL) { |
| 127519 | *lengthOffset = (unsigned char)pos; |
| 127520 | } else { |
| 127521 | *(UA_UInt16*)&buf[pos] = htons(hostshort: etherType); |
| 127522 | } |
| 127523 | pos += 2; |
| 127524 | return (unsigned char)pos; |
| 127525 | } |
| 127526 | |
| 127527 | static UA_StatusCode |
| 127528 | ETH_allocNetworkBuffer(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 127529 | UA_ByteString *buf, size_t bufSize) { |
| 127530 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 127531 | |
| 127532 | /* Get the ETH_FD */ |
| 127533 | UA_FD fd = (UA_FD)connectionId; |
| 127534 | ETH_FD *erfd = (ETH_FD*)ZIP_FIND(UA_FDTree, &pcm->fds, &fd); |
| 127535 | if(!erfd) |
| 127536 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 127537 | |
| 127538 | /* Allocate the buffer with the hidden Ethernet header in front */ |
| 127539 | UA_StatusCode res = UA_ByteString_allocBuffer(bs: buf, length: bufSize+erfd->headerSize); |
| 127540 | buf->data += erfd->headerSize; |
| 127541 | buf->length -= erfd->headerSize; |
| 127542 | return res; |
| 127543 | } |
| 127544 | |
| 127545 | static void |
| 127546 | ETH_freeNetworkBuffer(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 127547 | UA_ByteString *buf) { |
| 127548 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 127549 | |
| 127550 | /* Get the ETH_FD */ |
| 127551 | UA_FD fd = (UA_FD)connectionId; |
| 127552 | ETH_FD *erfd = (ETH_FD*)ZIP_FIND(UA_FDTree, &pcm->fds, &fd); |
| 127553 | if(!erfd) |
| 127554 | return; |
| 127555 | |
| 127556 | /* Unhide the Ethernet header */ |
| 127557 | buf->data -= erfd->headerSize; |
| 127558 | buf->length += erfd->headerSize; |
| 127559 | UA_ByteString_clear(p: buf); |
| 127560 | } |
| 127561 | |
| 127562 | /* Test if the ConnectionManager can be stopped */ |
| 127563 | static void |
| 127564 | ETH_checkStopped(UA_POSIXConnectionManager *pcm) { |
| 127565 | UA_LOCK_ASSERT(&((UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop)->elMutex, 1); |
| 127566 | |
| 127567 | if(pcm->fdsSize == 0 && |
| 127568 | pcm->cm.eventSource.state == UA_EVENTSOURCESTATE_STOPPING) { |
| 127569 | UA_LOG_DEBUG(logger: pcm->cm.eventSource.eventLoop->logger, category: UA_LOGCATEGORY_NETWORK, |
| 127570 | msg: "ETH\t| All sockets closed, the EventLoop has stopped"); |
| 127571 | pcm->cm.eventSource.state = UA_EVENTSOURCESTATE_STOPPED; |
| 127572 | } |
| 127573 | } |
| 127574 | |
| 127575 | /* This method must not be called from the application directly, but from within |
| 127576 | * the EventLoop. Otherwise we cannot be sure whether the file descriptor is |
| 127577 | * still used after calling close. */ |
| 127578 | static void |
| 127579 | ETH_close(UA_POSIXConnectionManager *pcm, ETH_FD *conn) { |
| 127580 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 127581 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 127582 | |
| 127583 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127584 | msg: "ETH %u\t| Closing connection", |
| 127585 | (unsigned)conn->rfd.fd); |
| 127586 | |
| 127587 | /* Deregister from the EventLoop */ |
| 127588 | UA_EventLoopPOSIX_deregisterFD(el, rfd: &conn->rfd); |
| 127589 | |
| 127590 | /* Deregister internally */ |
| 127591 | ZIP_REMOVE(UA_FDTree, &pcm->fds, &conn->rfd); |
| 127592 | UA_assert(pcm->fdsSize > 0); |
| 127593 | pcm->fdsSize--; |
| 127594 | |
| 127595 | /* Signal closing to the application */ |
| 127596 | conn->applicationCB(&pcm->cm, (uintptr_t)conn->rfd.fd, |
| 127597 | conn->application, &conn->context, |
| 127598 | UA_CONNECTIONSTATE_CLOSING, |
| 127599 | &UA_KEYVALUEMAP_NULL, UA_BYTESTRING_NULL); |
| 127600 | |
| 127601 | /* Close the socket */ |
| 127602 | int ret = UA_close(fd: conn->rfd.fd); |
| 127603 | if(ret == 0) { |
| 127604 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127605 | msg: "ETH %u\t| Socket closed", (unsigned)conn->rfd.fd); |
| 127606 | } else { |
| 127607 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 127608 | UA_LOG_WARNING(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 127609 | "ETH %u\t| Could not close the socket (%s)", |
| 127610 | (unsigned)conn->rfd.fd, errno_str)); |
| 127611 | } |
| 127612 | |
| 127613 | /* Don't call free here. This might be done automatically via the delayed |
| 127614 | * callback that calls ETH_close. */ |
| 127615 | /* UA_free(rfd); */ |
| 127616 | |
| 127617 | /* Stop if the ucm is stopping and this was the last open socket */ |
| 127618 | ETH_checkStopped(pcm); |
| 127619 | } |
| 127620 | |
| 127621 | static void |
| 127622 | ETH_delayedClose(void *application, void *context) { |
| 127623 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)application; |
| 127624 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 127625 | ETH_FD *conn = (ETH_FD*)context; |
| 127626 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 127627 | msg: "ETH %u\t| Delayed closing of the connection", |
| 127628 | (unsigned)conn->rfd.fd); |
| 127629 | UA_LOCK(&el->elMutex); |
| 127630 | ETH_close(pcm, conn); |
| 127631 | UA_UNLOCK(&el->elMutex); |
| 127632 | UA_free(ptr: conn); |
| 127633 | } |
| 127634 | |
| 127635 | /* Gets called when a socket receives data or closes */ |
| 127636 | static void |
| 127637 | ETH_connectionSocketCallback(UA_ConnectionManager *cm, UA_RegisteredFD *rfd, |
| 127638 | short event) { |
| 127639 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 127640 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 127641 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 127642 | |
| 127643 | ETH_FD *conn = (ETH_FD*)rfd; |
| 127644 | if(event == UA_FDEVENT_ERR) { |
| 127645 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 127646 | UA_LOG_DEBUG(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 127647 | "ETH %u\t| recv signaled the socket was shutdown (%s)", |
| 127648 | (unsigned)rfd->fd, errno_str)); |
| 127649 | ETH_close(pcm, conn); |
| 127650 | UA_free(ptr: rfd); |
| 127651 | return; |
| 127652 | } |
| 127653 | |
| 127654 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127655 | msg: "ETH %u\t| Allocate receive buffer", (unsigned)rfd->fd); |
| 127656 | |
| 127657 | /* Get the number of available bytes */ |
| 127658 | int bytes_available = 0; |
| 127659 | ioctl(fd: rfd->fd, FIONREAD, &bytes_available); |
| 127660 | if(bytes_available <= 0) |
| 127661 | return; |
| 127662 | |
| 127663 | UA_ByteString response; |
| 127664 | UA_StatusCode res = UA_ByteString_allocBuffer(bs: &response, length: (size_t)bytes_available); |
| 127665 | if(res != UA_STATUSCODE_GOOD) |
| 127666 | return; |
| 127667 | |
| 127668 | /* Receive */ |
| 127669 | #ifndef UA_ARCHITECTURE_WIN32 |
| 127670 | ssize_t ret = UA_recv(fd: rfd->fd, buf: (char*)response.data, |
| 127671 | n: response.length, MSG_DONTWAIT); |
| 127672 | #else |
| 127673 | int ret = UA_recv(rfd->fd, (char*)response.data, |
| 127674 | response.length, MSG_DONTWAIT); |
| 127675 | #endif |
| 127676 | |
| 127677 | /* Receive has failed */ |
| 127678 | if(ret <= 0) { |
| 127679 | if(UA_ERRNO == UA_INTERRUPTED) { |
| 127680 | UA_ByteString_clear(p: &response); |
| 127681 | return; |
| 127682 | } |
| 127683 | |
| 127684 | /* Orderly shutdown of the socket. We can immediately close as no method |
| 127685 | * "below" in the call stack will use the socket in this iteration of |
| 127686 | * the EventLoop. */ |
| 127687 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 127688 | UA_LOG_DEBUG(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 127689 | "ETH %u\t| recv signaled the socket was shutdown (%s)", |
| 127690 | (unsigned)rfd->fd, errno_str)); |
| 127691 | ETH_close(pcm, conn); |
| 127692 | UA_free(ptr: rfd); |
| 127693 | UA_ByteString_clear(p: &response); |
| 127694 | return; |
| 127695 | } |
| 127696 | |
| 127697 | /* Set the length of the received buffer */ |
| 127698 | response.length = (size_t)ret; |
| 127699 | |
| 127700 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127701 | msg: "ETH %u\t| Received message of size %u", |
| 127702 | (unsigned)rfd->fd, (unsigned)ret); |
| 127703 | |
| 127704 | /* Parse the Ethernet header */ |
| 127705 | unsigned char destAddr[ETHER_ADDR_LEN]; |
| 127706 | unsigned char sourceAddr[ETHER_ADDR_LEN]; |
| 127707 | UA_UInt16 etherType = 0; |
| 127708 | UA_UInt16 vid = 0; |
| 127709 | UA_Byte pcp = 0; |
| 127710 | UA_Boolean dei = 0; |
| 127711 | size_t headerSize = parseETHHeader(buf: &response, destAddr, sourceAddr, |
| 127712 | etherType: ðerType, vid: &vid, pcp: &pcp, dei: &dei); |
| 127713 | if(headerSize == 0) { |
| 127714 | UA_ByteString_clear(p: &response); |
| 127715 | return; |
| 127716 | } |
| 127717 | |
| 127718 | /* Set up the parameter arguments */ |
| 127719 | unsigned char destAddrBytes[18]; |
| 127720 | unsigned char sourceAddrBytes[18]; |
| 127721 | setAddrString(addrStr: destAddrBytes, addr: destAddr); |
| 127722 | setAddrString(addrStr: sourceAddrBytes, addr: sourceAddr); |
| 127723 | UA_String destAddrStr = {17, destAddrBytes}; |
| 127724 | UA_String sourceAddrStr = {17, sourceAddrBytes}; |
| 127725 | |
| 127726 | size_t paramsSize = 2; |
| 127727 | UA_KeyValuePair params[6]; |
| 127728 | params[0].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "destination-address"); |
| 127729 | UA_Variant_setScalar(v: ¶ms[0].value, p: &destAddrStr, type: &UA_TYPES[UA_TYPES_STRING]); |
| 127730 | params[1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "source-address"); |
| 127731 | UA_Variant_setScalar(v: ¶ms[1].value, p: &sourceAddrStr, type: &UA_TYPES[UA_TYPES_STRING]); |
| 127732 | if(etherType > 0) { |
| 127733 | params[2].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "ethertype"); |
| 127734 | UA_Variant_setScalar(v: ¶ms[1].value, p: ðerType, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 127735 | paramsSize++; |
| 127736 | } |
| 127737 | if(vid > 0) { |
| 127738 | params[paramsSize].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "vid"); |
| 127739 | UA_Variant_setScalar(v: ¶ms[paramsSize].value, p: &vid, type: &UA_TYPES[UA_TYPES_UINT16]); |
| 127740 | params[paramsSize+1].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "pcp"); |
| 127741 | UA_Variant_setScalar(v: ¶ms[paramsSize+1].value, p: &pcp, type: &UA_TYPES[UA_TYPES_BYTE]); |
| 127742 | params[paramsSize+2].key = UA_QUALIFIEDNAME(nsIndex: 0, chars: "dei"); |
| 127743 | UA_Variant_setScalar(v: ¶ms[paramsSize+2].value, p: &dei, type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 127744 | paramsSize += 3; |
| 127745 | } |
| 127746 | |
| 127747 | UA_KeyValueMap map = {paramsSize, params}; |
| 127748 | |
| 127749 | /* Callback to the application layer with the Ethernet header hidden */ |
| 127750 | response.data += headerSize; |
| 127751 | response.length -= headerSize; |
| 127752 | conn->applicationCB(cm, (uintptr_t)rfd->fd, conn->application, &conn->context, |
| 127753 | UA_CONNECTIONSTATE_ESTABLISHED, &map, response); |
| 127754 | response.data -= headerSize; |
| 127755 | response.length += headerSize; |
| 127756 | UA_ByteString_clear(p: &response); |
| 127757 | } |
| 127758 | |
| 127759 | static UA_StatusCode |
| 127760 | ETH_openListenConnection(UA_EventLoopPOSIX *el, ETH_FD *conn, |
| 127761 | const UA_KeyValueMap *params, |
| 127762 | int ifindex, UA_UInt16 etherType, |
| 127763 | UA_Boolean validate) { |
| 127764 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 127765 | |
| 127766 | /* Bind the socket to interface and EtherType. Don't receive anything else. */ |
| 127767 | struct sockaddr_ll sll; |
| 127768 | memset(s: &sll, c: 0, n: sizeof(struct sockaddr_ll)); |
| 127769 | sll.sll_family = AF_PACKET; |
| 127770 | sll.sll_protocol = htons(hostshort: etherType); |
| 127771 | sll.sll_ifindex = ifindex; |
| 127772 | if(!validate && bind(fd: conn->rfd.fd, addr: (struct sockaddr*)&sll, len: sizeof(sll)) < 0) |
| 127773 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127774 | |
| 127775 | /* Immediately register for listen events. Don't have to wait for a |
| 127776 | * connection to open. */ |
| 127777 | conn->rfd.listenEvents = UA_FDEVENT_IN; |
| 127778 | |
| 127779 | /* Set receiving to promiscuous (all target host addresses) */ |
| 127780 | const UA_Boolean *promiscuous = (const UA_Boolean*) |
| 127781 | UA_KeyValueMap_getScalar(map: params, key: ETHConfigParameters[ETH_PARAMINDEX_PROMISCUOUS].name, |
| 127782 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 127783 | if(promiscuous && *promiscuous) { |
| 127784 | struct packet_mreq mreq; |
| 127785 | memset(s: &mreq, c: 0, n: sizeof(struct packet_mreq)); |
| 127786 | mreq.mr_ifindex = ifindex; |
| 127787 | mreq.mr_type = PACKET_MR_PROMISC; |
| 127788 | int ret = setsockopt(fd: conn->rfd.fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, |
| 127789 | optval: &mreq, optlen: sizeof(mreq)); |
| 127790 | if(ret < 0) { |
| 127791 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 127792 | UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 127793 | "ETH %u\t| Could not set raw socket to promiscuous mode %s", |
| 127794 | (unsigned)conn->rfd.fd, errno_str)); |
| 127795 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127796 | } else { |
| 127797 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127798 | msg: "ETH %u\t| The socket was set to promiscuous mode", |
| 127799 | (unsigned)conn->rfd.fd); |
| 127800 | } |
| 127801 | } |
| 127802 | |
| 127803 | /* Register for multicast if an address is defined */ |
| 127804 | const UA_String *address = (const UA_String*) |
| 127805 | UA_KeyValueMap_getScalar(map: params, key: ETHConfigParameters[ETH_PARAMINDEX_ADDR].name, |
| 127806 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 127807 | if(address) { |
| 127808 | UA_Byte addr[ETHER_ADDR_LEN]; |
| 127809 | UA_StatusCode res = parseEthAddress(buf: address, addr); |
| 127810 | if(res != UA_STATUSCODE_GOOD) { |
| 127811 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127812 | msg: "ETH\t| Address for listening cannot be parsed"); |
| 127813 | return res; |
| 127814 | } |
| 127815 | |
| 127816 | if(!isMulticastEthAddress(address: addr)) { |
| 127817 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127818 | msg: "ETH\t| Address for listening is not a multicast address. Ignoring."); |
| 127819 | return UA_STATUSCODE_GOOD; |
| 127820 | } |
| 127821 | |
| 127822 | struct packet_mreq mreq; |
| 127823 | memset(s: &mreq, c: 0, n: sizeof(struct packet_mreq)); |
| 127824 | mreq.mr_ifindex = ifindex; |
| 127825 | mreq.mr_type = PACKET_MR_MULTICAST; |
| 127826 | mreq.mr_alen = ETH_ALEN; |
| 127827 | memcpy(dest: mreq.mr_address, src: addr, ETHER_ADDR_LEN); |
| 127828 | if(!validate && UA_setsockopt(fd: conn->rfd.fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, |
| 127829 | optval: (char *)&mreq, optlen: sizeof(mreq)) < 0) { |
| 127830 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 127831 | UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 127832 | "ETH\t| Registering for multicast failed with error %s", |
| 127833 | errno_str)); |
| 127834 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127835 | } |
| 127836 | } |
| 127837 | |
| 127838 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127839 | msg: "ETH %u\t| Opened an Ethernet listen socket", |
| 127840 | (unsigned)conn->rfd.fd); |
| 127841 | |
| 127842 | return UA_STATUSCODE_GOOD; |
| 127843 | } |
| 127844 | |
| 127845 | static UA_StatusCode |
| 127846 | ETH_openSendConnection(UA_EventLoopPOSIX *el, ETH_FD *conn, const UA_KeyValueMap *params, |
| 127847 | UA_Byte source[ETHER_ADDR_LEN], int ifindex, UA_UInt16 etherType) { |
| 127848 | UA_LOCK_ASSERT(&el->elMutex, 1); |
| 127849 | |
| 127850 | /* Parse the target address (has to exist) */ |
| 127851 | const UA_String *address = (const UA_String*) |
| 127852 | UA_KeyValueMap_getScalar(map: params, key: ETHConfigParameters[ETH_PARAMINDEX_ADDR].name, |
| 127853 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 127854 | UA_Byte dest[ETHER_ADDR_LEN]; |
| 127855 | UA_StatusCode res = parseEthAddress(buf: address, addr: dest); |
| 127856 | if(res != UA_STATUSCODE_GOOD) { |
| 127857 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127858 | msg: "ETH\t| Could not parse the Ethernet address \"%.*s\"", |
| 127859 | (int)address->length, (char*)address->data); |
| 127860 | return res; |
| 127861 | } |
| 127862 | |
| 127863 | /* Get the VLAN config */ |
| 127864 | UA_UInt16 vid = 0; |
| 127865 | UA_Byte pcp = 0; |
| 127866 | UA_Boolean eid = false; |
| 127867 | |
| 127868 | const UA_UInt16 *vidp = (const UA_UInt16*) |
| 127869 | UA_KeyValueMap_getScalar(map: params, key: ETHConfigParameters[ETH_PARAMINDEX_VID].name, |
| 127870 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 127871 | if(vidp) |
| 127872 | vid = *vidp; |
| 127873 | |
| 127874 | const UA_Byte *pcpp = (const UA_Byte*) |
| 127875 | UA_KeyValueMap_getScalar(map: params, key: ETHConfigParameters[ETH_PARAMINDEX_PCP].name, |
| 127876 | type: &UA_TYPES[UA_TYPES_BYTE]); |
| 127877 | if(pcpp) |
| 127878 | pcp = *pcpp; |
| 127879 | |
| 127880 | const UA_Boolean *eidp = (const UA_Boolean*) |
| 127881 | UA_KeyValueMap_getScalar(map: params, key: ETHConfigParameters[ETH_PARAMINDEX_DEI].name, |
| 127882 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 127883 | if(eidp) |
| 127884 | eid = *eidp; |
| 127885 | |
| 127886 | /* Store the structure for sendto */ |
| 127887 | conn->sll.sll_ifindex = ifindex; |
| 127888 | conn->sll.sll_halen = ETH_ALEN; |
| 127889 | memcpy(dest: conn->sll.sll_addr, src: dest, ETHER_ADDR_LEN); |
| 127890 | |
| 127891 | /* Generate the Ethernet header */ |
| 127892 | conn->headerSize = setETHHeader(buf: conn->header, destAddr: dest, sourceAddr: source, etherType, |
| 127893 | vid, pcp, dei: eid, lengthOffset: &conn->lengthOffset); |
| 127894 | |
| 127895 | |
| 127896 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127897 | msg: "ETH %u\t| Opened an Ethernet send socket", |
| 127898 | (unsigned)conn->rfd.fd); |
| 127899 | |
| 127900 | return UA_STATUSCODE_GOOD; |
| 127901 | } |
| 127902 | |
| 127903 | static UA_StatusCode |
| 127904 | ETH_openConnection(UA_ConnectionManager *cm, const UA_KeyValueMap *params, |
| 127905 | void *application, void *context, |
| 127906 | UA_ConnectionManager_connectionCallback connectionCallback) { |
| 127907 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 127908 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX *)cm->eventSource.eventLoop; |
| 127909 | |
| 127910 | UA_LOCK(&el->elMutex); |
| 127911 | |
| 127912 | /* Listen or send connection? */ |
| 127913 | const UA_Boolean *listen = (const UA_Boolean*) |
| 127914 | UA_KeyValueMap_getScalar(map: params, key: ETHConfigParameters[ETH_PARAMINDEX_LISTEN].name, |
| 127915 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 127916 | size_t ethParams = ETH_PARAMETERSSIZE; |
| 127917 | if(!listen || !*listen) |
| 127918 | ethParams++; /* Require the address parameter to exist */ |
| 127919 | |
| 127920 | /* Validate the parameters */ |
| 127921 | UA_StatusCode res = |
| 127922 | UA_KeyValueRestriction_validate(logger: el->eventLoop.logger, logprefix: "ETH", restrictions: ETHConfigParameters, |
| 127923 | restrictionsSize: ethParams, map: params); |
| 127924 | if(res != UA_STATUSCODE_GOOD) { |
| 127925 | UA_UNLOCK(&el->elMutex); |
| 127926 | return res; |
| 127927 | } |
| 127928 | |
| 127929 | /* Only validate the parameters? */ |
| 127930 | UA_Boolean validate = false; |
| 127931 | const UA_Boolean *validateParam = (const UA_Boolean*) |
| 127932 | UA_KeyValueMap_getScalar(map: params, |
| 127933 | key: ETHConfigParameters[ETH_PARAMINDEX_VALIDATE].name, |
| 127934 | type: &UA_TYPES[UA_TYPES_BOOLEAN]); |
| 127935 | if(validateParam) |
| 127936 | validate = *validateParam; |
| 127937 | |
| 127938 | /* Get the EtherType parameter */ |
| 127939 | UA_UInt16 etherType = ETH_P_ALL; |
| 127940 | const UA_UInt16 *etParam = (const UA_UInt16*) |
| 127941 | UA_KeyValueMap_getScalar(map: params, key: ETHConfigParameters[ETH_PARAMINDEX_ETHERTYPE].name, |
| 127942 | type: &UA_TYPES[UA_TYPES_UINT16]); |
| 127943 | if(etParam) |
| 127944 | etherType = *etParam; |
| 127945 | |
| 127946 | /* Get the interface index */ |
| 127947 | const UA_String *interface = (const UA_String*) |
| 127948 | UA_KeyValueMap_getScalar(map: params, key: ETHConfigParameters[ETH_PARAMINDEX_IFACE].name, |
| 127949 | type: &UA_TYPES[UA_TYPES_STRING]); |
| 127950 | if(interface->length >= 128) { |
| 127951 | UA_UNLOCK(&el->elMutex); |
| 127952 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127953 | } |
| 127954 | char ifname[128]; |
| 127955 | memcpy(dest: ifname, src: interface->data, n: interface->length); |
| 127956 | ifname[interface->length] = 0; |
| 127957 | int ifindex = (int)if_nametoindex(ifname: ifname); |
| 127958 | if(ifindex == 0) { |
| 127959 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127960 | msg: "ETH\t| Could not find the interface %s", ifname); |
| 127961 | UA_UNLOCK(&el->elMutex); |
| 127962 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127963 | } |
| 127964 | |
| 127965 | /* Create the socket and add the basic configuration */ |
| 127966 | ETH_FD *conn = NULL; |
| 127967 | UA_FD sockfd; |
| 127968 | if(listen && *listen) |
| 127969 | sockfd = socket(PF_PACKET, SOCK_RAW, protocol: htons(hostshort: etherType)); |
| 127970 | else |
| 127971 | sockfd = socket(PF_PACKET, SOCK_RAW, protocol: 0); /* Don't receive */ |
| 127972 | if(sockfd == -1) { |
| 127973 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 127974 | msg: "ETH\t| Could not create a raw Ethernet socket (are you root?)"); |
| 127975 | UA_UNLOCK(&el->elMutex); |
| 127976 | return UA_STATUSCODE_BADINTERNALERROR; |
| 127977 | } |
| 127978 | |
| 127979 | /* SO_REUSEADDR is unnecessary (and unsupported on some Linux systems): |
| 127980 | * res |= UA_EventLoopPOSIX_setReusable(sockfd); */ |
| 127981 | res |= UA_EventLoopPOSIX_setNonBlocking(sockfd); |
| 127982 | res |= UA_EventLoopPOSIX_setNoSigPipe(sockfd); |
| 127983 | if(res != UA_STATUSCODE_GOOD) |
| 127984 | goto cleanup; |
| 127985 | |
| 127986 | /* Create the FD object */ |
| 127987 | conn = (ETH_FD*)UA_calloc(nmemb: 1, size: sizeof(ETH_FD)); |
| 127988 | if(!conn) { |
| 127989 | res = UA_STATUSCODE_BADOUTOFMEMORY; |
| 127990 | goto cleanup; |
| 127991 | } |
| 127992 | |
| 127993 | conn->rfd.fd = sockfd; |
| 127994 | conn->rfd.es = &pcm->cm.eventSource; |
| 127995 | conn->rfd.eventSourceCB = (UA_FDCallback)ETH_connectionSocketCallback; |
| 127996 | conn->context = context; |
| 127997 | conn->application = application; |
| 127998 | conn->applicationCB = connectionCallback; |
| 127999 | |
| 128000 | /* Configure a listen or a send connection */ |
| 128001 | if(!listen || !*listen) { |
| 128002 | /* Get the source address for the interface */ |
| 128003 | struct ifreq ifr; |
| 128004 | memcpy(dest: ifr.ifr_name, src: ifname, n: interface->length); |
| 128005 | ifr.ifr_name[interface->length] = 0; |
| 128006 | int result = ioctl(fd: conn->rfd.fd, SIOCGIFHWADDR, &ifr); |
| 128007 | if(result == -1) { |
| 128008 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 128009 | UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 128010 | "ETH %u\t| Cannot get the source address, %s", |
| 128011 | (unsigned)conn->rfd.fd, errno_str)); |
| 128012 | res = UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 128013 | goto cleanup; |
| 128014 | } |
| 128015 | res = ETH_openSendConnection(el, conn, params, |
| 128016 | source: (unsigned char*)ifr.ifr_hwaddr.sa_data, |
| 128017 | ifindex, etherType); |
| 128018 | } else { |
| 128019 | res = ETH_openListenConnection(el, conn, params, ifindex, etherType, validate); |
| 128020 | } |
| 128021 | |
| 128022 | /* Don't actually open or shut down */ |
| 128023 | if(validate || res != UA_STATUSCODE_GOOD) |
| 128024 | goto cleanup; |
| 128025 | |
| 128026 | /* Register in the EventLoop */ |
| 128027 | res = UA_EventLoopPOSIX_registerFD(el, rfd: &conn->rfd); |
| 128028 | if(res != UA_STATUSCODE_GOOD) |
| 128029 | goto cleanup; |
| 128030 | |
| 128031 | /* Register locally */ |
| 128032 | ZIP_INSERT(UA_FDTree, &pcm->fds, &conn->rfd); |
| 128033 | pcm->fdsSize++; |
| 128034 | |
| 128035 | /* Register the listen socket in the application */ |
| 128036 | connectionCallback(cm, (uintptr_t)sockfd, application, &conn->context, |
| 128037 | UA_CONNECTIONSTATE_ESTABLISHED, &UA_KEYVALUEMAP_NULL, |
| 128038 | UA_BYTESTRING_NULL); |
| 128039 | UA_UNLOCK(&el->elMutex); |
| 128040 | return UA_STATUSCODE_GOOD; |
| 128041 | |
| 128042 | cleanup: |
| 128043 | UA_close(fd: sockfd); |
| 128044 | UA_free(ptr: conn); |
| 128045 | UA_UNLOCK(&el->elMutex); |
| 128046 | return res; |
| 128047 | } |
| 128048 | |
| 128049 | static void |
| 128050 | ETH_shutdown(UA_POSIXConnectionManager *pcm, ETH_FD *conn) { |
| 128051 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 128052 | UA_LOCK_ASSERT(&((UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop)->elMutex, 1); |
| 128053 | |
| 128054 | UA_DelayedCallback *dc = &conn->rfd.dc; |
| 128055 | if(dc->callback) { |
| 128056 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 128057 | msg: "ETH %u\t| Cannot close - already closing", |
| 128058 | (unsigned)conn->rfd.fd); |
| 128059 | return; |
| 128060 | } |
| 128061 | |
| 128062 | /* Shutdown the socket to cancel the current select/epoll */ |
| 128063 | shutdown(fd: conn->rfd.fd, UA_SHUT_RDWR); |
| 128064 | |
| 128065 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 128066 | msg: "ETH %u\t| Shutdown called", (unsigned)conn->rfd.fd); |
| 128067 | |
| 128068 | dc->callback = ETH_delayedClose; |
| 128069 | dc->application = pcm; |
| 128070 | dc->context = conn; |
| 128071 | |
| 128072 | /* Don't use the "public" el->addDelayedCallback. It takes a lock. */ |
| 128073 | dc->next = el->delayedCallbacks; |
| 128074 | el->delayedCallbacks = dc; |
| 128075 | } |
| 128076 | |
| 128077 | static UA_StatusCode |
| 128078 | ETH_shutdownConnection(UA_ConnectionManager *cm, uintptr_t connectionId) { |
| 128079 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 128080 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 128081 | UA_LOCK(&el->elMutex); |
| 128082 | |
| 128083 | /* Get the ETH_FD */ |
| 128084 | UA_FD fd = (UA_FD)connectionId; |
| 128085 | UA_RegisteredFD *rfd = ZIP_FIND(UA_FDTree, &pcm->fds, &fd); |
| 128086 | if(!rfd) { |
| 128087 | UA_LOG_WARNING(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 128088 | msg: "ETH\t| Cannot close Ethernet connection %u - not found", |
| 128089 | (unsigned)connectionId); |
| 128090 | UA_UNLOCK(&el->elMutex); |
| 128091 | return UA_STATUSCODE_BADNOTFOUND; |
| 128092 | } |
| 128093 | |
| 128094 | ETH_shutdown(pcm, conn: (ETH_FD*)rfd); |
| 128095 | UA_UNLOCK(&el->elMutex); |
| 128096 | return UA_STATUSCODE_GOOD; |
| 128097 | } |
| 128098 | |
| 128099 | static UA_StatusCode |
| 128100 | ETH_sendWithConnection(UA_ConnectionManager *cm, uintptr_t connectionId, |
| 128101 | const UA_KeyValueMap *params, UA_ByteString *buf) { |
| 128102 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 128103 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 128104 | |
| 128105 | UA_LOCK(&el->elMutex); |
| 128106 | |
| 128107 | /* Get the ETH_FD */ |
| 128108 | UA_FD fd = (UA_FD)connectionId; |
| 128109 | ETH_FD *conn = (ETH_FD*)ZIP_FIND(UA_FDTree, &pcm->fds, &fd); |
| 128110 | if(!conn) { |
| 128111 | UA_UNLOCK(&el->elMutex); |
| 128112 | return UA_STATUSCODE_BADCONNECTIONREJECTED; |
| 128113 | } |
| 128114 | |
| 128115 | /* Uncover and set the Ethernet header */ |
| 128116 | buf->data -= conn->headerSize; |
| 128117 | buf->length += conn->headerSize; |
| 128118 | memcpy(dest: buf->data, src: conn->header, n: conn->headerSize); |
| 128119 | if(conn->lengthOffset) { |
| 128120 | UA_UInt16 *ethLength = (UA_UInt16*)&buf->data[conn->lengthOffset]; |
| 128121 | *ethLength = htons(hostshort: (UA_UInt16)(buf->length - conn->headerSize)); |
| 128122 | } |
| 128123 | |
| 128124 | /* Prevent OS signals when sending to a closed socket */ |
| 128125 | int flags = MSG_NOSIGNAL; |
| 128126 | |
| 128127 | struct pollfd tmp_poll_fd; |
| 128128 | tmp_poll_fd.fd = (UA_FD)connectionId; |
| 128129 | tmp_poll_fd.events = UA_POLLOUT; |
| 128130 | |
| 128131 | /* Send the full buffer. This may require several calls to send */ |
| 128132 | size_t nWritten = 0; |
| 128133 | do { |
| 128134 | ssize_t n = 0; |
| 128135 | do { |
| 128136 | UA_LOG_DEBUG(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 128137 | msg: "ETH %u\t| Attempting to send", (unsigned)connectionId); |
| 128138 | size_t bytes_to_send = buf->length - nWritten; |
| 128139 | n = UA_sendto(fd: conn->rfd.fd, buf: (const char*)buf->data + nWritten, n: bytes_to_send, |
| 128140 | flags: flags, addr: (struct sockaddr*)&conn->sll, addr_len: sizeof(conn->sll)); |
| 128141 | if(n < 0) { |
| 128142 | /* An error we cannot recover from? */ |
| 128143 | if(UA_ERRNO != UA_INTERRUPTED && |
| 128144 | UA_ERRNO != UA_WOULDBLOCK && |
| 128145 | UA_ERRNO != UA_AGAIN) { |
| 128146 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 128147 | UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 128148 | "ETH %u\t| Send failed with error %s", |
| 128149 | (unsigned)connectionId, errno_str)); |
| 128150 | ETH_shutdown(pcm, conn); |
| 128151 | UA_UNLOCK(&el->elMutex); |
| 128152 | UA_ByteString_clear(p: buf); |
| 128153 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 128154 | } |
| 128155 | |
| 128156 | /* Poll for the socket resources to become available and retry |
| 128157 | * (blocking) */ |
| 128158 | int poll_ret; |
| 128159 | do { |
| 128160 | poll_ret = UA_poll(fds: &tmp_poll_fd, nfds: 1, timeout: 100); |
| 128161 | if(poll_ret < 0 && UA_ERRNO != UA_INTERRUPTED) { |
| 128162 | UA_LOG_SOCKET_ERRNO_WRAP( |
| 128163 | UA_LOG_ERROR(el->eventLoop.logger, UA_LOGCATEGORY_NETWORK, |
| 128164 | "ETH %u\t| Send failed with error %s", |
| 128165 | (unsigned)connectionId, errno_str)); |
| 128166 | ETH_shutdown(pcm, conn); |
| 128167 | UA_UNLOCK(&el->elMutex); |
| 128168 | UA_ByteString_clear(p: buf); |
| 128169 | return UA_STATUSCODE_BADCONNECTIONCLOSED; |
| 128170 | } |
| 128171 | } while(poll_ret <= 0); |
| 128172 | } |
| 128173 | } while(n < 0); |
| 128174 | nWritten += (size_t)n; |
| 128175 | } while(nWritten < buf->length); |
| 128176 | |
| 128177 | /* Free the buffer */ |
| 128178 | UA_UNLOCK(&el->elMutex); |
| 128179 | UA_ByteString_clear(p: buf); |
| 128180 | return UA_STATUSCODE_GOOD; |
| 128181 | } |
| 128182 | |
| 128183 | static UA_StatusCode |
| 128184 | ETH_eventSourceStart(UA_ConnectionManager *cm) { |
| 128185 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)cm->eventSource.eventLoop; |
| 128186 | UA_LOCK(&el->elMutex); |
| 128187 | |
| 128188 | /* Check the state */ |
| 128189 | if(cm->eventSource.state != UA_EVENTSOURCESTATE_STOPPED) { |
| 128190 | UA_LOG_ERROR(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 128191 | msg: "To start the Ethernet ConnectionManager, " |
| 128192 | "it has to be registered in an EventLoop and not started"); |
| 128193 | UA_UNLOCK(&el->elMutex); |
| 128194 | return UA_STATUSCODE_BADINTERNALERROR; |
| 128195 | } |
| 128196 | |
| 128197 | /* Set the EventSource to the started state */ |
| 128198 | cm->eventSource.state = UA_EVENTSOURCESTATE_STARTED; |
| 128199 | |
| 128200 | UA_UNLOCK(&el->elMutex); |
| 128201 | return UA_STATUSCODE_GOOD; |
| 128202 | } |
| 128203 | |
| 128204 | static void * |
| 128205 | ETH_shutdownCB(void *application, UA_RegisteredFD *rfd) { |
| 128206 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)application; |
| 128207 | ETH_shutdown(pcm, conn: (ETH_FD*)rfd); |
| 128208 | return NULL; |
| 128209 | } |
| 128210 | |
| 128211 | static void |
| 128212 | ETH_eventSourceStop(UA_ConnectionManager *cm) { |
| 128213 | UA_POSIXConnectionManager *pcm = (UA_POSIXConnectionManager*)cm; |
| 128214 | UA_EventLoopPOSIX *el = (UA_EventLoopPOSIX*)pcm->cm.eventSource.eventLoop; |
| 128215 | UA_LOCK(&el->elMutex); |
| 128216 | |
| 128217 | UA_LOG_INFO(logger: el->eventLoop.logger, category: UA_LOGCATEGORY_NETWORK, |
| 128218 | msg: "ETH\t| Shutting down the ConnectionManager"); |
| 128219 | |
| 128220 | /* Prevent new connections to open */ |
| 128221 | cm->eventSource.state = UA_EVENTSOURCESTATE_STOPPING; |
| 128222 | |
| 128223 | /* Shutdown all existing connection */ |
| 128224 | ZIP_ITER(UA_FDTree, &pcm->fds, ETH_shutdownCB, cm); |
| 128225 | |
| 128226 | /* Check if stopped once more (also checking inside ETH_close, but there we |
| 128227 | * don't check if there is no rfd at all) */ |
| 128228 | ETH_checkStopped(pcm); |
| 128229 | |
| 128230 | UA_UNLOCK(&el->elMutex); |
| 128231 | } |
| 128232 | |
| 128233 | static UA_StatusCode |
| 128234 | ETH_eventSourceDelete(UA_ConnectionManager *cm) { |
| 128235 | if(cm->eventSource.state >= UA_EVENTSOURCESTATE_STARTING) { |
| 128236 | UA_LOG_ERROR(logger: cm->eventSource.eventLoop->logger, category: UA_LOGCATEGORY_EVENTLOOP, |
| 128237 | msg: "ETH\t| The EventSource must be stopped before it can be deleted"); |
| 128238 | return UA_STATUSCODE_BADINTERNALERROR; |
| 128239 | } |
| 128240 | |
| 128241 | /* Delete the parameters */ |
| 128242 | UA_KeyValueMap_clear(map: &cm->eventSource.params); |
| 128243 | UA_String_clear(p: &cm->eventSource.name); |
| 128244 | UA_free(ptr: cm); |
| 128245 | return UA_STATUSCODE_GOOD; |
| 128246 | } |
| 128247 | |
| 128248 | static const char *ethName = "eth"; |
| 128249 | |
| 128250 | UA_ConnectionManager * |
| 128251 | UA_ConnectionManager_new_POSIX_Ethernet(const UA_String eventSourceName) { |
| 128252 | UA_POSIXConnectionManager *cm = (UA_POSIXConnectionManager*) |
| 128253 | UA_calloc(nmemb: 1, size: sizeof(UA_POSIXConnectionManager)); |
| 128254 | if(!cm) |
| 128255 | return NULL; |
| 128256 | |
| 128257 | cm->cm.eventSource.eventSourceType = UA_EVENTSOURCETYPE_CONNECTIONMANAGER; |
| 128258 | UA_String_copy(src: &eventSourceName, dst: &cm->cm.eventSource.name); |
| 128259 | cm->cm.eventSource.start = (UA_StatusCode (*)(UA_EventSource *))ETH_eventSourceStart; |
| 128260 | cm->cm.eventSource.stop = (void (*)(UA_EventSource *))ETH_eventSourceStop; |
| 128261 | cm->cm.eventSource.free = (UA_StatusCode (*)(UA_EventSource *))ETH_eventSourceDelete; |
| 128262 | cm->cm.protocol = UA_STRING(chars: (char*)(uintptr_t)ethName); |
| 128263 | cm->cm.openConnection = ETH_openConnection; |
| 128264 | cm->cm.allocNetworkBuffer = ETH_allocNetworkBuffer; |
| 128265 | cm->cm.freeNetworkBuffer = ETH_freeNetworkBuffer; |
| 128266 | cm->cm.sendWithConnection = ETH_sendWithConnection; |
| 128267 | cm->cm.closeConnection = ETH_shutdownConnection; |
| 128268 | return &cm->cm; |
| 128269 | } |
| 128270 | |
| 128271 | #endif /* defined(UA_ARCHITECTURE_POSIX) && defined(__linux__) */ |
| 128272 | |
| 128273 |
